diff --git a/.cmake.conf b/.cmake.conf
index 59d249587ee..185995ba180 100644
--- a/.cmake.conf
+++ b/.cmake.conf
@@ -1,4 +1,4 @@
-set(QT_REPO_MODULE_VERSION "6.6.0")
+set(QT_REPO_MODULE_VERSION "6.5.6")
 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/CHROMIUM_VERSION b/CHROMIUM_VERSION
index 586f452ee42..0361e1449db 100644
--- a/CHROMIUM_VERSION
+++ b/CHROMIUM_VERSION
@@ -1,3 +1,3 @@
 
-Based on Chromium version:                                      108.0.5359.181
-Patched with security patches up to Chromium version:           113.0.5672.126
+Based on Chromium version:                                      112.0.5615.213
+Patched with security patches up to Chromium version:           124.0.6367.208
diff --git a/CMakeLists.txt b/CMakeLists.txt
index faa9b1a51b0..e235794f24c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,10 +9,9 @@ cmake_minimum_required(VERSION 3.16)
 include(.cmake.conf)
 include(ExternalProject)
 include(cmake/Functions.cmake)
-include(src/core/api/Qt6WebEngineCoreMacros.cmake)
 
 project(QtWebEngineDummy)
-find_package(Qt6 6.2 CONFIG REQUIRED COMPONENTS BuildInternals Core)
+find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core)
 
 project(QtWebEngine
     VERSION ${Qt6Core_VERSION}
@@ -20,12 +19,14 @@ project(QtWebEngine
     HOMEPAGE_URL "https://qt.io/"
     LANGUAGES CXX C
 )
-qt_internal_project_setup()
+
+if(COMMAND qt_internal_project_setup)
+    qt_internal_project_setup()
+endif()
 
 find_package(Qt6 ${PROJECT_VERSION} CONFIG QUIET OPTIONAL_COMPONENTS
     Gui Widgets Network OpenGL Quick Qml PrintSupport
-    WebChannel WebChannelQuick Positioning QuickControls2
-    Test QuickWidgets QuickTest WebSockets Designer
+    WebChannel Positioning QuickControls2 Test QuickWidgets QuickTest WebSockets Designer
     JpegPrivate PngPrivate HarfbuzzPrivate FreetypePrivate ZlibPrivate
 )
 
diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake
index b90447ed36e..40554ad6b9a 100644
--- a/cmake/Functions.cmake
+++ b/cmake/Functions.cmake
@@ -1,6 +1,15 @@
 # Copyright (C) 2022 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
+# this macro is missing in 6.2
+if(NOT COMMAND _qt_internal_validate_all_args_are_parsed)
+    macro(_qt_internal_validate_all_args_are_parsed result)
+        if(DEFINED ${result}_UNPARSED_ARGUMENTS)
+            message(FATAL_ERROR "Unknown arguments (${${result}_UNPARSED_ARGUMENTS}).")
+        endif()
+    endmacro()
+endif()
+
 function(assertTargets)
     cmake_parse_arguments(PARSE_ARGV 0 arg
         "" "" "MODULES;TARGETS"
@@ -24,18 +33,6 @@ function(assertTargets)
     endforeach()
 endfunction()
 
-#TODO: remove me
-function(add_implicit_dependencies target)
-    if(TARGET ${target})
-        list(REMOVE_ITEM ARGN ${target})
-        foreach(qtTarget IN ITEMS ${ARGN})
-            if(TARGET Qt::${qtTarget})
-                add_dependencies(${target} Qt::${qtTarget})
-            endif()
-        endforeach()
-    endif()
-endfunction()
-
 # TODO: this should be idealy in qtbase
 function(add_check_for_support)
     cmake_parse_arguments(PARSE_ARGV 0 arg
@@ -49,7 +46,7 @@ function(add_check_for_support)
             set(${module}_SUPPORT ON)
         endif()
         if(${module}_SUPPORT)
-            if("x${arg_CONDITION}" STREQUAL x)
+            if("x${arg_CONDITION}" STREQUAL "x")
                 set(arg_CONDITION ON)
             endif()
             qt_evaluate_config_expression(result ${arg_CONDITION})
@@ -65,23 +62,6 @@ function(add_check_for_support)
     endforeach()
 endfunction()
 
-function(get_qt_features outList module)
-    get_cmake_property(variableList VARIABLES)
-    set(_featureList "")
-    foreach (variableKey ${variableList})
-        unset(FOUND)
-        string(REGEX MATCH QT_FEATURE_${module} FOUND ${variableKey})
-        if(FOUND)
-            list(APPEND _featureList "${variableKey}=${${variableKey}}")
-        endif()
-    endforeach()
-    if("${${outList}}" STREQUAL "")
-        set(${outList} ${_featureList} PARENT_SCOPE)
-    else()
-        set(${outList} "${${outList}}" "${_featureList}" PARENT_SCOPE)
-    endif()
-endfunction()
-
 function(create_cxx_config cmakeTarget arch configFileName)
     if(NOT QT_SUPERBUILD AND QT_WILL_INSTALL)
         get_target_property(mocFilePath Qt6::moc IMPORTED_LOCATION)
@@ -188,7 +168,7 @@ function(extend_gn_target target)
     cmake_parse_arguments(PARSE_ARGV 1 GN "" "" "CONDITION;${elements}")
     _qt_internal_validate_all_args_are_parsed(GN)
 
-    if("x${GN_CONDITION}" STREQUAL x)
+    if("x${GN_CONDITION}" STREQUAL "x")
         set(GN_CONDITION ON)
     endif()
     qt_evaluate_config_expression(result ${GN_CONDITION})
@@ -202,7 +182,7 @@ function(extend_gn_list outList)
     cmake_parse_arguments(PARSE_ARGV 1 GN "" "" "ARGS;CONDITION")
     _qt_internal_validate_all_args_are_parsed(GN)
 
-    if("x${GN_CONDITION}" STREQUAL x)
+    if("x${GN_CONDITION}" STREQUAL "x")
         set(GN_CONDITION ON)
     endif()
     qt_evaluate_config_expression(result ${GN_CONDITION})
@@ -222,10 +202,15 @@ function(configure_gn_target sourceDir inFilePath outFilePath)
     # FIXME: GN_CONFIG
     set(GN_CONFIG NOTUSED)
 
+    set(path_mode REALPATH)
+    if(APPLE AND QT_ALLOW_SYMLINK_IN_PATHS)
+        set(path_mode ABSOLUTE)
+    endif()
+
     # GN_SOURCES GN_HEADERS
     get_property(gnSources DIRECTORY PROPERTY GN_SOURCES)
     foreach(gnSourceFile ${gnSources})
-        get_filename_component(gnSourcePath ${sourceDir}/${gnSourceFile} REALPATH)
+        get_filename_component(gnSourcePath ${sourceDir}/${gnSourceFile} ${path_mode})
         list(APPEND sourceList \"${gnSourcePath}\")
     endforeach()
     set(GN_HEADERS ${sourceList})
@@ -245,7 +230,7 @@ function(configure_gn_target sourceDir inFilePath outFilePath)
     get_property(gnIncludes DIRECTORY PROPERTY GN_INCLUDES)
     list(REMOVE_DUPLICATES gnIncludes)
     foreach(gnInclude ${gnIncludes})
-        get_filename_component(gnInclude ${gnInclude} REALPATH)
+        get_filename_component(gnInclude ${gnInclude} ${path_mode})
         list(APPEND GN_ARGS_INCLUDES \"-I${gnInclude}\")
         list(APPEND GN_INCLUDE_DIRS \"${gnInclude}\")
     endforeach()
@@ -269,7 +254,7 @@ function(configure_gn_target sourceDir inFilePath outFilePath)
     list(REMOVE_DUPLICATES GN_CFLAGS_C)
 
     # GN_SOURCE_ROOT
-    get_filename_component(GN_SOURCE_ROOT "${sourceDir}" REALPATH)
+    get_filename_component(GN_SOURCE_ROOT "${sourceDir}" ${path_mode})
 
     if(APPLE) # this runs in scrpit mode without qt-cmake so on MACOS here
         recoverFrameworkBuild(GN_INCLUDE_DIRS GN_CFLAGS_C)
@@ -320,13 +305,6 @@ function(get_install_config result)
     endif()
 endfunction()
 
-macro(assertRunAsTopLevelBuild)
-    if(NOT DEFINED WEBENGINE_REPO_BUILD)
-        message(FATAL_ERROR "This cmake file should run as top level build.")
-        return()
-    endif()
-endmacro()
-
 # we need to pass -F or -iframework in case of frameworks builds, which gn treats as
 # compiler flag and cmake as include dir, so swap it.
 function(recoverFrameworkBuild includeDirs compilerFlags)
@@ -445,6 +423,7 @@ function(add_linker_options target buildDir completeStatic)
     set(objects_rsp "${buildDir}/${ninjaTarget}_objects.rsp")
     set(archives_rsp "${buildDir}/${ninjaTarget}_archives.rsp")
     set(libs_rsp "${buildDir}/${ninjaTarget}_libs.rsp")
+    set(ldir_rsp "${buildDir}/${ninjaTarget}_ldir.rsp")
     set_target_properties(${cmakeTarget} PROPERTIES STATIC_LIBRARY_OPTIONS "@${objects_rsp}")
     if(LINUX OR ANDROID)
          get_gn_arch(cpu ${TEST_architecture_arch})
@@ -460,38 +439,18 @@ function(add_linker_options target buildDir completeStatic)
              )
          endif()
 
-         # we need only the '-L' flags from lflags.rsp, filter them
-         set(lflags_rsp "${buildDir}/${ninjaTarget}_lflags.rsp")
-         set(lflags_filtered_rsp "${buildDir}/${ninjaTarget}_lflags_filtered.rsp")
-         set(lflags_filter_script "${buildDir}/${ninjaTarget}_lflags_filter.cmake")
-         file(GENERATE OUTPUT ${lflags_filter_script}
-              CONTENT "file(STRINGS ${lflags_rsp} lflags)
-                       string(REGEX MATCHALL \"-L.*\" lflags_filtered \${lflags})
-                       file(WRITE ${lflags_filtered_rsp} \${lflags_filtered})"
-              FILE_PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ
-         )
-         add_custom_command(
-            OUTPUT ${lflags_filtered_rsp}
-            COMMAND ${CMAKE_COMMAND} -P ${lflags_filter_script}
-            DEPENDS ${lflags_filter_script} ${lflags_rsp}
-         )
-         add_custom_target(
-            run_${cmakeTarget}_${config}_lflags_filter
-            DEPENDS ${lflags_filtered_rsp}
-         )
-         add_dependencies(${cmakeTarget} run_${cmakeTarget}_${config}_lflags_filter)
-
          # linker here options are just to prevent processing it by cmake
          target_link_libraries(${cmakeTarget} PRIVATE
-             "$<1:-Wl,--no-fatal-warnings $<$<CONFIG:${config}>:@${lflags_filtered_rsp}> $<$<CONFIG:${config}>:@${libs_rsp}> -Wl,--no-fatal-warnings>"
+             "$<1:-Wl,--no-fatal-warnings $<$<CONFIG:${config}>:@${ldir_rsp}> $<$<CONFIG:${config}>:@${libs_rsp}> -Wl,--no-fatal-warnings>"
          )
+         unset(cpu)
     endif()
     if(MACOS)
         target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:${config}>:@${objects_rsp}>")
         if(NOT completeStatic)
             target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:${config}>:@${archives_rsp}>")
         endif()
-        target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:${config}>:@${libs_rsp}>")
+        target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:${config}>:@${ldir_rsp}>" "$<$<CONFIG:${config}>:@${libs_rsp}>")
     endif()
     if(WIN32)
         get_copy_of_response_file(objects_rsp ${target} objects)
@@ -499,8 +458,10 @@ function(add_linker_options target buildDir completeStatic)
             target_link_options(${cmakeTarget}
                 PRIVATE /DELAYLOAD:mf.dll /DELAYLOAD:mfplat.dll /DELAYLOAD:mfreadwrite.dll /DELAYLOAD:winmm.dll
             )
-            # enable larger PDBs
-            target_link_options(${cmakeTarget} PRIVATE "/pdbpagesize:8192")
+            # enable larger PDBs if webenginecore debug build
+            if(cmakeTarget STREQUAL "WebEngineCore")
+                target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:Debug>:/pdbpagesize:8192>")
+            endif()
         endif()
         target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:${config}>:@${objects_rsp}>")
         if(NOT completeStatic)
@@ -663,46 +624,50 @@ 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)
-    if(arch STREQUAL "i386")
+    set(armList arm armv7-a)
+    set(mips64List mips64 mipsel64)
+    set(x86List i386 i686)
+    set(x64List x86_64 AMD64 x86_64h aarch64)
+    if(arch IN_LIST x86List)
         set(${result} "x86" PARENT_SCOPE)
-    elseif(arch STREQUAL "x86_64")
+    elseif(arch IN_LIST x64List)
         set(${result} "x64" PARENT_SCOPE)
-    elseif(arch STREQUAL "arm")
+    elseif(arch IN_LIST armList)
         set(${result} "arm" PARENT_SCOPE)
     elseif(arch STREQUAL "arm64")
         set(${result} "arm64" PARENT_SCOPE)
     elseif(arch STREQUAL "mipsel")
         set(${result} "mipsel" PARENT_SCOPE)
-    elseif(arch STREQUAL "mipsel64")
+    elseif(arch IN_LIST mipsList)
         set(${result} "mips64el" PARENT_SCOPE)
     elseif(arch STREQUAL "riscv64")
         set(${result} "riscv64" PARENT_SCOPE)
     else()
-        message(DEBUG "Unsupported architecture: ${arch}")
+        message(FATAL_ERROR "Unknown architecture: ${arch}")
     endif()
 endfunction()
 
+# Function maps gn architecture for v8
 function(get_v8_arch result targetArch hostArch)
-    set(list32 i386 arm mipsel)
+    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 "x86_64")
-            set(${result} "i386" PARENT_SCOPE)
+        if(hostArch STREQUAL "x64")
+            set(${result} "x86" PARENT_SCOPE)
         elseif(hostArch STREQUAL "arm64")
             set(${result} "arm" PARENT_SCOPE)
-        elseif(hostArch STREQUAL "mips64")
-            set(${result} "mipsel" PARENT_SCOPE)
-        elseif(hostArch STREQUAL "mipsel64")
+        elseif(hostArch STREQUAL "mips64el")
             set(${result} "mipsel" PARENT_SCOPE)
         elseif(hostArch STREQUAL "riscv64")
-            set(${result} "riscv64" PARENT_SCOPE)
+            set(${result} "riscv32" PARENT_SCOPE)
         elseif(hostArch IN_LIST list32)
             set(${result} "${hostArch}" PARENT_SCOPE)
         else()
-            message(FATAL_ERROR "Unsupported architecture: ${hostArch}")
+            message(FATAL_ERROR "Unknown architecture: ${hostArch}")
         endif()
     else()
         # assume 64bit target which matches 64bit host
@@ -745,12 +710,12 @@ function(get_ios_sysroot result arch)
     set(${result} ${sysroot} PARENT_SCOPE)
 endfunction()
 
-function(configure_gn_toolchain name binTargetCpu v8TargetCpu toolchainIn toolchainOut)
+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_arch(GN_CPU ${binTargetCpu})
-    get_gn_arch(GN_V8_CPU ${v8TargetCpu})
+    set(GN_CPU ${cpu})
+    set(GN_V8_CPU ${v8Cpu})
     configure_file(${toolchainIn} ${toolchainOut}/BUILD.gn @ONLY)
 endfunction()
 
@@ -832,17 +797,19 @@ macro(create_pkg_config_host_wrapper buildDir)
 endmacro()
 
 macro(setup_toolchains)
+    get_gn_arch(gn_arch ${TEST_architecture_arch})
     if(NOT CMAKE_CROSSCOMPILING) # delivered by hostBuild project
-        configure_gn_toolchain(host ${TEST_architecture_arch} ${TEST_architecture_arch}
+        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 ${TEST_architecture_arch} ${TEST_architecture_arch}
+        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 ${TEST_architecture_arch} ${TEST_architecture_arch}
+    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)
@@ -855,7 +822,8 @@ macro(append_build_type_setup)
         forbid_non_component_debug_builds=false
         treat_warnings_as_errors=false
         use_allocator_shim=false
-        use_allocator="none"
+        use_partition_alloc=true
+        use_partition_alloc_as_malloc=false
         use_custom_libcxx=false
     )
     if(${config} STREQUAL "Debug")
@@ -878,7 +846,7 @@ macro(append_build_type_setup)
     if(FEATURE_developer_build OR (${config} STREQUAL "Debug") OR QT_FEATURE_webengine_sanitizer)
         list(APPEND gnArgArg
              is_official_build=false
-             from_here_uses_location_builtins=false
+             use_viz_debugger=false
         )
     else()
         list(APPEND gnArgArg is_official_build=true)
@@ -924,7 +892,7 @@ macro(append_compiler_linker_sdk_setup)
     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)
+    extend_gn_list(gnArgArg ARGS is_gcc CONDITION LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
 
     if(CLANG)
         if(MACOS)
@@ -987,11 +955,13 @@ macro(append_compiler_linker_sdk_setup)
     if(MSVC)
         get_filename_component(windowsSdkPath $ENV{WINDOWSSDKDIR} ABSOLUTE)
         get_filename_component(visualStudioPath $ENV{VSINSTALLDIR} ABSOLUTE)
+        set(windowSdkVersion $ENV{WindowsSDKVersion})
         list(APPEND gnArgArg
             win_linker_timing=true
             use_incremental_linking=false
-            visual_studio_version=2019
+            visual_studio_version=2022
             visual_studio_path=\"${visualStudioPath}\"
+            windows_sdk_version=\"${windowsSdkVersion}\"
             windows_sdk_path=\"${windowsSdkPath}\"
         )
     endif()
@@ -1039,6 +1009,7 @@ macro(append_compiler_linker_sdk_setup)
         ARGS use_lld
         CONDITION QT_FEATURE_use_lld_linker
     )
+    unset(cpu)
 endmacro()
 
 macro(append_sanitizer_setup)
@@ -1059,24 +1030,33 @@ macro(append_sanitizer_setup)
             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(MINGW)
-        list(APPEND gnArgArg
-            # note '/' prefix
-            custom_toolchain="/${buildDir}/target_toolchain:target"
-            host_toolchain="/${buildDir}/host_toolchain:host"
-        )
-        list(APPEND gnArgArg host_cpu="${cpu}")
-    endif()
-    if(LINUX)
+    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"
         )
-        get_gn_arch(cpu ${TEST_architecture_arch})
         if(CMAKE_CROSSCOMPILING)
             list(APPEND gnArgArg
                 v8_snapshot_toolchain="${buildDir}/v8_toolchain:v8"
@@ -1088,17 +1068,18 @@ macro(append_toolchain_setup)
         if(CMAKE_SYSROOT)
             list(APPEND gnArgArg target_sysroot="${CMAKE_SYSROOT}")
         endif()
-    else()
+    elseif(MACOS)
         get_gn_arch(cpu ${arch})
         list(APPEND gnArgArg target_cpu="${cpu}")
-        if(IOS)
-            get_ios_sysroot(sysroot ${arch})
-            list(APPEND gnArgArg target_sysroot="${sysroot}" target_os="ios")
-        endif()
-    endif()
-    if(ANDROID)
-        list(APPEND gnArgArg target_os="android")
+    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}")
     endif()
+    unset(cpu)
 endmacro()
 
 
@@ -1161,7 +1142,7 @@ function(get_architectures result)
     set(${result} ${${result}} PARENT_SCOPE)
 endfunction()
 
-function(add_gn_build_aritfacts_to_target)
+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" ""
     )
@@ -1213,6 +1194,15 @@ function(add_gn_build_aritfacts_to_target)
         endforeach()
         list(GET archs 0 arch)
         set(target ${arg_NINJA_TARGET}_${config}_${arch})
+        # Work around for broken builds with new Apple linker ld_prime. Force
+        # use of the classic linker until this has been fixed.
+        # TODO: remove once this has been fixed by Apple. See issue FB13667242
+        # or QTBUG-122655 for details.
+        if(APPLECLANG)
+            if(CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "15.0.0")
+                target_link_options(${arg_CMAKE_TARGET} PRIVATE -ld_classic)
+            endif()
+        endif()
         if(QT_IS_MACOS_UNIVERSAL)
             add_lipo_command(${target} ${arg_BUILDDIR}/${config})
         endif()
@@ -1242,7 +1232,7 @@ function(add_gn_command)
     file(WRITE ${gnArgArgFile} ${arg_GN_ARGS})
 
     foreach(ninjaTarget ${arg_NINJA_TARGETS})
-        list(APPEND output ${ninjaTarget}_objects.rsp ${ninjaTarget}_archives.rsp ${ninjaTarget}_libs.rsp ${ninjaTarget}_lflags.rsp)
+        list(APPEND output ${ninjaTarget}_objects.rsp ${ninjaTarget}_archives.rsp ${ninjaTarget}_libs.rsp ${ninjaTarget}_ldir.rsp)
     endforeach()
     list(TRANSFORM output PREPEND "${arg_BUILDDIR}/")
 
@@ -1259,6 +1249,7 @@ function(add_gn_command)
              -DQT_HOST_GN_PATH=${QT_HOST_GN_PATH}
              -DPython3_EXECUTABLE=${Python3_EXECUTABLE}
              -DGN_THREADS=$ENV{QTWEBENGINE_GN_THREADS}
+             -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS}
              -P ${WEBENGINE_ROOT_SOURCE_DIR}/cmake/Gn.cmake
         WORKING_DIRECTORY ${WEBENGINE_ROOT_BUILD_DIR}
         COMMENT "Run gn for target ${arg_CMAKE_TARGET} in ${arg_BUILDDIR}"
@@ -1276,6 +1267,9 @@ function(add_gn_command)
             ${arg_BUILDDIR}/${targetConfigFileName}
     )
     add_dependencies(run_${arg_MODULE}_GnDone runGn_${arg_GN_TARGET})
+    if(TARGET thirdparty_sync_headers)
+        add_dependencies(runGn_${arg_GN_TARGET} thirdparty_sync_headers)
+    endif()
     create_gn_target_config(${arg_GN_TARGET} ${arg_BUILDDIR}/${targetConfigFileName})
 endfunction()
 
@@ -1307,16 +1301,6 @@ function(addCopyCommand target src dst)
     )
 endfunction()
 
-function(addCopyDirCommand target src dst)
-    add_custom_command(
-        POST_BUILD
-        COMMAND ${CMAKE_COMMAND} -E copy_directory ${src} ${dst}
-        TARGET ${target}
-        DEPENDS ${src}
-        USES_TERMINAL
-    )
-endfunction()
-
 function(check_for_ulimit)
     message("-- Checking 'ulimit -n'")
     execute_process(COMMAND bash -c "ulimit -n"
@@ -1380,7 +1364,7 @@ function(add_code_attributions_target)
     add_custom_command(
         OUTPUT ${arg_OUTPUT}
         COMMAND ${CMAKE_COMMAND}
-            -DLICENSE_SCRIPT=${WEBENGINE_ROOT_SOURCE_DIR}/src/3rdparty/chromium/tools/licenses.py
+            -DLICENSE_SCRIPT=${WEBENGINE_ROOT_SOURCE_DIR}/src/3rdparty/chromium/tools/licenses/licenses.py
             -DFILE_TEMPLATE=${fileTemplate}
             -DENTRY_TEMPLATE=${entryTemplate}
             -DGN_TARGET=${arg_GN_TARGET}
@@ -1390,7 +1374,7 @@ function(add_code_attributions_target)
             -P ${WEBENGINE_ROOT_SOURCE_DIR}/cmake/License.cmake
         WORKING_DIRECTORY ${WEBENGINE_ROOT_BUILD_DIR}
         DEPENDS
-            ${WEBENGINE_ROOT_SOURCE_DIR}/src/3rdparty/chromium/tools/licenses.py
+            ${WEBENGINE_ROOT_SOURCE_DIR}/src/3rdparty/chromium/tools/licenses/licenses.py
             ${arg_FILE_TEMPLATE}
             ${arg_ENTRY_TEMPLATE}
             ${WEBENGINE_ROOT_SOURCE_DIR}/cmake/License.cmake
diff --git a/cmake/Gn.cmake b/cmake/Gn.cmake
index 41dccc11b38..15b349e0898 100644
--- a/cmake/Gn.cmake
+++ b/cmake/Gn.cmake
@@ -9,8 +9,13 @@ if(NOT CMAKE_SCRIPT_MODE_FILE)
     return()
 endif()
 
-get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/.." REALPATH)
-get_filename_component(WEBENGINE_ROOT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}" REALPATH)
+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/Functions.cmake)
diff --git a/coin/module_config.yaml b/coin/module_config.yaml
index f1d69a2778f..61ce9a52591 100644
--- a/coin/module_config.yaml
+++ b/coin/module_config.yaml
@@ -1,4 +1,5 @@
 version: 2
+alias: qtwebengine
 accept_configuration:
   condition: property
   property: features
diff --git a/coin/qt-installer-package-config.json b/coin/qt-installer-package-config.json
index b3fa3a3a493..ac604d77b0d 100644
--- a/coin/qt-installer-package-config.json
+++ b/coin/qt-installer-package-config.json
@@ -7,11 +7,11 @@
             "**/lib/cmake/Qt*Gui/*Pdf*",
             "**/lib/cmake/Qt*Pdf*/*",
             "**/lib/cmake/Qt*Qml/QmlPlugins/*Pdf*",
-            "**/lib/metatypes/*pdf*",
             "**/lib/pkgconfig/*Pdf*",
             "**/lib/*Pdf*",
             "**/lib/static_chrome/*",
             "**/lib/QtPdf*.framework/**",
+            "**/metatypes/*pdf*",
             "**/mkspecs/modules/qt_lib_pdf*",
             "**/mkspecs/modules/qt_plugin_qpdf.pri",
             "**/modules/Pdf*",
diff --git a/config.tests/hostcompiler/hostcompiler.pro b/config.tests/hostcompiler/hostcompiler.pro
deleted file mode 100644
index 5a80246ab01..00000000000
--- a/config.tests/hostcompiler/hostcompiler.pro
+++ /dev/null
@@ -1,9 +0,0 @@
-option(host_build)
-
-gcc:equals(QT_ARCH, "x86_64"):contains(QT_TARGET_ARCH, "arm"):!contains(QT_TARGET_ARCH, "arm64") {
-    QMAKE_CXXFLAGS += -m32
-    QMAKE_LFLAGS += -m32
-}
-
-SOURCES = main.cpp
-
diff --git a/configure.cmake b/configure.cmake
index 2b150d84954..0b3e3e42bbe 100644
--- a/configure.cmake
+++ b/configure.cmake
@@ -11,7 +11,7 @@ if(QT_CONFIGURE_RUNNING)
 else()
     find_package(Ninja 1.7.2)
     find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT)
-    find_program(Python3_EXECUTABLE NAMES python3 HINTS $ENV{PYTHON3_PATH})
+    find_program(Python3_EXECUTABLE NAMES python3 python HINTS $ENV{PYTHON3_PATH})
     if(NOT Python3_EXECUTABLE)
         find_package(Python3 3.6)
     endif()
@@ -21,7 +21,7 @@ else()
     find_package(Perl)
     find_package(PkgConfig)
     find_package(Snappy)
-    find_package(Nodejs 12.0)
+    find_package(Nodejs 14.0)
 endif()
 
 if(PkgConfig_FOUND)
@@ -197,14 +197,21 @@ int main(void) {
 }"
 )
 
-qt_config_compile_test(winversion
-    LABEL "winversion"
+qt_config_compile_test(libavformat
+    LABEL "libavformat"
+    LIBRARIES
+        PkgConfig::FFMPEG
     CODE
 "
-#if !defined(__clang__) && _MSC_FULL_VER < 191426428
-#error unsupported Visual Studio version
+#include \"libavformat/version.h\"
+extern \"C\" {
+#include \"libavformat/avformat.h\"
+}
+int main(void) {
+#if LIBAVFORMAT_VERSION_MAJOR >= 59
+    AVStream stream;
+    auto first_dts = av_stream_get_first_dts(&stream);
 #endif
-int main(void){
     return 0;
 }"
 )
@@ -252,6 +259,7 @@ qt_feature("qtwebengine-quick-build" PRIVATE
 qt_feature("qtpdf-build" PUBLIC
     LABEL "Build Qt PDF"
     PURPOSE "Enables building the Qt Pdf modules."
+    CONDITION Qt6Core_VERSION VERSION_GREATER_EQUAL "6.3"
 )
 qt_feature("qtpdf-widgets-build" PRIVATE
     LABEL "Build QtPdfWidgets"
@@ -347,6 +355,7 @@ qt_feature("webengine-system-ffmpeg" PRIVATE
 )
 qt_feature("webengine-system-libvpx" PRIVATE
     LABEL "libvpx"
+    AUTODETECT FALSE
     CONDITION UNIX AND TEST_vpx
 )
 qt_feature("webengine-system-snappy" PRIVATE
@@ -484,12 +493,13 @@ add_check_for_support(
    MESSAGE "Build can be done only on Linux, Windows, macO, iOS and Android(on non-Windows hosts only)."
 )
 if(LINUX AND CMAKE_CROSSCOMPILING)
-   get_gn_arch(testArch ${TEST_architecture_arch})
+   set(supportedTargets "arm" "arm64" "armv7-a" "x86_64")
    add_check_for_support(
        MODULES QtWebEngine QtPdf
-       CONDITION testArch
+       CONDITION TEST_architecture_arch IN_LIST supportedTargets
        MESSAGE "Cross compiling is not supported for ${TEST_architecture_arch}."
    )
+   unset(supportedTargets)
 endif()
 add_check_for_support(
    MODULES QtWebEngine
@@ -499,13 +509,13 @@ add_check_for_support(
 add_check_for_support(
    MODULES QtWebEngine QtPdf
    CONDITION TARGET Nodejs::Nodejs
-   MESSAGE "node.js version 12 or later is required."
+   MESSAGE "node.js version 14 or later is required."
 )
 add_check_for_support(
     MODULES QtWebEngine
-    CONDITION NOT (Nodejs_ARCH STREQUAL ia32) AND
-              NOT (Nodejs_ARCH STREQUAL x86) AND
-              NOT (Nodejs_ARCH STREQUAL arm)
+    CONDITION NOT (Nodejs_ARCH STREQUAL "ia32") AND
+              NOT (Nodejs_ARCH STREQUAL "x86") AND
+              NOT (Nodejs_ARCH STREQUAL "arm")
     MESSAGE "32bit version of Nodejs is not supported."
 )
 add_check_for_support(
@@ -583,17 +593,12 @@ add_check_for_support(
    MESSAGE "Could not find all necessary libraries for qpa-xcb support.\
 ${xcbErrorMessage}"
 )
-add_check_for_support(
-   MODULES QtWebEngine QtPdf
-   CONDITION NOT MSVC OR TEST_winversion
-   MESSAGE "Build requires Visual Studio 2019 or higher."
-)
 add_check_for_support(
    MODULES QtWebEngine
    CONDITION MSVC OR
-       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) OR
-       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) OR
-       (MACOS AND CMAKE_CXX_COMPILER_ID STREQUAL AppleClang)
+       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
+       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR
+       (MACOS AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang")
    MESSAGE
        "${CMAKE_CXX_COMPILER_ID} compiler is not supported."
 )
@@ -601,22 +606,32 @@ add_check_for_support(
 add_check_for_support(
    MODULES QtPdf
    CONDITION MSVC OR
-       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL GNU) OR
-       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) OR
-       (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL AppleClang) OR
-       (ANDROID AND CMAKE_CXX_COMPILER_ID STREQUAL Clang) OR
-       (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL GNU)
+       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
+       (LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR
+       (APPLE AND CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang") OR
+       (ANDROID AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang") OR
+       (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") OR
+       (MINGW AND CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
    MESSAGE
        "${CMAKE_CXX_COMPILER_ID} compiler is not supported."
 )
-
 if(WIN32)
     if(MSVC)
-        add_check_for_support(
-            MODULES QtWebEngine QtPdf
-            CONDITION NOT MSVC_VERSION LESS 1929
-            MESSAGE "MSVC compiler version must be at least 14.29."
-        )
+        if(MSVC_TOOLSET_VERSION EQUAL 142) # VS 2019 (16.0)
+            add_check_for_support(
+                MODULES QtWebEngine QtPdf
+                CONDITION NOT MSVC_VERSION LESS 1929
+                MESSAGE "VS compiler version must be at least 14.29"
+            )
+        elseif(MSVC_TOOLSET_VERSION EQUAL 143) # VS 2022 (17.0)
+            add_check_for_support(
+                MODULES QtWebEngine QtPdf
+                CONDITION NOT MSVC_VERSION LESS 1936
+                MESSAGE "VS compiler version must be at least 14.36"
+            )
+        else()
+            message(FATAL_ERROR "Build requires Visual Studio 2019 or higher.")
+        endif()
     endif()
     set(windowsSdkVersion $ENV{WindowsSDKVersion})
     string(REGEX REPLACE "([0-9.]+).*" "\\1" windowsSdkVersion "${windowsSdkVersion}")
@@ -624,8 +639,8 @@ if(WIN32)
     message("-- Windows 10 SDK version: ${windowsSdkVersion}")
     add_check_for_support(
         MODULES QtWebEngine
-        CONDITION sdkMinor GREATER_EQUAL 20348
-        MESSAGE "Build requires Windows 10 SDK at least version 10.0.20348.0"
+        CONDITION sdkMinor GREATER_EQUAL 22621
+        MESSAGE "Build requires Windows 11 SDK at least version 10.0.22621.0"
     )
 endif()
 
diff --git a/dependencies.yaml b/dependencies.yaml
index 585a85f4fd8..21b73a6c7f5 100644
--- a/dependencies.yaml
+++ b/dependencies.yaml
@@ -1,13 +1,13 @@
 dependencies:
-  ../qtdeclarative:
-    ref: 649f5f650b4fc9d96e84be597176dda5e6893a0a
+  ../tqtc-qtdeclarative:
+    ref: 0bbb1c4e12e7d027b452a946652049f353a41132
     required: true
-  ../qtpositioning:
-    ref: c575b1271f9582fcb0522479fac5b5e14a44c47c
+  ../tqtc-qtpositioning:
+    ref: 384e6155a739c96be5f07a29ac4953463405d960
     required: false
-  ../qttools:
-    ref: 7dcd4cacf6bd845ea2993c68fb62f125f918f098
+  ../tqtc-qttools:
+    ref: b4920210050c18913531ac237f294e2632a2edda
     required: false
-  ../qtwebchannel:
-    ref: 20b419f3e6f0eda32289b0f562c6adc30060aae1
+  ../tqtc-qtwebchannel:
+    ref: 951929518a183f9dd254603140a33be1fc9f35f6
     required: false
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 2d3ccab7ec8..f3b098d0bca 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -4,7 +4,7 @@
 cmake_minimum_required(VERSION 3.16)
 
 qt_examples_build_begin(EXTERNAL_BUILD)
-if(NOT CMAKE_CROSSCOMPILING) #QTBUG-86533
+if(NOT CMAKE_CROSSCOMPILING AND Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5") #QTBUG-86533
     if(TARGET Qt::WebEngineCore)
         add_subdirectory(webenginequick)
     endif()
diff --git a/examples/pdf/multipage/doc/src/multipage.qdoc b/examples/pdf/multipage/doc/src/multipage.qdoc
index b4963c5087e..fff8b0d11ab 100644
--- a/examples/pdf/multipage/doc/src/multipage.qdoc
+++ b/examples/pdf/multipage/doc/src/multipage.qdoc
@@ -5,6 +5,7 @@
     \example multipage
     \meta installpath pdf
     \ingroup qtpdf-examples
+    \examplecategory {User Interface Components}
 
     \title PDF Multipage Viewer Example
     \brief A Qt Quick PDF viewer that allows scrolling through the pages.
diff --git a/examples/pdf/multipage/viewer.qml b/examples/pdf/multipage/viewer.qml
index d0b0a726354..9a3ca6bad4a 100644
--- a/examples/pdf/multipage/viewer.qml
+++ b/examples/pdf/multipage/viewer.qml
@@ -127,7 +127,10 @@ ApplicationWindow {
             }
             Shortcut {
                 sequence: StandardKey.Find
-                onActivated: searchField.forceActiveFocus()
+                onActivated: {
+                    searchField.forceActiveFocus()
+                    searchField.selectAll()
+                }
             }
             Shortcut {
                 sequence: StandardKey.Quit
diff --git a/examples/pdf/pdfviewer/viewer.qml b/examples/pdf/pdfviewer/viewer.qml
index a6203516627..1745b70d94d 100644
--- a/examples/pdf/pdfviewer/viewer.qml
+++ b/examples/pdf/pdfviewer/viewer.qml
@@ -129,7 +129,10 @@ ApplicationWindow {
             }
             Shortcut {
                 sequence: StandardKey.Find
-                onActivated: searchField.forceActiveFocus()
+                onActivated: {
+                    searchField.forceActiveFocus()
+                    searchField.selectAll()
+                }
             }
             Shortcut {
                 sequence: StandardKey.Quit
diff --git a/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc b/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc
index e585a84ef71..b56958a9f28 100644
--- a/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc
+++ b/examples/pdfwidgets/pdfviewer/doc/src/pdfviewer.qdoc
@@ -5,6 +5,7 @@
     \example pdfviewer
     \meta installpath pdfwidgets
     \ingroup qtpdf-examples
+    \examplecategory {User Interface Components}
 
     \title PDF Viewer Widget Example
     \brief A widget-based PDF viewer that allows scrolling through the pages.
diff --git a/examples/pdfwidgets/pdfviewer/mainwindow.cpp b/examples/pdfwidgets/pdfviewer/mainwindow.cpp
index 277f9cfb326..ce19359fc58 100644
--- a/examples/pdfwidgets/pdfviewer/mainwindow.cpp
+++ b/examples/pdfwidgets/pdfviewer/mainwindow.cpp
@@ -38,10 +38,10 @@ MainWindow::MainWindow(QWidget *parent)
     ui->mainToolBar->insertWidget(ui->actionZoom_In, m_zoomSelector);
 
     ui->mainToolBar->insertWidget(ui->actionForward, m_pageSelector);
-    connect(m_pageSelector, &QPdfPageSelector::valueChanged, this, &MainWindow::pageSelected);
+    connect(m_pageSelector, &QPdfPageSelector::currentPageChanged, this, &MainWindow::pageSelected);
     m_pageSelector->setDocument(m_document);
     auto nav = ui->pdfView->pageNavigator();
-    connect(nav, &QPdfPageNavigator::currentPageChanged, m_pageSelector, &QPdfPageSelector::setValue);
+    connect(nav, &QPdfPageNavigator::currentPageChanged, m_pageSelector, &QPdfPageSelector::setCurrentPage);
     connect(nav, &QPdfPageNavigator::backAvailableChanged, ui->actionBack, &QAction::setEnabled);
     connect(nav, &QPdfPageNavigator::forwardAvailableChanged, ui->actionForward, &QAction::setEnabled);
 
@@ -116,7 +116,7 @@ void MainWindow::pageSelected(int page)
     setWindowTitle(!documentTitle.isEmpty() ? documentTitle : QStringLiteral("PDF Viewer"));
     setWindowTitle(tr("%1: page %2 (%3 of %4)")
                    .arg(documentTitle.isEmpty() ? u"PDF Viewer"_qs : documentTitle,
-                        m_pageSelector->text(), QString::number(page + 1), QString::number(m_document->pageCount())));
+                        m_pageSelector->currentPageLabel(), QString::number(page + 1), QString::number(m_document->pageCount())));
 }
 
 void MainWindow::searchResultSelected(const QModelIndex &current, const QModelIndex &previous)
@@ -128,7 +128,7 @@ void MainWindow::searchResultSelected(const QModelIndex &current, const QModelIn
     const int page = current.data(int(QPdfSearchModel::Role::Page)).toInt();
     const QPointF location = current.data(int(QPdfSearchModel::Role::Location)).toPointF();
     ui->pdfView->pageNavigator()->jump(page, location);
-    ui->pdfView->setCurrentSearchResult(current.row());
+    ui->pdfView->setCurrentSearchResultIndex(current.row());
 }
 
 void MainWindow::on_actionOpen_triggered()
diff --git a/examples/webenginequick/lifecycle/doc/src/lifecycle.qdoc b/examples/webenginequick/lifecycle/doc/src/lifecycle.qdoc
index 4d997b1c407..1580da26d2e 100644
--- a/examples/webenginequick/lifecycle/doc/src/lifecycle.qdoc
+++ b/examples/webenginequick/lifecycle/doc/src/lifecycle.qdoc
@@ -6,6 +6,7 @@
     \title WebEngine Lifecycle Example
     \ingroup webengine-examples
     \brief Freezes and discards background tabs to reduce CPU and memory usage.
+    \examplecategory {Web Technologies}
 
     \image lifecycle.png
 
diff --git a/examples/webenginequick/quicknanobrowser/CMakeLists.txt b/examples/webenginequick/quicknanobrowser/CMakeLists.txt
index ac41569aacf..10daece4c9c 100644
--- a/examples/webenginequick/quicknanobrowser/CMakeLists.txt
+++ b/examples/webenginequick/quicknanobrowser/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
 cmake_minimum_required(VERSION 3.16)
@@ -19,9 +19,17 @@ qt_add_executable(quicknanobrowser
     utils.h
 )
 
+if(WIN32)
+    set_property(
+        TARGET quicknanobrowser
+        APPEND PROPERTY
+            SOURCES quicknanobrowser.exe.manifest)
+endif()
+
 set_target_properties(quicknanobrowser PROPERTIES
     WIN32_EXECUTABLE TRUE
     MACOSX_BUNDLE TRUE
+    MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.examples.webenginequick.quicknanobrowser"
 )
 
 target_link_libraries(quicknanobrowser PUBLIC
@@ -77,6 +85,18 @@ if(TARGET Qt::Widgets)
     )
 endif()
 
+if (APPLE)
+    set_target_properties(quicknanobrowser PROPERTIES
+        MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.cmake.macos.plist"
+    )
+
+    if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+        # Need to sign application for location permissions to work
+        add_custom_command(TARGET quicknanobrowser
+            POST_BUILD COMMAND codesign -s - quicknanobrowser.app)
+    endif()
+endif()
+
 install(TARGETS quicknanobrowser
     RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
     BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/webenginequick/quicknanobrowser/Info.cmake.macos.plist b/examples/webenginequick/quicknanobrowser/Info.cmake.macos.plist
new file mode 100644
index 00000000000..cac4fa1f405
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/Info.cmake.macos.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleName</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+    <key>CFBundleIdentifier</key>
+    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+    <key>CFBundleExecutable</key>
+    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+    <key>CFBundleVersion</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+    <key>CFBundleShortVersionString</key>
+    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
+    <key>NSHumanReadableCopyright</key>
+    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+    <key>CFBundleIconFile</key>
+    <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>NSSupportsAutomaticGraphicsSwitching</key>
+    <true/>
+    <key>NSLocationUsageDescription</key>
+    <string>Quick Nano Browser would like to give web sites access to your location for demo purposes.</string>
+    <key>NSMicrophoneUsageDescription</key>
+    <string>Quick Nano Browser would like to give web sites access to your computer's microphone for demo purposes.</string>
+    <key>NSCameraUsageDescription</key>
+    <string>Quick Nano Browser would like to give web sites access to your computer's camera for demo purposes.</string>
+</dict>
+</plist>
diff --git a/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc b/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc
index ee94e0fd72f..545002f3072 100644
--- a/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc
+++ b/examples/webenginequick/quicknanobrowser/doc/src/quicknanobrowser.qdoc
@@ -8,6 +8,8 @@
     \brief A web browser implemented using the WebEngineView QML type.
 
     \image quicknanobrowser-demo.jpg
+    \examplecategory {Application Examples}
+    \examplecategory {Web Technologies}
 
     \e {Quick Nano Browser} demonstrates how to use the \l{Qt WebEngine QML Types}
     {Qt WebEngine QML types} to develop a small web browser application that consists of a browser
@@ -142,6 +144,13 @@
     \skipto Escape
     \printuntil /^\ {4}\}/
 
+    \section1 Signing Requirement for macOS
+
+    To allow web sites access to the location, camera, and microphone when running
+    \e {Quick Nano Browser} on macOS, the application needs to be signed. This is
+    done automatically when building, but you need to set up a valid signing identity
+    for the build environment.
+
     \section1 Files and Attributions
 
     The example uses icons from the Tango Icon Library:
diff --git a/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json b/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json
index 681223b1297..d8d85d6f153 100644
--- a/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json
+++ b/examples/webenginequick/quicknanobrowser/icons/3rdparty/qt_attribution.json
@@ -12,13 +12,13 @@
     "LicenseId": "urn:dje:license:public-domain",
     "License": "Public Domain",
     "LicenseFile": "COPYING",
-    "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
-Steven Garrity <sgarrity@silverorange.com>
-Lapo Calamandrei <calamandrei@gmail.com>
-Ryan Collier <rcollier@novell.com>
-Rodney Dawes <dobey@novell.com>
-Andreas Nilsson <nisses.mail@home.se>
-Tuomas Kuosmanen <tigert@tigert.com>
-Garrett LeSage <garrett@novell.com>
-Jakub Steiner <jimmac@novell.com>"
+    "Copyright": ["Ulisse Perusin <uli.peru@gmail.com>",
+    "Steven Garrity <sgarrity@silverorange.com>",
+    "Lapo Calamandrei <calamandrei@gmail.com>",
+    "Ryan Collier <rcollier@novell.com>",
+    "Rodney Dawes <dobey@novell.com>",
+    "Andreas Nilsson <nisses.mail@home.se>",
+    "Tuomas Kuosmanen <tigert@tigert.com>",
+    "Garrett LeSage <garrett@novell.com>",
+    "Jakub Steiner <jimmac@novell.com>"]
 }
diff --git a/examples/webenginequick/quicknanobrowser/main.cpp b/examples/webenginequick/quicknanobrowser/main.cpp
index 850b8c443fb..1e693cbcd26 100644
--- a/examples/webenginequick/quicknanobrowser/main.cpp
+++ b/examples/webenginequick/quicknanobrowser/main.cpp
@@ -21,7 +21,7 @@ static QUrl startupUrl(const QCommandLineParser &parser)
         if (url.isValid())
             return url;
     }
-    return QUrl(QStringLiteral("https://www.qt.io"));
+    return QUrl(QStringLiteral("chrome://qt"));
 }
 
 int main(int argc, char **argv)
diff --git a/examples/webenginequick/quicknanobrowser/quicknanobrowser.exe.manifest b/examples/webenginequick/quicknanobrowser/quicknanobrowser.exe.manifest
new file mode 100644
index 00000000000..acc40177692
--- /dev/null
+++ b/examples/webenginequick/quicknanobrowser/quicknanobrowser.exe.manifest
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+    <!--The ID below indicates application support for Windows Vista -->
+    <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+    <!--The ID below indicates application support for Windows 7 -->
+    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+    <!--The ID below indicates application support for Windows 8 -->
+    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+    <!--The ID below indicates application support for Windows 8.1 -->
+    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+    <!--The ID below indicates application support for Windows 10/11 -->
+    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+    </application>
+</compatibility>
+</assembly>
diff --git a/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro b/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro
index e4c0cdfd1ab..bd5427dc529 100644
--- a/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro
+++ b/examples/webenginequick/quicknanobrowser/quicknanobrowser.pro
@@ -6,6 +6,11 @@ TARGET = quicknanobrowser
 HEADERS = utils.h
 SOURCES = main.cpp
 
+win32 {
+    CONFIG -= embed_manifest_exe
+    QMAKE_MANIFEST = $$PWD/quicknanobrowser.exe.manifest
+}
+
 RESOURCES += resources.qrc
 
 QT += qml quick webenginequick
diff --git a/examples/webenginewidgets/clientcertificate/doc/src/clientcertificate.qdoc b/examples/webenginewidgets/clientcertificate/doc/src/clientcertificate.qdoc
index 427e5052c51..c5440f08fa7 100644
--- a/examples/webenginewidgets/clientcertificate/doc/src/clientcertificate.qdoc
+++ b/examples/webenginewidgets/clientcertificate/doc/src/clientcertificate.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/clientcertificate
+    \examplecategory {Web Technologies}
     \title WebEngine Widgets Client Certificate Example
     \ingroup webengine-widgetexamples
     \brief A simple client certificate authentication scenario using \QWE and \l QSslServer.
diff --git a/examples/webenginewidgets/contentmanipulation/doc/src/contentmanipulation.qdoc b/examples/webenginewidgets/contentmanipulation/doc/src/contentmanipulation.qdoc
index dc0383357bb..ae91affe5c7 100644
--- a/examples/webenginewidgets/contentmanipulation/doc/src/contentmanipulation.qdoc
+++ b/examples/webenginewidgets/contentmanipulation/doc/src/contentmanipulation.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/contentmanipulation
+    \examplecategory {Web Technologies}
     \title WebEngine Content Manipulation Example
     \ingroup webengine-widgetexamples
     \brief Demonstrates how to load and manipulate web content.
diff --git a/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json b/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json
index 4cb51436e2e..35d9cf0d7ad 100644
--- a/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json
+++ b/examples/webenginewidgets/cookiebrowser/3rdparty/qt_attribution.json
@@ -12,13 +12,13 @@
     "LicenseId": "urn:dje:license:public-domain",
     "License": "Public Domain",
     "LicenseFile": "COPYING",
-    "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
-Steven Garrity <sgarrity@silverorange.com>
-Lapo Calamandrei <calamandrei@gmail.com>
-Ryan Collier <rcollier@novell.com>
-Rodney Dawes <dobey@novell.com>
-Andreas Nilsson <nisses.mail@home.se>
-Tuomas Kuosmanen <tigert@tigert.com>
-Garrett LeSage <garrett@novell.com>
-Jakub Steiner <jimmac@novell.com>"
+    "Copyright": ["Ulisse Perusin <uli.peru@gmail.com>",
+    "Steven Garrity <sgarrity@silverorange.com>",
+    "Lapo Calamandrei <calamandrei@gmail.com>",
+    "Ryan Collier <rcollier@novell.com>",
+    "Rodney Dawes <dobey@novell.com>",
+    "Andreas Nilsson <nisses.mail@home.se>",
+    "Tuomas Kuosmanen <tigert@tigert.com>",
+    "Garrett LeSage <garrett@novell.com>",
+    "Jakub Steiner <jimmac@novell.com>"]
 }
diff --git a/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc b/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc
index fe6d1b04673..adc302779ec 100644
--- a/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc
+++ b/examples/webenginewidgets/cookiebrowser/doc/src/cookiebrowser.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/cookiebrowser
+    \examplecategory {Web Technologies}
     \title WebEngine Cookie Browser Example
     \ingroup webengine-widgetexamples
     \brief A cookie browser based on \QWE Widgets.
diff --git a/examples/webenginewidgets/cookiebrowser/mainwindow.cpp b/examples/webenginewidgets/cookiebrowser/mainwindow.cpp
index bf65870f861..67454a9f16a 100644
--- a/examples/webenginewidgets/cookiebrowser/mainwindow.cpp
+++ b/examples/webenginewidgets/cookiebrowser/mainwindow.cpp
@@ -59,6 +59,7 @@ CookieWidget::CookieWidget(const QNetworkCookie &cookie, QWidget *parent): QWidg
 
 void CookieWidget::setHighlighted(bool enabled)
 {
+    m_isHighlighted = enabled;
     QPalette p = palette();
     p.setColor(backgroundRole(), enabled ? p.alternateBase().color() : p.base().color());
     setPalette(p);
@@ -112,9 +113,18 @@ void MainWindow::handleCookieAdded(const QNetworkCookie &cookie)
         return;
 
     CookieWidget *widget = new CookieWidget(cookie);
-    widget->setHighlighted(m_cookies.count() % 2);
     m_cookies.append(cookie);
-    m_layout->insertWidget(0,widget);
+    // Check whether the first widget in the layout is highlighted.
+    // if it is highlighted, then do not highlight the new item.
+    CookieWidget *firstWidget = m_layout->count()
+            ? qobject_cast<CookieWidget *>(m_layout->itemAt(0)->widget())
+            : nullptr;
+    if (firstWidget) {
+        widget->setHighlighted(!firstWidget->isHighlighted());
+    } else {
+        widget->setHighlighted(false);
+    }
+    m_layout->insertWidget(0, widget);
 
     connect(widget, &CookieWidget::deleteClicked, [this, cookie, widget]() {
         m_store->deleteCookie(cookie);
diff --git a/examples/webenginewidgets/cookiebrowser/mainwindow.h b/examples/webenginewidgets/cookiebrowser/mainwindow.h
index 76fd7de3edc..da0d438cab6 100644
--- a/examples/webenginewidgets/cookiebrowser/mainwindow.h
+++ b/examples/webenginewidgets/cookiebrowser/mainwindow.h
@@ -29,9 +29,13 @@ class CookieWidget : public QWidget,  public Ui_CookieWidget
 public:
     CookieWidget(const QNetworkCookie &cookie, QWidget *parent = nullptr);
     void setHighlighted(bool enabled);
+    bool isHighlighted() { return m_isHighlighted; }
 signals:
     void deleteClicked();
     void viewClicked();
+
+private:
+    bool m_isHighlighted = false;
 };
 
 class MainWindow : public QMainWindow, public Ui_MainWindow
diff --git a/examples/webenginewidgets/html2pdf/doc/src/html2pdf.qdoc b/examples/webenginewidgets/html2pdf/doc/src/html2pdf.qdoc
index ba05c4e2b7e..7199a812c47 100644
--- a/examples/webenginewidgets/html2pdf/doc/src/html2pdf.qdoc
+++ b/examples/webenginewidgets/html2pdf/doc/src/html2pdf.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/html2pdf
+    \examplecategory {Web Technologies}
     \title WebEngine Widgets Html2Pdf Example
     \ingroup webengine-widgetexamples
     \brief Converts web pages to PDF documents using \QWE.
diff --git a/examples/webenginewidgets/maps/CMakeLists.txt b/examples/webenginewidgets/maps/CMakeLists.txt
index f6e6b94ea42..524892957ac 100644
--- a/examples/webenginewidgets/maps/CMakeLists.txt
+++ b/examples/webenginewidgets/maps/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
 cmake_minimum_required(VERSION 3.16)
@@ -22,6 +22,7 @@ qt_add_executable(maps
 set_target_properties(maps PROPERTIES
     WIN32_EXECUTABLE TRUE
     MACOSX_BUNDLE TRUE
+    MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.examples.webenginewidgets.maps"
 )
 
 target_link_libraries(maps PUBLIC
@@ -30,6 +31,18 @@ target_link_libraries(maps PUBLIC
     Qt::WebEngineWidgets
 )
 
+if (APPLE)
+    set_target_properties(maps PROPERTIES
+        MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.cmake.macos.plist"
+    )
+
+    if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+        # Need to sign application for location permissions to work
+        add_custom_command(TARGET maps
+            POST_BUILD COMMAND codesign -s - maps.app)
+    endif()
+endif()
+
 install(TARGETS maps
     RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
     BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/webenginewidgets/maps/Info.cmake.macos.plist b/examples/webenginewidgets/maps/Info.cmake.macos.plist
new file mode 100644
index 00000000000..82336b25ad3
--- /dev/null
+++ b/examples/webenginewidgets/maps/Info.cmake.macos.plist
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleName</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+    <key>CFBundleIdentifier</key>
+    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+    <key>CFBundleExecutable</key>
+    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+    <key>CFBundleVersion</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+    <key>CFBundleShortVersionString</key>
+    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
+    <key>NSHumanReadableCopyright</key>
+    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+    <key>CFBundleIconFile</key>
+    <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>NSSupportsAutomaticGraphicsSwitching</key>
+    <true/>
+    <key>NSLocationUsageDescription</key>
+    <string>The maps demo would like to access your location for demo purposes.</string>
+
+</dict>
+</plist>
diff --git a/examples/webenginewidgets/maps/doc/src/maps.qdoc b/examples/webenginewidgets/maps/doc/src/maps.qdoc
index ad727e1652e..0175f8b6511 100644
--- a/examples/webenginewidgets/maps/doc/src/maps.qdoc
+++ b/examples/webenginewidgets/maps/doc/src/maps.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/maps
+    \examplecategory {Web Technologies}
     \title WebEngine Widgets Maps Example
     \ingroup webengine-widgetexamples
     \brief Demonstrates how to handle geolocation requests.
diff --git a/examples/webenginewidgets/notifications/doc/src/notifications.qdoc b/examples/webenginewidgets/notifications/doc/src/notifications.qdoc
index fd3ffa482c5..f4fe1818fe1 100644
--- a/examples/webenginewidgets/notifications/doc/src/notifications.qdoc
+++ b/examples/webenginewidgets/notifications/doc/src/notifications.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/notifications
+    \examplecategory {Web Technologies}
     \title WebEngine Notifications Example
     \ingroup webengine-widgetexamples
     \brief Demonstrates how to pass HTML5 web notifications to users.
diff --git a/examples/webenginewidgets/printme/CMakeLists.txt b/examples/webenginewidgets/printme/CMakeLists.txt
index 013ba48ca16..368d79bfecb 100644
--- a/examples/webenginewidgets/printme/CMakeLists.txt
+++ b/examples/webenginewidgets/printme/CMakeLists.txt
@@ -33,7 +33,6 @@ target_link_libraries(printme PUBLIC
 
 # Resources:
 set(data_resource_files
-    "data/icon.svg"
     "data/index.html"
     "data/style.css"
 )
diff --git a/examples/webenginewidgets/printme/data/data.qrc b/examples/webenginewidgets/printme/data/data.qrc
index a9c76cc7eed..b5e0b1fe0f1 100644
--- a/examples/webenginewidgets/printme/data/data.qrc
+++ b/examples/webenginewidgets/printme/data/data.qrc
@@ -2,6 +2,5 @@
     <qresource prefix="/">
         <file>index.html</file>
         <file>style.css</file>
-        <file>icon.svg</file>
     </qresource>
 </RCC>
diff --git a/examples/webenginewidgets/printme/data/icon.svg b/examples/webenginewidgets/printme/data/icon.svg
deleted file mode 100644
index b90ff26ddec..00000000000
--- a/examples/webenginewidgets/printme/data/icon.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-    width="94px" height="94px" viewBox="0 0 94 94" enable-background="new 0 0 94 94" xml:space="preserve">
-<g>
-    <circle fill="none" cx="47" cy="47" r="47"/>
-        <g>
-            <path fill="#46A2DA" d="M47,92.979c-11.779,0-23.559-4.484-32.526-13.451C-3.461,61.591-3.461,32.409,14.472,14.474
-                        C32.41-3.463,61.592-3.461,79.526,14.473c17.935,17.936,17.935,47.119,0.002,65.054l-0.002,0.001
-                        C70.559,88.495,58.779,92.979,47,92.979z"/>
-        </g>
-        <path fill="#80C342" d="M93,47C93,21.595,72.405,1,47,1C34.297,1,22.797,6.149,14.473,14.473l65.054,65.054
-                C87.851,71.203,93,59.703,93,47z"/>
-        <g>
-            <path fill="#46A2DA" d="M47,65c-4.808,0-9.328-1.873-12.728-5.272c-7.018-7.019-7.018-18.438,0-25.456
-                        C37.672,30.873,42.192,29,47,29s9.328,1.873,12.728,5.272c7.018,7.019,7.018,18.438,0,25.456C56.328,63.127,51.808,65,47,65z"/>
-            <path fill="#FFFFFF" d="M62.248,59.919c6.671-7.858,6.312-19.644-1.105-27.061C57.237,28.953,52.118,27,47,27
-                        c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284C36.763,65.047,41.882,67,47,67
-                        c4.379,0,8.752-1.441,12.372-4.3L77.88,81.209c0.989-0.895,1.935-1.837,2.843-2.814L62.248,59.919z M35.686,58.314
-                        c-6.238-6.238-6.238-16.389,0-22.627C38.708,32.664,42.726,31,47,31c4.274,0,8.292,1.664,11.314,4.686
-                        c6.238,6.238,6.238,16.389,0,22.627C55.292,61.336,51.274,63,47,63C42.726,63,38.708,61.336,35.686,58.314z"/>
-        </g>
-</g>
-</svg>
diff --git a/examples/webenginewidgets/printme/data/index.html b/examples/webenginewidgets/printme/data/index.html
index cf286e85a67..865152c1d17 100644
--- a/examples/webenginewidgets/printme/data/index.html
+++ b/examples/webenginewidgets/printme/data/index.html
@@ -12,13 +12,13 @@
    </head>
    <body>
       <form class="form">
-         <img class="logo" src="icon.svg" alt="qtwebengine">
          <div class="header">
             <h1>Hello Paper World!</h1>
             <h2>Press Ctrl+p to print with print preview</h2>
             <h2>Press Ctrl+Shift+p to print without print preview</h2>
             <h2>Click the button to print using JavaScript</h2>
             <p class="button" onclick="printNow()">Print Now</p>
+         </div>
       </form>
    </body>
 </html>
diff --git a/examples/webenginewidgets/printme/data/style.css b/examples/webenginewidgets/printme/data/style.css
index cf6a2b7bfc1..af8b70fda3a 100644
--- a/examples/webenginewidgets/printme/data/style.css
+++ b/examples/webenginewidgets/printme/data/style.css
@@ -1,72 +1,74 @@
+@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap');
+* {
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+}
+
 html,body {
-     height:100%;
-     width:100%;
-     margin:0;
+     height: 100%;
+     width: 100%;
 }
+
  body {
-     display:flex;
-}
- .logo {
-     width: 75px;
-     height: 75px;
-     float: left;
-     margin: 20px 20px 0px 20px;
-     -webkit-animation:spin 8s linear infinite;
-}
- @-webkit-keyframes spin {
-     100% {
-         -webkit-transform: rotate(360deg);
-    }
+     display: flex;
 }
+
  .header {
      display: inline
 }
+
  .form {
-     width: 480px;
-     height: 170px;
-     background: -webkit-linear-gradient(bottom, #ddd, #fff);
-     border: 1px solid #999;
-     border-radius: 12px;
+     width: 50%;
+     background: #fff;
+     border: 0.5px solid #999;
+     border-radius: 8px;
      color: #46a;
-     font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
-     font-size: 14px;
-     font-style: italic;
-     font-weight: bold;
+     font-family: 'Titillium Web', sans-serif;
+     font-size: 1rem;
      margin: auto;
-     padding: 10px;
+     padding: 1.5rem;
      position: relative;
-     line-height: 26px;
      text-decoration: none;
-     -webkit-box-shadow: 0px 0px 5px #444;
 }
- h1 {
-     padding-left:40px;
-     color: #46a2da;
+
+h1 {
+    color: #00414A;
+    font-size: 2.5rem;
+    font-weight: 700;
+    margin-top: -0.85rem;
+    margin-bottom: 2rem;
 }
- h2 {
-     color: #80c342;
-     font-size: 13px;
-     margin-top: -20px;
-}
- span {
-     margin-left: 20px;
+
+h2 {
+    color: #00414A;
+    font-size: 1.125rem;
+    font-weight: 400;
+    font-style: italic;
+    margin-bottom: 1rem;
 }
+
  .button{
-     display: inline-block;
-     background: #46a2da;
-     width: 100px;
-     height: 30px;
-     padding: 0px;
-     text-align: center;
-     font-weight: bold;
-     color: #ffffff;
-     text-decoration: none;
-     border: 1px solid #999;
-     margin-left: 190px;
+     display: flex;
+     align-items: center;
+     justify-content: center;
+     padding: 0.4444em 0.8889em;
+     height: 2.4em;
+     cursor: pointer;
+     background: #00414A;
+     color: #fff;
+     border-radius: 4px;
+     margin-top: 2rem;
+     font-family: 'Titillium Web', sans-serif;
+     font-size: 1.125rem;
+     font-weight: 400;
+     transition: color 300ms ease-out, border 300ms ease-out;
 }
+
  .button:hover {
-    background-color: #46a200
+    background: #19545C;
 }
+
  .button:active {
-     background-color: #3e8e41;
+     background-color: #19545C;
 }
diff --git a/examples/webenginewidgets/printme/doc/images/printme-example.png b/examples/webenginewidgets/printme/doc/images/printme-example.png
index a636972fd5a..dac4e61e627 100644
Binary files a/examples/webenginewidgets/printme/doc/images/printme-example.png and b/examples/webenginewidgets/printme/doc/images/printme-example.png differ
diff --git a/examples/webenginewidgets/printme/doc/src/printme.qdoc b/examples/webenginewidgets/printme/doc/src/printme.qdoc
index 76449f92efb..cac69aa41de 100644
--- a/examples/webenginewidgets/printme/doc/src/printme.qdoc
+++ b/examples/webenginewidgets/printme/doc/src/printme.qdoc
@@ -2,7 +2,8 @@
 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
 
 /*!
-   \example webenginewidgets/printme
+    \example webenginewidgets/printme
+    \examplecategory {Web Technologies}
     \title WebEngine Widgets PrintMe Example
     \ingroup webengine-widgetexamples
     \brief Demonstrates how to print web pages using Qt WebEngine Widgets.
diff --git a/examples/webenginewidgets/push-notifications/doc/src/push-notifications.qdoc b/examples/webenginewidgets/push-notifications/doc/src/push-notifications.qdoc
index 2f234c1e052..05ccf3e8b6d 100644
--- a/examples/webenginewidgets/push-notifications/doc/src/push-notifications.qdoc
+++ b/examples/webenginewidgets/push-notifications/doc/src/push-notifications.qdoc
@@ -4,6 +4,7 @@
 /*!
 
 \example webenginewidgets/push-notifications
+\examplecategory {Web Technologies}
 \title WebEngine Push Notifications Example
 \ingroup webengine-widgetexamples
 \brief Demonstrates how to subscribe to and unsubscribe from push notifications.
diff --git a/examples/webenginewidgets/recipebrowser/CMakeLists.txt b/examples/webenginewidgets/recipebrowser/CMakeLists.txt
index d10409c0940..41a3a5c6f6d 100644
--- a/examples/webenginewidgets/recipebrowser/CMakeLists.txt
+++ b/examples/webenginewidgets/recipebrowser/CMakeLists.txt
@@ -53,6 +53,11 @@ set(recipebrowser_resource_files
     "assets/pages/skewers.html"
     "assets/pages/soup.html"
     "assets/pages/steak.html"
+    "assets/icons/edit.svg"
+    "assets/icons/stylesheets.svg"
+    "assets/icons/add.svg"
+    "assets/icons/remove.svg"
+    "assets/icons/view.svg"
 )
 
 qt_add_resources(recipebrowser "recipebrowser"
diff --git a/examples/webenginewidgets/recipebrowser/assets/icons/add.svg b/examples/webenginewidgets/recipebrowser/assets/icons/add.svg
new file mode 100644
index 00000000000..b5ecf9ae283
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/icons/add.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="#0D0D0D"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M11 15C11 15.5523 11.4477 16 12 16C12.5523 16 13 15.5523 13 15V13H15C15.5523 13 16 12.5523 16 12C16 11.4477 15.5523 11 15 11H13V9C13 8.44772 12.5523 8 12 8C11.4477 8 11 8.44772 11 9V11H9C8.44772 11 8 11.4477 8 12C8 12.5523 8.44772 13 9 13H11V15Z" fill="#0D0D0D"/>
+</svg>
diff --git a/examples/webenginewidgets/recipebrowser/assets/icons/edit.svg b/examples/webenginewidgets/recipebrowser/assets/icons/edit.svg
new file mode 100644
index 00000000000..fe61445dc88
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/icons/edit.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M2 5C2 3.34315 3.34315 2 5 2H11C11.5523 2 12 2.44772 12 3C12 3.55228 11.5523 4 11 4H5C4.44772 4 4 4.44772 4 5V19C4 19.5523 4.44772 20 5 20H19C19.5523 20 20 19.5523 20 19V13.125C20 12.5727 20.4477 12.125 21 12.125C21.5523 12.125 22 12.5727 22 13.125V19C22 20.6569 20.6569 22 19 22H5C3.34315 22 2 20.6569 2 19V5Z" fill="#0D0D0D"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M19.1974 4C18.9845 4 18.7803 4.08457 18.6298 4.23509L18.1941 4.6708L19.3116 5.82359L19.7649 5.37021C19.9155 5.21969 20 5.01553 20 4.80265C20 4.58978 19.9155 4.38562 19.7649 4.23509C19.6144 4.08457 19.4102 4 19.1974 4ZM17.8972 7.23797L16.7797 6.08518L10.7528 12.1121L10.3744 13.6256L11.8879 13.2473L17.8972 7.23797ZM17.2156 2.82088C17.7412 2.29528 18.4541 2 19.1974 2C19.9407 2 20.6535 2.29528 21.1791 2.82088C21.7047 3.34648 22 4.05934 22 4.80265C22 5.54596 21.7047 6.25883 21.1791 6.78443L13.1062 14.8573C12.9781 14.9855 12.8175 15.0764 12.6417 15.1204L9.24256 15.9701C8.90178 16.0553 8.54129 15.9555 8.29291 15.7071C8.04453 15.4587 7.94468 15.0982 8.02988 14.7575L8.87966 11.3583C8.92362 11.1825 9.01453 11.0219 9.14269 10.8938L17.2156 2.82088Z" fill="#0D0D0D"/>
+</svg>
diff --git a/examples/webenginewidgets/recipebrowser/assets/icons/remove.svg b/examples/webenginewidgets/recipebrowser/assets/icons/remove.svg
new file mode 100644
index 00000000000..3a5a420ac16
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/icons/remove.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="#0D0D0D"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M8 12C8 11.4477 8.44772 11 9 11H15C15.5523 11 16 11.4477 16 12C16 12.5523 15.5523 13 15 13H9C8.44772 13 8 12.5523 8 12Z" fill="#0D0D0D"/>
+</svg>
diff --git a/examples/webenginewidgets/recipebrowser/assets/icons/stylesheets.svg b/examples/webenginewidgets/recipebrowser/assets/icons/stylesheets.svg
new file mode 100644
index 00000000000..e108265b7b6
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/icons/stylesheets.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4C7.58172 4 4 7.58172 4 12C4 16.4183 7.58172 20 12 20ZM12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22Z" fill="#0D0D0D"/>
+<path d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22V2Z" fill="#0D0D0D"/>
+</svg>
diff --git a/examples/webenginewidgets/recipebrowser/assets/icons/view.svg b/examples/webenginewidgets/recipebrowser/assets/icons/view.svg
new file mode 100644
index 00000000000..d2c0c474d9e
--- /dev/null
+++ b/examples/webenginewidgets/recipebrowser/assets/icons/view.svg
@@ -0,0 +1,4 @@
+<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
+<path fill-rule="evenodd" clip-rule="evenodd" d="M2.08086 11.6061C2.99143 9.48143 5.39011 4 12 4C15.2544 4 17.4247 5.25776 18.9399 6.87988C20.1459 8.17094 20.9403 9.71187 21.5334 10.8623C21.657 11.102 21.7719 11.3248 21.8799 11.5249L22.1676 12.0576L21.8289 12.5595C21.6963 12.7559 21.5424 13 21.3672 13.2781C20.7396 14.2738 19.8378 15.7048 18.6548 16.9413C17.1043 18.5619 14.9479 20 12 20C9.06156 20 6.9144 18.6096 5.36163 17.0026C4.11775 15.7152 3.19708 14.2194 2.55058 13.1691C2.40657 12.9351 2.27617 12.7233 2.15883 12.5408L1.8717 12.0941L2.08086 11.6061ZM4.12801 11.9149C4.18383 12.0048 4.24056 12.0967 4.29832 12.1903C4.94628 13.2397 5.72401 14.4993 6.79992 15.6128C8.10869 16.9673 9.76922 18 12 18C14.2213 18 15.8899 16.9381 17.2097 15.5587C18.2362 14.4858 18.9795 13.3089 19.6021 12.323C19.6836 12.194 19.7631 12.0682 19.8408 11.9464C19.7982 11.8645 19.7554 11.782 19.7124 11.6989C19.1185 10.5529 18.4761 9.31319 17.4784 8.24512C16.308 6.99224 14.6533 6 12 6C7.15387 6 5.13812 9.64957 4.12801 11.9149Z" fill="#0D0D0D"/>
+<path fill-rule="evenodd" clip-rule="evenodd" d="M12 10C10.8954 10 10 10.8954 10 12C10 13.1046 10.8954 14 12 14C13.1046 14 14 13.1046 14 12C14 10.8954 13.1046 10 12 10ZM8 12C8 9.79086 9.79086 8 12 8C14.2091 8 16 9.79086 16 12C16 14.2091 14.2091 16 12 16C9.79086 16 8 14.2091 8 12Z" fill="#0D0D0D"/>
+</svg>
diff --git a/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc b/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc
index dd701f1f2d7..0400fcecccd 100644
--- a/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc
+++ b/examples/webenginewidgets/recipebrowser/doc/src/recipebrowser.qdoc
@@ -4,11 +4,11 @@
 /*!
     \example webenginewidgets/recipebrowser
     \title Recipe Browser
-    \examplecategory {Application Examples}
     \meta tag {widgets, webengine, webchannel, webenginescript}
     \ingroup webengine-widgetexamples
     \brief Injecting custom stylsheets into web pages and providing a rich text preview
     tool for a custom markup language.
+    \examplecategory {Web Technologies}
 
     \image recipebrowser.webp
 
diff --git a/examples/webenginewidgets/recipebrowser/mainwindow.cpp b/examples/webenginewidgets/recipebrowser/mainwindow.cpp
index 7288fe4ceb3..7eedab4806f 100644
--- a/examples/webenginewidgets/recipebrowser/mainwindow.cpp
+++ b/examples/webenginewidgets/recipebrowser/mainwindow.cpp
@@ -122,8 +122,7 @@ void MainWindow::loadDefaultStyleSheets()
     settings.beginGroup("styleSheets");
 
     for (auto it = defaultStyleSheets.constBegin(); it != defaultStyleSheets.constEnd(); ++it) {
-        settings.setValue(it.key(), QVariant::fromValue(qMakePair(it.value(), true)));
-        insertStyleSheet(it.key(), it.value(), false);
+        settings.setValue(it.key(), QVariant::fromValue(qMakePair(it.value(), false)));
     }
 
     settings.endGroup();
@@ -144,10 +143,12 @@ void MainWindow::toggleEditView()
         ui->textEdit->show();
 
         ui->editViewButton->setText(QStringLiteral("View"));
+        ui->editViewButton->setIcon(QIcon(":/icons/view.svg"));
     } else {
         ui->textEdit->hide();
         ui->webEngineView->show();
 
         ui->editViewButton->setText(QStringLiteral("Edit"));
+        ui->editViewButton->setIcon(QIcon(":/icons/edit.svg"));
     }
 }
diff --git a/examples/webenginewidgets/recipebrowser/mainwindow.ui b/examples/webenginewidgets/recipebrowser/mainwindow.ui
index b7c29f1b81c..9c2539fd552 100644
--- a/examples/webenginewidgets/recipebrowser/mainwindow.ui
+++ b/examples/webenginewidgets/recipebrowser/mainwindow.ui
@@ -45,6 +45,10 @@
             <property name="text">
              <string>Edit</string>
             </property>
+            <property name="icon">
+             <iconset resource="recipebrowser.qrc">
+              <normaloff>:/icons/edit.svg</normaloff>:/icons/edit.svg</iconset>
+            </property>
            </widget>
           </item>
           <item>
@@ -58,6 +62,10 @@
             <property name="text">
              <string>Stylesheets</string>
             </property>
+            <property name="icon">
+             <iconset resource="recipebrowser.qrc">
+              <normaloff>:/icons/stylesheets.svg</normaloff>:/icons/stylesheets.svg</iconset>
+            </property>
            </widget>
           </item>
          </layout>
@@ -101,6 +109,8 @@
    <container>1</container>
   </customwidget>
  </customwidgets>
- <resources/>
+ <resources>
+  <include location="recipebrowser.qrc"/>
+ </resources>
  <connections/>
 </ui>
diff --git a/examples/webenginewidgets/recipebrowser/recipebrowser.qrc b/examples/webenginewidgets/recipebrowser/recipebrowser.qrc
index 2dc003f308f..c1eb909a7e1 100644
--- a/examples/webenginewidgets/recipebrowser/recipebrowser.qrc
+++ b/examples/webenginewidgets/recipebrowser/recipebrowser.qrc
@@ -1,15 +1,27 @@
 <RCC>
     <qresource prefix="/">
-        <file>assets/3rdparty/markdown.css</file>
-        <file>assets/3rdparty/marked.js</file>
-        <file>assets/custom.js</file>
-        <file>assets/custom.css</file>
-        <file>assets/pages/burger.html</file>
-        <file>assets/pages/cupcakes.html</file>
-        <file>assets/pages/pasta.html</file>
-        <file>assets/pages/pizza.html</file>
-        <file>assets/pages/skewers.html</file>
-        <file>assets/pages/soup.html</file>
-        <file>assets/pages/steak.html</file>
+        <file alias="3rdparty/markdown.css">assets/3rdparty/markdown.css</file>
+        <file alias="3rdparty/marked.js">assets/3rdparty/marked.js</file>
+        <file alias="custom.js">assets/custom.js</file>
+        <file alias="custom.css">assets/custom.css</file>
+        <file alias="pages/images/burger.jpg">assets/pages/images/burger.jpg</file>
+        <file alias="pages/images/cupcakes.jpg">assets/pages/images/cupcakes.jpg</file>
+        <file alias="pages/images/pasta.jpg">assets/pages/images/pasta.jpg</file>
+        <file alias="pages/images/pizza.jpg">assets/pages/images/pizza.jpg</file>
+        <file alias="pages/images/skewers.jpg">assets/pages/images/skewers.jpg</file>
+        <file alias="pages/images/soup.jpg">assets/pages/images/soup.jpg</file>
+        <file alias="pages/images/steak.jpg">assets/pages/images/steak.jpg</file>
+        <file alias="pages/burger.html">assets/pages/burger.html</file>
+        <file alias="pages/cupcakes.html">assets/pages/cupcakes.html</file>
+        <file alias="pages/pasta.html">assets/pages/pasta.html</file>
+        <file alias="pages/pizza.html">assets/pages/pizza.html</file>
+        <file alias="pages/skewers.html">assets/pages/skewers.html</file>
+        <file alias="pages/soup.html">assets/pages/soup.html</file>
+        <file alias="pages/steak.html">assets/pages/steak.html</file>
+        <file alias="icons/edit.svg">assets/icons/edit.svg</file>
+        <file alias="icons/stylesheets.svg">assets/icons/stylesheets.svg</file>
+        <file alias="icons/add.svg">assets/icons/add.svg</file>
+        <file alias="icons/remove.svg">assets/icons/remove.svg</file>
+        <file alias="icons/view.svg">assets/icons/view.svg</file>
     </qresource>
 </RCC>
diff --git a/examples/webenginewidgets/recipebrowser/stylesheetdialog.ui b/examples/webenginewidgets/recipebrowser/stylesheetdialog.ui
index 19db267e8da..6ef389195ad 100644
--- a/examples/webenginewidgets/recipebrowser/stylesheetdialog.ui
+++ b/examples/webenginewidgets/recipebrowser/stylesheetdialog.ui
@@ -68,6 +68,10 @@
           <property name="text">
            <string>Add</string>
           </property>
+          <property name="icon">
+           <iconset resource="recipebrowser.qrc">
+            <normaloff>:/icons/add.svg</normaloff>:/icons/add.svg</iconset>
+          </property>
          </widget>
         </item>
         <item>
@@ -75,6 +79,10 @@
           <property name="text">
            <string>Remove</string>
           </property>
+          <property name="icon">
+           <iconset resource="recipebrowser.qrc">
+            <normaloff>:/icons/remove.svg</normaloff>:/icons/remove.svg</iconset>
+          </property>
          </widget>
         </item>
        </layout>
@@ -84,7 +92,9 @@
    </item>
   </layout>
  </widget>
- <resources/>
+ <resources>
+  <include location="recipebrowser.qrc"/>
+ </resources>
  <connections>
   <connection>
    <sender>buttonBox</sender>
diff --git a/examples/webenginewidgets/simplebrowser/CMakeLists.txt b/examples/webenginewidgets/simplebrowser/CMakeLists.txt
index 2dd4fd57a34..0897cbeab4d 100644
--- a/examples/webenginewidgets/simplebrowser/CMakeLists.txt
+++ b/examples/webenginewidgets/simplebrowser/CMakeLists.txt
@@ -29,9 +29,17 @@ qt_add_executable(simplebrowser
     webview.cpp webview.h
 )
 
+if(WIN32)
+    set_property(
+        TARGET simplebrowser
+        APPEND PROPERTY
+            SOURCES simplebrowser.exe.manifest)
+endif()
+
 set_target_properties(simplebrowser PROPERTIES
     WIN32_EXECUTABLE TRUE
     MACOSX_BUNDLE TRUE
+    MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.examples.webenginewidgets.simplebrowser"
 )
 
 target_link_libraries(simplebrowser PUBLIC
@@ -75,6 +83,18 @@ qt_add_resources(simplebrowser "simplebrowser1"
         ${simplebrowser1_resource_files}
 )
 
+if (APPLE)
+    set_target_properties(simplebrowser PROPERTIES
+        MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.cmake.macos.plist"
+    )
+
+    if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+        # Need to sign application for location permissions to work
+        add_custom_command(TARGET simplebrowser
+            POST_BUILD COMMAND codesign -s - simplebrowser.app)
+    endif()
+endif()
+
 install(TARGETS simplebrowser
     RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
     BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
diff --git a/examples/webenginewidgets/simplebrowser/Info.cmake.macos.plist b/examples/webenginewidgets/simplebrowser/Info.cmake.macos.plist
new file mode 100644
index 00000000000..7abb7e01a77
--- /dev/null
+++ b/examples/webenginewidgets/simplebrowser/Info.cmake.macos.plist
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleName</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+    <key>CFBundleIdentifier</key>
+    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+    <key>CFBundleExecutable</key>
+    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+    <key>CFBundleVersion</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+    <key>CFBundleShortVersionString</key>
+    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
+    <key>NSHumanReadableCopyright</key>
+    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+    <key>CFBundleIconFile</key>
+    <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>NSSupportsAutomaticGraphicsSwitching</key>
+    <true/>
+    <key>NSLocationUsageDescription</key>
+    <string>Simple Browser would like to give web sites access to your location for demo purposes.</string>
+    <key>NSMicrophoneUsageDescription</key>
+    <string>Simple Browser would like to give web sites access to your computer's microphone for demo purposes.</string>
+    <key>NSCameraUsageDescription</key>
+    <string>Simple Browser would like to give web sites access to your computer's camera for demo purposes.</string>
+</dict>
+</plist>
diff --git a/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json b/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json
index d81f5bf2351..fbc96416ee1 100644
--- a/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json
+++ b/examples/webenginewidgets/simplebrowser/data/3rdparty/qt_attribution.json
@@ -12,13 +12,13 @@
     "LicenseId": "urn:dje:license:public-domain",
     "License": "Public Domain",
     "LicenseFile": "COPYING",
-    "Copyright": "Ulisse Perusin <uli.peru@gmail.com>
-Steven Garrity <sgarrity@silverorange.com>
-Lapo Calamandrei <calamandrei@gmail.com>
-Ryan Collier <rcollier@novell.com>
-Rodney Dawes <dobey@novell.com>
-Andreas Nilsson <nisses.mail@home.se>
-Tuomas Kuosmanen <tigert@tigert.com>
-Garrett LeSage <garrett@novell.com>
-Jakub Steiner <jimmac@novell.com>"
+    "Copyright": ["Ulisse Perusin <uli.peru@gmail.com>",
+    "Steven Garrity <sgarrity@silverorange.com>",
+    "Lapo Calamandrei <calamandrei@gmail.com>",
+    "Ryan Collier <rcollier@novell.com>",
+    "Rodney Dawes <dobey@novell.com>",
+    "Andreas Nilsson <nisses.mail@home.se>",
+    "Tuomas Kuosmanen <tigert@tigert.com>",
+    "Garrett LeSage <garrett@novell.com>",
+    "Jakub Steiner <jimmac@novell.com>"]
 }
diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
index f45b362df99..2c5fce10b52 100644
--- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
+++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc
@@ -6,6 +6,7 @@
     \title WebEngine Widgets Simple Browser Example
     \ingroup webengine-widgetexamples
     \brief A simple browser based on \QWE Widgets.
+    \examplecategory {Web Technologies}
 
     \image simplebrowser.png
 
@@ -321,6 +322,13 @@
     finished or when an error occurs. See \c downloadmanagerwidget.cpp for an
     example of how these signals can be handled.
 
+    \section1 Signing Requirement for macOS
+
+    To allow web sites access to the location, camera, and microphone when running
+    \e {Simple Browser} on macOS, the application needs to be signed. This is
+    done automatically when building, but you need to set up a valid signing identity
+    for the build environment.
+
     \section1 Files and Attributions
 
     The example uses icons from the Tango Icon Library:
diff --git a/examples/webenginewidgets/simplebrowser/main.cpp b/examples/webenginewidgets/simplebrowser/main.cpp
index d5d9e78abbc..bd9a3a19814 100644
--- a/examples/webenginewidgets/simplebrowser/main.cpp
+++ b/examples/webenginewidgets/simplebrowser/main.cpp
@@ -18,7 +18,7 @@ QUrl commandLineUrlArgument()
         if (!arg.startsWith(u'-'))
             return QUrl::fromUserInput(arg);
     }
-    return QUrl(u"https://www.qt.io"_s);
+    return QUrl(u"chrome://qt"_s);
 }
 
 int main(int argc, char **argv)
diff --git a/examples/webenginewidgets/simplebrowser/simplebrowser.exe.manifest b/examples/webenginewidgets/simplebrowser/simplebrowser.exe.manifest
new file mode 100644
index 00000000000..acc40177692
--- /dev/null
+++ b/examples/webenginewidgets/simplebrowser/simplebrowser.exe.manifest
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
+<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+    <application>
+    <!--The ID below indicates application support for Windows Vista -->
+    <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+    <!--The ID below indicates application support for Windows 7 -->
+    <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+    <!--The ID below indicates application support for Windows 8 -->
+    <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+    <!--The ID below indicates application support for Windows 8.1 -->
+    <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+    <!--The ID below indicates application support for Windows 10/11 -->
+    <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+    </application>
+</compatibility>
+</assembly>
diff --git a/examples/webenginewidgets/simplebrowser/simplebrowser.pro b/examples/webenginewidgets/simplebrowser/simplebrowser.pro
index 7584cfb0179..d4cce773826 100644
--- a/examples/webenginewidgets/simplebrowser/simplebrowser.pro
+++ b/examples/webenginewidgets/simplebrowser/simplebrowser.pro
@@ -23,6 +23,11 @@ SOURCES += \
     webpopupwindow.cpp \
     webview.cpp
 
+win32 {
+    CONFIG -= embed_manifest_exe
+    QMAKE_MANIFEST = $$PWD/simplebrowser.exe.manifest
+}
+
 FORMS += \
     certificateerrordialog.ui \
     passworddialog.ui \
diff --git a/examples/webenginewidgets/simplebrowser/webview.cpp b/examples/webenginewidgets/simplebrowser/webview.cpp
index e024f9126fe..037c53ad198 100644
--- a/examples/webenginewidgets/simplebrowser/webview.cpp
+++ b/examples/webenginewidgets/simplebrowser/webview.cpp
@@ -325,7 +325,7 @@ void WebView::handleFileSystemAccessRequested(QWebEngineFileSystemAccessRequest
         Q_UNREACHABLE();
     }
 
-    auto answer = QMessageBox::question(window(), tr("File system access reques"),
+    auto answer = QMessageBox::question(window(), tr("File system access request"),
                                         tr("Give %1 %2 access to %3?")
                                                 .arg(request.origin().host())
                                                 .arg(accessType)
diff --git a/examples/webenginewidgets/spellchecker/CMakeLists.txt b/examples/webenginewidgets/spellchecker/CMakeLists.txt
index 74cb626e164..6e6277d8e78 100644
--- a/examples/webenginewidgets/spellchecker/CMakeLists.txt
+++ b/examples/webenginewidgets/spellchecker/CMakeLists.txt
@@ -32,7 +32,6 @@ target_link_libraries(spellchecker PUBLIC
 
 # Resources:
 set(spellchecker_resource_files
-    "data/icon.svg"
     "data/index.html"
     "data/style.css"
 )
diff --git a/examples/webenginewidgets/spellchecker/data/icon.svg b/examples/webenginewidgets/spellchecker/data/icon.svg
deleted file mode 100644
index b90ff26ddec..00000000000
--- a/examples/webenginewidgets/spellchecker/data/icon.svg
+++ /dev/null
@@ -1,24 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!-- Generator: Adobe Illustrator 19.2.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
-<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
-    width="94px" height="94px" viewBox="0 0 94 94" enable-background="new 0 0 94 94" xml:space="preserve">
-<g>
-    <circle fill="none" cx="47" cy="47" r="47"/>
-        <g>
-            <path fill="#46A2DA" d="M47,92.979c-11.779,0-23.559-4.484-32.526-13.451C-3.461,61.591-3.461,32.409,14.472,14.474
-                        C32.41-3.463,61.592-3.461,79.526,14.473c17.935,17.936,17.935,47.119,0.002,65.054l-0.002,0.001
-                        C70.559,88.495,58.779,92.979,47,92.979z"/>
-        </g>
-        <path fill="#80C342" d="M93,47C93,21.595,72.405,1,47,1C34.297,1,22.797,6.149,14.473,14.473l65.054,65.054
-                C87.851,71.203,93,59.703,93,47z"/>
-        <g>
-            <path fill="#46A2DA" d="M47,65c-4.808,0-9.328-1.873-12.728-5.272c-7.018-7.019-7.018-18.438,0-25.456
-                        C37.672,30.873,42.192,29,47,29s9.328,1.873,12.728,5.272c7.018,7.019,7.018,18.438,0,25.456C56.328,63.127,51.808,65,47,65z"/>
-            <path fill="#FFFFFF" d="M62.248,59.919c6.671-7.858,6.312-19.644-1.105-27.061C57.237,28.953,52.118,27,47,27
-                        c-5.118,0-10.237,1.953-14.142,5.858c-7.81,7.81-7.81,20.474,0,28.284C36.763,65.047,41.882,67,47,67
-                        c4.379,0,8.752-1.441,12.372-4.3L77.88,81.209c0.989-0.895,1.935-1.837,2.843-2.814L62.248,59.919z M35.686,58.314
-                        c-6.238-6.238-6.238-16.389,0-22.627C38.708,32.664,42.726,31,47,31c4.274,0,8.292,1.664,11.314,4.686
-                        c6.238,6.238,6.238,16.389,0,22.627C55.292,61.336,51.274,63,47,63C42.726,63,38.708,61.336,35.686,58.314z"/>
-        </g>
-</g>
-</svg>
diff --git a/examples/webenginewidgets/spellchecker/data/index.html b/examples/webenginewidgets/spellchecker/data/index.html
index b6cec5fe036..f68d64bc4ea 100644
--- a/examples/webenginewidgets/spellchecker/data/index.html
+++ b/examples/webenginewidgets/spellchecker/data/index.html
@@ -6,28 +6,29 @@
       <link rel="stylesheet" type="text/css" href="style.css">
    </head>
    <body>
-      <form class="form">
-         <img class="logo" src="icon.svg" alt="qtwebengine">
-         <div class="header">
-            <h1>Contact us</h1>
-            <h2>We are here to help</h2>
-         </div>
-         <label>
-         <span>First Name:</span><input id="firstname" type="text" name="name" />
-         </label>
-         <label>
-         <span>Last Name:</span><input id="lastName" type="text" name="name" />
-         </label>
-         <label>
-         <span>Email Address:</span><input id="email" type="text" name="email" />
-         </label>
-         <label>
-         <span>Subject:</span><input id="subject" type="text" name="subject" />
-         </label>
-         <label>
-         <span>Message:</span><textarea id="feedback" name="feedback"></textarea>
-         </label>
-         <input type="submit" value="Send" />
-      </form>
+        <main>
+          <form class="form">
+             <div class="header">
+                <h1>Contact us</h1>
+                <h2>We are here to help</h2>
+             </div>
+             <label>
+             <span>First Name</span><input id="firstname" type="text" name="name" />
+             </label>
+             <label>
+             <span>Last Name</span><input id="lastName" type="text" name="name" />
+             </label>
+             <label>
+             <span>Email</span><input id="email" type="text" name="email" />
+             </label>
+             <label>
+             <span>Subject</span><input id="subject" type="text" name="subject" />
+             </label>
+             <label>
+             <span>Message</span><textarea id="feedback" name="feedback"></textarea>
+             </label>
+             <input type="submit" value="Send" />
+          </form>
+      </main>
    </body>
 </html>
diff --git a/examples/webenginewidgets/spellchecker/data/spellchecker.qrc b/examples/webenginewidgets/spellchecker/data/spellchecker.qrc
index a9c76cc7eed..b5e0b1fe0f1 100644
--- a/examples/webenginewidgets/spellchecker/data/spellchecker.qrc
+++ b/examples/webenginewidgets/spellchecker/data/spellchecker.qrc
@@ -2,6 +2,5 @@
     <qresource prefix="/">
         <file>index.html</file>
         <file>style.css</file>
-        <file>icon.svg</file>
     </qresource>
 </RCC>
diff --git a/examples/webenginewidgets/spellchecker/data/style.css b/examples/webenginewidgets/spellchecker/data/style.css
index 7b6736f1f7c..38873c5a013 100644
--- a/examples/webenginewidgets/spellchecker/data/style.css
+++ b/examples/webenginewidgets/spellchecker/data/style.css
@@ -1,90 +1,119 @@
-.logo {
- width: 50px;
- height: 50px;
- float: left;
- margin: 20px 20px 0px 20px;
- -webkit-animation:spin 8s linear infinite;
+@import url('https://fonts.googleapis.com/css2?family=Titillium+Web:ital,wght@0,200;0,300;0,400;0,600;0,700;0,900;1,200;1,300;1,400;1,600;1,700&display=swap');
+* {
+  padding: 0;
+  margin: 0;
+  box-sizing: border-box;
+}
+
+
+body {
+    width: 100%;
+    padding: 0px;
+    margin: 0px;
 }
-@-webkit-keyframes spin { 100% { -webkit-transform: rotate(360deg); } }
 
 .header {
- display: inline
+    display: inline;
+}
+
+.main {
+    max-width: 100%;
 }
 
 .form {
-  width: 450px;
-  height: 600px;
-  background: -webkit-linear-gradient(bottom, #ddd, #fff);
-  border: 1px solid #999;
-  border-radius: 12px;
-  color: #46a;
-  font-family: 'Lucida Sans Unicode', 'Lucida Grande', sans-serif;
-  font-size: 14px;
-  font-style: italic;
-  font-weight: bold;
-  margin: auto;
-  padding: 10px;
-  position: relative;
-  line-height: 26px;
-  text-decoration: none;
-  -webkit-box-shadow: 0px 0px 5px #444;
+    width: 100%;
+    height: 100%;
+    background: #fff;
+    border: 0px solid #999;
+    border-radius: 8px;
+    color: #46a;
+    font-family: 'Titillium Web', sans-serif;
+    font-size: 1rem;
+    margin: auto;
+    padding: 40px;
+    position: relative;
+    line-height: 26px;
+    text-decoration: none;
 }
 
 h1 {
- padding-left:40px;
- color: #46a2da;
+    padding-left: 20px;
+    color: #00414A;
+    font-size: 2.5rem;
+    font-weight: 700;
+    margin-bottom: 1rem;
 }
 
 h2 {
- color: #80c342;
- font-size: 13px;
- margin-top: -20px;
+    padding-left: 20px;
+    color: #00414A;
+    font-size: 1.125rem;
+    font-weight: 400;
+    font-style: italic;
+    margin-bottom: 1.75rem;
 }
 
 span {
-  margin-left: 20px;
+    font-size: 1.5rem;
+    margin-left: 20px;
+    color: #00414A;
+    font-weight: 700;
 }
 
 input {
-  width: 400px;
-  display: block;
-  border: 1px solid #999;
-  height: 25px;
-  margin-left: 20px;
-  margin-bottom: 10px;
-  padding-left: 10px;
-  -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
+    width: 90%;
+    display: block;
+    height: 2.25rem;
+    margin-left: 20px;
+    margin-right: 20px;
+    margin-bottom: 8px;
+    padding-left: 10px;
+    box-shadow: 1px 1px 4px 0px rgba(0, 0, 0, 0.15);
+    border-radius: var(--radius-radius-minimal, 0.25rem);
+    border: 1px solid var(--color-background-normal, #CCC);
+    background: var(--color-text-input-background, #FFF);
 }
 
 textarea {
-  width: 400px;
-  max-width: 400px;
-  height: 180px;
-  max-height: 400px;
-  display: block;
-  margin-left: 20px;
-  padding-left: 10px;
-  padding-right: 10px;
-  -webkit-box-shadow: 0px 0px 5px rgba(0, 0, 0, 0.3);
+    width: 90%;
+    max-width: 90%;
+    height: 10rem;
+    max-height: 14rem;
+    display: block;
+    margin-left: 20px;
+    margin-right: 20px;
+    padding-left: 10px;
+    padding-top: 10px;
+    box-shadow: 1px 1px 4px 0px rgba(0, 0, 0, 0.15);
+    border-radius: var(--radius-radius-minimal, 0.25rem);
+    border: 1px solid var(--color-background-normal, #CCC);
+    background: var(--color-text-input-background, #FFF);
 }
 
 input:focus, textarea:focus {
- outline:none;
- border: 1px solid #46a2da;
+    outline: none;
+    border: 1px solid #00414A;
 }
 
 input[type=submit] {
-  width: 100px;
-  left: 170px;
-  bottom: 10px;
-  background: #46a2da;
-  color: #fff;
-  height: 30px;
-  position: absolute;
-  border-radius: 14px;
+    display: flex;
+    align-items: center;
+    justify-content: center; /* Add this to horizontally center the content */
+    padding: 0.4444em 0.8889em;
+    height: 2.4em;
+    cursor: pointer;
+    width: 6.5rem;
+    background: #00414A;
+    color: #fff;
+    border-radius: 4px;
+    margin-top: 28px;
+    font-family: 'Titillium Web', sans-serif;
+    font-size: 1.125rem;
+    font-weight: 400;
+    transition: color 300ms ease-out, border 300ms ease-out;
 }
 
 input[type=submit]:hover {
-  background: #80c342;
+    background: #19545C;
 }
 
diff --git a/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png b/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png
index cc4e74946ae..1cbe9e6d3ef 100644
Binary files a/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png and b/examples/webenginewidgets/spellchecker/doc/images/spellchecker-example.png differ
diff --git a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
index 85b1b950ca8..1d9d7b73c14 100644
--- a/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
+++ b/examples/webenginewidgets/spellchecker/doc/src/spellchecker.qdoc
@@ -6,6 +6,7 @@
     \title WebEngine Widgets Spellchecker Example
     \ingroup webengine-widgetexamples
     \brief Integrates a spellchecker into a simple HTML form.
+    \examplecategory {Web Technologies}
 
     \image spellchecker-example.png
 
diff --git a/examples/webenginewidgets/spellchecker/main.cpp b/examples/webenginewidgets/spellchecker/main.cpp
index 63cccb6ea1a..55e06a87480 100644
--- a/examples/webenginewidgets/spellchecker/main.cpp
+++ b/examples/webenginewidgets/spellchecker/main.cpp
@@ -11,7 +11,7 @@ int main(int argc, char *argv[])
 
     WebView view;
     view.setUrl(QUrl(QStringLiteral("qrc:/index.html")));
-    view.resize(500, 640);
+    view.resize(500, 750);
     view.show();
 
     return app.exec();
diff --git a/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc b/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc
index 9dcd5c0ff18..931f08558e2 100644
--- a/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc
+++ b/examples/webenginewidgets/videoplayer/doc/src/videoplayer.qdoc
@@ -3,6 +3,7 @@
 
 /*!
     \example webenginewidgets/videoplayer
+    \examplecategory {Web Technologies}
     \title WebEngine Widgets Video Player Example
     \ingroup webengine-widgetexamples
     \brief Displays full screen video using \l QWebEngineView.
diff --git a/src/3rdparty b/src/3rdparty
index 45483c4d326..be3ba7a0ebb 160000
--- a/src/3rdparty
+++ b/src/3rdparty
@@ -1 +1 @@
-Subproject commit 45483c4d3267d923adf4441d6823600743132c18
+Subproject commit be3ba7a0ebb340b9498e82c3506cf46ec5ddbee6
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 59eb27e73e8..a7935e7de0b 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -5,8 +5,10 @@
 #  MAIN CONFIGURE
 ##
 
-get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.." REALPATH)
-get_filename_component(WEBENGINE_ROOT_BUILD_DIR "${PROJECT_BINARY_DIR}" REALPATH)
+qt_internal_get_filename_path_mode(path_mode)
+
+get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/.." ${path_mode})
+get_filename_component(WEBENGINE_ROOT_BUILD_DIR "${PROJECT_BINARY_DIR}" ${path_mode})
 
 # Note this is configure that does not belong to any module
 qt_feature_module_begin(ONLY_EVALUATE_FEATURES)
@@ -140,6 +142,7 @@ if(NOT Gn_FOUND)
                    -DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
                    -DCMAKE_PREFIX_PATH:PATH=<INSTALL_DIR>
                    -DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR}
+                   -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS}
     )
     if(QT_FEATURE_qtwebengine_core_build)
         add_dependencies(run_core_GnReady gn)
@@ -170,6 +173,7 @@ if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS)
         USES_TERMINAL_BUILD TRUE
         EXCLUDE_FROM_ALL TRUE
         CMAKE_ARGS -DCMAKE_TOOLCHAIN_FILE=${QT_HOST_PATH_CMAKE_DIR}/Qt6/qt.toolchain.cmake
+                   -DQT_USE_ORIGINAL_COMPILER=ON
                    -DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR}
                    -DWEBENGINE_ROOT_SOURCE_DIR=${WEBENGINE_ROOT_SOURCE_DIR}
                    -DGN_TARGET_CPU=${TEST_architecture_arch}
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 3600e161c8e..3b2e21d9bfa 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -4,7 +4,7 @@
 cmake_minimum_required(VERSION 3.19)
 
 find_package(Ninja 1.7.2 REQUIRED)
-find_package(Nodejs 12 REQUIRED)
+find_package(Nodejs 14.19 REQUIRED)
 find_package(Perl)
 find_package(PkgConfig)
 if(PkgConfig_FOUND)
@@ -48,7 +48,7 @@ foreach(arch ${archs})
         get_forward_declaration_macro(forwardDeclarationMacro)
         get_target_property(qtWebEngineProcessName WebEngineCore QTWEBENGINEPROCESS_NAME)
 
-        if(QT_FEATURE_debug_and_release AND ("${config}" STREQUAL "Debug"))
+        if("${config}" STREQUAL "Debug")
             set(qtWebEngineProcessName "${qtWebEngineProcessName}${CMAKE_DEBUG_POSTFIX}")
         endif()
 
@@ -78,6 +78,7 @@ foreach(arch ${archs})
                 ${gnCxxCompileOptions}
             SOURCES
                 accessibility_tree_formatter_qt.cpp
+                browser_accessibility_qt.cpp browser_accessibility_qt.h
                 authentication_dialog_controller.cpp authentication_dialog_controller.h authentication_dialog_controller_p.h
                 autofill_client_qt.cpp autofill_client_qt.h
                 autofill_popup_controller.cpp autofill_popup_controller.h autofill_popup_controller_p.h
@@ -152,6 +153,7 @@ foreach(arch ${archs})
                 ozone/platform_window_qt.cpp ozone/platform_window_qt.h
                 ozone/surface_factory_qt.cpp ozone/surface_factory_qt.h
                 permission_manager_qt.cpp permission_manager_qt.h
+                pdf_util_qt.cpp pdf_util_qt.h
                 platform_notification_service_qt.cpp platform_notification_service_qt.h
                 pointer_device_qt.cpp
                 pref_service_adapter.cpp pref_service_adapter.h
@@ -183,6 +185,7 @@ foreach(arch ${archs})
                 type_conversion.cpp type_conversion.h
                 user_notification_controller.cpp user_notification_controller.h
                 user_script.cpp user_script.h
+                version_ui_qt.cpp version_ui_qt.h
                 visited_links_manager_qt.cpp visited_links_manager_qt.h
                 web_contents_adapter.cpp web_contents_adapter.h
                 web_contents_adapter_client.h
@@ -200,7 +203,6 @@ foreach(arch ${archs})
         extend_gn_target(${buildGn} CONDITION QT_FEATURE_accessibility
             SOURCES
                 accessibility_activation_observer.cpp accessibility_activation_observer.h
-                browser_accessibility_qt.cpp browser_accessibility_qt.h
         )
 
         extend_gn_target(${buildGn} CONDITION QT_FEATURE_webengine_ozone_x11
@@ -226,11 +228,6 @@ foreach(arch ${archs})
                 compositor/native_skia_output_device_mac2.mm
         )
 
-        extend_gn_target(${buildGn} CONDITION MACOS AND QT_FEATURE_opengl
-            SOURCES
-                macos_context_type_helper.mm macos_context_type_helper.h
-        )
-
         extend_gn_target(${buildGn} CONDITION QT_FEATURE_webengine_pepper_plugins
             SOURCES
                 renderer/pepper/pepper_renderer_host_factory_qt.cpp renderer/pepper/pepper_renderer_host_factory_qt.h
@@ -268,6 +265,7 @@ foreach(arch ${archs})
                 extensions/extension_web_contents_observer_qt.cpp extensions/extension_web_contents_observer_qt.h
                 extensions/extensions_api_client_qt.cpp extensions/extensions_api_client_qt.h
                 extensions/extensions_browser_client_qt.cpp extensions/extensions_browser_client_qt.h
+                extensions/file_system_delegate_qt.cpp extensions/file_system_delegate_qt.h
                 extensions/messaging_delegate_qt.cpp extensions/messaging_delegate_qt.h
                 extensions/mime_handler_view_guest_delegate_qt.cpp extensions/mime_handler_view_guest_delegate_qt.h
                 extensions/plugin_service_filter_qt.cpp extensions/plugin_service_filter_qt.h
@@ -309,7 +307,6 @@ foreach(arch ${archs})
             enable_background_mode=false
             enable_ipc_fuzzer=false
             enable_ipc_logging=false
-            enable_js_type_check=false
             enable_media_remoting=false
             enable_message_center=false
             enable_nacl=false
@@ -319,6 +316,7 @@ foreach(arch ${archs})
             enable_resource_allowlist_generation=false
             enable_screen_ai_service=false
             enable_session_service=false
+            enable_supervised_users=false
             enable_swiftshader=false
             enable_swiftshader_vulkan=false
             angle_enable_swiftshader=false
@@ -337,16 +335,19 @@ foreach(arch ${archs})
             chrome_pgo_phase=0
             optimize_webui=false
             strip_absolute_paths_from_debug_symbols=false
+            pdf_use_skia=true
             devtools_fast_bundle=false
             devtools_skip_typecheck=false
-            enable_jxl_decoder=false # temporarily because libjxl causes internal compiler error on armv7
+            use_static_angle=true
+            chrome_root_store_supported=false
+            trial_comparison_cert_verifier_supported=false
         )
         extend_gn_list(gnArgArg
             ARGS use_v8_context_snapshot v8_use_external_startup_data
             CONDITION QT_FEATURE_webengine_v8_context_snapshot
         )
         extend_gn_list(gnArgArg
-            ARGS enable_basic_printing enable_print_preview enable_pdf
+            ARGS enable_printing enable_basic_printing enable_print_preview enable_pdf
             CONDITION QT_FEATURE_webengine_printing_and_pdf
         )
         extend_gn_list(gnArgArg
@@ -355,9 +356,14 @@ foreach(arch ${archs})
         )
         extend_gn_list(gnArgArg
             ARGS enable_plugins
-            CONDITION QT_FEATURE_webengine_pepper_plugins
+            CONDITION QT_FEATURE_webengine_printing_and_pdf OR
+            QT_FEATURE_webengine_pepper_plugins
         )
         extend_gn_list(gnArgArg
+            ARGS enable_ppapi
+            CONDITION QT_FEATURE_webengine_pepper_plugins
+        )
+         extend_gn_list(gnArgArg
             ARGS enable_spellcheck
             CONDITION QT_FEATURE_webengine_spellchecker
         )
@@ -365,6 +371,10 @@ foreach(arch ${archs})
             ARGS enable_webrtc
             CONDITION QT_FEATURE_webengine_webrtc
         )
+        extend_gn_list(gnArgArg
+            ARGS enable_screen_capture
+            CONDITION QT_FEATURE_webengine_webrtc
+        )
         extend_gn_list(gnArgArg
             ARGS enable_hangout_services_extension
             CONDITION QT_FEATURE_webengine_webrtc AND QT_FEATURE_webengine_extensions
@@ -421,7 +431,7 @@ foreach(arch ${archs})
                 ozone_extra_path="${CMAKE_CURRENT_LIST_DIR}/ozone/ozone_extra.gni"
             )
             set(systemLibs libjpeg libpng freetype harfbuzz libevent libwebp libxml
-                opus snappy icu ffmpeg re2 lcms2 libopenjpeg2
+                opus snappy icu ffmpeg re2 lcms2 libopenjpeg2 libvpx
             )
             foreach(slib ${systemLibs})
                 extend_gn_list(gnArgArg
@@ -475,13 +485,6 @@ foreach(arch ${archs})
                 ARGS use_vaapi
                 CONDITION QT_FEATURE_webengine_vaapi
             )
-            if(NOT QT_FEATURE_webengine_vaapi)
-                # hardware accelerated encoding requires bundled libvpx
-                extend_gn_list(gnArgArg
-                    ARGS use_system_libvpx
-                    CONDITION QT_FEATURE_webengine_system_libvpx
-                )
-            endif()
             extend_gn_list(gnArgArg
                 ARGS ozone_platform_x11 use_xkbcommon
                 CONDITION QT_FEATURE_webengine_ozone_x11
@@ -500,7 +503,7 @@ foreach(arch ${archs})
                      external_gssapi_include_dir="${GSSAPI_INCLUDE_DIRS}/gssapi"
                 )
             endif()
-
+            get_gn_arch(cpu ${TEST_architecture_arch})
             if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm")
                 check_thumb(armThumb)
                 if(NOT armThumb AND NOT QT_FEATURE_webengine_system_ffmpeg)
@@ -509,19 +512,20 @@ foreach(arch ${archs})
             endif()
 
             if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm64")
-                # V8 sandbox initialization is slow in QEMU.
                 # This is a workaround to avoid auto test timeouts on the QEMU arm64 CI.
                 if ("$ENV{TARGET_OSVERSION_COIN}" STREQUAL "qemu")
-                    list(APPEND gnArgArg v8_enable_sandbox=false)
+                    list(APPEND gnArgArg
+                        v8_enable_sandbox=false
+                        arm_control_flow_integrity="none"
+                    )
                 endif()
             endif()
+            unset(cpu)
         endif()
 
         if(MACOS)
             list(APPEND gnArgArg
                 use_external_popup_menu=false
-                angle_enable_vulkan=false
-                use_static_angle=true
             )
         endif()
 
@@ -569,7 +573,7 @@ if(QT_FEATURE_webengine_v8_context_snapshot)
     set(dataStamp obj/tools/v8_context_snapshot/v8_context_snapshot.stamp)
 endif()
 
-add_gn_build_aritfacts_to_target(
+add_gn_build_artifacts_to_target(
     CMAKE_TARGET WebEngineCore
     NINJA_TARGET QtWebEngineCore
     MODULE core
@@ -619,7 +623,7 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING)
         ../3rdparty/chromium/third_party/boringssl/src/include
         ${buildDir}/$<CONFIG>/${arch}/gen
     )
-    add_gn_build_aritfacts_to_target(
+    add_gn_build_artifacts_to_target(
         CMAKE_TARGET ${dict_target_name}
         NINJA_TARGET convert_dict
         MODULE core
diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt
index 73c5edba855..5bd8b9e2f94 100644
--- a/src/core/api/CMakeLists.txt
+++ b/src/core/api/CMakeLists.txt
@@ -33,15 +33,13 @@ qt_internal_add_module(WebEngineCore
         qwebenginescriptcollection.cpp qwebenginescriptcollection.h qwebenginescriptcollection_p.h
         qwebenginesettings.cpp qwebenginesettings.h
         qwebengineurlrequestinfo.cpp qwebengineurlrequestinfo.h qwebengineurlrequestinfo_p.h
-        qwebengineurlrequestinterceptor.h qwebengineurlresponseinterceptor.h
-        qwebengineurlresponseinfo.cpp qwebengineurlresponseinfo.h qwebengineurlresponseinfo_p.h
+        qwebengineurlrequestinterceptor.h qwebengineurlrequestinterceptor.cpp
         qwebengineurlrequestjob.cpp qwebengineurlrequestjob.h
         qwebengineurlscheme.cpp qwebengineurlscheme.h
         qwebengineurlschemehandler.cpp qwebengineurlschemehandler.h
         qwebengineglobalsettings.cpp qwebengineglobalsettings.h qwebengineglobalsettings_p.h
     DEFINES
         BUILDING_CHROMIUM
-        NOMINMAX
     INCLUDE_DIRECTORIES
         ../
         ../../3rdparty/chromium
@@ -57,6 +55,8 @@ qt_internal_add_module(WebEngineCore
         Qt::Gui
         Qt::Network
         Qt::Quick
+    EXTRA_CMAKE_FILES
+        "${CMAKE_CURRENT_LIST_DIR}/${INSTALL_CMAKE_NAMESPACE}WebEngineCoreDeploySupport.cmake"
 )
 
 set_target_properties(WebEngineCore PROPERTIES QTWEBENGINEPROCESS_NAME ${qtWebEngineProcessName})
@@ -65,7 +65,16 @@ set_target_properties(WebEngineCore PROPERTIES QTWEBENGINEPROCESS_NAME ${qtWebEn
 qt_skip_warnings_are_errors(WebEngineCore)
 
 if(CLANG OR GCC)
-    target_compile_options(WebEngineCore PRIVATE "-Wno-unused-parameter")
+    target_compile_options(WebEngineCore PRIVATE
+        "-Wno-unused-parameter"
+        "-Wno-expansion-to-defined"
+    )
+endif()
+
+if(GCC)
+    target_compile_options(WebEngineCore PRIVATE
+        "-Wno-packed-not-aligned"
+    )
 endif()
 
 qt_internal_extend_target(WebEngineCore CONDITION QT_FEATURE_webengine_webchannel
@@ -117,31 +126,47 @@ set(resourceList qtwebengine_resources.pak
 
 set(stamps ${buildDir}/${config}/${arch}/QtWebEngineCore.stamp)
 
-if(QT_FEATURE_webengine_v8_context_snapshot AND NOT MACOS)
-    list(APPEND resourceList v8_context_snapshot.bin)
-elseif(QT_FEATURE_webengine_v8_context_snapshot)
+qt_internal_get_filename_path_mode(path_mode)
+
+if(QT_FEATURE_webengine_v8_context_snapshot)
     foreach(arch ${archs})
        foreach(config ${configs})
-          get_filename_component(resSourcePath ${buildDir}/${config}/${arch}/v8_context_snapshot.${arch}.bin REALPATH)
-          list(APPEND resourceFiles ${resSourcePath})
+           if(MACOS)
+               set(ext_arch ".${arch}")
+               # QTBUG-118120 gn does not support x86_64h
+               if(ext_arch STREQUAL "x86_64h")
+                   set(ext_arch "x86_64")
+               endif()
+           else()
+               unset(ext_arch)
+           endif()
+           if("${config}" STREQUAL "Debug")
+               set(ext_debug ".debug")
+           else()
+               unset(ext_debug)
+           endif()
+           get_filename_component(resSourcePath ${buildDir}/${config}/${arch}/v8_context_snapshot${ext_arch}${ext_debug}.bin ${path_mode})
+           list(APPEND resourceFiles ${resSourcePath})
+           if(MACOS)
+               set(stamps ${stamps} ${buildDir}/${config}/${arch}/obj/tools/v8_context_snapshot/v8_context_snapshot.stamp)
+           endif()
        endforeach()
-       set(stamps ${stamps} ${buildDir}/${config}/${arch}/obj/tools/v8_context_snapshot/v8_context_snapshot.stamp)
     endforeach()
 endif()
 
 foreach(loc ${localeList})
-    get_filename_component(locSourcePath ${buildDir}/${config}/${arch}/qtwebengine_locales/${loc}.pak REALPATH)
+    get_filename_component(locSourcePath ${buildDir}/${config}/${arch}/qtwebengine_locales/${loc}.pak ${path_mode})
     list(APPEND localeFiles ${locSourcePath})
 endforeach()
 
 foreach(res ${resourceList})
-    get_filename_component(resSourcePath ${buildDir}/${config}/${arch}/${res} REALPATH)
+    get_filename_component(resSourcePath ${buildDir}/${config}/${arch}/${res} ${path_mode})
     list(APPEND resourceFiles ${resSourcePath})
 endforeach()
 
 
 if(NOT QT_FEATURE_webengine_system_icu)
-    get_filename_component(icuFile ${buildDir}/${config}/${arch}/icudtl.dat REALPATH)
+    get_filename_component(icuFile ${buildDir}/${config}/${arch}/icudtl.dat ${path_mode})
     list(APPEND resourceFiles ${icuFile})
     set_target_properties(WebEngineCore PROPERTIES ICUDTL_FILE ${icuFile})
 endif()
diff --git a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake
new file mode 100644
index 00000000000..856a54f17c7
--- /dev/null
+++ b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake
@@ -0,0 +1,176 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+# NOTE: This code should only ever be executed in script mode. It expects to be
+#       used either as part of an install(CODE) call or called by a script
+#       invoked via cmake -P as a POST_BUILD step. It would not normally be
+#       included directly, it should be pulled in automatically by the deploy
+#       support set up by qtbase.
+
+cmake_minimum_required(VERSION 3.16...3.21)
+
+_qt_internal_add_deployment_hook(_qt_internal_webenginecore_deploy_hook)
+
+if(NOT QT_DEPLOY_WEBENGINECORE_RESOURCES_DIR)
+    set(QT_DEPLOY_WEBENGINECORE_RESOURCES_DIR "resources")
+endif()
+
+function(_qt_internal_webenginecore_status_message)
+    if(__QT_DEPLOY_VERBOSE)
+        message(STATUS ${ARGV})
+    endif()
+endfunction()
+
+function(_qt_internal_webenginecore_deploy_hook)
+    set(no_value_options "")
+    set(single_value_options "")
+    set(multi_value_options RESOLVED_DEPENDENCIES)
+    cmake_parse_arguments(PARSE_ARGV 0 arg
+        "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+    )
+
+    set(webenginecore_dependency_found FALSE)
+    foreach(dependency IN LISTS arg_RESOLVED_DEPENDENCIES)
+        if(dependency MATCHES "/libQt[0-9]+WebEngineCore[^/]+")
+            set(webenginecore_dependency_found TRUE)
+            break()
+        endif()
+    endforeach()
+
+    if(NOT webenginecore_dependency_found)
+        _qt_internal_webenginecore_status_message(
+            "No QtWebEngineCore dependency found. "
+            "Skipping deployment of QtWebEngine assets."
+        )
+        return()
+    endif()
+
+    _qt_internal_deploy_webenginecore()
+endfunction()
+
+function(_qt_internal_deploy_webenginecore)
+    _qt_internal_deploy_webenginecore_binary()
+    _qt_internal_deploy_webenginecore_data()
+    _qt_internal_deploy_webenginecore_translations()
+endfunction()
+
+function(_qt_internal_deploy_webenginecore_binary)
+    _qt_internal_webenginecore_status_message("Deploying the WebEngineCore process binary")
+
+    set(candidates "QtWebEngineProcess")
+    if(__QT_DEPLOY_ACTIVE_CONFIG STREQUAL "Debug" AND __QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows")
+        list(PREPEND candidates "QtWebEngineProcessd")
+    endif()
+
+    list(TRANSFORM candidates
+        PREPEND "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_LIBEXECS}/"
+    )
+
+    set(process_path "")
+    foreach(file_path IN LISTS candidates)
+        if(EXISTS "${file_path}")
+            set(process_path "${file_path}")
+            break()
+        endif()
+    endforeach()
+
+    set(install_destination "${QT_DEPLOY_PREFIX}/")
+    if(__QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows")
+        string(APPEND install_destination "${QT_DEPLOY_BIN_DIR}")
+    else()
+        if(NOT DEFINED QT_DEPLOY_LIBEXEC_DIR)
+            set(QT_DEPLOY_LIBEXEC_DIR "libexec")
+        endif()
+        string(APPEND install_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}"
+            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}"
+        )
+    endif()
+endfunction()
+
+function(_qt_internal_deploy_webenginecore_data)
+    _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
+    )
+    get_filename_component(resources_dir "resources" ABSOLUTE
+        BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_DATA}"
+    )
+
+    _qt_internal_webenginecore_find_v8_context_snapshot(
+        snapshot_file
+        RESOURCES_DIR "${resources_dir}"
+    )
+    if(NOT snapshot_file STREQUAL "")
+        list(APPEND data_files "${snapshot_file}")
+    endif()
+
+    get_filename_component(install_destination "${QT_DEPLOY_WEBENGINECORE_RESOURCES_DIR}" ABSOLUTE
+        BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_DATA_DIR}"
+    )
+    foreach(data_file IN LISTS data_files)
+        file(INSTALL "${resources_dir}/${data_file}" DESTINATION "${install_destination}")
+    endforeach()
+endfunction()
+
+# The V8 snapshot file comes as debug or release build. Multi-config builds have both, a self-built
+# Qt might only have the debug one.
+#
+# This function returns the file name of the V8 context snapshot file in ${out_var}.
+# If no snapshot could be found, ${out_var} is the empty string.
+function(_qt_internal_webenginecore_find_v8_context_snapshot out_var)
+     set(no_value_options "")
+     set(single_value_options RESOURCES_DIR)
+     set(multi_value_options "")
+     cmake_parse_arguments(PARSE_ARGV 1 arg
+         "${no_value_options}" "${single_value_options}" "${multi_value_options}"
+     )
+
+    set(result "")
+    set(candidates
+        v8_context_snapshot.bin
+        v8_context_snapshot.debug.bin
+    )
+    if(__QT_DEPLOY_QT_IS_MULTI_CONFIG_BUILD_WITH_DEBUG
+            AND __QT_DEPLOY_ACTIVE_CONFIG STREQUAL "Debug")
+        # Favor the debug version of the snapshot.
+        list(REVERSE candidates)
+    endif()
+    foreach(candidate IN LISTS candidates)
+        if(EXISTS "${arg_RESOURCES_DIR}/${candidate}")
+            set(result "${candidate}")
+            break()
+        endif()
+    endforeach()
+    set("${out_var}" "${result}" PARENT_SCOPE)
+endfunction()
+
+function(_qt_internal_deploy_webenginecore_translations)
+    _qt_internal_webenginecore_status_message("Deploying the WebEngineCore translations")
+
+    get_filename_component(locales_dir "qtwebengine_locales" ABSOLUTE
+        BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_TRANSLATIONS}"
+    )
+    get_filename_component(install_destination "qtwebengine_locales" ABSOLUTE
+        BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}"
+    )
+    file(GLOB locale_files "${locales_dir}/*.pak")
+    foreach(locale_file IN LISTS locale_files)
+        file(INSTALL "${locale_file}" DESTINATION "${install_destination}")
+    endforeach()
+endfunction()
diff --git a/src/core/api/Qt6WebEngineCoreMacros.cmake b/src/core/api/Qt6WebEngineCoreMacros.cmake
index 7e23f377ec3..8bb73154841 100644
--- a/src/core/api/Qt6WebEngineCoreMacros.cmake
+++ b/src/core/api/Qt6WebEngineCoreMacros.cmake
@@ -1,6 +1,12 @@
 # Copyright (C) 2022 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
+# Install support uses the CMAKE_INSTALL_xxxDIR variables. Include this here
+# so that it is more likely to get pulled in earlier at a higher level, and also
+# to avoid re-including it many times later
+include(GNUInstallDirs)
+_qt_internal_add_deploy_support("${CMAKE_CURRENT_LIST_DIR}/Qt6WebEngineCoreDeploySupport.cmake")
+
 function(qt6_add_webengine_dictionary)
     set(options)
     set(oneValueArgs TARGET SOURCE OUTPUT_DIRECTORY)
@@ -23,7 +29,7 @@ function(qt6_add_webengine_dictionary)
         set(copyCommand COMMAND ${CMAKE_COMMAND} -E copy_directory ${ARGS_OUTPUT_DIRECTORY}/dict
            ${ARGS_OUTPUT_DIRECTORY}/$<CONFIG>
         )
-    elseif(isBundle)
+    elseif(APPLE AND isBundle)
         get_target_property(outputName ${ARGS_TARGET} OUTPUT_NAME)
         if(NOT outputName)
            set(outputName ${ARGS_TARGET})
diff --git a/src/core/api/configure.cmake b/src/core/api/configure.cmake
index c19f1825151..49ad00ed8b7 100644
--- a/src/core/api/configure.cmake
+++ b/src/core/api/configure.cmake
@@ -7,13 +7,13 @@ if(NOT QT_CONFIGURE_RUNNING)
     find_package(GLIB2 COMPONENTS GIO)
     find_package(GSSAPI)
     find_package(PkgConfig)
-    if(PkgConfig_FOUND)
+    if(PkgConfig_FOUND AND QT_FEATURE_pkg_config)
         pkg_check_modules(ALSA alsa IMPORTED_TARGET)
         pkg_check_modules(PULSEAUDIO libpulse>=0.9.10 libpulse-mainloop-glib)
         pkg_check_modules(XDAMAGE xdamage)
         pkg_check_modules(POPPLER_CPP poppler-cpp IMPORTED_TARGET)
         pkg_check_modules(GBM gbm)
-        pkg_check_modules(LIBVA libva)
+        pkg_check_modules(LIBVA libva>=1.14)
         if(NOT GIO_FOUND)
             pkg_check_modules(GIO gio-2.0)
         endif()
@@ -66,7 +66,7 @@ qt_feature("webengine-system-alsa" PRIVATE
 )
 qt_feature("webengine-v8-context-snapshot" PRIVATE
     LABEL "Use v8 context snapshot"
-    CONDITION NOT CMAKE_CROSSCOMPILING
+    AUTODETECT NOT CMAKE_CROSSCOMPILING
 )
 qt_feature("webengine-geolocation" PUBLIC
     LABEL "Geolocation"
@@ -162,12 +162,13 @@ qt_feature("webengine-vaapi" PRIVATE
     SECTION "WebEngine"
     LABEL "VA-API support"
     PURPOSE "Enables support for VA-API hardware acceleration"
-    AUTODETECT GBM_FOUND AND LIBVA_FOUND
-    CONDITION LINUX
+    AUTODETECT GBM_FOUND AND LIBVA_FOUND AND QT_FEATURE_vulkan
+    # hardware accelerated encoding requires bundled libvpx
+    CONDITION LINUX AND NOT QT_FEATURE_webengine_system_libvpx
 )
 # internal testing feature
 qt_feature("webengine-system-poppler" PRIVATE
-    LABEL "popler"
+    LABEL "poppler"
     CONDITION UNIX AND TEST_poppler
 )
 qt_configure_add_summary_section(NAME "Qt WebEngineCore")
@@ -226,3 +227,8 @@ qt_configure_add_report_entry(
     MESSAGE "WebRTC requires XDamage with qpa_xcb."
     CONDITION QT_FEATURE_webengine_ozone_x11 AND NOT XDAMAGE_FOUND
 )
+qt_configure_add_report_entry(
+    TYPE WARNING
+    MESSAGE "VA-API is incompatible with system libvpx."
+    CONDITION QT_FEATURE_webengine_system_libvpx AND QT_FEATURE_webengine_vaapi
+)
diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp
index 9082052f2fd..b9e2882a483 100644
--- a/src/core/api/qtwebenginecoreglobal.cpp
+++ b/src/core/api/qtwebenginecoreglobal.cpp
@@ -6,12 +6,6 @@
 #include <QGuiApplication>
 #if QT_CONFIG(opengl)
 # include <QOpenGLContext>
-#ifdef Q_OS_MACOS
-#include <sys/types.h>
-#include <sys/sysctl.h>
-#include <QOffscreenSurface>
-#include "macos_context_type_helper.h"
-#endif
 #endif
 #include <QThread>
 #include <QQuickWindow>
@@ -19,33 +13,15 @@
 
 #include "net/base/registry_controlled_domains/registry_controlled_domain.h"
 
-#if QT_CONFIG(opengl)
+#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS)
 QT_BEGIN_NAMESPACE
 Q_GUI_EXPORT void qt_gl_set_global_share_context(QOpenGLContext *context);
 Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context();
 QT_END_NAMESPACE
 #endif
 
-#if QT_CONFIG(opengl)
-#ifdef Q_OS_MACOS
-static bool needsOfflineRendererWorkaround()
-{
-    size_t hwmodelsize = 0;
-
-    if (sysctlbyname("hw.model", nullptr, &hwmodelsize, nullptr, 0) == -1)
-        return false;
-
-    char hwmodel[hwmodelsize];
-    if (sysctlbyname("hw.model", &hwmodel, &hwmodelsize, nullptr, 0) == -1)
-        return false;
-
-    return QString::fromLatin1(hwmodel) == QLatin1String("MacPro6,1");
-}
-#endif
-#endif
-
 namespace QtWebEngineCore {
-#if QT_CONFIG(opengl)
+#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS)
 static QOpenGLContext *shareContext;
 
 static void deleteShareContext()
@@ -64,14 +40,18 @@ static void deleteShareContext()
 
 Q_WEBENGINECORE_PRIVATE_EXPORT void initialize()
 {
-#if QT_CONFIG(opengl)
+#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS)
 #ifdef Q_OS_WIN32
     qputenv("QT_D3DCREATE_MULTITHREADED", "1");
 #endif
-#ifdef Q_OS_MACOS
-    if (needsOfflineRendererWorkaround())
-        qputenv("QT_MAC_PRO_WEBENGINE_WORKAROUND", "1");
+    auto api = QQuickWindow::graphicsApi();
+    if (api != QSGRendererInterface::OpenGL
+#if QT_VERSION >= QT_VERSION_CHECK(6, 4, 0)
+        && api != QSGRendererInterface::Vulkan && api != QSGRendererInterface::Metal
+        && api != QSGRendererInterface::Direct3D11
 #endif
+    )
+        QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
     // No need to override the shared context if QApplication already set one (e.g with Qt::AA_ShareOpenGLContexts).
     if (!qt_gl_global_share_context()) {
 
@@ -96,57 +76,6 @@ Q_WEBENGINECORE_PRIVATE_EXPORT void initialize()
         shareContext = new QOpenGLContext;
         QSurfaceFormat format = QSurfaceFormat::defaultFormat();
 
-#if defined(Q_OS_MACOS)
-        if (format == QSurfaceFormat()) {
-            QOpenGLContext testContext;
-
-            // Chromium turns off OpenGL for CoreProfiles with versions < 4.1
-            // The newest Mac that only supports 3.3 was released in Mid 2011,
-            // so it should be safe to request 4.1, but we still double check it
-            // works in order not to set an invalid default surface format.
-            format.setVersion(4, 1);
-            format.setProfile(QSurfaceFormat::CoreProfile);
-
-            testContext.setFormat(format);
-            if (testContext.create()) {
-                QOffscreenSurface surface;
-                surface.setFormat(format);
-                surface.create();
-
-                if (testContext.makeCurrent(&surface)) {
-                    // The Cocoa QPA integration allows sharing between OpenGL 3.2 and 4.1 contexts,
-                    // which means even though we requested a 4.1 context, if we only get a 3.2
-                    // context, it will still work an Chromium will not black list it.
-                    if (testContext.format().version() >= qMakePair(3, 2)
-                        && testContext.format().profile() == QSurfaceFormat::CoreProfile
-                        && !isCurrentContextSoftware()) {
-                        QSurfaceFormat::setDefaultFormat(format);
-                    } else {
-                        qWarning("The available OpenGL surface format was either not version 3.2 "
-                                 "or higher or not a Core Profile.\n"
-                                 "Chromium on macOS will fall back to software rendering in this "
-                                 "case.\n"
-                                 "Hardware acceleration and features such as WebGL will not be "
-                                 "available.");
-                        format = QSurfaceFormat::defaultFormat();
-                    }
-                    testContext.doneCurrent();
-                }
-                surface.destroy();
-            }
-        } else {
-            // The user explicitly requested a specific surface format that does not fit Chromium's
-            // requirements. Warn them about this.
-            if (format.version() < qMakePair(3, 2)
-                || format.profile() != QSurfaceFormat::CoreProfile) {
-                qWarning("An OpenGL surfcace format was requested that is either not version 3.2 "
-                         "or higher or a not Core Profile.\n"
-                         "Chromium on macOS will fall back to software rendering in this case.\n"
-                         "Hardware acceleration and features such as WebGL will not be available.");
-            }
-        }
-#endif
-
         shareContext->setFormat(format);
         shareContext->create();
         qAddPostRoutine(deleteShareContext);
@@ -156,22 +85,7 @@ Q_WEBENGINECORE_PRIVATE_EXPORT void initialize()
         app->setAttribute(Qt::AA_ShareOpenGLContexts);
     }
 
-#if defined(Q_OS_MACOS)
-    // Check that the default QSurfaceFormat OpenGL profile is compatible with the global OpenGL
-    // shared context profile, otherwise this could lead to a nasty crash.
-    QSurfaceFormat sharedFormat = qt_gl_global_share_context()->format();
-    QSurfaceFormat defaultFormat = QSurfaceFormat::defaultFormat();
-
-    if (defaultFormat.profile() != sharedFormat.profile()
-        && defaultFormat.profile() == QSurfaceFormat::CoreProfile
-        && defaultFormat.version() >= qMakePair(3, 2)) {
-        qFatal("QWebEngine: Default QSurfaceFormat OpenGL profile is not compatible with the "
-               "global shared context OpenGL profile. Please make sure you set a compatible "
-               "QSurfaceFormat before the QtGui application instance is created.");
-    }
-#endif
-
-#endif // QT_CONFIG(opengl)
+#endif // QT_CONFIG(opengl) && !defined(Q_OS_MACOS)
 }
 
 bool closingDown()
@@ -196,27 +110,9 @@ sandbox::SandboxInterfaceInfo *staticSandboxInterfaceInfo(sandbox::SandboxInterf
 #endif
 static void initialize()
 {
-#if QT_CONFIG(opengl)
-    if (QCoreApplication::instance()) {
-        // On Windows/ANGLE, calling QtWebEngineQuick::initialize from DllMain will result in a
-        // crash.
-        if (!qt_gl_global_share_context()
-            && !(QCoreApplication::testAttribute(Qt::AA_ShareOpenGLContexts)
-                 && QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGLRhi)) {
-            qWarning("Qt WebEngine seems to be initialized from a plugin. Please "
-                     "set Qt::AA_ShareOpenGLContexts using QCoreApplication::setAttribute and "
-                     "QSGRendererInterface::OpenGLRhi using QQuickWindow::setGraphicsApi "
-                     "before constructing QGuiApplication.");
-        }
-        return;
-    }
-
+#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS)
     // QCoreApplication is not yet instantiated, ensuring the call will be deferred
     qAddPreRoutine(QtWebEngineCore::initialize);
-    auto api = QQuickWindow::graphicsApi();
-    if (api != QSGRendererInterface::OpenGL && api != QSGRendererInterface::Vulkan
-        && api != QSGRendererInterface::Metal && api != QSGRendererInterface::Direct3D11)
-        QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
 #endif // QT_CONFIG(opengl)
 }
 
diff --git a/src/core/api/qtwebenginecoreglobal.h b/src/core/api/qtwebenginecoreglobal.h
index 166a82b788d..0041a72be79 100644
--- a/src/core/api/qtwebenginecoreglobal.h
+++ b/src/core/api/qtwebenginecoreglobal.h
@@ -5,11 +5,12 @@
 #define QTWEBENGINECOREGLOBAL_H
 
 #include <QtCore/qglobal.h>
-#include <QtCore/qurl.h>
 #include <QtWebEngineCore/qtwebenginecore-config.h>
 
 QT_BEGIN_NAMESPACE
 
+class QUrl;
+
 #if defined(BUILDING_CHROMIUM)
 #  define Q_WEBENGINECORE_EXPORT Q_DECL_EXPORT
 #else
diff --git a/src/core/api/qwebenginedownloadrequest.cpp b/src/core/api/qwebenginedownloadrequest.cpp
index e51fe7c0fd2..cbf46b4481b 100644
--- a/src/core/api/qwebenginedownloadrequest.cpp
+++ b/src/core/api/qwebenginedownloadrequest.cpp
@@ -219,16 +219,22 @@ void QWebEngineDownloadRequest::cancel()
 
     QWebEngineDownloadRequest::DownloadState state = d->downloadState;
 
-    if (state == QWebEngineDownloadRequest::DownloadCompleted
-            || state == QWebEngineDownloadRequest::DownloadCancelled)
+    if (state == QWebEngineDownloadRequest::DownloadCompleted)
         return;
 
-    // We directly cancel the download request if the user cancels
-    // before it even started, so no need to notify the profile here.
+    bool cancelled = state == QWebEngineDownloadRequest::DownloadCancelled;
+    if (cancelled)
+        return;
+
+    // Check if the download manager has a DownloadItem for this ID
+    // (network downloads or in progress page/resource saves)
     if (state == QWebEngineDownloadRequest::DownloadInProgress) {
         if (d->profileAdapter)
-            d->profileAdapter->cancelDownload(d->downloadId);
-    } else {
+            cancelled = d->profileAdapter->cancelDownload(d->downloadId);
+    }
+
+    // Not cancelled downloads are not even started yet at this point
+    if (!cancelled) {
         d->downloadState = QWebEngineDownloadRequest::DownloadCancelled;
         Q_EMIT stateChanged(d->downloadState);
         d->setFinished();
@@ -601,7 +607,7 @@ QString QWebEngineDownloadRequest::interruptReasonString() const
 QWebEnginePage *QWebEngineDownloadRequest::page() const
 {
     Q_D(const QWebEngineDownloadRequest);
-    if (d->adapterClient->clientType() == QtWebEngineCore::WebContentsAdapterClient::WidgetsClient)
+    if (d->adapterClient && d->adapterClient->clientType() == QtWebEngineCore::WebContentsAdapterClient::WidgetsClient)
         return const_cast<QWebEnginePage *>(static_cast<const QWebEnginePage *>(d->adapterClient->holdingQObject()));
     return nullptr;
 }
diff --git a/src/core/api/qwebenginefilesystemaccessrequest.cpp b/src/core/api/qwebenginefilesystemaccessrequest.cpp
index 6527e176650..3f901b671cf 100644
--- a/src/core/api/qwebenginefilesystemaccessrequest.cpp
+++ b/src/core/api/qwebenginefilesystemaccessrequest.cpp
@@ -27,6 +27,25 @@ QT_BEGIN_NAMESPACE
     either call accept() or reject().
 */
 
+/*!
+   \enum QWebEngineFileSystemAccessRequest::AccessFlag
+
+   This enum describes the type of the requested access: read, write or both. The options
+   can be OR-ed together from the following list:
+
+   \value Read
+   \value Write
+*/
+
+/*!
+   \enum QWebEngineFileSystemAccessRequest::HandleType
+
+   This enum describes the type of the requested file system entry.
+
+   \value File
+   \value Directory
+*/
+
 QWebEngineFileSystemAccessRequest::QWebEngineFileSystemAccessRequest(
         const QWebEngineFileSystemAccessRequest &other) = default;
 QWebEngineFileSystemAccessRequest &QWebEngineFileSystemAccessRequest::operator=(
diff --git a/src/core/api/qwebengineglobalsettings.cpp b/src/core/api/qwebengineglobalsettings.cpp
index 685d9d593e1..95138516bc0 100644
--- a/src/core/api/qwebengineglobalsettings.cpp
+++ b/src/core/api/qwebengineglobalsettings.cpp
@@ -1,91 +1,137 @@
 // Copyright (C) 2023 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 "services/network/network_service.h"
-#include "content/public/browser/network_service_instance.h"
-
 #include "qwebengineglobalsettings.h"
 #include "qwebengineglobalsettings_p.h"
 
+#ifdef signals
+#undef signals
+#endif
+
+#include "content/browser/network_service_instance_impl.h"
+#include "content/public/browser/network_service_instance.h"
+#include "services/network/network_service.h"
+
 QT_BEGIN_NAMESPACE
 
+ASSERT_ENUMS_MATCH(net::SecureDnsMode::kSecure, QWebEngineGlobalSettings::SecureDnsMode::SecureOnly)
+ASSERT_ENUMS_MATCH(net::SecureDnsMode::kAutomatic,
+                   QWebEngineGlobalSettings::SecureDnsMode::SecureWithFallback)
+ASSERT_ENUMS_MATCH(net::SecureDnsMode::kOff, QWebEngineGlobalSettings::SecureDnsMode::SystemOnly)
+
 /*!
-    \class QWebEngineGlobalSettings
-    \brief The QWebEngineGlobalSettings class configures global properties of the web engine.
+    \namespace QWebEngineGlobalSettings
+    \brief The QWebEngineGlobalSettings namespace holds global settings of the web engine.
     \since 6.6
     \inmodule QtWebEngineCore
 
-    The QWebEngineGlobalSettings class is a singleton that configures global properties
-    of the web engine.
+    The QWebEngineGlobalSettings namespace holds global properties of the web engine.
 
-    Invoke configureDnsOverHttps() to configure DNS-over-HTTPS capabilities.
+    Invoke setDnsMode() to configure DNS-over-HTTPS.
 
-    \sa QWebEngineGlobalSettings::configureDnsOverHttps()
+    \sa QWebEngineGlobalSettings::setDnsMode()
 */
 
-QWebEngineGlobalSettings::QWebEngineGlobalSettings(QObject *p)
-    : QObject(p), d_ptr(new QWebEngineGlobalSettingsPrivate)
-{
-}
-
-QWebEngineGlobalSettings::~QWebEngineGlobalSettings() { }
+/*!
+    \enum QWebEngineGlobalSettings::SecureDnsMode
+
+    This enum sets the DNS-over-HTTPS mode used by the DnsMode structure:
+
+    \value SystemOnly This is the default. Use the system DNS host resolution.
+    \value SecureWithFallback Enable DNS-over-HTTPS (DoH). DoH servers have to be
+    provided through \l {QWebEngineGlobalSettings::DnsMode::serverTemplates}{serverTemplates} in
+    the DnsMode structure. If a host cannot be resolved via the provided servers,
+    the system DNS host resolution is used.
+    \value SecureOnly Enable DNS-over-HTTPS and only allow hosts to be resolved
+    this way. DoH servers have to be provided through
+    \l {QWebEngineGlobalSettings::DnsMode::serverTemplates}{serverTemplates} in the DnsMode
+    structure. If the DNS-over-HTTPS resolution fails, there is no fallback and the DNS host
+    resolution fails completely.
+*/
 
 /*!
-    \fn QWebEngineGlobalSettings *QWebEngineGlobalSettings::GetInstance()
+    \class QWebEngineGlobalSettings::DnsMode
+    \brief The DnsMode struct provides means to specify the DNS host resolution mode.
+    \since 6.6
+    \inmodule QtWebEngineCore
 
-    Gets the global instance of QWebEngineGlobalSettings.
+    The QWebEngineGlobalSettings::DnsMode structure describes the DNS mode and
+    the associated DNS server template used for the DNS host resolution.
 */
-QWebEngineGlobalSettings *QWebEngineGlobalSettings::GetInstance()
-{
-    static QWebEngineGlobalSettings settings;
-    return &settings;
-}
 
 /*!
-    \enum QWebEngineGlobalSettings::DnsMode
+    \variable QWebEngineGlobalSettings::DnsMode::secureMode
+    \brief The DNS mode used for the host resolution.
+
+    Set \a secureMode to SecureDnsMode::SecureOnly to only allow DNS-over-HTTPS host resolution
+    using servers from \a serverTemplates.
+
+    Set \a secureMode to SecureDnsMode::SecureWithFallback to enable DNS-over-HTTPS host resolution
+    using servers from \a serverTemplates, with a fallback to the system DNS.
+
+    \sa QWebEngineGlobalSettings::SecureDnsMode
+*/
 
-    This enum sets the DNS-over-HTTPS mode:
+/*!
+    \variable QWebEngineGlobalSettings::DnsMode::serverTemplates
+    \brief A list of server URI templates used for secure DNS-over-HTTPS host resolution.
 
-    \value WithFallback Enable DNS-over-HTTPS with fallbacks. If a host
-    can't be resolved, try the insecure DNS client of Chromium. If that fails as
-    well, try the system DNS host resolution, which can be secure or insecure.
-    \value Secure Enable DNS-over-HTTPS and only allow the secure Chromium
-    DNS client to resolve hosts.
+    The \c serverTemplates structure member lists
+    \l{https://datatracker.ietf.org/d7oc/html/rfc6570}{URI templates}.
+    An example of a URI template is https://dns.google/dns-query{?dns}.
 */
 
 /*!
-    \fn QWebEngineGlobalSettings::configureDnsOverHttps(const DnsMode dnsMode,
-                                                        const QString &dnsOverHttpsTemplates)
+    \fn void QWebEngineGlobalSettings::setDnsMode(DnsMode dnsMode)
 
-    Configures the Chromium stub host resolver, thus allowing DNS-over-HTTPS functionality.
+    Sets \a dnsMode for DNS-over-HTTPS host resolution.
+
+    This function returns \c false if the \l {QWebEngineGlobalSettings::DnsMode::serverTemplates}
+    {serverTemplates} list in the \l {QWebEngineGlobalSettings::DnsMode}{DnsMode} structure is empty
+    or contains URI templates that cannot be parsed for SecureDnsMode::SecureOnly or
+    SecureDnsMode::SecureWithFallback. Otherwise, it returns \c true meaning that the DNS mode
+    change is triggered.
+*/
 
-    Set \a dnsMode to QWebEngineGlobalSettings::DnsMode::WithFallback to enable secure DNS
-    host resolution with a fallback to insecure DNS host resolution and a final fallback to
-    the system DNS resolution, which can be secure or insecure. Set it to
-    QWebEngineGlobalSettings::DnsMode::Secure to only allow secure DNS host resolution via
-    the Chromium DNS client.
+bool QWebEngineGlobalSettings::setDnsMode(DnsMode dnsMode)
+{
+    QWebEngineGlobalSettingsPrivate *d = QWebEngineGlobalSettingsPrivate::instance();
+    if (dnsMode.secureMode != SecureDnsMode::SystemOnly) {
+        const QString servers = dnsMode.serverTemplates.join(QChar::Space);
+        const std::string templates = servers.toStdString();
+        absl::optional<net::DnsOverHttpsConfig> dnsOverHttpsConfig =
+                net::DnsOverHttpsConfig::FromString(templates);
+        if (!dnsOverHttpsConfig.has_value())
+            return false;
+        d->dnsOverHttpsTemplates = templates;
+    }
+    d->dnsMode = dnsMode.secureMode;
+    d->configureStubHostResolver();
+    return true;
+}
 
-    Independently of \a {dnsMode}, \a dnsOverHttpsTemplates has to be set to one or multiple
-    valid \l{https://datatracker.ietf.org/doc/html/rfc6570}{URI templates} separated by
-    whitespace characters. One example URI template is https://dns.google/dns-query{?dns}.
+/*!
+    \internal
 */
-void QWebEngineGlobalSettings::configureDnsOverHttps(const DnsMode dnsMode,
-                                                     const QString &dnsOverHttpsTemplates)
+QWebEngineGlobalSettingsPrivate *QWebEngineGlobalSettingsPrivate::instance()
+{
+    static QWebEngineGlobalSettingsPrivate settings;
+    return &settings;
+}
+
+void QWebEngineGlobalSettingsPrivate::configureStubHostResolver()
 {
-    Q_D(QWebEngineGlobalSettings);
-
-    d->dnsMode = dnsMode;
-    d->dnsOverHttpsTemplates = dnsOverHttpsTemplates.toStdString();
-    d->isDnsOverHttpsUserConfigured = true;
-
-    // Make sure that DoH settings are in effect immediately if the network service already exists,
-    // thus allowing to change DoH configuration at any point
-    network::mojom::NetworkService *networkService = content::GetNetworkService();
-    if (networkService) {
-        networkService->ConfigureStubHostResolver(
-                d->insecureDnsClientEnabled, net::SecureDnsMode(d->dnsMode),
-                *net::DnsOverHttpsConfig::FromString(d->dnsOverHttpsTemplates),
-                d->additionalInsecureDnsTypesEnabled);
+    if (content::GetNetworkServiceAvailability()
+        != content::NetworkServiceAvailability::NOT_CREATED) {
+        network::mojom::NetworkService *networkService = content::GetNetworkService();
+        if (networkService) {
+            absl::optional<net::DnsOverHttpsConfig> dohConfig = dnsOverHttpsTemplates.empty()
+                    ? net::DnsOverHttpsConfig()
+                    : net::DnsOverHttpsConfig::FromString(dnsOverHttpsTemplates);
+            networkService->ConfigureStubHostResolver(insecureDnsClientEnabled,
+                                                      net::SecureDnsMode(dnsMode), *dohConfig,
+                                                      additionalInsecureDnsTypesEnabled);
+        }
     }
 }
 
diff --git a/src/core/api/qwebengineglobalsettings.h b/src/core/api/qwebengineglobalsettings.h
index a65a0835993..a9eff6d1255 100644
--- a/src/core/api/qwebengineglobalsettings.h
+++ b/src/core/api/qwebengineglobalsettings.h
@@ -4,38 +4,26 @@
 #ifndef QWEBENGINEGLOBALSETTINGS_H
 #define QWEBENGINEGLOBALSETTINGS_H
 
+#if 0
+#pragma qt_class(QWebEngineGlobalSettings)
+#endif
+
 #include <QtWebEngineCore/qtwebenginecoreglobal.h>
 #include <QtCore/QObject>
 #include <QtCore/QScopedPointer>
 
-namespace QtWebEngineCore {
-class SystemNetworkContextManager;
-}
-
 QT_BEGIN_NAMESPACE
 
-class QWebEngineGlobalSettingsPrivate;
-
-class Q_WEBENGINECORE_EXPORT QWebEngineGlobalSettings : public QObject
+namespace QWebEngineGlobalSettings {
+// Mapping net::SecureDnsMode
+enum class SecureDnsMode : quint8 { SystemOnly = 0, SecureWithFallback = 1, SecureOnly = 2 };
+struct DnsMode
 {
-    Q_OBJECT
-    Q_DISABLE_COPY(QWebEngineGlobalSettings)
-public:
-    static QWebEngineGlobalSettings *GetInstance();
-
-    // Mapping net::SecureDnsMode
-    enum class DnsMode { WithFallback = 1, Secure = 2 };
-
-    void configureDnsOverHttps(const DnsMode dnsMode, const QString &dnsOverHttpsTemplates);
-
-private:
-    QWebEngineGlobalSettings(QObject *p = nullptr);
-    ~QWebEngineGlobalSettings();
-
-    friend class QtWebEngineCore::SystemNetworkContextManager;
-    Q_DECLARE_PRIVATE(QWebEngineGlobalSettings)
-    QScopedPointer<QWebEngineGlobalSettingsPrivate> d_ptr;
+    SecureDnsMode secureMode = SecureDnsMode::SystemOnly;
+    QStringList serverTemplates;
 };
+Q_WEBENGINECORE_EXPORT bool setDnsMode(DnsMode dnsMode);
+}
 
 QT_END_NAMESPACE
 
diff --git a/src/core/api/qwebengineglobalsettings_p.h b/src/core/api/qwebengineglobalsettings_p.h
index 4c15f62b0bd..10ae502f014 100644
--- a/src/core/api/qwebengineglobalsettings_p.h
+++ b/src/core/api/qwebengineglobalsettings_p.h
@@ -25,17 +25,18 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEngineGlobalSettingsPrivate
 {
 public:
     QWebEngineGlobalSettingsPrivate()
-        : dnsMode(QWebEngineGlobalSettings::DnsMode::WithFallback)
+        : dnsMode(QWebEngineGlobalSettings::SecureDnsMode::SystemOnly)
         , dnsOverHttpsTemplates("")
-        , insecureDnsClientEnabled(true)
-        , additionalInsecureDnsTypesEnabled(true)
-        , isDnsOverHttpsUserConfigured(false){};
+        , insecureDnsClientEnabled(false)
+        , additionalInsecureDnsTypesEnabled(false){};
 
-    QWebEngineGlobalSettings::DnsMode dnsMode;
+    static QWebEngineGlobalSettingsPrivate *instance();
+    QWebEngineGlobalSettings::SecureDnsMode dnsMode;
     std::string dnsOverHttpsTemplates;
-    bool insecureDnsClientEnabled;
-    bool additionalInsecureDnsTypesEnabled;
-    bool isDnsOverHttpsUserConfigured;
+    const bool insecureDnsClientEnabled;
+    const bool additionalInsecureDnsTypesEnabled;
+
+    void configureStubHostResolver();
 };
 
 QT_END_NAMESPACE
diff --git a/src/core/api/qwebenginehistory.cpp b/src/core/api/qwebenginehistory.cpp
index b70c0b73d41..5d2fc8e9e14 100644
--- a/src/core/api/qwebenginehistory.cpp
+++ b/src/core/api/qwebenginehistory.cpp
@@ -242,13 +242,6 @@ QWebEngineHistory::QWebEngineHistory(QWebEngineHistoryPrivate *d) : d_ptr(d) { }
 
 QWebEngineHistory::~QWebEngineHistory() { }
 
-/*!
-    \qmlmethod void WebEngineHistory::clear()
-    \since QtWebEngine 1.11
-
-    Clears the history.
-*/
-
 void QWebEngineHistory::clear()
 {
     Q_D(const QWebEngineHistory);
diff --git a/src/core/api/qwebengineloadinginfo.cpp b/src/core/api/qwebengineloadinginfo.cpp
index ed9618f494d..a72117e9d31 100644
--- a/src/core/api/qwebengineloadinginfo.cpp
+++ b/src/core/api/qwebengineloadinginfo.cpp
@@ -23,7 +23,7 @@ class QWebEngineLoadingInfo::QWebEngineLoadingInfoPrivate : public QSharedData {
 public:
     QWebEngineLoadingInfoPrivate(const QUrl& url, LoadStatus status, bool isErrorPage,
                                  const QString& errorString, int errorCode, ErrorDomain errorDomain,
-                                 const QHash<QByteArray,QByteArray>& responseHeaders)
+                                 const QMultiMap<QByteArray,QByteArray>& responseHeaders)
         : url(url)
         , status(status)
         , isErrorPage(isErrorPage)
@@ -40,7 +40,7 @@ class QWebEngineLoadingInfo::QWebEngineLoadingInfoPrivate : public QSharedData {
     QString errorString;
     int errorCode;
     ErrorDomain errorDomain;
-    QHash<QByteArray,QByteArray> responseHeaders;
+    QMultiMap<QByteArray,QByteArray> responseHeaders;
 };
 
 /*!
@@ -56,7 +56,7 @@ class QWebEngineLoadingInfo::QWebEngineLoadingInfoPrivate : public QSharedData {
 */
 QWebEngineLoadingInfo::QWebEngineLoadingInfo(const QUrl& url, LoadStatus status, bool isErrorPage,
                                              const QString& errorString, int errorCode, ErrorDomain errorDomain,
-                                             const QHash<QByteArray,QByteArray>& responseHeaders)
+                                             const QMultiMap<QByteArray,QByteArray>& responseHeaders)
     : d_ptr(new QWebEngineLoadingInfoPrivate(url, status, isErrorPage, errorString, errorCode, errorDomain,
                                              responseHeaders))
 {
@@ -164,11 +164,12 @@ int QWebEngineLoadingInfo::errorCode() const
 
 /*!
     \property QWebEngineLoadingInfo::responseHeaders
+    \since 6.6
     \brief Holds the response headers when \c QWebEngineLoadingInfo::status()
            is equal to \c QWebEngineLoadingInfo::LoadSucceededStatus or
            \c QWebEngineLoadingInfo::LoadFailedStatus.
 */
-QHash<QByteArray,QByteArray> QWebEngineLoadingInfo::responseHeaders() const
+QMultiMap<QByteArray,QByteArray> QWebEngineLoadingInfo::responseHeaders() const
 {
     Q_D(const QWebEngineLoadingInfo);
     return d->responseHeaders;
diff --git a/src/core/api/qwebengineloadinginfo.h b/src/core/api/qwebengineloadinginfo.h
index 86d9dba4635..48d14601ab6 100644
--- a/src/core/api/qwebengineloadinginfo.h
+++ b/src/core/api/qwebengineloadinginfo.h
@@ -6,7 +6,7 @@
 
 #include <QtWebEngineCore/qtwebenginecoreglobal.h>
 
-#include <QtCore/qhash.h>
+#include <QtCore/qmap.h>
 #include <QtCore/qobject.h>
 #include <QtCore/qshareddata.h>
 #include <QtCore/qurl.h>
@@ -27,7 +27,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo
     Q_PROPERTY(QString errorString READ errorString CONSTANT FINAL)
     Q_PROPERTY(ErrorDomain errorDomain READ errorDomain CONSTANT FINAL)
     Q_PROPERTY(int errorCode READ errorCode CONSTANT FINAL)
-    Q_PROPERTY(QHash<QByteArray,QByteArray> responseHeaders READ responseHeaders CONSTANT FINAL)
+    Q_PROPERTY(QMultiMap<QByteArray,QByteArray> responseHeaders READ responseHeaders CONSTANT REVISION(6,6) FINAL)
 
 public:
     enum LoadStatus {
@@ -62,13 +62,13 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo
     QString errorString() const;
     ErrorDomain errorDomain() const;
     int errorCode() const;
-    QHash<QByteArray,QByteArray> responseHeaders() const;
+    QMultiMap<QByteArray,QByteArray> responseHeaders() const;
 
 private:
     QWebEngineLoadingInfo(const QUrl &url, LoadStatus status, bool isErrorPage = false,
                           const QString &errorString = QString(), int errorCode = 0,
                           ErrorDomain errorDomain = NoErrorDomain,
-                          const QHash<QByteArray, QByteArray> &responseHeaders = {});
+                          const QMultiMap<QByteArray,QByteArray> &responseHeaders = {});
     class QWebEngineLoadingInfoPrivate;
     Q_DECLARE_PRIVATE(QWebEngineLoadingInfo)
     QExplicitlySharedDataPointer<QWebEngineLoadingInfoPrivate> d_ptr;
diff --git a/src/core/api/qwebenginemessagepumpscheduler.cpp b/src/core/api/qwebenginemessagepumpscheduler.cpp
index 62244c787d7..a435e2c0c5a 100644
--- a/src/core/api/qwebenginemessagepumpscheduler.cpp
+++ b/src/core/api/qwebenginemessagepumpscheduler.cpp
@@ -11,9 +11,14 @@ QWebEngineMessagePumpScheduler::QWebEngineMessagePumpScheduler(std::function<voi
     : m_callback(std::move(callback))
 {}
 
-void QWebEngineMessagePumpScheduler::scheduleWork()
+void QWebEngineMessagePumpScheduler::scheduleImmediateWork()
 {
-    QCoreApplication::postEvent(this, new QTimerEvent(0));
+    QCoreApplication::postEvent(this, new QTimerEvent(0), Qt::NormalEventPriority);
+}
+
+void QWebEngineMessagePumpScheduler::scheduleIdleWork()
+{
+    QCoreApplication::postEvent(this, new QTimerEvent(0), Qt::LowEventPriority);
 }
 
 void QWebEngineMessagePumpScheduler::scheduleDelayedWork(int delay)
diff --git a/src/core/api/qwebenginemessagepumpscheduler_p.h b/src/core/api/qwebenginemessagepumpscheduler_p.h
index 7e84b4190af..4ec7ef1253e 100644
--- a/src/core/api/qwebenginemessagepumpscheduler_p.h
+++ b/src/core/api/qwebenginemessagepumpscheduler_p.h
@@ -28,7 +28,8 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEngineMessagePumpScheduler : public QOb
     Q_OBJECT
 public:
     QWebEngineMessagePumpScheduler(std::function<void()> callback);
-    void scheduleWork();
+    void scheduleImmediateWork();
+    void scheduleIdleWork();
     void scheduleDelayedWork(int delay);
 
 protected:
diff --git a/src/core/api/qwebenginenavigationrequest.cpp b/src/core/api/qwebenginenavigationrequest.cpp
index c14a7bf41e0..0a30f647279 100644
--- a/src/core/api/qwebenginenavigationrequest.cpp
+++ b/src/core/api/qwebenginenavigationrequest.cpp
@@ -89,7 +89,10 @@ void QWebEngineNavigationRequest::setAction(QWebEngineNavigationRequest::Navigat
         return;
 
     acceptRequest ? accept() : reject();
+QT_WARNING_PUSH
+QT_WARNING_DISABLE_DEPRECATED
     emit actionChanged();
+QT_WARNING_POP
 }
 #endif
 /*!
diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp
index afb4cde3ce1..71769714c22 100644
--- a/src/core/api/qwebenginepage.cpp
+++ b/src/core/api/qwebenginepage.cpp
@@ -103,7 +103,9 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
 {
     memset(actions, 0, sizeof(actions));
 
+#if QT_DEPRECATED_SINCE(6, 5)
     qRegisterMetaType<QWebEngineQuotaRequest>();
+#endif
     qRegisterMetaType<QWebEngineRegisterProtocolHandlerRequest>();
     qRegisterMetaType<QWebEngineFileSystemAccessRequest>();
     qRegisterMetaType<QWebEngineFindTextResult>();
@@ -329,6 +331,109 @@ void QWebEnginePagePrivate::createNewWindow(WindowOpenDisposition disposition, b
     Q_EMIT q->newWindowRequested(request);
 }
 
+QString QWebEnginePagePrivate::actionText(int action)
+{
+    switch (action) {
+    case QWebEnginePage::Back:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Back);
+    case QWebEnginePage::Forward:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Forward);
+    case QWebEnginePage::Stop:
+        return QWebEnginePage::tr("Stop");
+    case QWebEnginePage::Reload:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Reload);
+    case QWebEnginePage::ReloadAndBypassCache:
+        return QWebEnginePage::tr("Reload and Bypass Cache");
+    case QWebEnginePage::Cut:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Cut);
+    case QWebEnginePage::Copy:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Copy);
+    case QWebEnginePage::Paste:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Paste);
+    case QWebEnginePage::Undo:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Undo);
+    case QWebEnginePage::Redo:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Redo);
+    case QWebEnginePage::SelectAll:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SelectAll);
+    case QWebEnginePage::PasteAndMatchStyle:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::PasteAndMatchStyle);
+    case QWebEnginePage::OpenLinkInThisWindow:
+        return QWebEnginePage::tr("Open link in this window");
+    case QWebEnginePage::OpenLinkInNewWindow:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewWindow);
+    case QWebEnginePage::OpenLinkInNewTab:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewTab);
+    case QWebEnginePage::OpenLinkInNewBackgroundTab:
+        return QWebEnginePage::tr("Open link in new background tab");
+    case QWebEnginePage::CopyLinkToClipboard:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyLinkToClipboard);
+    case QWebEnginePage::DownloadLinkToDisk:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadLinkToDisk);
+    case QWebEnginePage::CopyImageToClipboard:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageToClipboard);
+    case QWebEnginePage::CopyImageUrlToClipboard:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageUrlToClipboard);
+    case QWebEnginePage::DownloadImageToDisk:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadImageToDisk);
+    case QWebEnginePage::CopyMediaUrlToClipboard:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyMediaUrlToClipboard);
+    case QWebEnginePage::ToggleMediaControls:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaControls);
+    case QWebEnginePage::ToggleMediaLoop:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaLoop);
+    case QWebEnginePage::ToggleMediaPlayPause:
+        return QWebEnginePage::tr("Toggle Play/Pause");
+    case QWebEnginePage::ToggleMediaMute:
+        return QWebEnginePage::tr("Toggle Mute");
+    case QWebEnginePage::DownloadMediaToDisk:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadMediaToDisk);
+    case QWebEnginePage::InspectElement:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::InspectElement);
+    case QWebEnginePage::ExitFullScreen:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ExitFullScreen);
+    case QWebEnginePage::RequestClose:
+        return QWebEnginePage::tr("Close Page");
+    case QWebEnginePage::Unselect:
+        return QWebEnginePage::tr("Unselect");
+    case QWebEnginePage::SavePage:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SavePage);
+    case QWebEnginePage::ViewSource:
+        return RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ViewSource);
+    case QWebEnginePage::ToggleBold:
+        return QWebEnginePage::tr("&Bold");
+    case QWebEnginePage::ToggleItalic:
+        return QWebEnginePage::tr("&Italic");
+    case QWebEnginePage::ToggleUnderline:
+        return QWebEnginePage::tr("&Underline");
+    case QWebEnginePage::ToggleStrikethrough:
+        return QWebEnginePage::tr("&Strikethrough");
+    case QWebEnginePage::AlignLeft:
+        return QWebEnginePage::tr("Align &Left");
+    case QWebEnginePage::AlignCenter:
+        return QWebEnginePage::tr("Align &Center");
+    case QWebEnginePage::AlignRight:
+        return QWebEnginePage::tr("Align &Right");
+    case QWebEnginePage::AlignJustified:
+        return QWebEnginePage::tr("Align &Justified");
+    case QWebEnginePage::Indent:
+        return QWebEnginePage::tr("&Indent");
+    case QWebEnginePage::Outdent:
+        return QWebEnginePage::tr("&Outdent");
+    case QWebEnginePage::InsertOrderedList:
+        return QWebEnginePage::tr("Insert &Ordered List");
+    case QWebEnginePage::InsertUnorderedList:
+        return QWebEnginePage::tr("Insert &Unordered List");
+    case QWebEnginePage::ChangeTextDirectionLTR:
+        return QWebEnginePage::tr("Change text direction left to right");
+    case QWebEnginePage::ChangeTextDirectionRTL:
+        return QWebEnginePage::tr("Change text direction right to left");
+    default:
+        break;
+    }
+    return {};
+}
+
 class WebContentsAdapterOwner : public QObject
 {
 public:
@@ -351,6 +456,8 @@ bool QWebEnginePagePrivate::adoptWebContents(WebContentsAdapter *webContents)
 
     m_isBeingAdopted = true;
 
+    webContents->setRequestInterceptor(adapter->requestInterceptor());
+
     // This throws away the WebContentsAdapter that has been used until now.
     // All its states, particularly the loading URL, are replaced by the adopted WebContentsAdapter.
     WebContentsAdapterOwner *adapterOwner = new WebContentsAdapterOwner(adapter->sharedFromThis());
@@ -508,6 +615,15 @@ void QWebEnginePagePrivate::runRegisterProtocolHandlerRequest(QWebEngineRegister
     Q_EMIT q->registerProtocolHandlerRequested(request);
 }
 
+/*!
+    \fn void QWebEnginePage::fileSystemAccessRequested(QWebEngineFileSystemAccessRequest request)
+    \since 6.4
+
+    This signal is emitted when the web page requests access to local files or directories.
+
+    The request object \a request can be used to accept or reject the request.
+*/
+
 void QWebEnginePagePrivate::runFileSystemAccessRequest(QWebEngineFileSystemAccessRequest request)
 {
     Q_Q(QWebEnginePage);
@@ -1042,154 +1158,7 @@ QAction *QWebEnginePage::action(WebAction action) const
     if (d->actions[action])
         return d->actions[action];
 
-    QString text;
-    switch (action) {
-    case Back:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Back);
-        break;
-    case Forward:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Forward);
-        break;
-    case Stop:
-        text = tr("Stop");
-        break;
-    case Reload:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Reload);
-        break;
-    case ReloadAndBypassCache:
-        text = tr("Reload and Bypass Cache");
-        break;
-    case Cut:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Cut);
-        break;
-    case Copy:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Copy);
-        break;
-    case Paste:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Paste);
-        break;
-    case Undo:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Undo);
-        break;
-    case Redo:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Redo);
-        break;
-    case SelectAll:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SelectAll);
-        break;
-    case PasteAndMatchStyle:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::PasteAndMatchStyle);
-        break;
-    case OpenLinkInThisWindow:
-        text = tr("Open link in this window");
-        break;
-    case OpenLinkInNewWindow:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewWindow);
-        break;
-    case OpenLinkInNewTab:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewTab);
-        break;
-    case OpenLinkInNewBackgroundTab:
-        text = tr("Open link in new background tab");
-        break;
-    case CopyLinkToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyLinkToClipboard);
-        break;
-    case DownloadLinkToDisk:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadLinkToDisk);
-        break;
-    case CopyImageToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageToClipboard);
-        break;
-    case CopyImageUrlToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageUrlToClipboard);
-        break;
-    case DownloadImageToDisk:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadImageToDisk);
-        break;
-    case CopyMediaUrlToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyMediaUrlToClipboard);
-        break;
-    case ToggleMediaControls:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaControls);
-        break;
-    case ToggleMediaLoop:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaLoop);
-        break;
-    case ToggleMediaPlayPause:
-        text = tr("Toggle Play/Pause");
-        break;
-    case ToggleMediaMute:
-        text = tr("Toggle Mute");
-        break;
-    case DownloadMediaToDisk:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadMediaToDisk);
-        break;
-    case InspectElement:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::InspectElement);
-        break;
-    case ExitFullScreen:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ExitFullScreen);
-        break;
-    case RequestClose:
-        text = tr("Close Page");
-        break;
-    case Unselect:
-        text = tr("Unselect");
-        break;
-    case SavePage:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SavePage);
-        break;
-    case ViewSource:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ViewSource);
-        break;
-    case ToggleBold:
-        text = tr("&Bold");
-        break;
-    case ToggleItalic:
-        text = tr("&Italic");
-        break;
-    case ToggleUnderline:
-        text = tr("&Underline");
-        break;
-    case ToggleStrikethrough:
-        text = tr("&Strikethrough");
-        break;
-    case AlignLeft:
-        text = tr("Align &Left");
-        break;
-    case AlignCenter:
-        text = tr("Align &Center");
-        break;
-    case AlignRight:
-        text = tr("Align &Right");
-        break;
-    case AlignJustified:
-        text = tr("Align &Justified");
-        break;
-    case Indent:
-        text = tr("&Indent");
-        break;
-    case Outdent:
-        text = tr("&Outdent");
-        break;
-    case InsertOrderedList:
-        text = tr("Insert &Ordered List");
-        break;
-    case InsertUnorderedList:
-        text = tr("Insert &Unordered List");
-        break;
-    case ChangeTextDirectionLTR:
-        text = tr("Change text direction left to right");
-        break;
-    case ChangeTextDirectionRTL:
-        text = tr("Change text direction right to left");
-        break;
-    case NoWebAction:
-    case WebActionCount:
-        Q_UNREACHABLE();
-        break;
-    }
+    const QString text = QWebEnginePagePrivate::actionText(action);
 
     QAction *a = new QAction(const_cast<QWebEnginePage*>(this));
     a->setText(text);
@@ -1514,7 +1483,7 @@ void QWebEnginePagePrivate::contextMenuRequested(QWebEngineContextMenuRequest *d
 }
 
 /*!
-    \fn bool QWebEnginePage::navigationRequested(QWebEngineNavigationRequest &request)
+    \fn void QWebEnginePage::navigationRequested(QWebEngineNavigationRequest &request)
     \since 6.2
 
     This signal is emitted on navigation together with the call the acceptNavigationRequest().
@@ -1655,6 +1624,17 @@ void QWebEnginePagePrivate::setToolTip(const QString &toolTipText)
         view->setToolTip(toolTipText);
 }
 
+/*!
+    \fn void QWebEnginePage::printRequested()
+    \since 5.12
+
+    This signal is emitted when the JavaScript \c{window.print()} method is called or the user pressed the print
+    button of PDF viewer plugin.
+    Typically, the signal handler can simply call printToPdf().
+
+    \sa printToPdf()
+*/
+
 void QWebEnginePagePrivate::printRequested()
 {
     Q_Q(QWebEnginePage);
@@ -1717,7 +1697,9 @@ void QWebEnginePagePrivate::visibleChanged(bool visible)
 
     The page does not take ownership of the pointer. This interceptor is called
     after any interceptors on the profile, and unlike profile interceptors, only
-    URL requests from this page are intercepted.
+    URL requests from this page are intercepted. If the original request was
+    already blocked or redirected by the profile interceptor, it will not be
+    intercepted by this.
 
     To unset the request interceptor, set a \c nullptr.
 
@@ -1730,26 +1712,6 @@ void QWebEnginePage::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *i
     d->adapter->setRequestInterceptor(interceptor);
 }
 
-/*!
-    \since 6.6
-
-    Registers the response interceptor \a interceptor to intercept URL response headers.
-
-    The page does not take ownership of the pointer. This interceptor is called
-    after any interceptors on the profile, and unlike profile interceptors, only
-    URL responses to this page are intercepted.
-
-    To unset the response interceptor, set a \c nullptr.
-
-    \sa QWebEngineUrlResponseInterceptor, QWebEngineProfile::setUrlResponseInterceptor()
-*/
-
-void QWebEnginePage::setUrlResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor)
-{
-    Q_D(QWebEnginePage);
-    d->adapter->setResponseInterceptor(interceptor);
-}
-
 void QWebEnginePage::setFeaturePermission(const QUrl &securityOrigin, QWebEnginePage::Feature feature, QWebEnginePage::PermissionPolicy policy)
 {
     Q_D(QWebEnginePage);
@@ -2179,9 +2141,9 @@ void QWebEnginePage::setDevToolsPage(QWebEnginePage *devToolsPage)
    Protocol}.
 */
 
-QString QWebEnginePage::devToolsId()
+QString QWebEnginePage::devToolsId() const
 {
-    Q_D(QWebEnginePage);
+    Q_D(const QWebEnginePage);
     d->ensureInitialized();
     return d->adapter->devToolsId();
 }
diff --git a/src/core/api/qwebenginepage.h b/src/core/api/qwebenginepage.h
index d0f1c70ee48..61bc63e1976 100644
--- a/src/core/api/qwebenginepage.h
+++ b/src/core/api/qwebenginepage.h
@@ -40,7 +40,6 @@ class QWebEngineRegisterProtocolHandlerRequest;
 class QWebEngineScriptCollection;
 class QWebEngineSettings;
 class QWebEngineUrlRequestInterceptor;
-class QWebEngineUrlResponseInterceptor;
 
 class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject
 {
@@ -50,7 +49,7 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject
     Q_PROPERTY(QUrl requestedUrl READ requestedUrl)
     Q_PROPERTY(qreal zoomFactor READ zoomFactor WRITE setZoomFactor)
     Q_PROPERTY(QString title READ title)
-    Q_PROPERTY(QUrl url READ url WRITE setUrl)
+    Q_PROPERTY(QUrl url READ url WRITE setUrl NOTIFY urlChanged)
     Q_PROPERTY(QUrl iconUrl READ iconUrl NOTIFY iconUrlChanged)
     Q_PROPERTY(QIcon icon READ icon NOTIFY iconChanged)
     Q_PROPERTY(QColor backgroundColor READ backgroundColor WRITE setBackgroundColor)
@@ -286,10 +285,9 @@ class Q_WEBENGINECORE_EXPORT QWebEnginePage : public QObject
     QWebEnginePage *inspectedPage() const;
     void setDevToolsPage(QWebEnginePage *page);
     QWebEnginePage *devToolsPage() const;
-    QString devToolsId();
+    QString devToolsId() const;
 
     void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
-    void setUrlResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor);
 
     LifecycleState lifecycleState() const;
     void setLifecycleState(LifecycleState state);
diff --git a/src/core/api/qwebenginepage_p.h b/src/core/api/qwebenginepage_p.h
index bb33c7e984e..532a9b942fa 100644
--- a/src/core/api/qwebenginepage_p.h
+++ b/src/core/api/qwebenginepage_p.h
@@ -186,6 +186,8 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEnginePagePrivate : public QtWebEngineC
     void setFullScreenMode(bool);
     void ensureInitialized() const;
 
+    static QString actionText(int action);
+
     QSharedPointer<QtWebEngineCore::WebContentsAdapter> adapter;
     QWebEngineHistory *history;
     QWebEngineProfile *profile;
diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp
index 3a4c899d9f0..70051b3b472 100644
--- a/src/core/api/qwebengineprofile.cpp
+++ b/src/core/api/qwebengineprofile.cpp
@@ -62,12 +62,9 @@ using QtWebEngineCore::ProfileAdapter;
     The default profile can be accessed by defaultProfile(). It is a built-in profile that all
     web pages not specifically created with another profile belong to.
 
-    You can implement interceptor interfaces for URL requests and responses and register them
-    on a profile to intercept, block, or modify URL requests before they reach the networking
-    stack of Chromium or response headers right after they come off the networking stack of
-    Chromium. For requests, implement QWebEngineUrlRequestInterceptor and register it via
-    setUrlRequestInterceptor(). For response headers, implement QWebEngineUrlResponseInterceptor
-    and register it via setUrlResponseInterceptor().
+    Implementing the QWebEngineUrlRequestInterceptor interface and registering the interceptor on a
+    profile by setUrlRequestInterceptor() enables intercepting, blocking, and modifying URL
+    requests (QWebEngineUrlRequestInfo) before they reach the networking stack of Chromium.
 
     A QWebEngineUrlSchemeHandler can be registered for a profile by installUrlSchemeHandler()
     to add support for custom URL schemes. Requests for the scheme are then issued to
@@ -463,7 +460,7 @@ void QWebEngineProfile::setCachePath(const QString &path)
     "Windows NT 6.2" (Windows 8), unless the application does contain a manifest
     that declares newer Windows versions as supported.
 
-    \sa setHttpUserAgent()
+    \sa setHttpUserAgent(), {windows_manifest} {Windows Application Manifest}
 */
 QString QWebEngineProfile::httpUserAgent() const
 {
@@ -498,7 +495,10 @@ QWebEngineProfile::HttpCacheType QWebEngineProfile::httpCacheType() const
 /*!
     Sets the HTTP cache type to \a httpCacheType.
 
-    \sa httpCacheType(), setCachePath()
+    \note Setting the \a httpCacheType to NoCache on the profile, which has already some cache
+    entries does not trigger the removal of those entries.
+
+    \sa httpCacheType(), setCachePath(), clearHttpCache()
 */
 void QWebEngineProfile::setHttpCacheType(QWebEngineProfile::HttpCacheType httpCacheType)
 {
@@ -605,21 +605,6 @@ void QWebEngineProfile::setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor
     d->profileAdapter()->setRequestInterceptor(interceptor);
 }
 
-/*!
-    Registers a response interceptor singleton \a interceptor to intercept URL response headers.
-
-    The profile does not take ownership of the pointer.
-
-    \since 6.6
-    \sa QWebEngineUrlResponseInterceptor
-*/
-
-void QWebEngineProfile::setUrlResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor)
-{
-    Q_D(QWebEngineProfile);
-    d->profileAdapter()->setResponseInterceptor(interceptor);
-}
-
 /*!
     Clears all links from the visited links database.
 
diff --git a/src/core/api/qwebengineprofile.h b/src/core/api/qwebengineprofile.h
index bd051c7843a..9fb4c8e74bf 100644
--- a/src/core/api/qwebengineprofile.h
+++ b/src/core/api/qwebengineprofile.h
@@ -24,7 +24,6 @@ class QWebEngineProfilePrivate;
 class QWebEngineSettings;
 class QWebEngineScriptCollection;
 class QWebEngineUrlRequestInterceptor;
-class QWebEngineUrlResponseInterceptor;
 class QWebEngineUrlSchemeHandler;
 
 class Q_WEBENGINECORE_EXPORT QWebEngineProfile : public QObject
@@ -75,7 +74,6 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfile : public QObject
 
     QWebEngineCookieStore *cookieStore();
     void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
-    void setUrlResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor);
 
     void clearAllVisitedLinks();
     void clearVisitedLinks(const QList<QUrl> &urls);
diff --git a/src/core/api/qwebenginesettings.h b/src/core/api/qwebenginesettings.h
index 8cb10f6a7e6..7919719a1d1 100644
--- a/src/core/api/qwebenginesettings.h
+++ b/src/core/api/qwebenginesettings.h
@@ -60,7 +60,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineSettings
         DnsPrefetchEnabled,
         PdfViewerEnabled,
         NavigateOnDropEnabled,
-        DisableReadingFromCanvas,
+        ReadingFromCanvasEnabled,
     };
 
     enum FontSize {
diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp
index 162ae7daf4a..fa8870c09c2 100644
--- a/src/core/api/qwebengineurlrequestinfo.cpp
+++ b/src/core/api/qwebengineurlrequestinfo.cpp
@@ -285,8 +285,6 @@ void QWebEngineUrlRequestInfo::block(bool shouldBlock)
 
 void QWebEngineUrlRequestInfo::setHttpHeader(const QByteArray &name, const QByteArray &value)
 {
-    d_ptr->changed = true;
-
     // Headers are case insentive, so we need to compare manually
     for (auto it = d_ptr->extraHeaders.begin(); it != d_ptr->extraHeaders.end(); ++it) {
         if (it.key().compare(name, Qt::CaseInsensitive) == 0) {
diff --git a/src/core/api/qwebengineurlrequestinterceptor.cpp b/src/core/api/qwebengineurlrequestinterceptor.cpp
new file mode 100644
index 00000000000..c3cd49a5bce
--- /dev/null
+++ b/src/core/api/qwebengineurlrequestinterceptor.cpp
@@ -0,0 +1,11 @@
+// Copyright (C) 2021 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 "qwebengineurlrequestinterceptor.h"
+
+QT_BEGIN_NAMESPACE
+
+// Has to stay empty till Qt7
+QWebEngineUrlRequestInterceptor::~QWebEngineUrlRequestInterceptor() = default;
+
+QT_END_NAMESPACE
diff --git a/src/core/api/qwebengineurlrequestinterceptor.h b/src/core/api/qwebengineurlrequestinterceptor.h
index 98f135e733d..2ca8ee914e5 100644
--- a/src/core/api/qwebengineurlrequestinterceptor.h
+++ b/src/core/api/qwebengineurlrequestinterceptor.h
@@ -14,10 +14,9 @@ QT_BEGIN_NAMESPACE
 class Q_WEBENGINECORE_EXPORT QWebEngineUrlRequestInterceptor : public QObject
 {
     Q_OBJECT
-    Q_DISABLE_COPY(QWebEngineUrlRequestInterceptor)
 public:
     explicit QWebEngineUrlRequestInterceptor(QObject *p = nullptr) : QObject(p) {}
-
+    ~QWebEngineUrlRequestInterceptor() override;
     virtual void interceptRequest(QWebEngineUrlRequestInfo &info) = 0;
 };
 
diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp
index 099efef8e3d..6e978ef2879 100644
--- a/src/core/api/qwebengineurlrequestjob.cpp
+++ b/src/core/api/qwebengineurlrequestjob.cpp
@@ -118,7 +118,7 @@ QMap<QByteArray, QByteArray> QWebEngineUrlRequestJob::requestHeaders() const
     is called.
 */
 void QWebEngineUrlRequestJob::setAdditionalResponseHeaders(
-        const QMap<QByteArray, QByteArray> &additionalResponseHeaders) const
+        const QMultiMap<QByteArray, QByteArray> &additionalResponseHeaders) const
 {
     d_ptr->setAdditionalResponseHeaders(additionalResponseHeaders);
 }
diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h
index 75e065566f5..aa1bf893a5b 100644
--- a/src/core/api/qwebengineurlrequestjob.h
+++ b/src/core/api/qwebengineurlrequestjob.h
@@ -44,7 +44,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineUrlRequestJob : public QObject
     void fail(Error error);
     void redirect(const QUrl &url);
     void setAdditionalResponseHeaders(
-            const QMap<QByteArray, QByteArray> &additionalResponseHeaders) const;
+            const QMultiMap<QByteArray, QByteArray> &additionalResponseHeaders) const;
 
 private:
     QWebEngineUrlRequestJob(QtWebEngineCore::URLRequestCustomJobDelegate *);
diff --git a/src/core/api/qwebengineurlresponseinfo.cpp b/src/core/api/qwebengineurlresponseinfo.cpp
deleted file mode 100644
index 8ec1024dad9..00000000000
--- a/src/core/api/qwebengineurlresponseinfo.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2023 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 "qwebengineurlresponseinfo.h"
-#include "qwebengineurlresponseinfo_p.h"
-
-QT_BEGIN_NAMESPACE
-
-/*!
-    \class QWebEngineUrlResponseInfo
-    \brief A utility type for the QWebEngineUrlResponseInterceptor.
-    \inmodule QtWebEngineCore
-    \since 6.6
-
-    Contains information about the request that has caused the response
-    intercepted by a QWebEngineUrlResponseInterceptor.
-
-    \sa QWebEngineUrlResponseInterceptor
-*/
-QWebEngineUrlResponseInfo::QWebEngineUrlResponseInfo(
-        const QUrl &requestUrl, const QHash<QByteArray, QByteArray> &requestHeaders,
-        const QHash<QByteArray, QByteArray> &responseHeaders, QObject *p)
-    : QObject(p)
-    , d_ptr(new QWebEngineUrlResponseInfoPrivate(requestUrl, requestHeaders, responseHeaders))
-{
-}
-
-/*!
-    \property QWebEngineUrlResponseInfo::requestUrl
-    \brief Holds the URL of the URL load request.
-*/
-QUrl QWebEngineUrlResponseInfo::requestUrl() const
-{
-    Q_D(const QWebEngineUrlResponseInfo);
-    return d->requestUrl;
-}
-
-/*!
-    \property QWebEngineUrlResponseInfo::requestHeaders
-    \brief Holds the request headers of the URL load request.
-*/
-QHash<QByteArray, QByteArray> QWebEngineUrlResponseInfo::requestHeaders() const
-{
-    Q_D(const QWebEngineUrlResponseInfo);
-    return d->requestHeaders;
-}
-
-/*!
-    \property QWebEngineUrlResponseInfo::responseHeaders
-    \brief Holds the response headers of the URL load request.
-*/
-QHash<QByteArray, QByteArray> QWebEngineUrlResponseInfo::responseHeaders() const
-{
-    Q_D(const QWebEngineUrlResponseInfo);
-    return d->responseHeaders;
-}
-
-/*!
-    \fn void QWebEngineUrlResponseInfo::setResponseHeaders(
-        const QHash<QByteArray, QByteArray> &newResponseHeaders)
-    \brief Sets the response headers to \a newResponseHeaders.
-
-    Sets the response headers to \a newResponseHeaders. If \a newResponseHeaders
-    differ from the current response headers then
-    QWebEngineUrlResponseInfo::isModified() will now return \c true.
-*/
-void QWebEngineUrlResponseInfo::setResponseHeaders(
-        const QHash<QByteArray, QByteArray> &newResponseHeaders)
-{
-    Q_D(QWebEngineUrlResponseInfo);
-    if (d->responseHeaders != newResponseHeaders) {
-        d->responseHeaders = newResponseHeaders;
-        d->isModified = true;
-    }
-}
-
-QT_END_NAMESPACE
-
-#include "moc_qwebengineurlresponseinfo.cpp"
diff --git a/src/core/api/qwebengineurlresponseinfo.h b/src/core/api/qwebengineurlresponseinfo.h
deleted file mode 100644
index e8286b313c9..00000000000
--- a/src/core/api/qwebengineurlresponseinfo.h
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2023 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
-
-#ifndef QWEBENGINEURLRESPONSEINFO_H
-#define QWEBENGINEURLRESPONSEINFO_H
-
-#include <QtWebEngineCore/qtwebenginecoreglobal.h>
-
-#include <QtCore/QUrl>
-#include <QtCore/QHash>
-#include <QtCore/QObject>
-
-namespace QtWebEngineCore {
-class InterceptedRequest;
-}
-
-QT_BEGIN_NAMESPACE
-
-class QWebEngineUrlResponseInfoPrivate;
-
-class Q_WEBENGINECORE_EXPORT QWebEngineUrlResponseInfo : public QObject
-{
-    Q_OBJECT
-    Q_PROPERTY(QUrl requestUrl READ requestUrl CONSTANT FINAL)
-    Q_PROPERTY(QHash<QByteArray,QByteArray> requestHeaders READ requestHeaders CONSTANT FINAL)
-    Q_PROPERTY(QHash<QByteArray,QByteArray> responseHeaders READ responseHeaders WRITE
-                       setResponseHeaders)
-
-public:
-    QWebEngineUrlResponseInfo(const QUrl &requestUrl,
-                              const QHash<QByteArray, QByteArray> &requestHeaders,
-                              const QHash<QByteArray, QByteArray> &responseHeaders,
-                              QObject *p = nullptr);
-
-    QUrl requestUrl() const;
-    QHash<QByteArray, QByteArray> requestHeaders() const;
-    QHash<QByteArray, QByteArray> responseHeaders() const;
-
-    void setResponseHeaders(const QHash<QByteArray, QByteArray> &newResponseHeaders);
-
-private:
-    friend class QtWebEngineCore::InterceptedRequest;
-    Q_DECLARE_PRIVATE(QWebEngineUrlResponseInfo)
-    QWebEngineUrlResponseInfoPrivate *d_ptr;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWEBENGINEURLRESPONSEINFO_H
diff --git a/src/core/api/qwebengineurlresponseinfo_p.h b/src/core/api/qwebengineurlresponseinfo_p.h
deleted file mode 100644
index 0e500e3f012..00000000000
--- a/src/core/api/qwebengineurlresponseinfo_p.h
+++ /dev/null
@@ -1,46 +0,0 @@
-// Copyright (C) 2023 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
-
-#ifndef QWEBENGINEURLRESPONSEINFO_P_H
-#define QWEBENGINEURLRESPONSEINFO_P_H
-
-//
-//  W A R N I N G
-//  -------------
-//
-// This file is not part of the Qt API.  It exists purely as an
-// implementation detail.  This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qtwebenginecoreglobal_p.h"
-
-#include <QtCore/QHash>
-#include <QtCore/QUrl>
-
-QT_BEGIN_NAMESPACE
-
-class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEngineUrlResponseInfoPrivate
-{
-public:
-    QWebEngineUrlResponseInfoPrivate(const QUrl &requestUrl,
-                                     const QHash<QByteArray, QByteArray> &requestHeaders,
-                                     const QHash<QByteArray, QByteArray> &responseHeaders)
-        : requestUrl(requestUrl)
-        , requestHeaders(requestHeaders)
-        , responseHeaders(responseHeaders)
-        , isModified(false)
-    {
-    }
-
-    QUrl requestUrl;
-    QHash<QByteArray, QByteArray> requestHeaders;
-    QHash<QByteArray, QByteArray> responseHeaders;
-    bool isModified;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWEBENGINEURLRESPONSEINFO_P_H
diff --git a/src/core/api/qwebengineurlresponseinterceptor.h b/src/core/api/qwebengineurlresponseinterceptor.h
deleted file mode 100644
index 505acce5723..00000000000
--- a/src/core/api/qwebengineurlresponseinterceptor.h
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2023 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
-
-#ifndef QWEBENGINEURLRESPONSEINTERCEPTOR_H
-#define QWEBENGINEURLRESPONSEINTERCEPTOR_H
-
-#include <QtWebEngineCore/qtwebenginecoreglobal.h>
-
-#include <QtCore/QObject>
-
-QT_BEGIN_NAMESPACE
-
-class QWebEngineUrlResponseInfo;
-
-class Q_WEBENGINECORE_EXPORT QWebEngineUrlResponseInterceptor : public QObject
-{
-    Q_OBJECT
-    Q_DISABLE_COPY(QWebEngineUrlResponseInterceptor)
-public:
-    explicit QWebEngineUrlResponseInterceptor(QObject *p = nullptr) : QObject(p) { }
-
-    virtual void interceptResponseHeaders(QWebEngineUrlResponseInfo &info) = 0;
-};
-
-QT_END_NAMESPACE
-
-#endif // QWEBENGINEURLRESPONSEINTERCEPTOR_H
diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp
index 595d64e5c1c..3093c2b8edd 100644
--- a/src/core/api/qwebengineurlscheme.cpp
+++ b/src/core/api/qwebengineurlscheme.cpp
@@ -163,7 +163,7 @@ class QWebEngineUrlSchemePrivate : public QSharedData
   generated automatically by the QWebEngineUrlRequestJob class. By default only
   \c http and \c https are CORS enabled. (Added in Qt 5.14)
 
-  \value FetchApiAllowed
+  \value [since 6.6] FetchApiAllowed
   Enables a URL scheme to be used by the HTML5 fetch API and \c XMLHttpRequest.send with
   a body. By default only \c http and \c https can be send to using the Fetch API or with
   an XMLHttpRequest with a body.
diff --git a/src/core/autofill_client_qt.cpp b/src/core/autofill_client_qt.cpp
index aaf775d60e0..c7becd60569 100644
--- a/src/core/autofill_client_qt.cpp
+++ b/src/core/autofill_client_qt.cpp
@@ -10,11 +10,10 @@
 #include "web_contents_adapter_client.h"
 #include "web_contents_view_qt.h"
 
-#include "base/task/thread_pool.h"
-#include "base/threading/thread_task_runner_handle.h"
 #include "chrome/browser/profiles/profile.h"
 #include "components/autofill/core/common/autofill_prefs.h"
 #include "content/browser/web_contents/web_contents_impl.h"
+#include "services/network/public/cpp/shared_url_loader_factory.h"
 
 namespace QtWebEngineCore {
 
@@ -51,9 +50,6 @@ const PrefService *AutofillClientQt::GetPrefs() const
 void AutofillClientQt::ShowAutofillPopup(const autofill::AutofillClient::PopupOpenArgs &open_args,
                                          base::WeakPtr<autofill::AutofillPopupDelegate> delegate)
 {
-    // Specific popups (personal, address, credit card, password) are not supported.
-    DCHECK(open_args.popup_type == autofill::PopupType::kUnspecified);
-
     m_popupController->d->delegate = delegate;
     m_popupController->d->suggestions = open_args.suggestions;
     m_popupController->updateModel();
@@ -85,11 +81,11 @@ autofill::AutofillClient::PopupOpenArgs AutofillClientQt::GetReopenPopupArgs() c
     return autofill::AutofillClient::PopupOpenArgs();
 }
 
-base::span<const autofill::Suggestion> AutofillClientQt::GetPopupSuggestions() const
+std::vector<autofill::Suggestion> AutofillClientQt::GetPopupSuggestions() const
 {
     // Called by password_manager component only.
     NOTIMPLEMENTED();
-    return base::span<const autofill::Suggestion>();
+    return {};
 }
 
 void AutofillClientQt::UpdatePopup(const std::vector<autofill::Suggestion> &, autofill::PopupType)
@@ -103,7 +99,7 @@ void AutofillClientQt::HideAutofillPopup(autofill::PopupHidingReason)
     adapterClient()->hideAutofillPopup();
 }
 
-bool AutofillClientQt::IsAutocompleteEnabled()
+bool AutofillClientQt::IsAutocompleteEnabled() const
 {
     return autofill::prefs::IsAutocompleteEnabled(GetPrefs());
 }
@@ -113,6 +109,16 @@ bool AutofillClientQt::IsPasswordManagerEnabled()
     return false;
 }
 
+bool AutofillClientQt::IsOffTheRecord()
+{
+    return web_contents()->GetBrowserContext()->IsOffTheRecord();
+}
+
+scoped_refptr<network::SharedURLLoaderFactory> AutofillClientQt::GetURLLoaderFactory()
+{
+    return nullptr;
+}
+
 void AutofillClientQt::PropagateAutofillPredictions(autofill::AutofillDriver *,
                                                     const std::vector<autofill::FormStructure *> &)
 {
diff --git a/src/core/autofill_client_qt.h b/src/core/autofill_client_qt.h
index 95ae460f225..46e40f1da27 100644
--- a/src/core/autofill_client_qt.h
+++ b/src/core/autofill_client_qt.h
@@ -49,14 +49,15 @@ class AutofillClientQt : public autofill::AutofillClient,
                                            const std::vector<std::u16string> &labels) override;
     void PinPopupView() override;
     autofill::AutofillClient::PopupOpenArgs GetReopenPopupArgs() const override;
-    base::span<const autofill::Suggestion> GetPopupSuggestions() const override;
+    std::vector<autofill::Suggestion> GetPopupSuggestions() const override;
     void UpdatePopup(const std::vector<autofill::Suggestion> &, autofill::PopupType) override;
     void HideAutofillPopup(autofill::PopupHidingReason reason) override;
-    bool IsAutocompleteEnabled() override;
+    bool IsAutocompleteEnabled() const override;
     bool IsPasswordManagerEnabled() override;
     void PropagateAutofillPredictions(autofill::AutofillDriver *,
                                       const std::vector<autofill::FormStructure *> &) override;
-
+    bool IsOffTheRecord() override;
+    scoped_refptr<network::SharedURLLoaderFactory> GetURLLoaderFactory() override;
 
 private:
     explicit AutofillClientQt(content::WebContents *webContents);
diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp
index 49a193b057a..07785626696 100644
--- a/src/core/browser_accessibility_manager_qt.cpp
+++ b/src/core/browser_accessibility_manager_qt.cpp
@@ -13,10 +13,6 @@
 #include "render_widget_host_view_qt.h" // WebContentsAccessibilityQt
 
 #include "content/browser/accessibility/browser_accessibility.h"
-#if QT_CONFIG(webengine_extensions)
-#include "content/browser/renderer_host/render_frame_host_impl.h"
-#include "content/public/browser/web_contents.h"
-#endif // QT_CONFIG(webengine_extensions)
 #include "ui/accessibility/ax_enums.mojom.h"
 
 #include <QtGui/qaccessible.h>
@@ -34,12 +30,10 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create(
     QtWebEngineCore::WebContentsAccessibilityQt *access = nullptr;
     access = static_cast<QtWebEngineCore::WebContentsAccessibilityQt *>(delegate->AccessibilityGetWebContentsAccessibility());
 
-#if QT_CONFIG(webengine_extensions)
-    // Accessibility is not supported for guest views.
+    // Accessibility is not supported for guest views and child frames.
     if (!access) {
         return nullptr;
     }
-#endif // QT_CONFIG(webengine_extensions)
 
     return new BrowserAccessibilityManagerQt(access, initialTree, delegate);
 #else
@@ -80,7 +74,7 @@ BrowserAccessibilityManagerQt::~BrowserAccessibilityManagerQt()
 
 QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible()
 {
-    content::BrowserAccessibility *parent_node = GetParentNodeFromParentTree();
+    content::BrowserAccessibility *parent_node = GetParentNodeFromParentTreeAsBrowserAccessibility();
     if (!parent_node) {
         Q_ASSERT(m_webContentsAccessibility);
         return QAccessible::queryAccessibleInterface(m_webContentsAccessibility->accessibilityParentObject());
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index d1cdd4b2067..de3347df36d 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -10,6 +10,7 @@
 #include "qtwebenginecoreglobal_p.h"
 #include "type_conversion.h"
 
+#if QT_CONFIG(accessibility)
 #include "content/browser/accessibility/browser_accessibility.h"
 #include "ui/accessibility/ax_enums.mojom.h"
 
@@ -25,10 +26,9 @@ class BrowserAccessibilityQt
     BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager, ui::AXNode *node);
     ~BrowserAccessibilityQt();
 
-    QtWebEngineCore::BrowserAccessibilityInterface *interface() const { return m_interface; }
+    bool isReady() const;
 
-private:
-    QtWebEngineCore::BrowserAccessibilityInterface *m_interface = nullptr;
+    QtWebEngineCore::BrowserAccessibilityInterface *interface = nullptr;
 };
 
 class BrowserAccessibilityInterface
@@ -41,6 +41,7 @@ class BrowserAccessibilityInterface
 {
 public:
     BrowserAccessibilityInterface(BrowserAccessibilityQt *chromiumInterface);
+    ~BrowserAccessibilityInterface() override;
 
     void destroy();
 
@@ -133,15 +134,24 @@ class BrowserAccessibilityInterface
     BrowserAccessibilityQt *q;
 };
 
-BrowserAccessibilityQt::BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager, ui::AXNode *node)
-    : content::BrowserAccessibility(manager, node),
-      m_interface(new BrowserAccessibilityInterface(this))
+BrowserAccessibilityQt::BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager,
+                                               ui::AXNode *node)
+    : content::BrowserAccessibility(manager, node)
+    , interface(new BrowserAccessibilityInterface(this))
 {
 }
 
 BrowserAccessibilityQt::~BrowserAccessibilityQt()
 {
-    m_interface->destroy();
+    if (interface)
+        interface->destroy();
+}
+
+bool BrowserAccessibilityQt::isReady() const
+{
+    // FIXME: This is just a workaround, remove this when the commented out assert in
+    //        BrowserAccessibilityManager::GetFromID(int32_t id) gets fixed.
+    return manager()->GetFromID(node()->id()) != nullptr;
 }
 
 BrowserAccessibilityInterface::BrowserAccessibilityInterface(BrowserAccessibilityQt *chromiumInterface)
@@ -157,6 +167,11 @@ BrowserAccessibilityInterface::BrowserAccessibilityInterface(BrowserAccessibilit
     m_id = QAccessible::registerAccessibleInterface(this);
 }
 
+BrowserAccessibilityInterface::~BrowserAccessibilityInterface()
+{
+    q->interface = nullptr;
+}
+
 void BrowserAccessibilityInterface::destroy()
 {
     QAccessible::deleteAccessibleInterface(m_id);
@@ -164,6 +179,9 @@ void BrowserAccessibilityInterface::destroy()
 
 bool BrowserAccessibilityInterface::isValid() const
 {
+    if (!q->isReady())
+        return false;
+
     auto managerQt = static_cast<content::BrowserAccessibilityManagerQt *>(q->manager());
     return managerQt && managerQt->isValid();
 }
@@ -214,11 +232,7 @@ void *BrowserAccessibilityInterface::interface_cast(QAccessible::InterfaceType t
     }
     case QAccessible::TableCellInterface: {
         QAccessible::Role r = role();
-        if (r == QAccessible::Cell) {
-            Q_ASSERT(findTable());
-            return static_cast<QAccessibleTableCellInterface *>(this);
-        }
-        if (r == QAccessible::ListItem || r == QAccessible::TreeItem) {
+        if (r == QAccessible::Cell || r == QAccessible::ListItem || r == QAccessible::TreeItem) {
             if (findTable())
                 return static_cast<QAccessibleTableCellInterface *>(this);
         }
@@ -271,6 +285,9 @@ int BrowserAccessibilityInterface::indexOfChild(const QAccessibleInterface *ifac
 
 QString BrowserAccessibilityInterface::text(QAccessible::Text t) const
 {
+    if (!q->isReady())
+        return QString();
+
     switch (t) {
     case QAccessible::Name:
         return toQt(q->GetStringAttribute(ax::mojom::StringAttribute::kName));
@@ -292,7 +309,7 @@ void BrowserAccessibilityInterface::setText(QAccessible::Text t, const QString &
 
 QRect BrowserAccessibilityInterface::rect() const
 {
-    if (!q->manager()) // needed implicitly by GetScreenBoundsRect()
+    if (!q->manager() || !q->isReady()) // needed implicitly by GetScreenBoundsRect()
         return QRect();
     gfx::Rect bounds = q->GetUnclippedScreenBoundsRect();
     bounds = gfx::ScaleToRoundedRect(bounds, 1.f / q->manager()->device_scale_factor()); // FIXME: check
@@ -694,6 +711,11 @@ QAccessible::Role BrowserAccessibilityInterface::role() const
 QAccessible::State BrowserAccessibilityInterface::state() const
 {
     QAccessible::State state = QAccessible::State();
+    if (!q->isReady()) {
+        state.invalid = true;
+        return state;
+    }
+
     if (q->HasState(ax::mojom::State::kCollapsed))
         state.collapsed = true;
     if (q->HasState(ax::mojom::State::kDefault))
@@ -1130,22 +1152,31 @@ void BrowserAccessibilityInterface::modelChange(QAccessibleTableModelChangeEvent
 
 } // namespace QtWebEngineCore
 
+#endif // QT_CONFIG(accessibility)
 namespace content {
 
 // static
 std::unique_ptr<BrowserAccessibility> BrowserAccessibility::Create(BrowserAccessibilityManager *man, ui::AXNode *node)
 {
+#if QT_CONFIG(accessibility)
     return std::unique_ptr<BrowserAccessibility>(new QtWebEngineCore::BrowserAccessibilityQt(man, node));
+#else
+    Q_UNUSED(man);
+    Q_UNUSED(node);
+    return nullptr;
+#endif // #if QT_CONFIG(accessibility)
 }
 
+#if QT_CONFIG(accessibility)
 QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj)
 {
-    return static_cast<QtWebEngineCore::BrowserAccessibilityQt *>(obj)->interface();
+    return static_cast<QtWebEngineCore::BrowserAccessibilityQt *>(obj)->interface;
 }
 
 const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *obj)
 {
-    return static_cast<const QtWebEngineCore::BrowserAccessibilityQt *>(obj)->interface();
+    return static_cast<const QtWebEngineCore::BrowserAccessibilityQt *>(obj)->interface;
 }
+#endif // #if QT_CONFIG(accessibility)
 
 } // namespace content
diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h
index 45547824728..598aa3ef52d 100644
--- a/src/core/browser_accessibility_qt.h
+++ b/src/core/browser_accessibility_qt.h
@@ -4,8 +4,9 @@
 #ifndef BROWSER_ACCESSIBILITY_QT_H
 #define BROWSER_ACCESSIBILITY_QT_H
 
-#include <QtCore/qtconfigmacros.h>
+#include <QtGui/qtguiglobal.h>
 
+#if QT_CONFIG(accessibility)
 QT_FORWARD_DECLARE_CLASS(QAccessibleInterface)
 
 namespace content {
@@ -15,5 +16,6 @@ QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj);
 const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *obj);
 
 } // namespace content
+#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 e58822c29ce..9cdce0eeb6c 100644
--- a/src/core/browser_main_parts_qt.cpp
+++ b/src/core/browser_main_parts_qt.cpp
@@ -50,6 +50,7 @@
 #include "web_engine_context.h"
 #include "web_usb_detector_qt.h"
 
+#include <QDeadlineTimer>
 #include <QtGui/qtgui-config.h>
 #include <QStandardPaths>
 
@@ -61,6 +62,7 @@
 #if BUILDFLAG(IS_MAC)
 #include "base/message_loop/message_pump_mac.h"
 #include "services/device/public/cpp/geolocation/geolocation_manager.h"
+#include "services/device/public/cpp/geolocation/system_geolocation_source.h"
 #include "ui/base/idle/idle.h"
 #endif
 
@@ -120,7 +122,7 @@ class MessagePumpForUIQt : public base::MessagePump
     {
         // NOTE: This method may called from any thread at any time.
         ensureDelegate();
-        m_scheduler.scheduleWork();
+        m_scheduler.scheduleImmediateWork();
     }
 
     void ScheduleDelayedWork(const Delegate::NextWorkInfo &next_work_info) override
@@ -193,13 +195,16 @@ class MessagePumpForUIQt : public base::MessagePump
     {
         ScopedGLContextChecker glContextChecker;
 
+        QDeadlineTimer timer(std::chrono::milliseconds(2));
         base::MessagePump::Delegate::NextWorkInfo more_work_info = m_delegate->DoWork();
+        while (more_work_info.is_immediate() && !timer.hasExpired())
+            more_work_info = m_delegate->DoWork();
 
         if (more_work_info.is_immediate())
-            return ScheduleWork();
+            return m_scheduler.scheduleImmediateWork();
 
         if (m_delegate->DoIdleWork())
-            return ScheduleWork();
+            return m_scheduler.scheduleIdleWork();
 
         ScheduleDelayedWork(more_work_info.delayed_run_time);
     }
@@ -209,19 +214,20 @@ class MessagePumpForUIQt : public base::MessagePump
 };
 
 #if BUILDFLAG(IS_MAC)
-class FakeGeolocationManager : public device::GeolocationManager
+class FakeGeolocationSource : public device::SystemGeolocationSource
 {
 public:
-    FakeGeolocationManager() = default;
-    ~FakeGeolocationManager() override = default;
+    FakeGeolocationSource() = default;
+    ~FakeGeolocationSource() override = default;
 
-    // GeolocationManager implementation:
+    // SystemGeolocationSource implementation:
     void StartWatchingPosition(bool) override {}
     void StopWatchingPosition() override {}
-    device::LocationSystemPermissionStatus GetSystemPermission() const override
+    void RegisterPermissionUpdateCallback(PermissionUpdateCallback callback)
     {
-        return device::LocationSystemPermissionStatus::kDenied;
+        callback.Run(device::LocationSystemPermissionStatus::kDenied);
     }
+    void RegisterPositionUpdateCallback(PositionUpdateCallback callback) {}
 };
 #endif // BUILDFLAG(IS_MAC)
 
@@ -250,7 +256,7 @@ int BrowserMainPartsQt::PreEarlyInitialization()
 void BrowserMainPartsQt::PreCreateMainMessageLoop()
 {
 #if BUILDFLAG(IS_MAC)
-    m_geolocationManager = std::make_unique<FakeGeolocationManager>();
+    m_geolocationManager = std::make_unique<device::GeolocationManager>(std::make_unique<FakeGeolocationSource>());
 #endif
 }
 
diff --git a/src/core/browser_message_filter_qt.h b/src/core/browser_message_filter_qt.h
index 53c48eb6e65..0f5721c824f 100644
--- a/src/core/browser_message_filter_qt.h
+++ b/src/core/browser_message_filter_qt.h
@@ -4,7 +4,7 @@
 #ifndef BROWSER_MESSAGE_FILTER_QT_H
 #define BROWSER_MESSAGE_FILTER_QT_H
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "content/public/browser/browser_message_filter.h"
 
 class GURL;
diff --git a/src/core/browsing_data_remover_delegate_qt.cpp b/src/core/browsing_data_remover_delegate_qt.cpp
index bbfd902ec41..6a408598a48 100644
--- a/src/core/browsing_data_remover_delegate_qt.cpp
+++ b/src/core/browsing_data_remover_delegate_qt.cpp
@@ -3,8 +3,8 @@
 
 #include "browsing_data_remover_delegate_qt.h"
 
-#include "base/bind.h"
-#include "base/callback.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback.h"
 #include "components/web_cache/browser/web_cache_manager.h"
 #include "content/public/browser/browsing_data_remover.h"
 
diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h
index b61845e7b5f..4fb1a3c7798 100644
--- a/src/core/certificate_error_controller.h
+++ b/src/core/certificate_error_controller.h
@@ -16,8 +16,10 @@
 #define CERTIFICATE_ERROR_CONTROLLER_H
 
 #include "qtwebenginecoreglobal_p.h"
-#include "base/callback.h"
+
+#include "base/functional/callback.h"
 #include "content/public/browser/certificate_request_result_type.h"
+
 #include "qwebenginecertificateerror.h"
 #include <QtCore/QDateTime>
 #include <QtCore/QScopedPointer>
diff --git a/src/core/client_cert_select_controller.cpp b/src/core/client_cert_select_controller.cpp
index a4ce6f6dad3..d6af984c187 100644
--- a/src/core/client_cert_select_controller.cpp
+++ b/src/core/client_cert_select_controller.cpp
@@ -3,7 +3,7 @@
 
 #include "client_cert_select_controller.h"
 
-#include <base/bind.h>
+#include <base/functional/bind.h>
 #include <content/public/browser/client_certificate_delegate.h>
 #include <net/cert/x509_certificate.h>
 #include <net/ssl/client_cert_identity.h>
@@ -77,7 +77,8 @@ void ClientCertSelectController::select(const QSslCertificate &certificate)
     }
     QByteArray derCertificate = certificate.toDer();
     scoped_refptr<net::X509Certificate> selectedCert =
-            net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)derCertificate.constData(), derCertificate.length()));
+            net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)derCertificate.constData(),
+                                                                  (long unsigned)derCertificate.length()));
     for (auto &certInfo : m_clientCerts) {
         scoped_refptr<net::X509Certificate> cert = certInfo->certificate();
         if (cert->EqualsExcludingChain(selectedCert.get())) {
diff --git a/src/core/client_hints.cpp b/src/core/client_hints.cpp
index 2a30bb51b26..2fcecde58f4 100644
--- a/src/core/client_hints.cpp
+++ b/src/core/client_hints.cpp
@@ -151,7 +151,7 @@ bool ClientHints::IsJavaScriptAllowed(const GURL &url, content::RenderFrameHost
     return true;
 }
 
-bool ClientHints::AreThirdPartyCookiesBlocked(const GURL &url)
+bool ClientHints::AreThirdPartyCookiesBlocked(const GURL &url, content::RenderFrameHost *rfh)
 {
     return false; // we probably can not report anything more specific
 }
diff --git a/src/core/client_hints.h b/src/core/client_hints.h
index a80629fc9dc..193982d1600 100644
--- a/src/core/client_hints.h
+++ b/src/core/client_hints.h
@@ -58,7 +58,7 @@ class ClientHints : public KeyedService, public content::ClientHintsControllerDe
 
     bool IsJavaScriptAllowed(const GURL &url, content::RenderFrameHost *parent_rfh) override;
 
-    bool AreThirdPartyCookiesBlocked(const GURL &url) override;
+    bool AreThirdPartyCookiesBlocked(const GURL &url, content::RenderFrameHost *rfh) override;
 
     blink::UserAgentMetadata GetUserAgentMetadata() override;
 
diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp
index 009235a7228..fe56a5db167 100644
--- a/src/core/clipboard_qt.cpp
+++ b/src/core/clipboard_qt.cpp
@@ -27,6 +27,8 @@
 #include <QImageWriter>
 #include <QMimeData>
 
+#include <memory>
+
 namespace QtWebEngineCore {
 
 static void registerMetaTypes()
@@ -60,12 +62,12 @@ using namespace QtWebEngineCore;
 
 namespace {
 
-QScopedPointer<QMimeData> uncommittedData;
+std::unique_ptr<QMimeData> uncommittedData;
 QMimeData *getUncommittedData()
 {
     if (!uncommittedData)
         uncommittedData.reset(new QMimeData);
-    return uncommittedData.data();
+    return uncommittedData.get();
 }
 
 } // namespace
@@ -104,7 +106,7 @@ void ClipboardQt::WritePortableAndPlatformRepresentations(ui::ClipboardBuffer ty
 
     // Commit the accumulated data.
     if (uncommittedData)
-        QGuiApplication::clipboard()->setMimeData(uncommittedData.take(),
+        QGuiApplication::clipboard()->setMimeData(uncommittedData.release(),
                                                   type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard
                                                                                           : QClipboard::Selection);
 
diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp
index c147f988b35..4d0648e1aca 100644
--- a/src/core/compositor/compositor.cpp
+++ b/src/core/compositor/compositor.cpp
@@ -7,7 +7,6 @@
 #include "components/viz/common/surfaces/frame_sink_id.h"
 
 #include <QHash>
-#include <QImage>
 #include <QMutex>
 #include <QQuickWindow>
 
@@ -94,10 +93,8 @@ void Compositor::Observer::unbind()
 
 Compositor::Handle<Compositor> Compositor::Observer::compositor()
 {
-    if (!m_binding)
-        return nullptr;
     g_bindings.lock();
-    if (m_binding->compositor)
+    if (m_binding && m_binding->compositor)
         return m_binding->compositor; // delay unlock
     g_bindings.unlock();
     return nullptr;
@@ -128,10 +125,8 @@ void Compositor::unbind()
 
 Compositor::Handle<Compositor::Observer> Compositor::observer()
 {
-    if (!m_binding)
-        return nullptr;
     g_bindings.lock();
-    if (m_binding->observer)
+    if (m_binding && m_binding->observer)
         return m_binding->observer; // delay unlock
     g_bindings.unlock();
     return nullptr;
@@ -157,12 +152,10 @@ bool Compositor::textureIsFlipped()
     return false;
 }
 
-#if QT_CONFIG(webengine_vulkan)
-void Compositor::releaseVulkanResources(QQuickWindow *)
+void Compositor::releaseResources(QQuickWindow *)
 {
     Q_UNREACHABLE();
 }
-#endif
 
 // static
 void Compositor::unlockBindings()
diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h
index 018d965ba82..bf3e29c9182 100644
--- a/src/core/compositor/compositor.h
+++ b/src/core/compositor/compositor.h
@@ -4,7 +4,6 @@
 #ifndef COMPOSITOR_H
 #define COMPOSITOR_H
 
-#include <QtGui/qtguiglobal.h>
 #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
 
 QT_BEGIN_NAMESPACE
@@ -134,10 +133,8 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT Compositor
     // Is the texture produced upside down?
     virtual bool textureIsFlipped();
 
-#if QT_CONFIG(webengine_vulkan)
-    // (Vulkan) Release Vulkan resources created by Qt's Vulkan instance.
-    virtual void releaseVulkanResources(QQuickWindow *win);
-#endif
+    // Release resources created in texture()
+    virtual void releaseResources(QQuickWindow *win);
 
 protected:
     Compositor(Type type) : m_type(type) { }
diff --git a/src/core/compositor/content_gpu_client_qt.cpp b/src/core/compositor/content_gpu_client_qt.cpp
index d12074d2e9b..6ef8048f295 100644
--- a/src/core/compositor/content_gpu_client_qt.cpp
+++ b/src/core/compositor/content_gpu_client_qt.cpp
@@ -3,7 +3,6 @@
 
 #include "content_gpu_client_qt.h"
 #include "ozone/gl_share_context_qt.h"
-#include "web_engine_context.h"
 
 namespace QtWebEngineCore {
 
diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp
index 2baff5d2044..1ca245ff831 100644
--- a/src/core/compositor/display_overrides.cpp
+++ b/src/core/compositor/display_overrides.cpp
@@ -30,6 +30,9 @@ viz::SkiaOutputSurfaceImplOnGpu::CreateOutputDevice()
                 shared_image_representation_factory_.get(),
                 GetDidSwapBuffersCompleteCallback());
     }
+#ifdef Q_OS_MACOS
+    qFatal("macOS only supports ANGLE");
+#endif
 #if QT_CONFIG(opengl)
     return std::make_unique<QtWebEngineCore::DisplaySkiaOutputDevice>(
             context_state_,
diff --git a/src/core/compositor/display_skia_output_device.cpp b/src/core/compositor/display_skia_output_device.cpp
index 9f946219363..d46154f7e57 100644
--- a/src/core/compositor/display_skia_output_device.cpp
+++ b/src/core/compositor/display_skia_output_device.cpp
@@ -3,6 +3,7 @@
 
 #include "display_skia_output_device.h"
 
+#include "compositor_resource_fence.h"
 #include "type_conversion.h"
 
 #include "gpu/command_buffer/service/skia_utils.h"
@@ -318,7 +319,7 @@ void DisplaySkiaOutputDevice::SwapBuffers(BufferPresentedCallback feedback,
 
     {
         QMutexLocker locker(&m_mutex);
-        m_taskRunner = base::ThreadTaskRunnerHandle::Get();
+        m_taskRunner = base::SingleThreadTaskRunner::GetCurrentDefault();
         std::swap(m_middleBuffer, m_backBuffer);
         m_readyToUpdate = true;
     }
@@ -472,7 +473,7 @@ VkImageLayout DisplaySkiaOutputDevice::vkImageLayout()
     return m_frontBuffer->imageLayout();
 }
 
-void DisplaySkiaOutputDevice::releaseVulkanResources(QQuickWindow *win)
+void DisplaySkiaOutputDevice::releaseResources(QQuickWindow *win)
 {
     VkDevice *vkDevicePtr = static_cast<VkDevice *>(
             win->rendererInterface()->getResource(win, QSGRendererInterface::DeviceResource));
diff --git a/src/core/compositor/display_skia_output_device.h b/src/core/compositor/display_skia_output_device.h
index 27bee2d1df7..abe0e05e971 100644
--- a/src/core/compositor/display_skia_output_device.h
+++ b/src/core/compositor/display_skia_output_device.h
@@ -4,14 +4,18 @@
 #ifndef DISPLAY_SKIA_OUTPUT_DEVICE_H
 #define DISPLAY_SKIA_OUTPUT_DEVICE_H
 
-#include "compositor_resource_fence.h"
+#include <QtCore/QMutex>
+#include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
+
 #include "compositor.h"
 
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task/single_thread_task_runner.h"
 #include "components/viz/service/display_embedder/skia_output_device.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
 
-#include <QMutex>
+#if QT_CONFIG(webengine_vulkan)
+#include <vulkan/vulkan.h>
+#endif
 
 QT_BEGIN_NAMESPACE
 class QQuickWindow;
@@ -49,10 +53,11 @@ class DisplaySkiaOutputDevice final : public viz::SkiaOutputDevice, public Compo
     QSize size() override;
     bool requiresAlphaChannel() override;
     float devicePixelRatio() override;
+
 #if QT_CONFIG(webengine_vulkan)
     VkImage vkImage(QQuickWindow *win);
     VkImageLayout vkImageLayout();
-    void releaseVulkanResources(QQuickWindow *win) override;
+    void releaseResources(QQuickWindow *win) override;
 #endif
 
 private:
diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp
index 9d6534c28aa..c326c8cdf02 100644
--- a/src/core/compositor/display_software_output_surface.cpp
+++ b/src/core/compositor/display_software_output_surface.cpp
@@ -4,10 +4,9 @@
 #include "display_software_output_surface.h"
 
 #include "compositor.h"
-#include "render_widget_host_view_qt_delegate.h"
 #include "type_conversion.h"
 
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task/single_thread_task_runner.h"
 #include "components/viz/service/display/display.h"
 #include "components/viz/service/display/output_surface_frame.h"
 
@@ -25,7 +24,7 @@ class DisplaySoftwareOutputSurface::Device final : public viz::SoftwareOutputDev
 
     // Overridden from viz::SoftwareOutputDevice.
     void Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) override;
-    void OnSwapBuffers(SwapBuffersCallback swap_ack_callback) override;
+    void OnSwapBuffers(SwapBuffersCallback swap_ack_callback, gfx::FrameData data) override;
 
     // Overridden from Compositor.
     void swapFrame() override;
@@ -60,11 +59,11 @@ void DisplaySoftwareOutputSurface::Device::Resize(const gfx::Size &sizeInPixels,
     surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(sizeInPixels.width(), sizeInPixels.height()));
 }
 
-void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(SwapBuffersCallback swap_ack_callback)
+void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(SwapBuffersCallback swap_ack_callback, gfx::FrameData data)
 {
     { // MEMO don't hold a lock together with an 'observer', as the call from Qt's scene graph may come at the same time
         QMutexLocker locker(&m_mutex);
-        m_taskRunner = base::ThreadTaskRunnerHandle::Get();
+        m_taskRunner = base::SingleThreadTaskRunner::GetCurrentDefault();
         m_swapCompletionCallback = std::move(swap_ack_callback);
     }
 
diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp
index aa0be8c264f..3067e14a7ec 100644
--- a/src/core/compositor/native_skia_output_device.cpp
+++ b/src/core/compositor/native_skia_output_device.cpp
@@ -16,10 +16,8 @@
 #include "third_party/skia/include/core/SkSurfaceProps.h"
 #include "ui/gl/gl_fence.h"
 
-#if defined(Q_OS_MACOS)
-#include "ui/gl/gl_image_io_surface.h"
-#elif defined(Q_OS_WIN)
-#include "ui/gl/gl_image_d3d.h"
+#if defined(Q_OS_WIN)
+#include <QtCore/private/qsystemerror_p.h>
 #include <QtQuick/qsgtexture.h>
 #include <d3d11_1.h>
 #endif
@@ -145,7 +143,7 @@ class NativeSkiaOutputDevice::Buffer
         DCHECK(!m_scopedSkiaWriteAccess);
         DCHECK(!m_scopedOverlayReadAccess);
 
-        m_scopedOverlayReadAccess = m_overlayRepresentation->BeginScopedReadAccess(true);
+        m_scopedOverlayReadAccess = m_overlayRepresentation->BeginScopedReadAccess();
         DCHECK(m_scopedOverlayReadAccess);
         m_acquireFence = TakeGpuFence(m_scopedOverlayReadAccess->TakeAcquireFence());
     }
@@ -159,16 +157,28 @@ class NativeSkiaOutputDevice::Buffer
             return;
 
         m_scopedOverlayReadAccess.reset();
+    }
+
+    void freeTexture()
+    {
         if (m_textureCleanup) {
             m_textureCleanup();
             m_textureCleanup = nullptr;
         }
     }
-    gl::GLImage *glImage()
+#if defined(Q_OS_WIN)
+    absl::optional<gl::DCLayerOverlayImage> overlayImage() const
+    {
+        DCHECK(m_presentCount);
+        return m_scopedOverlayReadAccess->GetDCLayerOverlayImage();
+    }
+#elif defined(Q_OS_MACOS)
+    gfx::ScopedIOSurface ioSurface() const
     {
         DCHECK(m_presentCount);
-        return m_scopedOverlayReadAccess->gl_image();
+        return m_scopedOverlayReadAccess->GetIOSurface();
     }
+#endif
 
     void createFence()
     {
@@ -268,7 +278,7 @@ void NativeSkiaOutputDevice::SwapBuffers(BufferPresentedCallback feedback,
     {
         QMutexLocker locker(&m_mutex);
         m_backBuffer->createFence();
-        m_taskRunner = base::ThreadTaskRunnerHandle::Get();
+        m_taskRunner = base::SingleThreadTaskRunner::GetCurrentDefault();
         std::swap(m_middleBuffer, m_backBuffer);
         m_readyToUpdate = true;
     }
@@ -320,6 +330,8 @@ void NativeSkiaOutputDevice::swapFrame()
             m_readyWithTexture = true;
             m_frontBuffer->beginPresent();
         }
+        if (m_middleBuffer)
+            m_middleBuffer->freeTexture();
     }
 }
 
@@ -337,23 +349,40 @@ void NativeSkiaOutputDevice::releaseTexture()
     }
 }
 
-#ifdef Q_OS_MACOS
+void NativeSkiaOutputDevice::releaseResources(QQuickWindow *)
+{
+    if (m_frontBuffer)
+        m_frontBuffer->freeTexture();
+}
+
+#if defined(Q_OS_MACOS)
 QSGTexture *makeMetalTexture(QQuickWindow *win, IOSurfaceRef io_surface, uint io_surface_plane, int width, int height, uint32_t textureOptions);
+QSGTexture *makeCGLTexture(QQuickWindow *win, IOSurfaceRef io_surface, int width, int height, uint32_t textureOptions, uint32_t *heldTexture);
+void releaseGlTexture(uint32_t);
 
 QSGTexture *NativeSkiaOutputDevice::texture(QQuickWindow *win, uint32_t textureOptions)
 {
     if (!m_frontBuffer || !m_readyWithTexture)
         return nullptr;
-    gl::GLImageIOSurface *gl_image_iosurface = gl::GLImageIOSurface::FromGLImage(m_frontBuffer->glImage());
+    static const auto graphicsApi = QQuickWindow::graphicsApi();
+
     QSGTexture *texture = nullptr;
-    if (gl_image_iosurface) {
-        texture = makeMetalTexture(win, gl_image_iosurface->io_surface().release(), /* plane */ 0,
+    gfx::ScopedIOSurface ioSurface = m_frontBuffer->ioSurface();
+    if (graphicsApi == QSGRendererInterface::Metal) {
+        texture = makeMetalTexture(win, ioSurface.release(), /* plane */ 0,
                                    m_shape.characterization.width(), m_shape.characterization.height(),
                                    textureOptions);
-    } else {
-        qWarning() << "GLImage not an IOSURFACE";
+#if QT_CONFIG(opengl)
+    } else if (graphicsApi == QSGRendererInterface::OpenGL) {
+        uint heldTexture;
+        texture = makeCGLTexture(win, ioSurface.release(),
+                                 m_shape.characterization.width(), m_shape.characterization.height(),
+                                 textureOptions, &heldTexture);
+        m_frontBuffer->m_textureCleanup = [heldTexture]() { releaseGlTexture(heldTexture); };
+#endif
     }
-
+    if (!texture)
+        qFatal("Unknown QSG graphics backend");
     return texture;
 }
 #elif defined(Q_OS_WIN)
@@ -364,37 +393,45 @@ QSGTexture *NativeSkiaOutputDevice::texture(QQuickWindow *win, uint32_t textureO
     Q_ASSERT(QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11);
 
     QSGTexture *texture = nullptr;
-    gl::GLImageD3D *gl_image_d3d = gl::GLImageD3D::FromGLImage(m_frontBuffer->glImage());
-    if (gl_image_d3d) {
+    auto overlay_image = m_frontBuffer->overlayImage();
+    if (overlay_image) {
         // Pass texture between two D3D devices:
         HRESULT status = S_OK;
-        HANDLE sharedHandle;
-        sharedHandle = gl_image_d3d->shared_handle();
-        if (!sharedHandle) {
-            qWarning() << "No shared handle";
+        HANDLE sharedHandle = nullptr;
+        IDXGIResource1 *resource = nullptr;
+        if (!overlay_image->nv12_texture()) {
+            qWarning() << "No D3D texture";
             return nullptr;
         }
+        status = overlay_image->nv12_texture()->QueryInterface(__uuidof(IDXGIResource1), (void**)&resource);
+        Q_ASSERT(status == S_OK);
+        status = resource->CreateSharedHandle(NULL, DXGI_SHARED_RESOURCE_READ, NULL, &sharedHandle);
+        Q_ASSERT(status == S_OK);
         Q_ASSERT(sharedHandle);
 
-        HANDLE sharedHandleDup;
-        DuplicateHandle(GetCurrentProcess(), sharedHandle, GetCurrentProcess(), &sharedHandleDup, 0, FALSE, DUPLICATE_SAME_ACCESS);
-
         QSGRendererInterface *ri = win->rendererInterface();
         ID3D11Device1 *device = static_cast<ID3D11Device1 *>(ri->getResource(win, QSGRendererInterface::DeviceResource));
 
         ID3D11Texture2D *qtTexture;
-        status = device->OpenSharedResource1(sharedHandleDup, __uuidof(ID3D11Texture2D), (void**)&qtTexture);
-        Q_ASSERT(status == S_OK);
+        status = device->OpenSharedResource1(sharedHandle, __uuidof(ID3D11Texture2D), (void**)&qtTexture);
+        if (status != S_OK) {
+            qWarning("Failed to share D3D11 texture (%s). This will result in failed rendering. Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu",
+                     qPrintable(QSystemError::windowsComString(status)));
+            ::CloseHandle(sharedHandle);
+            return nullptr;
+        }
+
+        Q_ASSERT(qtTexture);
 
         QQuickWindow::CreateTextureOptions texOpts(textureOptions);
         texture = QNativeInterface::QSGD3D11Texture::fromNative(qtTexture, win, size(), texOpts);
 
-        m_frontBuffer->m_textureCleanup = [qtTexture,sharedHandleDup]() {
+        m_frontBuffer->m_textureCleanup = [qtTexture,sharedHandle]() {
             qtTexture->Release();
-            ::CloseHandle(sharedHandleDup);
+            ::CloseHandle(sharedHandle);
         };
     } else {
-        qWarning() << "GLImage is not D3D";
+        qWarning() << "No overlay image";
     }
 
     return texture;
diff --git a/src/core/compositor/native_skia_output_device.h b/src/core/compositor/native_skia_output_device.h
index 450f909b0b3..6313007e4bd 100644
--- a/src/core/compositor/native_skia_output_device.h
+++ b/src/core/compositor/native_skia_output_device.h
@@ -6,7 +6,7 @@
 
 #include "compositor.h"
 
-#include "base/threading/thread_task_runner_handle.h"
+#include "base/task/single_thread_task_runner.h"
 #include "components/viz/service/display_embedder/skia_output_device.h"
 #include "gpu/command_buffer/service/shared_context_state.h"
 
@@ -56,6 +56,7 @@ class NativeSkiaOutputDevice final : public viz::SkiaOutputDevice, public Compos
     void swapFrame() override;
     void waitForTexture() override;
     void releaseTexture() override;
+    void releaseResources(QQuickWindow *win) override;
     QSGTexture *texture(QQuickWindow *win, uint32_t textureOptions) override;
     bool textureIsFlipped() override;
     QSize size() override;
diff --git a/src/core/compositor/native_skia_output_device_mac.mm b/src/core/compositor/native_skia_output_device_mac.mm
index 51b11b13f85..beadeeb1d1c 100644
--- a/src/core/compositor/native_skia_output_device_mac.mm
+++ b/src/core/compositor/native_skia_output_device_mac.mm
@@ -1,10 +1,11 @@
 // Copyright (C) 2023 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
 
+#import <AppKit/AppKit.h>
 #import <IOSurface/IOSurface.h>
 #import <Metal/Metal.h>
 
-#include <QtCore/qtconfigmacros.h>
+#include <QtGui/qtguiglobal.h>
 
 QT_BEGIN_NAMESPACE
 class QSGTexture;
@@ -27,4 +28,11 @@
     return makeMetalTexture2(win, texture, width, height, textureOptions);
 }
 
+#if QT_CONFIG(opengl)
+CGLContextObj getCGLContext(NSOpenGLContext *context)
+{
+    return [context CGLContextObj];
+}
+#endif
+
 } // namespace
diff --git a/src/core/compositor/native_skia_output_device_mac2.mm b/src/core/compositor/native_skia_output_device_mac2.mm
index 645f26c617d..3778ee8a0ba 100644
--- a/src/core/compositor/native_skia_output_device_mac2.mm
+++ b/src/core/compositor/native_skia_output_device_mac2.mm
@@ -1,9 +1,17 @@
 // Copyright (C) 2023 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 <qquickwindow.h>
-#include <qsgrendererinterface.h>
-#include <qsgtexture.h>
+#include <QtQuick/qquickwindow.h>
+#include <QtQuick/qsgrendererinterface.h>
+#include <QtQuick/qsgtexture.h>
+
+#if QT_CONFIG(opengl)
+#include <OpenGL/OpenGL.h>
+#include <QtGui/qopenglcontext.h>
+#include <QtGui/qopenglextrafunctions.h>
+#include <QtOpenGL/qopengltextureblitter.h>
+#include <QtOpenGL/qopenglframebufferobject.h>
+#endif
 
 @class MTLDevice;
 @protocol MTLTexture;
@@ -22,4 +30,60 @@ @protocol MTLTexture;
     return QNativeInterface::QSGMetalTexture::fromNative(mtlTexture, win, {width, height}, texOpts);
 }
 
+#if QT_CONFIG(opengl)
+CGLContextObj getCGLContext(NSOpenGLContext *context);
+
+void releaseGlTexture(uint32_t glTexture)
+{
+    auto *glContext = QOpenGLContext::currentContext();
+    if (!glContext)
+        return;
+    auto glFun = glContext->functions();
+    glFun->glDeleteTextures(1, &glTexture);
+}
+
+QSGTexture *makeCGLTexture(QQuickWindow *win, IOSurfaceRef io_surface, int width, int height, uint32_t textureOptions, uint32_t *heldTexture)
+{
+    auto glContext = QOpenGLContext::currentContext();
+    auto glFun = glContext->extraFunctions();
+    auto nscontext = glContext->nativeInterface<QNativeInterface::QCocoaGLContext>()->nativeContext();
+    CGLContextObj cglContext = getCGLContext(nscontext);
+
+    win->beginExternalCommands();
+    // Bind the IO surface to a texture
+    GLuint glTexture;
+    glFun->glGenTextures(1, &glTexture);
+    glFun->glBindTexture(GL_TEXTURE_RECTANGLE_ARB, glTexture);
+    CGLTexImageIOSurface2D(cglContext, GL_TEXTURE_RECTANGLE_ARB, GL_RGBA, width, height, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, io_surface, 0);
+    glFun->glBindTexture(GL_TEXTURE_RECTANGLE_ARB, 0);
+    glFun->glViewport(0, 0, width, height);
+
+    // The bound IO surface is a weird dynamic bind, so take a snapshot of it to a normal texture
+    {
+        QOpenGLFramebufferObject fbo(width, height, GL_TEXTURE_2D);
+        auto success = fbo.bind();
+        Q_ASSERT(success);
+
+        QOpenGLTextureBlitter blitter;
+        success = blitter.create();
+        Q_ASSERT(success);
+        glFun->glDisable(GL_BLEND);
+        glFun->glDisable(GL_SCISSOR_TEST);
+        blitter.bind(GL_TEXTURE_RECTANGLE_ARB);
+        blitter.blit(glTexture, {}, QOpenGLTextureBlitter::OriginBottomLeft);
+        blitter.release();
+        blitter.destroy();
+
+        glFun->glDeleteTextures(1, &glTexture);
+        glTexture = fbo.takeTexture();
+        fbo.release();
+    }
+    win->endExternalCommands();
+
+    *heldTexture = glTexture;
+    QQuickWindow::CreateTextureOptions texOpts(textureOptions);
+    return QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, {width, height}, texOpts);
+}
+#endif
+
 } // namespace
diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in
index 86369cbbbbe..fe4f306b019 100644
--- a/src/core/configure/BUILD.root.gn.in
+++ b/src/core/configure/BUILD.root.gn.in
@@ -87,20 +87,19 @@ config("embedded_config") {
   defines = [ "QTWEBENGINE_EMBEDDED_SWITCHES=1" ]
 }
 
-config("cpp17_config") {
-  # static initialized constexpr expressions must be compiled always as c++14 or always as c++17
-  # and our qtwebengine core sources use them as c++17
+config("cpp20_config") {
+  # Chromium is build with C++20
   if (is_win) {
-    cflags_cc = [ "/std:c++17" ]
+    cflags_cc = [ "/std:c++20" ]
   } else {
-    cflags_cc = [ "-std=c++17" ]
+    cflags_cc = [ "-std=c++20" ]
   }
 }
 
 shared_library("QtWebEngineCore") {
-  rsp_types = [ "objects", "archives", "libs", "lflags"]
+  rsp_types = [ "objects", "archives", "libs", "ldir"]
   configs += [
-    ":cpp17_config",
+    ":cpp20_config",
     ":QtWebEngineCore_config",
     "//build/config:precompiled_headers"
   ]
@@ -125,6 +124,7 @@ shared_library("QtWebEngineCore") {
     "//components/gcm_driver",
     "//components/history/content/browser",
     "//components/keyed_service/content",
+    "//components/lens:buildflags",
     "//components/navigation_interception",
     "//components/network_hints/browser",
     "//components/network_hints/common:mojo_bindings",
@@ -135,6 +135,7 @@ shared_library("QtWebEngineCore") {
     "//components/web_cache/browser",
     "//components/web_cache/renderer",
     "//components/spellcheck:buildflags",
+    "//components/supervised_user/core/common:buildflags",
     "//components/profile_metrics",
     "//components/proxy_config",
     "//components/user_prefs",
@@ -225,7 +226,7 @@ source_set("qtwebengine_spellcheck_sources") {
 }
 
 source_set("devtools_sources") {
-  configs += [ ":cpp17_config" ]
+  configs += [ ":cpp20_config" ]
   deps = [
     "//components/zoom",
     "//third_party/blink/public/mojom:mojom_platform",
@@ -252,7 +253,7 @@ source_set("devtools_sources") {
 
 source_set("qtwebengine_sources") {
   configs += [
-    ":cpp17_config",
+    ":cpp20_config",
     "//skia:skia_config",
     "//third_party/boringssl:external_config",
   ]
@@ -355,20 +356,24 @@ source_set("qtwebengine_sources") {
     "//components/embedder_support/user_agent_utils.cc",
     "//components/embedder_support/user_agent_utils.h",
   ]
-  if (use_ozone && use_vaapi) {
+  if (use_vaapi_x11) {
     deps += [
       "//ui/base/x:gl",
       "//ui/gfx/linux:gpu_memory_buffer_support_x11",
     ]
     sources += [
-      "//ui/ozone/platform/wayland/gpu/wayland_gl_egl_utility.cc",
-      "//ui/ozone/platform/wayland/gpu/wayland_gl_egl_utility.h",
       "//ui/ozone/platform/x11/gl_egl_utility_x11.cc",
       "//ui/ozone/platform/x11/gl_egl_utility_x11.h",
       "//ui/ozone/platform/x11/native_pixmap_glx_binding.cc",
       "//ui/ozone/platform/x11/native_pixmap_glx_binding.h",
     ]
   }
+  if (use_vaapi) {
+    sources += [
+      "//ui/ozone/platform/wayland/gpu/wayland_gl_egl_utility.cc",
+      "//ui/ozone/platform/wayland/gpu/wayland_gl_egl_utility.h",
+    ]
+  }
   if (enable_extensions) {
     deps += [
       ":qtwebengine_extensions_features",
@@ -386,7 +391,6 @@ source_set("qtwebengine_sources") {
       "//extensions/common:core_api_provider",
       "//extensions/browser",
       "//extensions/browser/api",
-      "//extensions/browser:core_api_provider",
       "//extensions/renderer",
       "//extensions:extensions_resources",
       "//extensions/strings",
@@ -514,7 +518,7 @@ source_set("qtwebengine_sources") {
 if (is_win) {
   static_library("QtWebEngineCoreSandbox") {
     complete_static_lib = true
-    configs += [ ":cpp17_config",
+    configs += [ ":cpp20_config",
                  ":QtWebEngineCore_config",
                  "//build/config:precompiled_headers"
     ]
@@ -549,6 +553,7 @@ repack("qtwebengine_repack_resources") {
     "$root_gen_dir/chrome/net_internals_resources.pak",
     "$root_gen_dir/components/components_resources.pak",
     "$root_gen_dir/components/dev_ui_components_resources.pak",
+    "$root_gen_dir/content/attribution_internals_resources.pak",
     "$root_gen_dir/content/browser/resources/media/media_internals_resources.pak",
     "$root_gen_dir/content/browser/tracing/tracing_resources.pak",
     "$root_gen_dir/content/content_resources.pak",
@@ -558,7 +563,7 @@ repack("qtwebengine_repack_resources") {
     "$root_gen_dir/mojo/public/js/mojo_bindings_resources.pak",
     "$root_gen_dir/net/net_resources.pak",
     "$root_gen_dir/third_party/blink/public/resources/blink_resources.pak",
-    "$root_gen_dir/ui/resources/webui_generated_resources.pak",
+    "$root_gen_dir/ui/resources/webui_resources.pak",
   ]
   output = "$root_out_dir/qtwebengine_resources.pak"
   deps = [
@@ -568,6 +573,7 @@ repack("qtwebengine_repack_resources") {
      "//chrome/common:resources_grit",
      "//components/resources:components_resources_grit",
      "//components/resources:dev_ui_components_resources_grit",
+     "//content/browser/resources/attribution_reporting:resources",
      "//content/browser/resources/media:resources",
      "//content/browser/tracing:resources",
      "//content:content_resources",
@@ -577,7 +583,7 @@ repack("qtwebengine_repack_resources") {
      "//mojo/public/js:resources",
      "//net:net_resources_grit",
      "//third_party/blink/public:resources_grit",
-     "//ui/resources:webui_generated_resources_grd",
+     "//ui/resources:webui_resources_grd",
   ]
   if (enable_extensions) {
     sources += [
@@ -712,7 +718,7 @@ if (enable_extensions) {
 
 if (enable_spellcheck) {
   shared_library("convert_dict") {
-    rsp_types = [ "objects", "archives", "libs", "lflags" ]
+    rsp_types = [ "objects", "archives", "libs", "ldir" ]
     configs += [ "//build/config/compiler:wexit_time_destructors" ]
     deps = [
       "//chrome/tools/convert_dict:lib",
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index fab8a5abb0a..08db0920a94 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -30,8 +30,10 @@
 #include <QLibraryInfo>
 #include <QString>
 
+
 #if BUILDFLAG(ENABLE_LIBRARY_CDMS)
 #include "media/cdm/cdm_paths.h"  // nogncheck
+#include "media/cdm/clear_key_cdm_common.h"
 #include "third_party/widevine/cdm/buildflags.h"
 #include "third_party/widevine/cdm/widevine_cdm_common.h"
 #if BUILDFLAG(ENABLE_WIDEVINE) && !BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
@@ -61,7 +63,7 @@ static QString webenginePluginsPath()
 {
     // Look for plugins in /plugins/webengine or application dir.
     static bool initialized = false;
-    static QString potentialPluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath) % QLatin1String("/webengine");
+    static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/webengine");
     if (!initialized) {
         initialized = true;
         if (!QFileInfo::exists(potentialPluginsPath))
@@ -105,7 +107,7 @@ static QString ppapiPluginsPath()
 {
     // Look for plugins in /plugins/ppapi or application dir.
     static bool initialized = false;
-    static QString potentialPluginsPath = QLibraryInfo::location(QLibraryInfo::PluginsPath) % QLatin1String("/ppapi");
+    static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/ppapi");
     if (!initialized) {
         initialized = true;
         if (!QFileInfo::exists(potentialPluginsPath))
diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp
index 2033a296b4c..0aea6ca207f 100644
--- a/src/core/content_main_delegate_qt.cpp
+++ b/src/core/content_main_delegate_qt.cpp
@@ -14,7 +14,6 @@
 #include "content/public/browser/browser_main_runner.h"
 #include "content/public/common/content_paths.h"
 #include "content/public/common/content_switches.h"
-#include "media/gpu/buildflags.h"
 #include "ui/base/l10n/l10n_util.h"
 #include "ui/base/ui_base_paths.h"
 #include "ui/base/resource/resource_bundle.h"
@@ -39,9 +38,6 @@
 #include "ui/base/ui_base_switches.h"
 #endif
 
-// must be included before vaapi_wrapper.h
-#include <QtCore/qcoreapplication.h>
-
 #if BUILDFLAG(IS_WIN)
 #include "media/gpu/windows/dxva_video_decode_accelerator_win.h"
 #include "media/gpu/windows/media_foundation_video_encode_accelerator_win.h"
@@ -53,9 +49,7 @@
 #include "media/gpu/mac/vt_video_decode_accelerator_mac.h"
 #endif
 
-#if BUILDFLAG(USE_VAAPI)
-#include "media/gpu/vaapi/vaapi_wrapper.h"
-#endif
+#include <QtCore/qcoreapplication.h>
 
 namespace content {
 ContentClient *GetContentClient();
@@ -89,7 +83,7 @@ struct LazyDirectoryListerCacher
                 webui::GetI18nTemplateHtml(
                     ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_DIR_HEADER_HTML),
                     std::move(dict));
-        html_data = base::RefCountedString::TakeString(&html);
+        html_data = base::MakeRefCounted<base::RefCountedString>(std::move(html));
     }
 
     scoped_refptr<base::RefCountedMemory> html_data;
@@ -171,21 +165,21 @@ void ContentMainDelegateQt::PreSandboxStartup()
         setlocale(LC_NUMERIC, "C");
 #endif
 
-    // from gpu_main.cc:
-#if BUILDFLAG(USE_VAAPI)
-    media::VaapiWrapper::PreSandboxInitialization();
-#endif
+    bool isBrowserProcess = !parsedCommandLine->HasSwitch(switches::kProcessType);
+    if (isBrowserProcess) {
+        // from gpu_main.cc:
 #if BUILDFLAG(IS_WIN)
-    media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
-    media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
+        media::DXVAVideoDecodeAccelerator::PreSandboxInitialization();
+        media::MediaFoundationVideoEncodeAccelerator::PreSandboxInitialization();
 #endif
 
 #if BUILDFLAG(IS_MAC)
-    {
-        TRACE_EVENT0("gpu", "Initialize VideoToolbox");
-        media::InitializeVideoToolbox();
-    }
+        {
+            TRACE_EVENT0("gpu", "Initialize VideoToolbox");
+            media::InitializeVideoToolbox();
+        }
 #endif
+    }
 
     if (parsedCommandLine->HasSwitch(switches::kApplicationName)) {
         std::string appName = parsedCommandLine->GetSwitchValueASCII(switches::kApplicationName);
diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp
index f802c2517c5..047026826ce 100644
--- a/src/core/devtools_frontend_qt.cpp
+++ b/src/core/devtools_frontend_qt.cpp
@@ -62,7 +62,7 @@ DevToolsFrontendQt *DevToolsFrontendQt::Show(QSharedPointer<WebContentsAdapter>
             new DevToolsFrontendQt(frontendAdapter, inspectedContents);
 
     if (contents->GetURL() == GURL(GetFrontendURL())) {
-        contents->GetController().Reload(content::ReloadType::ORIGINAL_REQUEST_URL, false);
+        contents->GetController().LoadOriginalRequestURL();
     } else {
         content::NavigationController::LoadURLParams loadParams((GURL(GetFrontendURL())));
         loadParams.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_AUTO_TOPLEVEL
@@ -136,12 +136,12 @@ WebContentsDelegateQt *DevToolsFrontendQt::frontendDelegate() const
 
 void DevToolsFrontendQt::ColorPickedInEyeDropper(int r, int g, int b, int a)
 {
-    base::DictionaryValue color;
-    color.SetInteger("r", r);
-    color.SetInteger("g", g);
-    color.SetInteger("b", b);
-    color.SetInteger("a", a);
-    m_bindings->CallClientMethod("DevToolsAPI", "eyeDropperPickedColor", std::move(color));
+    base::Value::Dict color;
+    color.Set("r", r);
+    color.Set("g", g);
+    color.Set("b", b);
+    color.Set("a", a);
+    m_bindings->CallClientMethod("DevToolsAPI", "eyeDropperPickedColor", base::Value(std::move(color)));
 }
 
 // content::WebContentsObserver implementation
@@ -162,7 +162,7 @@ void DevToolsFrontendQt::ActivateWindow()
     web_contents()->Focus();
 }
 
-void DevToolsFrontendQt::InspectElementCompleted()
+void DevToolsFrontendQt::OnLoadCompleted()
 {
     m_bindings->CallClientMethod("DevToolsAPI", "setUseSoftMenu", base::Value(true));
 }
@@ -209,4 +209,9 @@ std::string DevToolsFrontendQt::GetId(content::WebContents *inspectedContents)
     return content::DevToolsAgentHost::GetOrCreateFor(inspectedContents)->GetId();
 }
 
+void DevToolsFrontendQt::CloseWindow()
+{
+    web_contents()->Close();
+}
+
 } // namespace QtWebEngineCore
diff --git a/src/core/devtools_frontend_qt.h b/src/core/devtools_frontend_qt.h
index e822fe5916d..ec7ccce838e 100644
--- a/src/core/devtools_frontend_qt.h
+++ b/src/core/devtools_frontend_qt.h
@@ -55,18 +55,18 @@ class DevToolsFrontendQt : public DevToolsUIBindings::Delegate, public content::
 
     // DevToolsUIBindings::Delegate overrides
     void ActivateWindow() override;
-    void InspectElementCompleted() override;
     void SetEyeDropperActive(bool active) override;
     void OpenInNewTab(const std::string &url) override;
     void InspectedContentsClosing() override;
+    void OnLoadCompleted() override;
 
-    void CloseWindow() override{};
+    void InspectElementCompleted() override{};
+    void CloseWindow() override;
     void Inspect(scoped_refptr<content::DevToolsAgentHost>) override{};
     void SetInspectedPageBounds(const gfx::Rect &) override{};
     void SetIsDocked(bool) override{};
     void SetWhitelistedShortcuts(const std::string &) override{};
     void OpenNodeFrontend() override{};
-    void OnLoadCompleted() override{};
     void ReadyForTest() override{};
     void ConnectionReady() override{};
     void SetOpenNewWindowForPopups(bool) override{};
diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf
index 5cbe9e5007f..d322cc285f2 100644
--- a/src/core/doc/qtwebengine.qdocconf
+++ b/src/core/doc/qtwebengine.qdocconf
@@ -31,7 +31,8 @@ qhp.QtWebEngine.subprojects.examples.selectors = doc:example
 qhp.QtWebEngine.subprojects.examples.sortPages = true
 
 manifestmeta.highlighted.names += "QtWebEngine/WebEngine Widgets Simple Browser Example" \
-                "QtWebEngine/WebEngine Quick Nano Browser"
+                "QtWebEngine/WebEngine Quick Nano Browser" \
+                "QtWebEngine/Recipe Browser"
 
 tagfile                 = ../../../doc/qtwebengine/qtwebengine.tags
 
diff --git a/src/core/doc/snippets/qtwebengine_qwebenginepage_snippet.cpp b/src/core/doc/snippets/qtwebengine_qwebenginepage_snippet.cpp
index 309ad8233a8..c362f402e3d 100644
--- a/src/core/doc/snippets/qtwebengine_qwebenginepage_snippet.cpp
+++ b/src/core/doc/snippets/qtwebengine_qwebenginepage_snippet.cpp
@@ -5,8 +5,8 @@ void wrapInFunction()
 {
 
 //! [0]
-    m_view->page()->findText(QStringLiteral("Qt"), QWebEnginePage::FindFlags(), [this](bool found) {
-        if (!found) QMessageBox::information(m_view, QString(), QStringLiteral("No occurrences found"));
+    m_view->page()->findText(QStringLiteral("Qt"), QWebEnginePage::FindFlags(), [this](const QWebEngineFindTextResult &result) {
+        if (result.numberOfMatches() == 0) QMessageBox::information(m_view, QString(), QStringLiteral("No occurrences found"));
     });
 //! [0]
 
diff --git a/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc b/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc
index ee22ea774c9..9a7370d62f2 100644
--- a/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc
+++ b/src/core/doc/snippets/qtwebenginecore_build_snippet.qdoc
@@ -7,5 +7,5 @@ QT += webenginecore
 
 //! [2]
 find_package(Qt6 REQUIRED COMPONENTS WebEngineCore)
-target_link_libraries(target PRIVATE Qt::WebEngineCore)
+target_link_libraries(target PRIVATE Qt6::WebEngineCore)
 //! [2]
diff --git a/src/core/doc/src/qtwebengine-debugging.qdoc b/src/core/doc/src/qtwebengine-debugging.qdoc
index 3bb6a702996..3dd4d9276c3 100644
--- a/src/core/doc/src/qtwebengine-debugging.qdoc
+++ b/src/core/doc/src/qtwebengine-debugging.qdoc
@@ -49,6 +49,12 @@
     interface on, so that you can access the developer tools from a remote
     device.
 
+    To avoid WebSocket errors during remote debugging, add an additional command-line
+    argument \c {--remote-allow-origins=<origin>[,<origin>, ...]}, where \c <origin> refers to the request origin.
+    Use \c {--remote-allow-origins=*} to allow connections from all origins. If nothing is specified,
+    \QWE will add \c {--remote-allow-origins=*} to command-line arguments when remote-debugging is enabled,
+    thereby allowing requests from all origins.
+
     For a detailed explanation of the capabilities of developer tools, see the
     \l {Chrome DevTools} page.
 
diff --git a/src/core/doc/src/qtwebengine-deploying.qdoc b/src/core/doc/src/qtwebengine-deploying.qdoc
index 7504965e30b..08f7a6b1c26 100644
--- a/src/core/doc/src/qtwebengine-deploying.qdoc
+++ b/src/core/doc/src/qtwebengine-deploying.qdoc
@@ -4,6 +4,7 @@
 /*!
     \page qtwebengine-deploying.html
     \title Deploying Qt WebEngine Applications
+    \ingroup explanations-webtechnologies
 
     The way to package and deploy applications varies between operating systems.
     For Windows and \macos, \l{The Windows Deployment Tool}{windeployqt} and
@@ -97,6 +98,12 @@
         \li \c icudtl.dat provides support for International Components for
             Unicode (ICU). It is the Chromium version of ICU, which is not
             needed if \QWE was configured to use the system ICU.
+        \li \c v8_context_snapshot.bin contains a previously prepared snapshot
+            of a v8 context used to speed up initialization. Debug builds use
+            separate snapshots with the file name extension \c .debug.bin instead
+            of \c .bin. On \macos, there is a snapshot for each architecture named
+            accordingly, for example \c v8_context_snapshot.arm64.bin or
+            \c v8_context_snapshot.arm64.debug.bin.
     \endlist
 
     Resources are searched from the following locations:
@@ -140,6 +147,10 @@
 
     \section2 \macos Specific Deployment Steps
 
+    To deploy a \QWE application on \maocs, you will need to ensure that the \QWE process is signed
+    with an entitlements file that at least contains the entitlements listed in
+    QtWebEngineCore.framework/Helpers/QtWebEngineProcess.app/Contents/Resources/QtWebEngineProcess.entitlements.
+
     To deploy a \QWE application that accesses the microphone or camera
     on \macos, you will need to provide texts for the messages that will be shown to the user to
     explain why the application asks for permission to access to the camera or microphone.
@@ -152,7 +163,8 @@
     <string>Your message text for camera usage.</string>
     \endcode
 
-    \sa \l{https://developer.apple.com/documentation/bundleresources/information_property_list/nscamerausagedescription} {Apple's property list file documentation}
+    See also \l{https://developer.apple.com/documentation/bundleresources/information_property_list/nscamerausagedescription}
+    {Apple's property list file documentation}.
 
     For the microphone usage message, provide a text using the following key:
     \code
@@ -160,7 +172,8 @@
     <string>Your message text for microphone usage.</string>
     \endcode
 
-    \sa \l{https://developer.apple.com/documentation/bundleresources/information_property_list/nsmicrophoneusagedescription} {Apple's property list file documentation}
+    See also \l{https://developer.apple.com/documentation/bundleresources/information_property_list/nsmicrophoneusagedescription}
+    {Apple's property list file documentation}.
 
     To notarize an application that accesses the camera or the microphone,
     you will need to add the corresponding keys to your application's entitlements file used for
@@ -172,7 +185,8 @@
     <true/>
     \endcode
 
-    \sa \l{https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_device_camera} {Apple's camera entitlement documentation}.
+    See also \l{https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_device_camera}
+    {Apple's camera entitlement documentation}.
 
     To enable access to the microphone, add:
     \code
@@ -180,5 +194,6 @@
     <true/>
     \endcode
 
-    /sa \l{https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_device_microphone} {Apple's microphone entitlement documentation}.
+    See also \l{https://developer.apple.com/documentation/bundleresources/entitlements/com_apple_security_device_microphone}
+    {Apple's microphone entitlement documentation}.
 */
diff --git a/src/core/doc/src/qtwebengine-features.qdoc b/src/core/doc/src/qtwebengine-features.qdoc
index 3d6d0fea8c7..b4befe48ea1 100644
--- a/src/core/doc/src/qtwebengine-features.qdoc
+++ b/src/core/doc/src/qtwebengine-features.qdoc
@@ -4,6 +4,7 @@
 /*!
     \page qtwebengine-features.html
     \title Qt WebEngine Features
+    \ingroup explanations-webtechnologies
 
     \brief Summarizes \QWE features.
 
@@ -82,7 +83,7 @@
 
     This feature can be tested by launching a \QWE application with the
     command line option \c {--remote-debugging-port=[your-port]} or by setting
-    the environment variable \c QTWEBENGINE_REMOTE_DEBUGGING, and then using a
+    the environment variable \c QTWEBENGINE_REMOTE_DEBUGGING and then using a
     Chromium based browser (such as \l{WebEngine Widgets Simple Browser Example}
     {Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}) to connect
     to \c {http://localhost:[your-port]}.
@@ -95,6 +96,12 @@
     --webEngineArgs --remote-debugging-port=5000
     \endcode
 
+    To avoid WebSocket errors during remote debugging, add an additional command-line argument
+    \c {--remote-allow-origins=<origin>[,<origin>, ...]}, where \c <origin> refers to the request origin.
+    Use \c {--remote-allow-origins=*} to allow connections from all origins. If nothing is specified,
+    \QWE will add \c {--remote-allow-origins=*} to command-line arguments when remote-debugging is enabled,
+    thereby allowing requests from all origins.
+
     The Chromium DevTools page can also be shown within the application. To set
     this up, you can call either QWebEnginePage::setInspectedPage() to the page
     to be inspected, which implicitly loads the DevTools into the \c this page,
diff --git a/src/core/doc/src/qtwebengine-global.qdoc b/src/core/doc/src/qtwebengine-global.qdoc
index d4bbef01ae6..8fb1f2d5e75 100644
--- a/src/core/doc/src/qtwebengine-global.qdoc
+++ b/src/core/doc/src/qtwebengine-global.qdoc
@@ -46,8 +46,8 @@
     \relates <qtwebenginecoreglobal.h>
     \since 6.6
 
-    Returns the domain of the host i.e. the effective top-level domain (eTLD)
-    plus the first domain below.
+    Returns the domain of the host, that is, the effective top-level domain
+    (eTLD) and the first domain below it, from \a url.
 
-    If the host is not a domain an empty string is returned.
+    If the host is not a domain, returns an empty string.
 */
diff --git a/src/core/doc/src/qtwebengine-overview.qdoc b/src/core/doc/src/qtwebengine-overview.qdoc
index b1e8ee3da6c..6eccc669e6a 100644
--- a/src/core/doc/src/qtwebengine-overview.qdoc
+++ b/src/core/doc/src/qtwebengine-overview.qdoc
@@ -4,6 +4,7 @@
 /*!
     \page qtwebengine-overview.html
     \title Qt WebEngine Overview
+    \ingroup explanations-webtechnologies
 
     The \QWE module provides a web browser engine that makes it easy to embed content from
     the World Wide Web into your Qt application on platforms that do not have a native web engine.
diff --git a/src/core/doc/src/qtwebengine-platform-notes.qdoc b/src/core/doc/src/qtwebengine-platform-notes.qdoc
index e005012dc4b..33bac101a08 100644
--- a/src/core/doc/src/qtwebengine-platform-notes.qdoc
+++ b/src/core/doc/src/qtwebengine-platform-notes.qdoc
@@ -34,11 +34,12 @@
     On all platforms, the following tools are required at build time:
 
     \list
+        \li C++20 compiler support
         \li CMake 3.19 or newer
         \li \l Python 3 with html5lib library
         \li Bison, Flex
         \li GPerf
-        \li Node.js version 12 or later
+        \li Node.js version 14 or later
     \endlist
 
     \section2 Windows
@@ -49,7 +50,7 @@
         \li Visual Studio 2019 or later, or clang-cl version 10 or later
         \li Active Template Library (ATL), usually included in the Visual Studio
             installation
-        \li Windows 10 SDK version 10.0.20348.0 or later
+        \li Windows 11 SDK version 10.0.22621.0 or later
     \endlist
 
     \note It is not recommended to use tools from  \c msys2 or \c cygwin to build \QWE as it may result in build errors.
@@ -197,4 +198,26 @@
     Because of a limitation in the Windows compositor, applications that show a fullscreen web
     engine view will not properly display popups or other top-level windows. The reason and
     workaround is described in \l {Fullscreen OpenGL Based Windows}.
+
+    \target windows_manifest
+    \section1 Windows Application Manifest
+    A manifest is an XML file that is read when the program starts and informs Windows how to run the program.
+    Some \QWE features may require adding a manifest file for the user application to work correctly on Windows.
+
+    The following snippets show the manifest file's structure and how to embed it into the program.
+
+    \note These code snippets are taken from the \l {WebEngine Quick Nano Browser} example.
+
+    The manifest file defines which Windows versions the application supports.
+    \l {QWebEngineProfile::} {httpUserAgent} needs this information to report the correct Windows version.
+    \quotefile ../../../../examples/webenginequick/quicknanobrowser/quicknanobrowser.exe.manifest
+
+    To embed the file into the executable, add it to the sources:
+    \quotefromfile ../../../../examples/webenginequick/quicknanobrowser/CMakeLists.txt
+    \skipto qt_add_executable
+    \dots
+    \printuntil endif
+    \dots
+
+    For more information, see the \l {https://learn.microsoft.com/en-us/windows/win32/sbscs/application-manifests} {Application manifest documentation page}.
 */
diff --git a/src/core/doc/src/qwebenginepage_lgpl.qdoc b/src/core/doc/src/qwebenginepage_lgpl.qdoc
index fe84ff76bb7..a8a31da113d 100644
--- a/src/core/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/core/doc/src/qwebenginepage_lgpl.qdoc
@@ -115,89 +115,86 @@
            should be enabled to get automatic focus.
     \value PasteAndMatchStyle Paste content from the clipboard with current style.
 
-    \value OpenLinkInThisWindow Open the current link in the current window. (Added in Qt 5.6)
-    \value OpenLinkInNewWindow Open the current link in a new window. Requires implementation of
-           \l createWindow() or \l newWindowRequested() (Added in Qt 5.6)
-    \value OpenLinkInNewTab Open the current link in a new tab. Requires implementation of
-           \l createWindow() or \l newWindowRequested(). (Added in Qt 5.6)
-    \value OpenLinkInNewBackgroundTab Open the current link in a new background tab. Requires
-           implementation of \l createWindow() or \l newWindowRequested(). (Added in Qt 5.7)
-    \value CopyLinkToClipboard Copy the current link to the clipboard. (Added in Qt 5.6)
-
-    \value CopyImageToClipboard Copy the clicked image to the clipboard. (Added in Qt 5.6)
-    \value CopyImageUrlToClipboard Copy the clicked image's URL to the clipboard. (Added in Qt 5.6)
-    \value CopyMediaUrlToClipboard Copy the hovered audio or video's URL to the clipboard. (Added in Qt 5.6)
-    \value ToggleMediaControls Toggle between showing and hiding the controls for the hovered audio
-           or video element. (Added in Qt 5.6)
-    \value ToggleMediaLoop Toggle whether the hovered audio or video should loop on completetion or
-           not. (Added in Qt 5.6)
-    \value ToggleMediaPlayPause Toggle the play/pause state of the hovered audio or video element.
-           (Added in Qt 5.6)
-    \value ToggleMediaMute Mute or unmute the hovered audio or video element. (Added in Qt 5.6)
-    \value DownloadLinkToDisk Download the current link to the disk. Requires a slot for
-           \l{QWebEngineProfile::}{downloadRequested()}. (Added in Qt 5.6)
-    \value DownloadImageToDisk Download the highlighted image to the disk. Requires a slot for
-           \l{QWebEngineProfile::}{downloadRequested()}. (Added in Qt 5.6)
-    \value DownloadMediaToDisk Download the hovered audio or video to the disk. Requires a slot for
-           \l{QWebEngineProfile::}{downloadRequested()}. (Added in Qt 5.6)
-
-    \value InspectElement Trigger any attached Web Inspector to inspect the highlighed element.
-           (Added in Qt 5.6)
-    \value ExitFullScreen Exit the fullscreen mode. (Added in Qt 5.6)
-    \value RequestClose Request to close the web page. If defined, the \c{window.onbeforeunload}
+    \value [since 5.6] OpenLinkInThisWindow Open the current link in the current window.
+    \value [since 5.6] OpenLinkInNewWindow Open the current link in a new window. Requires implementation of
+           \l createWindow() or \l newWindowRequested().
+    \value [since 5.6] OpenLinkInNewTab Open the current link in a new tab. Requires implementation of
+           \l createWindow() or \l newWindowRequested().
+    \value [since 5.7] OpenLinkInNewBackgroundTab Open the current link in a new background tab. Requires
+           implementation of \l createWindow() or \l newWindowRequested().
+    \value [since 5.6] CopyLinkToClipboard Copy the current link to the clipboard.
+
+    \value [since 5.6] CopyImageToClipboard Copy the clicked image to the clipboard.
+    \value [since 5.6] CopyImageUrlToClipboard Copy the clicked image's URL to the clipboard.
+    \value [since 5.6] CopyMediaUrlToClipboard Copy the hovered audio or video's URL to the clipboard.
+    \value [since 5.6] ToggleMediaControls Toggle between showing and hiding the controls for the hovered audio
+           or video element.
+    \value [since 5.6] ToggleMediaLoop Toggle whether the hovered audio or video should loop on completetion or
+           not.
+    \value [since 5.6] ToggleMediaPlayPause Toggle the play/pause state of the hovered audio or video element.
+    \value [since 5.6] ToggleMediaMute Mute or unmute the hovered audio or video element.
+    \value [since 5.6] DownloadLinkToDisk Download the current link to the disk. Requires a slot for
+           \l{QWebEngineProfile::}{downloadRequested()}.
+    \value [since 5.6] DownloadImageToDisk Download the highlighted image to the disk. Requires a slot for
+           \l{QWebEngineProfile::}{downloadRequested()}.
+    \value [since 5.6] DownloadMediaToDisk Download the hovered audio or video to the disk. Requires a slot for
+           \l{QWebEngineProfile::}{downloadRequested()}.
+
+    \value [since 5.6] InspectElement Trigger any attached Web Inspector to inspect the highlighed element.
+    \value [since 5.6] ExitFullScreen Exit the fullscreen mode.
+    \value [since 5.6] RequestClose Request to close the web page. If defined, the \c{window.onbeforeunload}
            handler is run, and the user can confirm or reject to close the page. If the close
-           request is confirmed, \c windowCloseRequested is emitted. (Added in Qt 5.6)
-    \value Unselect Clear the current selection. (Added in Qt 5.7)
-    \value SavePage Save the current page to disk. MHTML is the default format that is used to store
+           request is confirmed, \c windowCloseRequested is emitted.
+    \value [since 5.7] Unselect Clear the current selection.
+    \value [since 5.7] SavePage Save the current page to disk. MHTML is the default format that is used to store
            the web page on disk. Requires a slot for \l{QWebEngineProfile::}{downloadRequested()}.
-           (Added in Qt 5.7)
-    \value ViewSource Show the source of the current page in a new tab. Requires implementation of
-            \l createWindow() or \l newWindowRequested(). (Added in Qt 5.8)
+    \value [since 5.8] ViewSource Show the source of the current page in a new tab. Requires implementation of
+            \l createWindow() or \l newWindowRequested().
 
-    \value ToggleBold
+    \value [since 5.10] ToggleBold
            Toggles boldness for the selection or at the cursor position.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value ToggleItalic
+           Requires \c contenteditable="true".
+    \value [since 5.10] ToggleItalic
            Toggles italics for the selection or at the cursor position.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value ToggleUnderline
+           Requires \c contenteditable="true".
+    \value [since 5.10] ToggleUnderline
            Toggles underlining of the selection or at the cursor position.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value ToggleStrikethrough
+           Requires \c contenteditable="true".
+    \value [since 5.10] ToggleStrikethrough
            Toggles striking through the selection or at the cursor position.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
+           Requires \c contenteditable="true".
 
-    \value AlignLeft
+    \value [since 5.10] AlignLeft
            Aligns the lines containing the selection or the cursor to the left.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value AlignCenter
+           Requires \c contenteditable="true".
+    \value [since 5.10] AlignCenter
            Aligns the lines containing the selection or the cursor at the center.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value AlignRight
+           Requires \c contenteditable="true".
+    \value [since 5.10] AlignRight
            Aligns the lines containing the selection or the cursor to the right.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value AlignJustified
+           Requires \c contenteditable="true".
+    \value [since 5.10] AlignJustified
            Stretches the lines containing the selection or the cursor so that each
            line has equal width.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value Indent
+           Requires \c contenteditable="true".
+    \value [since 5.10] Indent
            Indents the lines containing the selection or the cursor.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value Outdent
+           Requires \c contenteditable="true".
+    \value [since 5.10] Outdent
            Outdents the lines containing the selection or the cursor.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
+           Requires \c contenteditable="true".
 
-    \value InsertOrderedList
+    \value [since 5.10] InsertOrderedList
            Inserts an ordered list at the current cursor position, deleting the current selection.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value InsertUnorderedList
+           Requires \c contenteditable="true".
+    \value [since 5.10] InsertUnorderedList
            Inserts an unordered list at the current cursor position,
            deleting the current selection.
-           Requires \c contenteditable="true". (Added in Qt 5.10)
-    \value ChangeTextDirectionLTR
-           Changes text direction to left-to-right in the focused input element. (Added in Qt 6.6)
-    \value ChangeTextDirectionRTL
-           Changes text direction to right-to-left in the focused input element. (Added in Qt 6.6)
+           Requires \c contenteditable="true".
+    \value [since 6.6] ChangeTextDirectionLTR
+           Changes text direction to left-to-right in the focused input element.
+    \value [since 6.6] ChangeTextDirectionRTL
+           Changes text direction to right-to-left in the focused input element.
     \omitvalue WebActionCount
 
 */
@@ -213,8 +210,8 @@
             A web browser tab.
     \value  WebDialog
             A window without decoration.
-    \value  WebBrowserBackgroundTab
-            A web browser tab without hiding the current visible WebEngineView. (Added in Qt 5.7)
+    \value [since 5.7] WebBrowserBackgroundTab
+            A web browser tab without hiding the current visible WebEngineView.
 */
 
 /*!
@@ -268,7 +265,7 @@
     \value NavigationTypeFormSubmitted The navigation request resulted from a form submission.
     \value NavigationTypeBackForward The navigation request resulted from a back or forward action.
     \value NavigationTypeReload The navigation request resulted from a reload action.
-    \value NavigationTypeRedirect The navigation request resulted from a content or server controlled redirect. This also includes automatic reloads. (Added in Qt 5.14)
+    \value [since 5.14] NavigationTypeRedirect The navigation request resulted from a content or server controlled redirect. This also includes automatic reloads.
     \value NavigationTypeOther The navigation request was triggered by other means not covered by the above.
 
     \sa acceptNavigationRequest()
@@ -293,11 +290,11 @@
     \value  MouseLock
             Mouse locking, which locks the mouse pointer to the web view and is typically used in
             games.
-    \value  DesktopVideoCapture
+    \value [since 5.10] DesktopVideoCapture
             Video output capture, that is, the capture of the user's display,
-            for screen sharing purposes for example. (Added in Qt 5.10)
-    \value  DesktopAudioVideoCapture
-            Both audio and video output capture. (Added in Qt 5.10)
+            for screen sharing purposes for example.
+    \value [since 5.10] DesktopAudioVideoCapture
+            Both audio and video output capture.
 
     \sa featurePermissionRequested(), featurePermissionRequestCanceled(), setFeaturePermission(), PermissionPolicy
 
@@ -455,6 +452,9 @@
     The action is owned by the QWebEnginePage but you can customize the look by
     changing its properties.
 
+    \l{QWebEnginePage::action(WebAction action)} does not have a default styled icon.
+    Use \l{QWebEngineView::pageAction()} to have an action with a default styled icon.
+
     QWebEnginePage also takes care of implementing the action, so that upon
     triggering the corresponding action is performed on the page.
 
@@ -710,6 +710,7 @@
     is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}.
 
     External objects referenced in the content are located relative to \a baseUrl.
+    For external objects with relative URLs to be loaded, \c baseUrl cannot be empty.
 
     The \a data is loaded immediately; external objects are loaded asynchronously.
 
diff --git a/src/core/doc/src/qwebenginesettings_lgpl.qdoc b/src/core/doc/src/qwebenginesettings_lgpl.qdoc
index 3fdce3ea925..d98cef8c9d9 100644
--- a/src/core/doc/src/qwebenginesettings_lgpl.qdoc
+++ b/src/core/doc/src/qwebenginesettings_lgpl.qdoc
@@ -15,8 +15,8 @@
     \inmodule QtWebEngineCore
 
     QWebEngineSettings allows configuration of browser properties, such as font sizes and
-    families, the location of a custom style sheet, and generic attributes, such as JavaScript
-    support. Individual attributes are set using the setAttribute() function. The
+    families, and generic attributes, such as JavaScript support.
+    Individual attributes are set using the setAttribute() function. The
     \l{QWebEngineSettings::WebAttribute}{WebAttribute} enum further describes each attribute.
 
     Each QWebEnginePage object has its own QWebEngineSettings object, which configures the
@@ -168,9 +168,10 @@
     \value NavigateOnDropEnabled Specifies that navigations can be triggered by dropping URLs on
            the view.
            Enabled by default. (Added in Qt 6.4)
-    \value DisableReadingFromCanvas Specifies that reading from all canvas elements will be disabled.
-           This setting will have impact on all HTML5 canvas elements irrespective of origin.
-           Disabled by default. (Added in Qt 6.6)
+    \value ReadingFromCanvasEnabled Specifies that reading from all canvas elements is enabled.
+           This setting will have impact on all HTML5 canvas elements irrespective of origin, and can be disabled
+           to prevent canvas fingerprinting.
+           Enabled by default. (Added in Qt 6.6)
 */
 
 /*!
diff --git a/src/core/doc/src/qwebengineurlresponseinterceptor.qdoc b/src/core/doc/src/qwebengineurlresponseinterceptor.qdoc
deleted file mode 100644
index cbbd88bcfdd..00000000000
--- a/src/core/doc/src/qwebengineurlresponseinterceptor.qdoc
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2023 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
-
-/*!
-    \class QWebEngineUrlResponseInterceptor
-    \since 6.6
-    \brief The QWebEngineUrlResponseInterceptor class provides an abstract base class for
-           URL response interception.
-
-    \inmodule QtWebEngineCore
-
-    Implementing the \l{QWebEngineUrlResponseInterceptor} interface and installing the
-    interceptor on the profile or the page enables intercepting, blocking, and modifying
-    URL responses right as they come off the networking stack. Currently, only the response
-    headers can be accessed and modified.
-
-    You can install the interceptor on a profile via
-    QWebEngineProfile::setUrlResponseInterceptor() or
-    QQuickWebEngineProfile::setUrlResponseInterceptor() and on a page via
-    QWebEnginePage::setUrlResponseInterceptor().
-
-    \sa QWebEngineUrlResponseInterceptor::interceptResponseHeaders(),
-        QWebEngineProfile::setUrlResponseInterceptor(),
-        QQuickWebEngineProfile::setUrlResponseInterceptor(),
-        QWebEnginePage::setUrlResponseInterceptor()
-*/
-
-/*!
-    \fn QWebEngineUrlResponseInterceptor::QWebEngineUrlResponseInterceptor(QObject *p = nullptr)
-
-    Creates a new response interceptor object with \a p as parent.
-*/
-
-/*!
-    \fn void QWebEngineUrlResponseInterceptor::interceptResponseHeaders(
-        QWebEngineUrlResponseInfo &info)
-
-    Reimplement this virtual function to intercept URL
-    response headers. This method stalls the URL load until handled.
-
-    \a info contains the request and response data. Call
-    info.setResponseHeaders() to modify the response headers.
-
-    \sa QWebEngineUrlResponseInfo
-*/
diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp
index 2838b59ff23..c0fd0d3eeed 100644
--- a/src/core/download_manager_delegate_qt.cpp
+++ b/src/core/download_manager_delegate_qt.cpp
@@ -59,10 +59,13 @@ void DownloadManagerDelegateQt::cancelDownload(content::DownloadTargetCallback c
                             download::DownloadInterruptReason::DOWNLOAD_INTERRUPT_REASON_USER_CANCELED);
 }
 
-void DownloadManagerDelegateQt::cancelDownload(quint32 downloadId)
+bool DownloadManagerDelegateQt::cancelDownload(quint32 downloadId)
 {
-    if (download::DownloadItem *download = findDownloadById(downloadId))
+    if (download::DownloadItem *download = findDownloadById(downloadId)) {
         download->Cancel(/* user_cancel */ true);
+        return true;
+    }
+    return false;
 }
 
 void DownloadManagerDelegateQt::pauseDownload(quint32 downloadId)
@@ -102,9 +105,37 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *
         return true;
     }
 
-    QString suggestedFilename = toQt(item->GetSuggestedFilename());
+    bool acceptedByDefault = false;
+    QString suggestedFilePath;
+    QString suggestedFilename;
+    bool isSavePageDownload = false;
+    WebContentsAdapterClient *adapterClient = nullptr;
+    if (content::WebContents *webContents = content::DownloadItemUtils::GetWebContents(item)) {
+        WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate());
+        adapterClient = contentsDelegate->adapterClient();
+        if (SavePageInfo *spi = contentsDelegate->savePageInfo()) {
+            // We end up here when saving non text-based files (MHTML, PDF or images)
+            suggestedFilePath = spi->requestedFilePath;
+            const QFileInfo fileInfo(suggestedFilePath);
+            if (fileInfo.isRelative()) {
+                const QDir downloadDir(m_profileAdapter->downloadPath());
+                suggestedFilePath = downloadDir.absoluteFilePath(suggestedFilePath);
+            }
+            suggestedFilename = fileInfo.fileName();
+
+            if (!suggestedFilePath.isEmpty() && !suggestedFilename.isEmpty())
+                acceptedByDefault = true;
+            isSavePageDownload = true;
+
+            // Clear the delegate's SavePageInfo. It's only valid for the page currently being saved.
+            contentsDelegate->setSavePageInfo(nullptr);
+        }
+    }
+
     QString mimeTypeString = toQt(item->GetMimeType());
 
+    if (suggestedFilename.isEmpty())
+        suggestedFilename = toQt(item->GetSuggestedFilename());
 
     if (suggestedFilename.isEmpty())
         suggestedFilename = toQt(net::HttpContentDisposition(item->GetContentDisposition(), net::kCharsetLatin1).filename());
@@ -127,16 +158,12 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *
 
     QDir defaultDownloadDirectory(m_profileAdapter->downloadPath());
 
-    QString suggestedFilePath = m_profileAdapter->determineDownloadPath(defaultDownloadDirectory.absolutePath(), suggestedFilename, item->GetStartTime().ToTimeT());
+    if (suggestedFilePath.isEmpty())
+        suggestedFilePath = m_profileAdapter->determineDownloadPath(defaultDownloadDirectory.absolutePath(), suggestedFilename, item->GetStartTime().ToTimeT());
 
     item->AddObserver(this);
     QList<ProfileAdapterClient*> clients = m_profileAdapter->clients();
     if (!clients.isEmpty()) {
-        content::WebContents *webContents = content::DownloadItemUtils::GetWebContents(item);
-        WebContentsAdapterClient *adapterClient = nullptr;
-        if (webContents)
-            adapterClient = static_cast<WebContentsDelegateQt *>(webContents->GetDelegate())->adapterClient();
-
         Q_ASSERT(m_currentId == item->GetId());
         ProfileAdapterClient::DownloadItemInfo info = {
             item->GetId(),
@@ -147,10 +174,10 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *
             mimeTypeString,
             suggestedFilePath,
             ProfileAdapterClient::UnknownSavePageFormat,
-            false /* accepted */,
+            acceptedByDefault,
             false /* paused */,
             false /* done */,
-            false /* isSavePageDownload */,
+            isSavePageDownload,
             item->GetLastReason(),
             adapterClient,
             suggestedFilename,
@@ -220,12 +247,18 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
     if (clients.isEmpty())
         return;
 
+    bool acceptedByDefault = false;
+    QString suggestedFilePath;
+    ProfileAdapterClient::SavePageFormat suggestedSaveFormat = ProfileAdapterClient::UnknownSavePageFormat;
     WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt *>(
             web_contents->GetDelegate());
-    const SavePageInfo &spi = contentsDelegate->savePageInfo();
+    if (SavePageInfo *spi = contentsDelegate->savePageInfo()) {
+        suggestedFilePath = spi->requestedFilePath;
+        suggestedSaveFormat = static_cast<ProfileAdapterClient::SavePageFormat>(spi->requestedFormat);
+        // Clear the delegate's SavePageInfo. It's only valid for the page currently being saved.
+        contentsDelegate->setSavePageInfo(nullptr);
+    }
 
-    bool acceptedByDefault = false;
-    QString suggestedFilePath = spi.requestedFilePath;
     if (suggestedFilePath.isEmpty()) {
         suggestedFilePath = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName()
                 + QStringLiteral(".mhtml");
@@ -237,14 +270,9 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content
         suggestedFilePath = downloadDir.absoluteFilePath(suggestedFilePath);
     }
 
-    ProfileAdapterClient::SavePageFormat suggestedSaveFormat
-            = static_cast<ProfileAdapterClient::SavePageFormat>(spi.requestedFormat);
     if (suggestedSaveFormat == ProfileAdapterClient::UnknownSavePageFormat)
         suggestedSaveFormat = ProfileAdapterClient::MimeHtmlSaveFormat;
 
-    // Clear the delegate's SavePageInfo. It's only valid for the page currently being saved.
-    contentsDelegate->setSavePageInfo(SavePageInfo());
-
     WebContentsAdapterClient *adapterClient = nullptr;
     if (web_contents)
         adapterClient = static_cast<WebContentsDelegateQt *>(web_contents->GetDelegate())->adapterClient();
diff --git a/src/core/download_manager_delegate_qt.h b/src/core/download_manager_delegate_qt.h
index f807301d10b..cc6d49764f6 100644
--- a/src/core/download_manager_delegate_qt.h
+++ b/src/core/download_manager_delegate_qt.h
@@ -46,7 +46,7 @@ class DownloadManagerDelegateQt
                         bool can_save_as_complete,
                         content::SavePackagePathPickedCallback callback) override;
 
-    void cancelDownload(quint32 downloadId);
+    bool cancelDownload(quint32 downloadId);
     void pauseDownload(quint32 downloadId);
     void resumeDownload(quint32 downloadId);
     void removeDownload(quint32 downloadId);
diff --git a/src/core/extensions/extension_host_delegate_qt.cpp b/src/core/extensions/extension_host_delegate_qt.cpp
index 6cc268e75cf..067ec3d9d35 100644
--- a/src/core/extensions/extension_host_delegate_qt.cpp
+++ b/src/core/extensions/extension_host_delegate_qt.cpp
@@ -33,13 +33,13 @@ content::JavaScriptDialogManager *ExtensionHostDelegateQt::GetJavaScriptDialogMa
 void ExtensionHostDelegateQt::CreateTab(std::unique_ptr<content::WebContents> web_contents,
                                         const std::string &extension_id,
                                         WindowOpenDisposition disposition,
-                                        const gfx::Rect &initial_rect,
+                                        const blink::mojom::WindowFeatures &features,
                                         bool user_gesture)
 {
     Q_UNUSED(web_contents);
     Q_UNUSED(extension_id);
     Q_UNUSED(disposition);
-    Q_UNUSED(initial_rect);
+    Q_UNUSED(features);
     Q_UNUSED(user_gesture);
 
     Q_UNREACHABLE();
diff --git a/src/core/extensions/extension_host_delegate_qt.h b/src/core/extensions/extension_host_delegate_qt.h
index e5577b3fd40..1c2688933ea 100644
--- a/src/core/extensions/extension_host_delegate_qt.h
+++ b/src/core/extensions/extension_host_delegate_qt.h
@@ -20,7 +20,7 @@ class ExtensionHostDelegateQt : public ExtensionHostDelegate
     void CreateTab(std::unique_ptr<content::WebContents> web_contents,
                    const std::string &extension_id,
                    WindowOpenDisposition disposition,
-                   const gfx::Rect &initial_rect,
+                   const blink::mojom::WindowFeatures &features,
                    bool user_gesture) override;
     void ProcessMediaAccessRequest(content::WebContents *web_contents,
                                    const content::MediaStreamRequest &request,
diff --git a/src/core/extensions/extension_system_qt.cpp b/src/core/extensions/extension_system_qt.cpp
index 0f44b8db332..d55d7d03680 100644
--- a/src/core/extensions/extension_system_qt.cpp
+++ b/src/core/extensions/extension_system_qt.cpp
@@ -11,7 +11,7 @@
 
 #include "base/base_paths.h"
 #include "base/base_switches.h"
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/files/file_util.h"
@@ -69,28 +69,28 @@ namespace extensions {
 
 namespace {
 
-std::string GenerateId(const base::DictionaryValue *manifest, const base::FilePath &path)
+std::string GenerateId(const base::Value::Dict &manifest, const base::FilePath &path)
 {
-    std::string raw_key;
+    const std::string *raw_key;
     std::string id_input;
-    CHECK(manifest->GetString(manifest_keys::kPublicKey, &raw_key));
-    CHECK(Extension::ParsePEMKeyBytes(raw_key, &id_input));
+    CHECK(raw_key = manifest.FindString(manifest_keys::kPublicKey));
+    CHECK(Extension::ParsePEMKeyBytes(*raw_key, &id_input));
     std::string id = crx_file::id_util::GenerateId(id_input);
     return id;
 }
 
 // Implementation based on ComponentLoader::ParseManifest.
-std::unique_ptr<base::DictionaryValue> ParseManifest(const std::string &manifest_contents)
+absl::optional<base::Value::Dict> ParseManifest(base::StringPiece manifest_contents)
 {
     JSONStringValueDeserializer deserializer(manifest_contents);
-    std::unique_ptr<base::Value> manifest(deserializer.Deserialize(NULL, NULL));
+    std::unique_ptr<base::Value> manifest = deserializer.Deserialize(nullptr, nullptr);
 
     if (!manifest.get() || !manifest->is_dict()) {
         LOG(ERROR) << "Failed to parse extension manifest.";
-        return NULL;
+        return absl::nullopt;
     }
-    // Transfer ownership to the caller.
-    return base::DictionaryValue::From(std::move(manifest));
+
+    return std::move(*manifest).TakeDict();
 }
 
 } // namespace
@@ -129,14 +129,15 @@ class ContentVerifierDelegateQt : public ContentVerifierDelegate
     void Shutdown() override {}
 };
 
-void ExtensionSystemQt::LoadExtension(std::string extension_id, std::unique_ptr<base::DictionaryValue> manifest, const base::FilePath &directory)
+void ExtensionSystemQt::LoadExtension(std::string extension_id, const base::Value::Dict &manifest, const base::FilePath &directory)
 {
     int flags = Extension::REQUIRE_KEY;
     std::string error;
+
     scoped_refptr<const Extension> extension = Extension::Create(
             directory,
             mojom::ManifestLocation::kComponent,
-            *manifest,
+            manifest,
             flags,
             &error);
     if (!extension.get())
@@ -191,8 +192,10 @@ void ExtensionSystemQt::NotifyExtensionLoaded(const Extension *extension)
 #if BUILDFLAG(ENABLE_PLUGINS)
     // Register plugins included with the extension.
     // Implementation based on PluginManager::OnExtensionLoaded.
+    bool plugins_changed = false;
     const MimeTypesHandler *handler = MimeTypesHandler::GetHandler(extension);
     if (handler && handler->HasPlugin()) {
+        plugins_changed = true;
         content::WebPluginInfo info;
         info.type = content::WebPluginInfo::PLUGIN_TYPE_BROWSER_PLUGIN;
         info.name = base::UTF8ToUTF16(extension->name());
@@ -214,6 +217,8 @@ void ExtensionSystemQt::NotifyExtensionLoaded(const Extension *extension)
         plugin_service->RefreshPlugins();
         plugin_service->RegisterInternalPlugin(info, true);
     }
+    if (plugins_changed)
+      content::PluginService::GetInstance()->PurgePluginListCache(browser_context_, false);
 #endif // BUILDFLAG(ENABLE_PLUGINS)
 }
 
@@ -331,24 +336,26 @@ void ExtensionSystemQt::Init(bool extensions_enabled)
             std::string pdf_manifest = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_PDF_MANIFEST);
             base::ReplaceFirstSubstringAfterOffset(&pdf_manifest, 0, "<NAME>", "chromium-pdf");
 
-            std::unique_ptr<base::DictionaryValue> pdfManifestDict = ParseManifest(pdf_manifest);
+            auto pdfManifestDict = ParseManifest(pdf_manifest);
+            CHECK(pdfManifestDict);
             base::FilePath path;
             base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &path);
             path = path.Append(base::FilePath(FILE_PATH_LITERAL("pdf")));
-            std::string id = GenerateId(pdfManifestDict.get(), path);
-            LoadExtension(id, std::move(pdfManifestDict), path);
+            std::string id = GenerateId(pdfManifestDict.value(), path);
+            LoadExtension(id, pdfManifestDict.value(), path);
         }
 #endif // BUILDFLAG(ENABLE_PDF)
 
 #if BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION)
         {
             std::string hangout_manifest = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(IDR_HANGOUT_SERVICES_MANIFEST);
-            std::unique_ptr<base::DictionaryValue> hangoutManifestDict = ParseManifest(hangout_manifest);
+            auto hangoutManifestDict = ParseManifest(hangout_manifest);
+            CHECK(hangoutManifestDict);
             base::FilePath path;
             base::PathService::Get(base::DIR_QT_LIBRARY_DATA, &path);
             path = path.Append(base::FilePath(FILE_PATH_LITERAL("hangout_services")));
-            std::string id = GenerateId(hangoutManifestDict.get(), path);
-            LoadExtension(id, std::move(hangoutManifestDict), path);
+            std::string id = GenerateId(hangoutManifestDict.value(), path);
+            LoadExtension(id, hangoutManifestDict.value(), path);
         }
 #endif // BUILDFLAG(ENABLE_HANGOUT_SERVICES_EXTENSION)
     }
diff --git a/src/core/extensions/extension_system_qt.h b/src/core/extensions/extension_system_qt.h
index 02fbaee371c..87e740820da 100644
--- a/src/core/extensions/extension_system_qt.h
+++ b/src/core/extensions/extension_system_qt.h
@@ -83,7 +83,7 @@ class ExtensionSystemQt : public ExtensionSystem
     void OnExtensionRegisteredWithRequestContexts(scoped_refptr<const extensions::Extension> extension);
 
     void NotifyExtensionLoaded(const Extension *extension);
-    void LoadExtension(std::string extension_id, std::unique_ptr<base::DictionaryValue> manifest, const base::FilePath &directory);
+    void LoadExtension(std::string extension_id, const base::Value::Dict &manifest, const base::FilePath &directory);
     // The services that are shared between normal and incognito profiles.
 
     // Data to be accessed on the IO thread. Must outlive process_manager_.
diff --git a/src/core/extensions/extensions_api_client_qt.cpp b/src/core/extensions/extensions_api_client_qt.cpp
index 3d86c65f775..60536888075 100644
--- a/src/core/extensions/extensions_api_client_qt.cpp
+++ b/src/core/extensions/extensions_api_client_qt.cpp
@@ -7,6 +7,7 @@
 // found in the LICENSE file.
 
 #include "extensions_api_client_qt.h"
+#include "file_system_delegate_qt.h"
 #include "messaging_delegate_qt.h"
 
 #include <memory>
@@ -20,6 +21,7 @@
 
 #if BUILDFLAG(ENABLE_PDF)
 #include "components/pdf/browser/pdf_web_contents_helper.h"
+#include "printing/pdf_web_contents_helper_client_qt.h"
 #endif
 
 #if BUILDFLAG(ENABLE_PRINTING) && BUILDFLAG(ENABLE_PRINT_PREVIEW)
@@ -39,6 +41,13 @@ AppViewGuestDelegate *ExtensionsAPIClientQt::CreateAppViewGuestDelegate() const
     return nullptr;
 }
 
+FileSystemDelegate *ExtensionsAPIClientQt::GetFileSystemDelegate()
+{
+    if (!m_fileSystemDelegate)
+        m_fileSystemDelegate = std::make_unique<FileSystemDelegateQt>();
+    return m_fileSystemDelegate.get();
+}
+
 std::unique_ptr<guest_view::GuestViewManagerDelegate> ExtensionsAPIClientQt::CreateGuestViewManagerDelegate(content::BrowserContext *context) const
 {
     return std::make_unique<extensions::ExtensionsGuestViewManagerDelegate>(context);
@@ -56,6 +65,10 @@ void ExtensionsAPIClientQt::AttachWebContentsHelpers(content::WebContents *web_c
     QtWebEngineCore::PrintViewManagerQt::CreateForWebContents(web_contents);
 #endif
     ExtensionWebContentsObserverQt::CreateForWebContents(web_contents);
+
+#if BUILDFLAG(ENABLE_PDF)
+    pdf::PDFWebContentsHelper::CreateForWebContentsWithClient(web_contents, std::make_unique<PDFWebContentsHelperClientQt>());
+#endif
 }
 
 MessagingDelegate *ExtensionsAPIClientQt::GetMessagingDelegate()
diff --git a/src/core/extensions/extensions_api_client_qt.h b/src/core/extensions/extensions_api_client_qt.h
index 7eb74b96c2b..334917a4399 100644
--- a/src/core/extensions/extensions_api_client_qt.h
+++ b/src/core/extensions/extensions_api_client_qt.h
@@ -13,6 +13,7 @@
 
 namespace extensions {
 
+class FileSystemDelegate;
 class MessagingDelegate;
 
 class ExtensionsAPIClientQt : public ExtensionsAPIClient
@@ -22,6 +23,7 @@ class ExtensionsAPIClientQt : public ExtensionsAPIClient
 
     // ExtensionsAPIClient implementation.
     AppViewGuestDelegate *CreateAppViewGuestDelegate() const override;
+    FileSystemDelegate *GetFileSystemDelegate() override;
     std::unique_ptr<guest_view::GuestViewManagerDelegate>
     CreateGuestViewManagerDelegate(content::BrowserContext *context) const override;
     std::unique_ptr<MimeHandlerViewGuestDelegate>
@@ -30,6 +32,7 @@ class ExtensionsAPIClientQt : public ExtensionsAPIClient
     MessagingDelegate *GetMessagingDelegate() override;
 
 private:
+    std::unique_ptr<FileSystemDelegate> m_fileSystemDelegate;
     std::unique_ptr<MessagingDelegate> m_messagingDelegate;
 };
 
diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp
index ab44c23ebbb..54610586610 100644
--- a/src/core/extensions/extensions_browser_client_qt.cpp
+++ b/src/core/extensions/extensions_browser_client_qt.cpp
@@ -19,9 +19,9 @@
 #include "chrome/browser/profiles/profile.h"
 #include "content/public/browser/browser_context.h"
 #include "content/public/browser/render_frame_host.h"
+#include "extensions/browser/api/core_extensions_browser_api_provider.h"
 #include "extensions/browser/api/extensions_api_client.h"
 #include "extensions/browser/api/runtime/runtime_api_delegate.h"
-#include "extensions/browser/core_extensions_browser_api_provider.h"
 #include "extensions/browser/event_router.h"
 #include "extensions/browser/extension_host_delegate.h"
 #include "extensions/browser/extension_protocols.h"
@@ -79,7 +79,7 @@ scoped_refptr<base::RefCountedMemory> GetResource(int resource_id, const std::st
         base::StringPiece input(reinterpret_cast<const char *>(bytes->front()), bytes->size());
         std::string temp_str = ui::ReplaceTemplateExpressions(input, *replacements);
         DCHECK(!temp_str.empty());
-        return base::RefCountedString::TakeString(&temp_str);
+        return base::MakeRefCounted<base::RefCountedString>(std::move(temp_str));
     }
     return bytes;
 }
diff --git a/src/core/extensions/file_system_delegate_qt.cpp b/src/core/extensions/file_system_delegate_qt.cpp
new file mode 100644
index 00000000000..7c1c5bbd843
--- /dev/null
+++ b/src/core/extensions/file_system_delegate_qt.cpp
@@ -0,0 +1,146 @@
+// Copyright (C) 2023 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 "file_system_delegate_qt.h"
+
+#include "select_file_dialog_factory_qt.h"
+#include "type_conversion.h"
+
+#include "base/files/file_path.h"
+#include "base/files/file_path.h"
+#include "base/functional/callback.h"
+#include "base/functional/callback.h"
+#include "base/memory/ref_counted.h"
+#include "content/public/browser/web_contents.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/browser/api/file_system/file_system_delegate.h"
+#include "extensions/browser/extension_function.h"
+#include "ui/shell_dialogs/selected_file_info.h"
+
+#include <QStandardPaths>
+
+namespace extensions {
+
+FileEntryPickerQt::FileEntryPickerQt(
+        content::WebContents *web_contents,
+        const base::FilePath &suggested_name,
+        const ui::SelectFileDialog::FileTypeInfo *file_type_info,
+        ui::SelectFileDialog::Type picker_type,
+        FileSystemDelegate::FilesSelectedCallback files_selected_callback,
+        base::OnceClosure file_selection_canceled_callback)
+    : m_filesSelectedCallback(std::move(files_selected_callback))
+    , m_fileSelectionCanceledCallback(std::move(file_selection_canceled_callback))
+{
+    const GURL caller = web_contents->GetPrimaryMainFrame()->GetLastCommittedURL();
+    m_selectFileDialog = ui::SelectFileDialog::Create(
+        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);
+}
+
+FileEntryPickerQt::~FileEntryPickerQt() = default;
+
+void FileEntryPickerQt::FileSelected(const base::FilePath &path,
+        int index,
+        void *params)
+{
+    MultiFilesSelected({path}, params);
+}
+
+void FileEntryPickerQt::FileSelectedWithExtraInfo(const ui::SelectedFileInfo& file,
+        int index,
+        void *params)
+{
+    FileSelected(file.file_path, index, params);
+}
+
+void FileEntryPickerQt::MultiFilesSelected(const std::vector<base::FilePath>& files,
+                      void* params)
+{
+    Q_UNUSED(params);
+    std::move(m_filesSelectedCallback).Run(files);
+    delete this;
+}
+
+void FileEntryPickerQt::MultiFilesSelectedWithExtraInfo(
+        const std::vector<ui::SelectedFileInfo> &files,
+        void *params)
+{
+    std::vector<base::FilePath> paths;
+    for (const auto& file : files)
+        paths.push_back(file.file_path);
+    MultiFilesSelected(paths, params);
+}
+
+void FileEntryPickerQt::FileSelectionCanceled(void *params)
+{
+    std::move(m_fileSelectionCanceledCallback).Run();
+    delete this;
+}
+
+FileSystemDelegateQt::FileSystemDelegateQt()
+{
+}
+
+base::FilePath FileSystemDelegateQt::GetDefaultDirectory()
+{
+    return QtWebEngineCore::toFilePath(
+        QStandardPaths::writableLocation(QStandardPaths::DocumentsLocation));
+}
+
+base::FilePath FileSystemDelegateQt::GetManagedSaveAsDirectory(
+        content::BrowserContext *browser_context,
+        const Extension &extension)
+{
+    Q_UNUSED(browser_context);
+    Q_UNUSED(extension);
+    return base::FilePath();
+}
+
+bool FileSystemDelegateQt::ShowSelectFileDialog(
+        scoped_refptr<ExtensionFunction> extension_function,
+        ui::SelectFileDialog::Type type,
+        const base::FilePath &default_path,
+        const ui::SelectFileDialog::FileTypeInfo *file_type_info,
+        FileSystemDelegate::FilesSelectedCallback files_selected_callback,
+        base::OnceClosure file_selection_canceled_callback)
+{
+    content::WebContents *web_contents = extension_function->GetSenderWebContents();
+    if (!web_contents)
+        return false;
+
+    new FileEntryPickerQt(web_contents, default_path, file_type_info, type,
+            std::move(files_selected_callback),
+            std::move(file_selection_canceled_callback));
+    return true;
+}
+
+void FileSystemDelegateQt::ConfirmSensitiveDirectoryAccess(
+        bool has_write_permission,
+        const std::u16string &app_name,
+        content::WebContents *web_contents,
+        base::OnceClosure on_accept,
+        base::OnceClosure on_cancel)
+{
+    Q_UNUSED(has_write_permission);
+    Q_UNUSED(app_name);
+    Q_UNUSED(web_contents);
+    Q_UNUSED(on_accept);
+    std::move(on_cancel).Run();
+}
+
+int FileSystemDelegateQt::GetDescriptionIdForAcceptType(const std::string &accept_type)
+{
+    Q_UNUSED(accept_type);
+    return 0;
+}
+
+SavedFilesServiceInterface *FileSystemDelegateQt::GetSavedFilesService(
+        content::BrowserContext *browser_context)
+{
+    Q_UNUSED(browser_context);
+    return nullptr;
+}
+
+} // namespace extensions
diff --git a/src/core/extensions/file_system_delegate_qt.h b/src/core/extensions/file_system_delegate_qt.h
new file mode 100644
index 00000000000..1e9d87c38fa
--- /dev/null
+++ b/src/core/extensions/file_system_delegate_qt.h
@@ -0,0 +1,89 @@
+// Copyright (C) 2023 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
+
+#ifndef FILE_SYSTEM_DELEGATE_QT_H
+#define FILE_SYSTEM_DELEGATE_QT_H
+
+#include "extensions/browser/api/file_system/file_system_delegate.h"
+
+#include "base/files/file_path.h"
+#include "base/functional/callback.h"
+#include "base/memory/ref_counted.h"
+#include "extensions/browser/extension_function.h"
+#include "ui/shell_dialogs/select_file_dialog.h"
+
+#include <memory>
+#include <vector>
+
+namespace content {
+class BrowserContext;
+}  // namespace content
+
+namespace extensions {
+
+class FileEntryPickerQt : public ui::SelectFileDialog::Listener {
+public:
+    FileEntryPickerQt(
+        content::WebContents *web_contents,
+        const base::FilePath &suggested_name,
+        const ui::SelectFileDialog::FileTypeInfo *file_type_info,
+        ui::SelectFileDialog::Type picker_type,
+        FileSystemDelegate::FilesSelectedCallback files_selected_callback,
+        base::OnceClosure file_selection_canceled_callback);
+
+    FileEntryPickerQt(const FileEntryPickerQt &) = delete;
+    FileEntryPickerQt &operator=(const FileEntryPickerQt &) = delete;
+
+private:
+    ~FileEntryPickerQt() override;
+
+    // ui::SelectFileDialog::Listener implementation.
+    void FileSelected(const base::FilePath &path,
+        int index,
+        void *params) override;
+    void FileSelectedWithExtraInfo(const ui::SelectedFileInfo &file,
+        int index,
+        void *params) override;
+    void MultiFilesSelected(const std::vector<base::FilePath> &files,
+                          void *params) override;
+    void MultiFilesSelectedWithExtraInfo(
+        const std::vector<ui::SelectedFileInfo> &files,
+        void *params) override;
+    void FileSelectionCanceled(void *params) override;
+
+    FileSystemDelegate::FilesSelectedCallback m_filesSelectedCallback;
+    base::OnceClosure m_fileSelectionCanceledCallback;
+    scoped_refptr<ui::SelectFileDialog> m_selectFileDialog;
+};
+
+class FileSystemDelegateQt : public FileSystemDelegate
+{
+public:
+    FileSystemDelegateQt();
+
+    // FileSystemDelegate implementation
+    virtual base::FilePath GetDefaultDirectory() override;
+    virtual base::FilePath GetManagedSaveAsDirectory(
+        content::BrowserContext *browser_context,
+        const Extension &extension) override;
+    virtual bool ShowSelectFileDialog(
+        scoped_refptr<ExtensionFunction> extension_function,
+        ui::SelectFileDialog::Type type,
+        const base::FilePath &default_path,
+        const ui::SelectFileDialog::FileTypeInfo *file_types,
+        FileSystemDelegate::FilesSelectedCallback files_selected_callback,
+        base::OnceClosure file_selection_canceled_callback) override;
+    virtual void ConfirmSensitiveDirectoryAccess(
+        bool has_write_permission,
+        const std::u16string &app_name,
+        content::WebContents *web_contents,
+        base::OnceClosure on_accept,
+        base::OnceClosure on_cancel) override;
+    virtual int GetDescriptionIdForAcceptType(const std::string &accept_type) override;
+    virtual SavedFilesServiceInterface *GetSavedFilesService(
+        content::BrowserContext *browser_context) override;
+};
+
+} // namespace extensions
+
+#endif // FILE_SYSTEM_DELEGATE_QT_H
diff --git a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp
index 5a93b4b8461..9a2feb8165d 100644
--- a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp
+++ b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp
@@ -9,6 +9,7 @@
 
 #include "extensions/pdf_iframe_navigation_throttle_qt.h"
 
+#include "base/task/sequenced_task_runner.h"
 #include "chrome/grit/renderer_resources.h"
 #include "components/strings/grit/components_strings.h"
 #include "content/public/browser/download_utils.h"
@@ -25,19 +26,18 @@
 #include "ui/base/webui/jstemplate_builder.h"
 #include "ui/base/webui/web_ui_util.h"
 
+#include "pdf_util_qt.h"
+
 #include <QtGlobal>
 
 namespace extensions {
 
-constexpr char kPDFMimeType[] = "application/pdf";
-
 // Used to scope the posted navigation task to the lifetime of |web_contents|.
 class PdfWebContentsLifetimeHelper : public content::WebContentsUserData<PdfWebContentsLifetimeHelper>
 {
 public:
     explicit PdfWebContentsLifetimeHelper(content::WebContents *web_contents)
         : content::WebContentsUserData<PdfWebContentsLifetimeHelper>(*web_contents)
-        , web_contents_(web_contents)
     {}
 
     base::WeakPtr<PdfWebContentsLifetimeHelper> GetWeakPtr()
@@ -47,13 +47,12 @@ class PdfWebContentsLifetimeHelper : public content::WebContentsUserData<PdfWebC
 
     void NavigateIFrameToPlaceholder(const content::OpenURLParams &url_params)
     {
-        web_contents_->OpenURL(url_params);
+        GetWebContents().OpenURL(url_params);
     }
 
 private:
     friend class content::WebContentsUserData<PdfWebContentsLifetimeHelper>;
 
-    content::WebContents *const web_contents_;
     base::WeakPtrFactory<PdfWebContentsLifetimeHelper> weak_factory_{this};
 
     WEB_CONTENTS_USER_DATA_KEY_DECL();
@@ -74,10 +73,11 @@ bool IsPDFPluginEnabled(content::NavigationHandle *navigation_handle, bool *is_s
     content::WebPluginInfo plugin_info;
     // Will check WebEngineSettings by PluginServiceFilterQt
     return content::PluginService::GetInstance()->GetPluginInfo(
-                process_id, routing_id, nullptr, navigation_handle->GetURL(),
-                kPDFMimeType,
-                false /* allow_wildcard */, is_stale, &plugin_info,
-                nullptr /* actual_mime_type */);
+                process_id, routing_id,
+                navigation_handle->GetWebContents()->GetBrowserContext(),
+                navigation_handle->GetURL(),
+                QtWebEngineCore::kPDFMimeType, false /* allow_wildcard */,
+                is_stale, &plugin_info, nullptr /* actual_mime_type */);
 }
 
 std::string GetPDFPlaceholderHTML(const GURL &pdf_url)
@@ -119,7 +119,7 @@ content::NavigationThrottle::ThrottleCheckResult PDFIFrameNavigationThrottleQt::
 
     std::string mime_type;
     response_headers->GetMimeType(&mime_type);
-    if (mime_type != kPDFMimeType)
+    if (mime_type != QtWebEngineCore::kPDFMimeType)
         return content::NavigationThrottle::PROCEED;
 
     // We MUST download responses marked as attachments rather than showing
@@ -182,7 +182,7 @@ void PDFIFrameNavigationThrottleQt::LoadPlaceholderHTML()
 
     PdfWebContentsLifetimeHelper::CreateForWebContents(web_contents);
     PdfWebContentsLifetimeHelper *helper = PdfWebContentsLifetimeHelper::FromWebContents(web_contents);
-    base::SequencedTaskRunnerHandle::Get()->PostTask(
+    base::SequencedTaskRunner::GetCurrentDefault()->PostTask(
         FROM_HERE,
         base::BindOnce(&PdfWebContentsLifetimeHelper::NavigateIFrameToPlaceholder,
                        helper->GetWeakPtr(), std::move(params)));
diff --git a/src/core/favicon_service_factory_qt.cpp b/src/core/favicon_service_factory_qt.cpp
index d76bfab118c..1ed33d559e2 100644
--- a/src/core/favicon_service_factory_qt.cpp
+++ b/src/core/favicon_service_factory_qt.cpp
@@ -23,12 +23,17 @@ void HistoryClientQt::OnHistoryServiceCreated(history::HistoryService *history_s
 
 void HistoryClientQt::Shutdown() { }
 
-bool HistoryClientQt::CanAddURL(const GURL &url)
+static bool CanAddURL(const GURL &url)
 {
     Q_UNUSED(url);
     return true;
 }
 
+history::CanAddURLCallback HistoryClientQt::GetThreadSafeCanAddURLCallback() const
+{
+    return base::BindRepeating(&CanAddURL);
+}
+
 void HistoryClientQt::NotifyProfileError(sql::InitStatus init_status,
                                          const std::string &diagnostics)
 {
@@ -84,7 +89,7 @@ HistoryServiceFactoryQt::BuildServiceInstanceFor(content::BrowserContext *contex
 
     std::unique_ptr<history::HistoryService> historyService(
             new history::HistoryService(std::make_unique<HistoryClientQt>(), nullptr));
-    if (!historyService->Init(history::HistoryDatabaseParamsForPath(context->GetPath()))) {
+    if (!historyService->Init(history::HistoryDatabaseParamsForPath(context->GetPath(), version_info::Channel::DEFAULT))) {
         return nullptr;
     }
     return historyService.release();
diff --git a/src/core/favicon_service_factory_qt.h b/src/core/favicon_service_factory_qt.h
index 44a43211ee5..0c3bfd7b56a 100644
--- a/src/core/favicon_service_factory_qt.h
+++ b/src/core/favicon_service_factory_qt.h
@@ -48,7 +48,7 @@ class HistoryClientQt : public history::HistoryClient
 
     void OnHistoryServiceCreated(history::HistoryService *history_service) override;
     void Shutdown() override;
-    bool CanAddURL(const GURL &url) override;
+    history::CanAddURLCallback GetThreadSafeCanAddURLCallback() const override;
     void NotifyProfileError(sql::InitStatus init_status, const std::string &diagnostics) override;
     std::unique_ptr<history::HistoryBackendClient> CreateBackendClient() override;
     void UpdateBookmarkLastUsedTime(int64_t bookmark_node_id, base::Time time) override;
diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp
index 6ec7258b9d3..9b452135865 100644
--- a/src/core/file_picker_controller.cpp
+++ b/src/core/file_picker_controller.cpp
@@ -136,7 +136,7 @@ void FilePickerController::accepted(const QVariant &files)
 {
     QStringList stringList;
 
-    if (files.canConvert(QMetaType::QStringList)) {
+    if (files.canConvert(QMetaType{QMetaType::QStringList})) {
         stringList = files.toStringList();
     } else if (files.canConvert<QList<QUrl> >()) {
         const QList<QUrl> urls = files.value<QList<QUrl>>();
diff --git a/src/core/file_system_access/file_system_access_permission_context_qt.cpp b/src/core/file_system_access/file_system_access_permission_context_qt.cpp
index 2fd710ad693..8bb9d8d7783 100644
--- a/src/core/file_system_access/file_system_access_permission_context_qt.cpp
+++ b/src/core/file_system_access/file_system_access_permission_context_qt.cpp
@@ -241,6 +241,8 @@ FileSystemAccessPermissionContextQt::GetReadPermissionGrant(const url::Origin &o
         break;
     case UserAction::kLoadFromStorage:
         break;
+    case UserAction::kNone:
+        Q_UNREACHABLE();
     }
 
     return existing_grant;
@@ -285,6 +287,8 @@ FileSystemAccessPermissionContextQt::GetWritePermissionGrant(const url::Origin &
     case UserAction::kDragAndDrop:
     case UserAction::kLoadFromStorage:
         break;
+    case UserAction::kNone:
+        Q_UNREACHABLE();
     }
 
     return existing_grant;
@@ -471,4 +475,8 @@ void FileSystemAccessPermissionContextQt::PermissionGrantDestroyed(
         grants.erase(grant_it);
 }
 
+void FileSystemAccessPermissionContextQt::NotifyEntryMoved(const url::Origin &, const base::FilePath &, const base::FilePath &)
+{
+}
+
 } // namespace QtWebEngineCore
diff --git a/src/core/file_system_access/file_system_access_permission_context_qt.h b/src/core/file_system_access/file_system_access_permission_context_qt.h
index 09e890038b0..06fbfae3f0e 100644
--- a/src/core/file_system_access/file_system_access_permission_context_qt.h
+++ b/src/core/file_system_access/file_system_access_permission_context_qt.h
@@ -52,6 +52,7 @@ class FileSystemAccessPermissionContextQt : public content::FileSystemAccessPerm
     GetLastPickedDirectory(const url::Origin &origin, const std::string &id) override;
     base::FilePath GetWellKnownDirectoryPath(blink::mojom::WellKnownDirectory directory, const url::Origin &origin) override;
     std::u16string GetPickerTitle(const blink::mojom::FilePickerOptionsPtr &) override;
+    void NotifyEntryMoved(const url::Origin &, const base::FilePath &, const base::FilePath &) override;
 
     void NavigatedAwayFromOrigin(const url::Origin &origin);
     content::BrowserContext *profile() const { return m_profile; }
diff --git a/src/core/file_system_access/file_system_access_permission_request_manager_qt.h b/src/core/file_system_access/file_system_access_permission_request_manager_qt.h
index f8746eabf37..84085491153 100644
--- a/src/core/file_system_access/file_system_access_permission_request_manager_qt.h
+++ b/src/core/file_system_access/file_system_access_permission_request_manager_qt.h
@@ -4,9 +4,9 @@
 #ifndef FILE_SYSTEM_ACCESS_PERMISSION_REQUEST_MANAGER_QT_H
 #define FILE_SYSTEM_ACCESS_PERMISSION_REQUEST_MANAGER_QT_H
 
-#include "base/callback_helpers.h"
 #include "base/containers/circular_deque.h"
 #include "base/files/file_path.h"
+#include "base/functional/callback_helpers.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/file_system_access_permission_context.h"
 #include "content/public/browser/web_contents_observer.h"
diff --git a/src/core/javascript_dialog_controller_p.h b/src/core/javascript_dialog_controller_p.h
index 8345cd50b54..af064250bce 100644
--- a/src/core/javascript_dialog_controller_p.h
+++ b/src/core/javascript_dialog_controller_p.h
@@ -15,7 +15,7 @@
 // We mean it.
 //
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "content/public/browser/javascript_dialog_manager.h"
 
 #include "web_contents_adapter_client.h"
diff --git a/src/core/location_provider_qt.cpp b/src/core/location_provider_qt.cpp
index c7273eaeaf2..8952c7c6953 100644
--- a/src/core/location_provider_qt.cpp
+++ b/src/core/location_provider_qt.cpp
@@ -1,4 +1,4 @@
-// Copyright (C) 2016 The Qt Company Ltd.
+// Copyright (C) 2023 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 "location_provider_qt.h"
@@ -12,7 +12,11 @@
 #include <QtCore/QThread>
 #include <QtPositioning/QGeoPositionInfoSource>
 
-#include "base/bind.h"
+#if QT_CONFIG(permissions)
+#include <QtCore/qpermissions.h>
+#endif
+
+#include "base/functional/bind.h"
 #include "base/memory/weak_ptr.h"
 #include "content/public/browser/browser_thread.h"
 #include "services/device/geolocation/geolocation_provider.h"
@@ -37,6 +41,7 @@ private Q_SLOTS:
     void error(QGeoPositionInfoSource::Error positioningError);
 
 private:
+    void startImpl(bool highAccuracy);
     LocationProviderQt *m_locationProvider;
     QGeoPositionInfoSource *m_positionInfoSource;
     base::WeakPtrFactory<LocationProviderQt> m_locationProviderFactory;
@@ -66,6 +71,38 @@ static bool isHighAccuracySource(const QGeoPositionInfoSource *source)
 void QtPositioningHelper::start(bool highAccuracy)
 {
     DCHECK_CURRENTLY_ON(BrowserThread::UI);
+
+    // New Qt permissions API from 6.5.0
+#if QT_CONFIG(permissions)
+    QLocationPermission locationPermission;
+    locationPermission.setAvailability(QLocationPermission::WhenInUse);
+
+    QLocationPermission::Accuracy accuracy = highAccuracy ? QLocationPermission::Precise
+                                                          : QLocationPermission::Approximate;
+    locationPermission.setAccuracy(accuracy);
+
+    switch (qApp->checkPermission(locationPermission)) {
+    case Qt::PermissionStatus::Undetermined:
+        qApp->requestPermission(locationPermission, this,
+                    [this, &highAccuracy](const QPermission &permission) {
+                      if (permission.status() == Qt::PermissionStatus::Granted)
+                          this->startImpl(highAccuracy);
+                    });
+
+        return;
+    case Qt::PermissionStatus::Denied:
+        qWarning("Failed to initialize location provider: The user does not have the right "
+                 "permissions or has denied the permission request.");
+        return;
+    case Qt::PermissionStatus::Granted:
+        break; // Proceed
+    }
+#endif
+    startImpl(highAccuracy);
+}
+
+void QtPositioningHelper::startImpl(bool highAccuracy){
+    DCHECK_CURRENTLY_ON(BrowserThread::UI);
     if (!m_positionInfoSource)
         m_positionInfoSource = QGeoPositionInfoSource::createDefaultSource(this);
     if (!m_positionInfoSource) {
diff --git a/src/core/macos_context_type_helper.h b/src/core/macos_context_type_helper.h
deleted file mode 100644
index 1a2b0ff61ee..00000000000
--- a/src/core/macos_context_type_helper.h
+++ /dev/null
@@ -1,7 +0,0 @@
-// Copyright (C) 2020 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
-#ifndef MACOS_CONTEXT_TYPE_HELPER_H_
-#define MACOS_CONTEXT_TYPE_HELPER_H_
-bool isCurrentContextSoftware();
-void* cglContext(NSOpenGLContext*);
-#endif // MACOS_CONTEXT_TYPE_HELPER_H_
diff --git a/src/core/macos_context_type_helper.mm b/src/core/macos_context_type_helper.mm
deleted file mode 100644
index 9bdd360857e..00000000000
--- a/src/core/macos_context_type_helper.mm
+++ /dev/null
@@ -1,18 +0,0 @@
-// Copyright (C) 2020 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
-#import <Foundation/Foundation.h>
-#import <AppKit/AppKit.h>
-
-#include "macos_context_type_helper.h"
-
-bool isCurrentContextSoftware()
-{
-    int rendererID = 0;
-    [NSOpenGLContext.currentContext getValues:&rendererID forParameter:NSOpenGLContextParameterCurrentRendererID];
-    return (rendererID & kCGLRendererIDMatchingMask) == kCGLRendererGenericFloatID;
-}
-
-void* cglContext(NSOpenGLContext *nsOpenGLContext)
-{
-   return [nsOpenGLContext CGLContextObj];
-}
diff --git a/src/core/net/client_cert_qt.cpp b/src/core/net/client_cert_qt.cpp
index d5ea1a77615..1a6f9707961 100644
--- a/src/core/net/client_cert_qt.cpp
+++ b/src/core/net/client_cert_qt.cpp
@@ -3,8 +3,8 @@
 
 #include "client_cert_qt.h"
 
-#include "base/bind.h"
-#include "base/callback_forward.h"
+#include "base/functional/bind.h"
+#include "base/functional/callback_forward.h"
 #include "content/public/browser/browser_task_traits.h"
 #include "crypto/crypto_buildflags.h"
 #include "net/ssl/client_cert_store.h"
diff --git a/src/core/net/client_cert_qt.h b/src/core/net/client_cert_qt.h
index 85b0d28be70..96579fae65d 100644
--- a/src/core/net/client_cert_qt.h
+++ b/src/core/net/client_cert_qt.h
@@ -4,9 +4,9 @@
 #ifndef CLIENT_CERT_QT_P_H
 #define CLIENT_CERT_QT_P_H
 
-#include "net/ssl/client_cert_store.h"
-#include "base/callback_forward.h"
+#include "base/functional/callback_forward.h"
 #include "net/cert/x509_certificate.h"
+#include "net/ssl/client_cert_store.h"
 
 namespace net {
 class SSLCertRequestInfo;
diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp
index 306e782e040..0de6885df85 100644
--- a/src/core/net/client_cert_store_data.cpp
+++ b/src/core/net/client_cert_store_data.cpp
@@ -97,7 +97,8 @@ void ClientCertificateStoreData::add(const QSslCertificate &certificate, const Q
 
     Entry *data = new Entry;
     data->keyPtr = wrapOpenSSLPrivateKey(sslKeyInBytes);
-    data->certPtr = net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)certInBytes.data(), certInBytes.length()));
+    data->certPtr = net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)certInBytes.data(),
+                                                                          (unsigned long)certInBytes.length()));
     data->key = privateKey;
     data->certificate = certificate;
     extraCerts.append(data);
diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp
index dc47de20793..147e63f9a99 100644
--- a/src/core/net/cookie_monster_delegate_qt.cpp
+++ b/src/core/net/cookie_monster_delegate_qt.cpp
@@ -3,7 +3,7 @@
 
 #include "cookie_monster_delegate_qt.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "net/cookies/cookie_util.h"
 #include "services/network/public/mojom/cookie_manager.mojom.h"
 
diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp
index bd19aa436f8..69b7c6b6842 100644
--- a/src/core/net/custom_url_loader_factory.cpp
+++ b/src/core/net/custom_url_loader_factory.cpp
@@ -271,7 +271,8 @@ class CustomURLLoader : public network::mojom::URLLoader
         m_head->encoded_data_length = m_head->headers->raw_headers().length();
 
         if (!m_redirect.is_empty()) {
-            m_head->content_length = m_head->encoded_body_length = -1;
+            m_head->content_length = {};
+            m_head->encoded_body_length = {};
             net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy =
                     m_request.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT
                                                                  : net::RedirectInfo::FirstPartyURLPolicy::NEVER_CHANGE_URL;
@@ -339,7 +340,8 @@ class CustomURLLoader : public network::mojom::URLLoader
         }
         m_head->headers = base::MakeRefCounted<net::HttpResponseHeaders>(net::HttpUtil::AssembleRawHeaders(headers));
         m_head->encoded_data_length = m_head->headers->raw_headers().length();
-        m_head->content_length = m_head->encoded_body_length = -1;
+        m_head->content_length = {};
+        m_head->encoded_body_length = {};
         m_client->OnReceiveResponse(std::move(m_head), mojo::ScopedDataPipeConsumerHandle(), absl::nullopt);
         CompleteWithFailure(net::Error(error));
     }
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 f61fb704a60..fb765639233 100644
--- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
+++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp
@@ -8,7 +8,7 @@
 
 #include "plugin_response_interceptor_url_loader_throttle.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/guid.h"
 #include "chrome/browser/extensions/api/streams_private/streams_private_api.h"
 #include "content/public/browser/browser_context.h"
diff --git a/src/core/net/proxy_config_service_qt.cpp b/src/core/net/proxy_config_service_qt.cpp
index 70bcb59b430..fcce08550a9 100644
--- a/src/core/net/proxy_config_service_qt.cpp
+++ b/src/core/net/proxy_config_service_qt.cpp
@@ -16,14 +16,15 @@
 
 net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qtProxy)
 {
-    net::HostPortPair hostPortPair(qtProxy.hostName().toStdString(), qtProxy.port());
+    std::string host = qtProxy.hostName().toStdString();
+    uint16_t port = qtProxy.port();
     switch (qtProxy.type()) {
     case QNetworkProxy::Socks5Proxy:
-        return net::ProxyServer(net::ProxyServer::SCHEME_SOCKS5, hostPortPair);
+        return net::ProxyServer::FromSchemeHostAndPort(net::ProxyServer::SCHEME_SOCKS5, host, port);
     case QNetworkProxy::HttpProxy:
     case QNetworkProxy::HttpCachingProxy:
     case QNetworkProxy::FtpCachingProxy:
-        return net::ProxyServer(net::ProxyServer::SCHEME_HTTP, hostPortPair);
+        return net::ProxyServer::FromSchemeHostAndPort(net::ProxyServer::SCHEME_HTTP, host, port);
     case QNetworkProxy::NoProxy:
     case QNetworkProxy::DefaultProxy:
         return net::ProxyServer(net::ProxyServer::SCHEME_DIRECT, net::HostPortPair());
diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp
index 8608d35cd23..5bae987e2ee 100644
--- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp
+++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp
@@ -66,16 +66,15 @@ ProxyingRestrictedCookieManagerQt::~ProxyingRestrictedCookieManagerQt()
 
 void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url,
                                                      const net::SiteForCookies &site_for_cookies,
-                                                     const url::Origin &top_frame_origin,
+                                                     const url::Origin &top_frame_origin, bool has_storage_access,
                                                      network::mojom::CookieManagerGetOptionsPtr options,
-                                                     bool partitioned_cookies_runtime_feature_enabled,
                                                      GetAllForUrlCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
     if (allowCookies(url, site_for_cookies)) {
-        underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, std::move(options),
-                                                            partitioned_cookies_runtime_feature_enabled, std::move(callback));
+        underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, has_storage_access,
+                                                            std::move(options), std::move(callback));
     } else {
         std::move(callback).Run(std::vector<net::CookieWithAccessResult>());
     }
@@ -85,13 +84,15 @@ 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::CookieInclusionStatus status,
                                                            SetCanonicalCookieCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
     if (allowCookies(url, site_for_cookies)) {
-        underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, top_frame_origin, status, std::move(callback));
+        underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, top_frame_origin,
+                                                                  has_storage_access, status, std::move(callback));
     } else {
         std::move(callback).Run(false);
     }
@@ -100,25 +101,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,
                                                           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, std::move(listener), std::move(callback));
+    underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, has_storage_access,
+                                                             std::move(listener), std::move(callback));
 }
 
 void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url,
                                                             const net::SiteForCookies &site_for_cookies,
-                                                            const url::Origin &top_frame_origin,
+                                                            const url::Origin &top_frame_origin, bool has_storage_access,
                                                             const std::string &cookie,
-                                                            bool partitioned_cookies_runtime_feature_enabled,
                                                             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, cookie,
-                                                                   partitioned_cookies_runtime_feature_enabled, std::move(callback));
+        underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, has_storage_access,
+                                                                   cookie, std::move(callback));
     } else {
         std::move(callback).Run(false, false); // FIXME: is true, true in aw_proxying_restricted_cookie_manager.cc though..
     }
@@ -126,15 +128,14 @@ 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 partitioned_cookies_runtime_feature_enabled,
+                                                         const url::Origin &top_frame_origin, bool has_storage_access,
                                                          GetCookiesStringCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
 
     if (allowCookies(url, site_for_cookies)) {
         underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, top_frame_origin,
-                                                                partitioned_cookies_runtime_feature_enabled, std::move(callback));
+                                                                has_storage_access, std::move(callback));
     } else {
         std::move(callback).Run("");
     }
@@ -143,17 +144,13 @@ 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*/,
                                                           CookiesEnabledForCallback callback)
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::IO);
     std::move(callback).Run(allowCookies(url, site_for_cookies));
 }
 
-void ProxyingRestrictedCookieManagerQt::ConvertPartitionedCookiesToUnpartitioned(const GURL&)
-{
-    NOTIMPLEMENTED();
-}
-
 bool ProxyingRestrictedCookieManagerQt::allowCookies(const GURL &url, const net::SiteForCookies &site_for_cookies) const
 {
     if (!m_profileIoData)
diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h
index 95e193f761f..6afdc9301af 100644
--- a/src/core/net/proxying_restricted_cookie_manager_qt.h
+++ b/src/core/net/proxying_restricted_cookie_manager_qt.h
@@ -27,36 +27,39 @@ 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,
                       network::mojom::CookieManagerGetOptionsPtr options,
-                      bool partitioned_cookies_runtime_feature_enabled,
                       GetAllForUrlCallback callback) override;
+
     void SetCanonicalCookie(const net::CanonicalCookie& cookie,
                             const GURL &url,
                             const net::SiteForCookies &site_for_cookies,
                             const url::Origin &top_frame_origin,
+                            bool has_storage_access,
                             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,
                            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,
                              const std::string &cookie,
-                             bool partitioned_cookies_runtime_feature_enabled,
                              SetCookieFromStringCallback callback) override;
     void GetCookiesString(const GURL &url,
                           const net::SiteForCookies &site_for_cookies,
                           const url::Origin &top_frame_origin,
-                          bool partitioned_cookies_runtime_feature_enabled,
+                          bool has_storage_access,
                           GetCookiesStringCallback callback) override;
     void CookiesEnabledFor(const GURL &url,
                            const net::SiteForCookies &site_for_cookies,
                            const url::Origin &top_frame_origin,
+                           bool has_storage_access,
                            CookiesEnabledForCallback callback) override;
-    void ConvertPartitionedCookiesToUnpartitioned(const GURL&) override;
 
     // Internal:
     bool allowCookies(const GURL &url, const net::SiteForCookies &site_for_cookies) const;
diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp
index 4e40f9fc806..2478a363804 100644
--- a/src/core/net/proxying_url_loader_factory_qt.cpp
+++ b/src/core/net/proxying_url_loader_factory_qt.cpp
@@ -5,7 +5,7 @@
 
 #include <utility>
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "content/browser/web_contents/web_contents_impl.h"
 #include "content/public/browser/browser_thread.h"
 #include "content/public/browser/web_contents.h"
@@ -20,14 +20,11 @@
 #include "url/url_util_qt.h"
 
 #include "api/qwebengineurlrequestinfo_p.h"
-#include "api/qwebengineurlresponseinfo_p.h"
 #include "type_conversion.h"
 #include "web_contents_adapter.h"
 #include "web_contents_adapter_client.h"
 #include "web_contents_view_qt.h"
 
-#include <QtWebEngineCore/QWebEngineUrlResponseInfo>
-
 // originally based on aw_proxying_url_loader_factory.cc:
 // Copyright 2018 The Chromium Authors. All rights reserved.
 // Use of this source code is governed by a BSD-style license that can be
@@ -129,8 +126,6 @@ class InterceptedRequest : public network::mojom::URLLoader
     void PauseReadingBodyFromNet() override;
     void ResumeReadingBodyFromNet() override;
 
-    static inline void cleanup(QWebEngineUrlRequestInfo *info) { delete info; }
-
 private:
     void InterceptOnUIThread();
     void ContinueAfterIntercept();
@@ -151,11 +146,6 @@ class InterceptedRequest : public network::mojom::URLLoader
     content::WebContents* webContents();
     QWebEngineUrlRequestInterceptor* getProfileInterceptor();
     QWebEngineUrlRequestInterceptor* getPageInterceptor();
-    QWebEngineUrlResponseInterceptor *getProfileResponseInterceptor();
-    QWebEngineUrlResponseInterceptor *getPageResponseInterceptor();
-
-    void interceptResponseHeaders(QWebEngineUrlResponseInterceptor *const interceptor,
-                                  net::HttpResponseHeaders *const responseHeadersPtr);
 
     QPointer<ProfileAdapter> profile_adapter_;
     const int frame_tree_node_id_;
@@ -177,7 +167,13 @@ class InterceptedRequest : public network::mojom::URLLoader
 
     const net::MutableNetworkTrafficAnnotationTag traffic_annotation_;
 
-    QScopedPointer<QWebEngineUrlRequestInfo, InterceptedRequest> request_info_;
+    struct RequestInfoDeleter
+    {
+        void operator()(QWebEngineUrlRequestInfo *ptr) const
+        { delete ptr; }
+    };
+
+    std::unique_ptr<QWebEngineUrlRequestInfo, RequestInfoDeleter> request_info_;
 
     mojo::Receiver<network::mojom::URLLoader> proxied_loader_receiver_;
     mojo::Remote<network::mojom::URLLoaderClient> target_client_;
@@ -260,59 +256,6 @@ QWebEngineUrlRequestInterceptor* InterceptedRequest::getPageInterceptor()
     return nullptr;
 }
 
-QWebEngineUrlResponseInterceptor* InterceptedRequest::getProfileResponseInterceptor()
-{
-    return profile_adapter_ ? profile_adapter_->responseInterceptor() : nullptr;
-}
-
-QWebEngineUrlResponseInterceptor* InterceptedRequest::getPageResponseInterceptor()
-{
-    if (auto wc = webContents()) {
-        auto view = static_cast<content::WebContentsImpl *>(wc)->GetView();
-        if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client())
-            return client->webContentsAdapter()->responseInterceptor();
-    }
-    return nullptr;
-}
-
-void InterceptedRequest::interceptResponseHeaders(
-        QWebEngineUrlResponseInterceptor *const interceptor,
-        net::HttpResponseHeaders *const responseHeadersPtr)
-{
-    QHash<QByteArray, QByteArray> responseHeaders;
-    std::unordered_set<std::string> headersToRemove;
-    {
-        std::size_t iter = 0;
-        std::string name;
-        std::string value;
-        while (responseHeadersPtr->EnumerateHeaderLines(&iter, &name, &value)) {
-            responseHeaders.insert(QByteArray::fromStdString(name),
-                                   QByteArray::fromStdString(value));
-            headersToRemove.insert(name);
-        }
-    }
-
-    const QUrl requestUrl = QUrl::fromEncoded(QByteArray::fromStdString(request_.url.spec()));
-    const QHash<QByteArray, QByteArray> requestHeaders =
-            [](const net::HttpRequestHeaders &headers) {
-                QHash<QByteArray, QByteArray> result;
-                for (const auto &header : headers.GetHeaderVector()) {
-                    result.insert(QByteArray::fromStdString(header.key),
-                                  QByteArray::fromStdString(header.value));
-                }
-                return result;
-            }(request_.headers);
-
-    QWebEngineUrlResponseInfo info(requestUrl, requestHeaders, responseHeaders);
-    interceptor->interceptResponseHeaders(info);
-
-    if (info.d_ptr->isModified) {
-        responseHeadersPtr->RemoveHeaders(headersToRemove);
-        for (auto it = info.responseHeaders().cbegin(); it != info.responseHeaders().cend(); ++it)
-            responseHeadersPtr->AddHeader(it.key().toStdString(), it.value().toStdString());
-    }
-}
-
 void InterceptedRequest::Restart()
 {
     DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
@@ -415,22 +358,21 @@ void InterceptedRequest::ContinueAfterIntercept()
 
     if (request_info_) {
         // cleanup in scope because of delete this and it's not needed else where after
-        decltype(request_info_) scoped_request_info(request_info_.take());
+        const auto scoped_request_info = std::move(request_info_);
         QWebEngineUrlRequestInfoPrivate &info = *scoped_request_info->d_ptr;
 
+        for (auto header = info.extraHeaders.constBegin(); header != info.extraHeaders.constEnd(); ++header) {
+            std::string h = header.key().toStdString();
+            if (base::EqualsCaseInsensitiveASCII(h, "referer"))
+                request_.referrer = GURL(header.value().toStdString());
+            else
+                request_.headers.SetHeader(h, header.value().toStdString());
+        }
+
         if (info.changed) {
             if (info.shouldBlockRequest)
                 return SendErrorAndCompleteImmediately(net::ERR_BLOCKED_BY_CLIENT);
 
-            for (auto header = info.extraHeaders.constBegin(); header != info.extraHeaders.constEnd(); ++header) {
-                std::string h = header.key().toStdString();
-                if (base::EqualsCaseInsensitiveASCII(h, "referer")) {
-                    request_.referrer = GURL(header.value().toStdString());
-                } else {
-                    request_.headers.SetHeader(h, header.value().toStdString());
-                }
-            }
-
             if (info.shouldRedirectRequest) {
                 net::RedirectInfo::FirstPartyURLPolicy first_party_url_policy =
                         request_.update_first_party_url_on_redirect ? net::RedirectInfo::FirstPartyURLPolicy::UPDATE_URL_ON_REDIRECT
@@ -470,12 +412,6 @@ void InterceptedRequest::ContinueAfterIntercept()
 
 void InterceptedRequest::OnReceiveResponse(network::mojom::URLResponseHeadPtr head, mojo::ScopedDataPipeConsumerHandle handle, absl::optional<mojo_base::BigBuffer> buffer)
 {
-    QWebEngineUrlResponseInterceptor *const responseInterceptor = getProfileResponseInterceptor()
-            ? getProfileResponseInterceptor()
-            : getPageResponseInterceptor();
-    if (responseInterceptor)
-        interceptResponseHeaders(responseInterceptor, head->headers.get());
-
     current_response_ = head.Clone();
 
     target_client_->OnReceiveResponse(std::move(head), std::move(handle), std::move(buffer));
diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp
index ab66acac0d3..a8b4e4388a2 100644
--- a/src/core/net/qrc_url_scheme_handler.cpp
+++ b/src/core/net/qrc_url_scheme_handler.cpp
@@ -10,6 +10,8 @@
 #include <QMimeDatabase>
 #include <QMimeType>
 
+#include <memory>
+
 namespace QtWebEngineCore {
 
 void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
@@ -22,7 +24,7 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
 
     QUrl requestUrl = job->requestUrl();
     QString requestPath = requestUrl.path();
-    QScopedPointer<QFile> file(new QFile(':' + requestPath, job));
+    auto file = std::make_unique<QFile>(':' + requestPath, job);
     if (!file->exists() || file->size() == 0) {
         qWarning("QResource '%s' not found or is empty", qUtf8Printable(requestPath));
         job->fail(QWebEngineUrlRequestJob::UrlNotFound);
@@ -32,9 +34,9 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job)
     QMimeDatabase mimeDatabase;
     QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo);
     if (mimeType.name() == QStringLiteral("application/x-extension-html"))
-        job->reply("text/html", file.take());
+        job->reply("text/html", file.release());
     else
-        job->reply(mimeType.name().toUtf8(), file.take());
+        job->reply(mimeType.name().toUtf8(), file.release());
 }
 
 } // namespace QtWebEngineCore
diff --git a/src/core/net/ssl_host_state_delegate_qt.cpp b/src/core/net/ssl_host_state_delegate_qt.cpp
index d0308389d3e..20429e62efd 100644
--- a/src/core/net/ssl_host_state_delegate_qt.cpp
+++ b/src/core/net/ssl_host_state_delegate_qt.cpp
@@ -3,7 +3,7 @@
 
 #include "ssl_host_state_delegate_qt.h"
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 
 namespace QtWebEngineCore {
 
diff --git a/src/core/net/system_network_context_manager.cpp b/src/core/net/system_network_context_manager.cpp
index 8df65b7a573..65b5d9c970b 100644
--- a/src/core/net/system_network_context_manager.cpp
+++ b/src/core/net/system_network_context_manager.cpp
@@ -8,8 +8,8 @@
 
 #include "net/system_network_context_manager.h"
 
-#include "base/bind.h"
 #include "base/command_line.h"
+#include "base/functional/bind.h"
 #include "base/strings/string_split.h"
 #include "chrome/browser/net/chrome_mojo_proxy_resolver_factory.h"
 #include "chrome/common/chrome_switches.h"
@@ -265,18 +265,7 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(network::mojom::Networ
     // resolver of the network service here, each time it is instantiated, with our global
     // DNS-Over-HTTPS settings. This ensures that the global settings don't get lost
     // on reinstantiation and are in effect upon initial instantiation.
-    QWebEngineGlobalSettings *const globalSettings = QWebEngineGlobalSettings::GetInstance();
-    if (globalSettings->d_ptr->isDnsOverHttpsUserConfigured) {
-        const bool insecureDnsClientEnabled = globalSettings->d_ptr->insecureDnsClientEnabled;
-        const bool additionalInsecureDnsTypesEnabled =
-                globalSettings->d_ptr->additionalInsecureDnsTypesEnabled;
-        const net::SecureDnsMode dnsMode = net::SecureDnsMode(globalSettings->d_ptr->dnsMode);
-        const absl::optional<net::DnsOverHttpsConfig> dnsOverHttpsTemplates =
-                net::DnsOverHttpsConfig::FromString(globalSettings->d_ptr->dnsOverHttpsTemplates);
-        content::GetNetworkService()->ConfigureStubHostResolver(insecureDnsClientEnabled, dnsMode,
-                                                                *dnsOverHttpsTemplates,
-                                                                additionalInsecureDnsTypesEnabled);
-    }
+    QWebEngineGlobalSettingsPrivate::instance()->configureStubHostResolver();
 }
 
 void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params)
diff --git a/src/core/net/url_request_custom_job_delegate.cpp b/src/core/net/url_request_custom_job_delegate.cpp
index 07a1de1ec5e..6319fb160e0 100644
--- a/src/core/net/url_request_custom_job_delegate.cpp
+++ b/src/core/net/url_request_custom_job_delegate.cpp
@@ -52,7 +52,7 @@ QMap<QByteArray, QByteArray> URLRequestCustomJobDelegate::requestHeaders() const
 }
 
 void URLRequestCustomJobDelegate::setAdditionalResponseHeaders(
-        const QMap<QByteArray, QByteArray> &additionalResponseHeaders)
+        const QMultiMap<QByteArray, QByteArray> &additionalResponseHeaders)
 {
     m_additionalResponseHeaders = additionalResponseHeaders;
 }
diff --git a/src/core/net/url_request_custom_job_delegate.h b/src/core/net/url_request_custom_job_delegate.h
index 6b6ee68cf25..6b860bea89e 100644
--- a/src/core/net/url_request_custom_job_delegate.h
+++ b/src/core/net/url_request_custom_job_delegate.h
@@ -49,7 +49,7 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT URLRequestCustomJobDelegate : public QObjec
     QMap<QByteArray, QByteArray> requestHeaders() const;
 
     void
-    setAdditionalResponseHeaders(const QMap<QByteArray, QByteArray> &additionalResponseHeaders);
+    setAdditionalResponseHeaders(const QMultiMap<QByteArray, QByteArray> &additionalResponseHeaders);
     void reply(const QByteArray &contentType, QIODevice *device);
     void redirect(const QUrl &url);
     void abort();
@@ -71,7 +71,7 @@ private Q_SLOTS:
     QByteArray m_method;
     QUrl m_initiatorOrigin;
     const QMap<QByteArray, QByteArray> m_requestHeaders;
-    QMap<QByteArray, QByteArray> m_additionalResponseHeaders;
+    QMultiMap<QByteArray, QByteArray> m_additionalResponseHeaders;
 };
 
 } // namespace
diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp
index d548055b580..31c024a529a 100644
--- a/src/core/net/url_request_custom_job_proxy.cpp
+++ b/src/core/net/url_request_custom_job_proxy.cpp
@@ -41,7 +41,7 @@ void URLRequestCustomJobProxy::release()
 }
 
 void URLRequestCustomJobProxy::reply(std::string contentType, QIODevice *device,
-                                     QMap<QByteArray, QByteArray> additionalResponseHeaders)
+                                     QMultiMap<QByteArray, QByteArray> additionalResponseHeaders)
 {
     if (!m_client)
         return;
@@ -59,7 +59,7 @@ void URLRequestCustomJobProxy::reply(std::string contentType, QIODevice *device,
     }
     m_client->m_mimeType = qcontentType.trimmed().toStdString();
     m_client->m_device = device;
-    m_client->m_additionalResponseHeaders = additionalResponseHeaders;
+    m_client->m_additionalResponseHeaders = std::move(additionalResponseHeaders);
     if (m_client->m_device && !m_client->m_device->isReadable())
         m_client->m_device->open(QIODevice::ReadOnly);
 
diff --git a/src/core/net/url_request_custom_job_proxy.h b/src/core/net/url_request_custom_job_proxy.h
index 1f8c77da239..b02214f23f2 100644
--- a/src/core/net/url_request_custom_job_proxy.h
+++ b/src/core/net/url_request_custom_job_proxy.h
@@ -31,7 +31,7 @@ class URLRequestCustomJobProxy : public base::RefCountedThreadSafe<URLRequestCus
     public:
         std::string m_mimeType;
         std::string m_charset;
-        QMap<QByteArray, QByteArray> m_additionalResponseHeaders;
+        QMultiMap<QByteArray, QByteArray> m_additionalResponseHeaders;
         GURL m_redirect;
         QIODevice *m_device;
         int64_t m_firstBytePosition;
@@ -53,7 +53,7 @@ class URLRequestCustomJobProxy : public base::RefCountedThreadSafe<URLRequestCus
     // Called from URLRequestCustomJobDelegate via post:
     //void setReplyCharset(const std::string &);
     void reply(std::string mimeType, QIODevice *device,
-               QMap<QByteArray, QByteArray> additionalResponseHeaders);
+               QMultiMap<QByteArray, QByteArray> additionalResponseHeaders);
     void redirect(GURL url);
     void abort();
     void fail(int error);
diff --git a/src/core/net/webui_controller_factory_qt.cpp b/src/core/net/webui_controller_factory_qt.cpp
index edfe9ade27e..ed35a3e36fe 100644
--- a/src/core/net/webui_controller_factory_qt.cpp
+++ b/src/core/net/webui_controller_factory_qt.cpp
@@ -10,8 +10,7 @@
 
 #include "build_config_qt.h"
 #include "devtools_frontend_qt.h"
-
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "build/build_config.h"
 #include "chrome/browser/accessibility/accessibility_ui.h"
 #include "chrome/browser/profiles/profile.h"
@@ -26,6 +25,7 @@
 #include "media/media_buildflags.h"
 #include "printing/buildflags/buildflags.h"
 #include "url/gurl.h"
+#include "version_ui_qt.h"
 
 #if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_LINUX)
 #include "chrome/browser/ui/webui/sandbox/sandbox_internals_ui.h"
@@ -107,6 +107,9 @@ WebUIFactoryFunction GetWebUIFactoryFunction(WebUI *web_ui, Profile *profile, co
     if (url.host_piece() == chrome::kChromeUIDeviceLogHost)
         return &NewWebUI<chromeos::DeviceLogUI>;
 
+    if (url.host_piece() == chrome::kChromeUIVersionQtHost)
+        return &NewWebUI<VersionUIQt>;
+
 //    if (url.host_piece() == chrome::kChromeUIInspectHost)
 //        return &NewWebUI<InspectUI>;
 //
diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp
index 40fa92b9924..accfe375f8f 100644
--- a/src/core/ozone/gl_context_qt.cpp
+++ b/src/core/ozone/gl_context_qt.cpp
@@ -8,11 +8,11 @@
 #include <QThread>
 #include <QtGui/private/qtgui-config_p.h>
 #include <qpa/qplatformnativeinterface.h>
-#include "ui/gl/gl_context_egl.h"
-#include "ui/gl/gl_implementation.h"
 
 #if BUILDFLAG(IS_WIN)
+#include "ui/gl/gl_context_egl.h"
 #include "ui/gl/gl_context_wgl.h"
+#include "ui/gl/gl_implementation.h"
 #endif
 
 QT_BEGIN_NAMESPACE
diff --git a/src/core/ozone/gl_context_qt.h b/src/core/ozone/gl_context_qt.h
index f3ec219e6f4..655fd7e19e9 100644
--- a/src/core/ozone/gl_context_qt.h
+++ b/src/core/ozone/gl_context_qt.h
@@ -8,7 +8,6 @@
 #include "ui/gl/gl_context.h"
 
 namespace gl {
-class GLContext;
 class GLSurface;
 }
 
diff --git a/src/core/ozone/gl_ozone_egl_qt.cpp b/src/core/ozone/gl_ozone_egl_qt.cpp
index 5e2540af862..7b27fb9211b 100644
--- a/src/core/ozone/gl_ozone_egl_qt.cpp
+++ b/src/core/ozone/gl_ozone_egl_qt.cpp
@@ -6,58 +6,37 @@
 #include "gl_ozone_egl_qt.h"
 #include "gl_surface_egl_qt.h"
 
-#include "base/files/file_path.h"
-#include "base/native_library.h"
 #include "media/gpu/buildflags.h"
 #include "ui/gl/gl_bindings.h"
-#include "ui/gl/gl_context_egl.h"
 #include "ui/gl/gl_display.h"
-#include "ui/gl/gl_implementation.h"
-#include "ui/gl/gl_egl_api_implementation.h"
 #include "ui/gl/gl_surface.h"
 #include "ui/gl/gl_utils.h"
-#include "ui/gl/init/gl_factory.h"
-#include "ui/gl/init/gl_initializer.h"
 #include "ui/ozone/common/native_pixmap_egl_binding.h"
 
-#include <EGL/egl.h>
-#include <dlfcn.h>
-
 namespace ui {
 
-bool GLOzoneEGLQt::LoadGLES2Bindings(const gl::GLImplementationParts & /*implementation*/)
+bool LoadQtEGLBindings()
 {
-    base::NativeLibrary eglgles2Library = dlopen(NULL, RTLD_LAZY);
-    if (!eglgles2Library) {
-        LOG(ERROR) << "Failed to open EGL/GLES2 context " << dlerror();
-        return false;
-    }
-
-    gl::GLGetProcAddressProc get_proc_address =
-            reinterpret_cast<gl::GLGetProcAddressProc>(
-                base::GetFunctionPointerFromNativeLibrary(eglgles2Library,
-                                                          "eglGetProcAddress"));
-    if (!get_proc_address) {
-        // QTBUG-63341 most likely libgles2 not linked with libegl -> fallback to qpa
-        get_proc_address =
-                reinterpret_cast<gl::GLGetProcAddressProc>(GLContextHelper::getEglGetProcAddress());
-    }
-
+    gl::GLGetProcAddressProc get_proc_address = reinterpret_cast<gl::GLGetProcAddressProc>(GLContextHelper::getEglGetProcAddress());
     if (!get_proc_address) {
         LOG(ERROR) << "eglGetProcAddress not found.";
-        base::UnloadNativeLibrary(eglgles2Library);
         return false;
     }
-
     gl::SetGLGetProcAddressProc(get_proc_address);
-    gl::AddGLNativeLibrary(eglgles2Library);
     return true;
 }
 
-gl::GLDisplay *GLOzoneEGLQt::InitializeGLOneOffPlatform(uint64_t system_device_id)
+bool GLOzoneEGLQt::LoadGLES2Bindings(const gl::GLImplementationParts & /*implementation*/)
 {
-    if (auto display = gl::GLSurfaceEGLQt::InitializeOneOff(system_device_id)) {
-        if (!static_cast<gl::GLDisplayEGL*>(display)->Initialize(GetNativeDisplay())) {
+    return LoadQtEGLBindings();
+}
+
+gl::GLDisplay *GLOzoneEGLQt::InitializeGLOneOffPlatform(bool supports_angle,
+                                                        std::vector<gl::DisplayType> init_displays,
+                                                        gl::GpuPreference gpu_preference)
+{
+    if (auto display = gl::GLSurfaceEGLQt::InitializeOneOff(gpu_preference)) {
+        if (!static_cast<gl::GLDisplayEGL*>(display)->Initialize(supports_angle, std::move(init_displays), GetNativeDisplay())) {
             LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
             return nullptr;
         }
@@ -66,6 +45,7 @@ gl::GLDisplay *GLOzoneEGLQt::InitializeGLOneOffPlatform(uint64_t system_device_i
     return nullptr;
 }
 
+
 bool GLOzoneEGLQt::InitializeExtensionSettingsOneOffPlatform(gl::GLDisplay *display)
 {
     return static_cast<gl::GLDisplayEGL*>(display)->InitializeExtensionSettings();
diff --git a/src/core/ozone/gl_ozone_egl_qt.h b/src/core/ozone/gl_ozone_egl_qt.h
index 6a313c8faac..7ac55979a86 100644
--- a/src/core/ozone/gl_ozone_egl_qt.h
+++ b/src/core/ozone/gl_ozone_egl_qt.h
@@ -12,7 +12,9 @@ namespace ui {
 
 class GLOzoneEGLQt : public GLOzoneEGL {
 public:
-    gl::GLDisplay *InitializeGLOneOffPlatform(uint64_t system_device_id) override;
+    gl::GLDisplay *InitializeGLOneOffPlatform(bool supports_angle,
+                                              std::vector<gl::DisplayType> init_displays,
+                                              gl::GpuPreference gpu_preference) override;
     bool InitializeExtensionSettingsOneOffPlatform(gl::GLDisplay *display) override;
     scoped_refptr<gl::GLSurface> CreateViewGLSurface(
             gl::GLDisplay *display,
diff --git a/src/core/ozone/gl_ozone_glx_qt.cpp b/src/core/ozone/gl_ozone_glx_qt.cpp
index e9946806aeb..a4a4ac5fbaa 100644
--- a/src/core/ozone/gl_ozone_glx_qt.cpp
+++ b/src/core/ozone/gl_ozone_glx_qt.cpp
@@ -14,14 +14,16 @@
 #include "ui/gl/gl_context_glx.h"
 #include "ui/gl/gl_gl_api_implementation.h"
 #include "ui/gl/gl_glx_api_implementation.h"
+#include "ui/gl/presenter.h"
 #include "ui/ozone/platform/x11/native_pixmap_glx_binding.h"
 
 #include <dlfcn.h>
 
 namespace ui {
 
-gl::GLDisplay *GLOzoneGLXQt::InitializeGLOneOffPlatform(uint64_t system_device_id) {
-    return gl::GLSurfaceGLXQt::InitializeOneOff(system_device_id);
+gl::GLDisplay *GLOzoneGLXQt::InitializeGLOneOffPlatform(bool, std::vector<gl::DisplayType>, gl::GpuPreference preference)
+{
+    return gl::GLSurfaceGLXQt::InitializeOneOff(preference);
 }
 
 bool GLOzoneGLXQt::InitializeStaticGLBindings(
@@ -91,7 +93,7 @@ scoped_refptr<gl::GLSurface> GLOzoneGLXQt::CreateViewGLSurface(
     return nullptr;
 }
 
-scoped_refptr<gl::GLSurface> GLOzoneGLXQt::CreateSurfacelessViewGLSurface(
+scoped_refptr<gl::Presenter> GLOzoneGLXQt::CreateSurfacelessViewGLSurface(
         gl::GLDisplay* display,
         gfx::AcceleratedWidget window) {
     return nullptr;
diff --git a/src/core/ozone/gl_ozone_glx_qt.h b/src/core/ozone/gl_ozone_glx_qt.h
index cc0feb563be..4df26ba7124 100644
--- a/src/core/ozone/gl_ozone_glx_qt.h
+++ b/src/core/ozone/gl_ozone_glx_qt.h
@@ -15,7 +15,7 @@ class GLOzoneGLXQt : public GLOzone {
     GLOzoneGLXQt() {}
     ~GLOzoneGLXQt() override {}
 
-    gl::GLDisplay *InitializeGLOneOffPlatform(uint64_t system_device_id) override;
+    gl::GLDisplay *InitializeGLOneOffPlatform(bool, std::vector<gl::DisplayType>, gl::GpuPreference) override;
     bool InitializeStaticGLBindings(const gl::GLImplementationParts &implementation) override;
     bool InitializeExtensionSettingsOneOffPlatform(gl::GLDisplay *display) override;
     void ShutdownGL(gl::GLDisplay *display) override;
@@ -39,7 +39,7 @@ class GLOzoneGLXQt : public GLOzone {
             gl::GLDisplay* display,
             gfx::AcceleratedWidget window) override;
 
-    scoped_refptr<gl::GLSurface> CreateSurfacelessViewGLSurface(
+    scoped_refptr<gl::Presenter> CreateSurfacelessViewGLSurface(
             gl::GLDisplay* display,
             gfx::AcceleratedWidget window) override;
 
diff --git a/src/core/ozone/gl_share_context_qt.cpp b/src/core/ozone/gl_share_context_qt.cpp
index 35bd18f22de..b1c5e201f10 100644
--- a/src/core/ozone/gl_share_context_qt.cpp
+++ b/src/core/ozone/gl_share_context_qt.cpp
@@ -12,10 +12,6 @@
 #include <QtGui/qopenglcontext_platform.h>
 #include <QOpenGLContext>
 #include <QOpenGLExtraFunctions>
-
-#if defined(Q_OS_MACOS)
-#include "macos_context_type_helper.h"
-#endif // defined(Q_OS_MACOS)
 #endif // QT_CONFIG(opengl)
 
 namespace QtWebEngineCore {
@@ -25,9 +21,7 @@ QtShareGLContext::QtShareGLContext(QOpenGLContext *context)
 {
 #if QT_CONFIG(opengl)
 #if defined(Q_OS_MACOS)
-    auto *mac_ctx = context->nativeInterface<QNativeInterface::QCocoaGLContext>();
-    if (mac_ctx)
-        m_handle = cglContext(mac_ctx->nativeContext());
+    qFatal("macOS only support using ANGLE.");
 #endif
 #if defined(Q_OS_WIN)
     auto *win_ctx = context->nativeInterface<QNativeInterface::QWGLContext>();
diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp
index b83f8f50664..a0c120ac61c 100644
--- a/src/core/ozone/gl_surface_egl_qt.cpp
+++ b/src/core/ozone/gl_surface_egl_qt.cpp
@@ -12,7 +12,6 @@
 #include "ui/gl/gl_bindings.h"
 #include "ui/gl/gl_display.h"
 #include "ui/gl/gl_display_manager.h"
-#include "ui/gl/gl_surface_egl.h"
 #include "ui/gl/init/gl_factory.h"
 
 #if !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN)
@@ -21,75 +20,6 @@ using ui::GetLastEGLErrorString;
 
 namespace gl {
 
-bool GLDisplayEGL::InitializeExtensionSettings()
-{
-    if (display_ == EGL_NO_DISPLAY)
-        return false;
-    ext->UpdateConditionalExtensionSettings(display_);
-    return true;
-}
-
-GLDisplayEGL *GLDisplayEGL::GetDisplayForCurrentContext()
-{
-    GLContext *context = GLContext::GetCurrent();
-    return context ? context->GetGLDisplayEGL() : nullptr;
-}
-
-bool GLDisplayEGL::IsEGLSurfacelessContextSupported()
-{
-    return GLSurfaceEGLQt::g_egl_surfaceless_context_supported;
-}
-
-bool GLDisplayEGL::IsEGLContextPrioritySupported()
-{
-    return false;
-}
-
-bool GLDisplayEGL::Initialize(gl::EGLDisplayPlatform native_display)
-{
-    auto glDisplay = GLSurfaceEGLQt::InitializeOneOff(0);
-
-    if (glDisplay) {
-        display_ = glDisplay->GetDisplay();
-        native_display_ = native_display;
-        std::string platform_extensions(ext->GetPlatformExtensions(display_));
-        gfx::ExtensionSet extensions(gfx::MakeExtensionSet(platform_extensions));
-        ext->b_EGL_EXT_image_dma_buf_import =
-                gfx::HasExtension(extensions, "EGL_EXT_image_dma_buf_import");
-        ext->b_EGL_EXT_image_dma_buf_import_modifiers =
-                gfx::HasExtension(extensions, "EGL_EXT_image_dma_buf_import_modifiers");
-//        ext->InitializeExtensionSettings(display_); Not functional for us at this moment
-    }
-
-    return glDisplay;
-}
-
-bool GLDisplayEGL::IsAndroidNativeFenceSyncSupported()
-{
-    return false;
-}
-
-// static
-GLDisplayEGL *GLSurfaceEGL::GetGLDisplayEGL()
-{
-    return GLDisplayManagerEGL::GetInstance()->GetDisplay(GpuPreference::kDefault);
-}
-
-DisplayType GLDisplayEGL::GetDisplayType() const
-{
-    return DisplayType::DEFAULT;
-}
-
-EGLDisplayPlatform GLDisplayEGL::GetNativeDisplay() const
-{
-    return native_display_;
-}
-
-GLSurface *GLSurfaceEGL::createSurfaceless(gl::GLDisplayEGL *display, const gfx::Size& size)
-{
-    return new GLSurfacelessQtEGL(display, size);
-}
-
 bool GLSurfaceEGLQt::g_egl_surfaceless_context_supported = false;
 bool GLSurfaceEGLQt::s_initialized = false;
 
@@ -104,12 +34,12 @@ GLSurfaceEGLQt::~GLSurfaceEGLQt()
     Destroy();
 }
 
-gl::GLDisplay *GLSurfaceEGLQt::InitializeOneOff(uint64_t system_device_id)
+gl::GLDisplay *GLSurfaceEGLQt::InitializeOneOff(gl::GpuPreference preference)
 {
     if (s_initialized)
         return g_display;
 
-    auto *egl_display = GLDisplayManagerEGL::GetInstance()->GetDisplay(system_device_id);
+    auto *egl_display = GLDisplayManagerEGL::GetInstance()->GetDisplay(preference);
     g_display = egl_display;
     egl_display->SetDisplay(GLContextHelper::getEGLDisplay());
     if (!egl_display->GetDisplay()) {
@@ -128,7 +58,6 @@ gl::GLDisplay *GLSurfaceEGLQt::InitializeOneOff(uint64_t system_device_id)
         return nullptr;
     }
 
-    g_client_extensions = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
     g_extensions = eglQueryString(egl_display->GetDisplay(), EGL_EXTENSIONS);
     g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions.c_str(), "EGL_KHR_surfaceless_context");
     if (g_egl_surfaceless_context_supported) {
@@ -265,15 +194,5 @@ void* GLSurfacelessQtEGL::GetShareHandle()
     return NULL;
 }
 
-std::string DisplayExtensionsEGL::GetPlatformExtensions(EGLDisplay)
-{
-    EGLDisplay display = GLContextHelper::getEGLDisplay();
-    if (display == EGL_NO_DISPLAY)
-        return "";
-
-    const char* str = eglQueryString(display, EGL_EXTENSIONS);
-    return str ? std::string(str) : "";
-}
-
 } // namespace gl
 #endif // !BUILDFLAG(IS_MAC) && !BUILDFLAG(IS_WIN)
diff --git a/src/core/ozone/gl_surface_egl_qt.h b/src/core/ozone/gl_surface_egl_qt.h
index 71992e7004e..d581f9079aa 100644
--- a/src/core/ozone/gl_surface_egl_qt.h
+++ b/src/core/ozone/gl_surface_egl_qt.h
@@ -6,7 +6,6 @@
 
 #include "gl_surface_qt.h"
 #include <EGL/egl.h>
-#include <EGL/eglext.h>
 
 namespace gl {
 
@@ -16,7 +15,7 @@ class GLSurfaceEGLQt: public GLSurfaceQt {
 public:
     explicit GLSurfaceEGLQt(gl::GLDisplayEGL *display, const gfx::Size& size);
 
-    static gl::GLDisplay *InitializeOneOff(uint64_t system_device_id);
+    static gl::GLDisplay *InitializeOneOff(gl::GpuPreference preference);
     static bool InitializeExtensionSettingsOneOff();
 
     bool Initialize(GLSurfaceFormat format) override;
diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp
index 21de815a81f..a2a76ce00d0 100644
--- a/src/core/ozone/gl_surface_glx_qt.cpp
+++ b/src/core/ozone/gl_surface_glx_qt.cpp
@@ -88,12 +88,12 @@ GLSurfaceGLXQt::~GLSurfaceGLXQt()
     Destroy();
 }
 
-GLDisplay *GLSurfaceGLXQt::InitializeOneOff(uint64_t system_device_id)
+GLDisplay *GLSurfaceGLXQt::InitializeOneOff(gl::GpuPreference preference)
 {
     if (s_initialized)
         return g_display;
 
-    g_display = GLDisplayManagerX11::GetInstance()->GetDisplay(system_device_id);
+    g_display = GLDisplayManagerX11::GetInstance()->GetDisplay(preference);
     if (!g_display->GetDisplay()) {
         LOG(ERROR) << "GLContextHelper::getXDisplay() failed.";
         return nullptr;
diff --git a/src/core/ozone/gl_surface_glx_qt.h b/src/core/ozone/gl_surface_glx_qt.h
index f81f6e9df60..8cbf1fcf297 100644
--- a/src/core/ozone/gl_surface_glx_qt.h
+++ b/src/core/ozone/gl_surface_glx_qt.h
@@ -12,7 +12,7 @@ class GLSurfaceGLXQt: public GLSurfaceQt {
 public:
     explicit GLSurfaceGLXQt(const gfx::Size& size);
 
-    static gl::GLDisplay *InitializeOneOff(uint64_t system_device_id);
+    static gl::GLDisplay *InitializeOneOff(gl::GpuPreference preference);
     static bool InitializeExtensionSettingsOneOff();
 
     bool Initialize(GLSurfaceFormat format) override;
diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp
index b6242b427a0..67d534f95bf 100644
--- a/src/core/ozone/gl_surface_qt.cpp
+++ b/src/core/ozone/gl_surface_qt.cpp
@@ -16,9 +16,9 @@
 #if BUILDFLAG(IS_WIN)
 #include "web_engine_context.h"
 #include "ozone/gl_surface_wgl_qt.h"
-#include "ozone/gl_surface_egl_qt.h"
 
 #include "gpu/ipc/service/image_transport_surface.h"
+#include "ui/gl/init/gl_display_initializer.h"
 #include "ui/gl/direct_composition_support.h"
 #include "ui/gl/gl_display.h"
 #include "ui/gl/gl_implementation.h"
@@ -32,7 +32,6 @@ namespace gl {
 
 GLDisplay *GLSurfaceQt::g_display = nullptr;
 void *GLSurfaceQt::g_config = nullptr;
-std::string GLSurfaceQt::g_client_extensions;
 std::string GLSurfaceQt::g_extensions;
 
 GLSurfaceQt::~GLSurfaceQt()
@@ -62,7 +61,7 @@ bool GLSurfaceQt::IsOffscreen()
     return true;
 }
 
-gfx::SwapResult GLSurfaceQt::SwapBuffers(PresentationCallback callback, FrameData data)
+gfx::SwapResult GLSurfaceQt::SwapBuffers(PresentationCallback callback, gfx::FrameData data)
 {
     LOG(ERROR) << "Attempted to call SwapBuffers on a pbuffer.";
     Q_UNREACHABLE();
@@ -92,18 +91,18 @@ void* GLSurfaceQt::GetConfig()
 #if BUILDFLAG(IS_WIN)
 namespace init {
 
-gl::GLDisplay *InitializeGLOneOffPlatform(uint64_t system_device_id)
+gl::GLDisplay *InitializeGLOneOffPlatform(gl::GpuPreference gpu_preference)
 {
     VSyncProviderWin::InitializeOneOff();
 
     if (GetGLImplementation() == kGLImplementationDesktopGL || GetGLImplementation() == kGLImplementationDesktopGLCoreProfile)
-        return GLSurfaceWGLQt::InitializeOneOff(system_device_id);
+        return GLSurfaceWGLQt::InitializeOneOff(gpu_preference);
 
-    GLDisplayEGL *display = GetDisplayEGL(system_device_id);
+    GLDisplayEGL *display = GetDisplayEGL(gpu_preference);
     switch (GetGLImplementation()) {
     case kGLImplementationEGLANGLE:
     case kGLImplementationEGLGLES2:
-        if (!display->Initialize(EGLDisplayPlatform(GetDC(nullptr)))) {
+        if (!InitializeDisplay(display, EGLDisplayPlatform(GetDC(nullptr)))) {
             LOG(ERROR) << "GLDisplayEGL::Initialize failed.";
             return nullptr;
         }
diff --git a/src/core/ozone/gl_surface_qt.h b/src/core/ozone/gl_surface_qt.h
index 0ef8fbbcae5..1ae41a078e5 100644
--- a/src/core/ozone/gl_surface_qt.h
+++ b/src/core/ozone/gl_surface_qt.h
@@ -21,7 +21,7 @@ class GLSurfaceQt: public GLSurface {
     GLDisplay *GetGLDisplay() override;
     void *GetConfig() override;
     bool IsOffscreen() override;
-    gfx::SwapResult SwapBuffers(PresentationCallback callback, FrameData data) override;
+    gfx::SwapResult SwapBuffers(PresentationCallback callback, gfx::FrameData data) override;
     gfx::Size GetSize() override;
     GLSurfaceFormat GetFormat() override;
 
@@ -36,7 +36,6 @@ class GLSurfaceQt: public GLSurface {
     static void* g_config;
     static GLDisplay *g_display;
     static std::string g_extensions;
-    static std::string g_client_extensions;
 };
 
 } // namespace gl
diff --git a/src/core/ozone/gl_surface_wgl_qt.cpp b/src/core/ozone/gl_surface_wgl_qt.cpp
index 0788a04c14e..db4aed88461 100644
--- a/src/core/ozone/gl_surface_wgl_qt.cpp
+++ b/src/core/ozone/gl_surface_wgl_qt.cpp
@@ -20,10 +20,10 @@ GLSurfaceWGLQt::~GLSurfaceWGLQt()
     Destroy();
 }
 
-gl::GLDisplay *GLSurfaceWGLQt::InitializeOneOff(uint64_t system_device_id)
+gl::GLDisplay *GLSurfaceWGLQt::InitializeOneOff(gl::GpuPreference gpu_preference)
 {
     if (GLSurfaceWGL::InitializeOneOff())
-        return GLDisplayManagerWGL::GetInstance()->GetDisplay(GpuPreference::kDefault);
+        return GLDisplayManagerWGL::GetInstance()->GetDisplay(gpu_preference);
 
     return nullptr;
 }
diff --git a/src/core/ozone/gl_surface_wgl_qt.h b/src/core/ozone/gl_surface_wgl_qt.h
index 5b671ebd931..6c590e46c6d 100644
--- a/src/core/ozone/gl_surface_wgl_qt.h
+++ b/src/core/ozone/gl_surface_wgl_qt.h
@@ -16,7 +16,7 @@ class GLSurfaceWGLQt: public GLSurfaceQt {
 public:
     explicit GLSurfaceWGLQt(const gfx::Size& size);
 
-    static gl::GLDisplay *InitializeOneOff(uint64_t system_device_id);
+    static gl::GLDisplay *InitializeOneOff(gl::GpuPreference gpu_preference);
 
     bool Initialize(GLSurfaceFormat format) override;
     void Destroy() override;
diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp
index 8dcb56446fc..12a204f20b0 100644
--- a/src/core/ozone/ozone_platform_qt.cpp
+++ b/src/core/ozone/ozone_platform_qt.cpp
@@ -70,13 +70,14 @@ class OzonePlatformQt : public OzonePlatform {
         static OzonePlatform::PlatformRuntimeProperties properties;
 #if BUILDFLAG(USE_VAAPI)
         if (has_initialized_gpu()) {
+#if BUILDFLAG(USE_VAAPI_X11)
             if (GetQtXDisplay()) {
                 // This property is set when the GetPlatformRuntimeProperties is
                 // called on the gpu process side.
                 properties.supports_native_pixmaps = ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device();
-            } else {
+            } else
+#endif
                 properties.supports_native_pixmaps = true; // buffer_manager_->GetGbmDevice() != nullptr
-            }
         }
 #endif
         return properties;
diff --git a/src/core/ozone/platform_window_qt.cpp b/src/core/ozone/platform_window_qt.cpp
index fe8a715ce7e..4923f0f8884 100644
--- a/src/core/ozone/platform_window_qt.cpp
+++ b/src/core/ozone/platform_window_qt.cpp
@@ -3,7 +3,7 @@
 
 #if defined(USE_OZONE)
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "ozone/platform_window_qt.h"
 #include "ui/base/cursor/platform_cursor.h"
 #include "ui/events/ozone/events_ozone.h"
diff --git a/src/core/ozone/platform_window_qt.h b/src/core/ozone/platform_window_qt.h
index 0d1743f6830..c025102bbfb 100644
--- a/src/core/ozone/platform_window_qt.h
+++ b/src/core/ozone/platform_window_qt.h
@@ -33,7 +33,7 @@ class PlatformWindowQt : public PlatformWindow, public PlatformEventDispatcher
     void SetCapture() override { }
     void ReleaseCapture() override { }
     bool HasCapture() const override { return false; }
-    void ToggleFullscreen() override { }
+    void SetFullscreen(bool, int64_t) override { }
     void Maximize() override { }
     void Minimize() override { }
     void Restore() override { }
diff --git a/src/core/pdf_util_qt.cpp b/src/core/pdf_util_qt.cpp
new file mode 100644
index 00000000000..9503f59109f
--- /dev/null
+++ b/src/core/pdf_util_qt.cpp
@@ -0,0 +1,92 @@
+// Copyright (C) 2023 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 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE.Chromium file.
+
+#include "pdf_util_qt.h"
+
+#include <QtGlobal>
+
+#include "base/check.h"
+#include "chrome/common/webui_url_constants.h"
+#include "content/public/browser/render_frame_host.h"
+#include "content/public/browser/render_process_host.h"
+#include "content/public/browser/web_contents.h"
+#include "extensions/buildflags/buildflags.h"
+#include "url/gurl.h"
+#include "url/origin.h"
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
+#include "extensions/common/constants.h"
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+
+namespace QtWebEngineCore {
+
+bool IsPdfExtensionOrigin(const url::Origin &origin)
+{
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    return origin.scheme() == extensions::kExtensionScheme
+        && origin.host() == extension_misc::kPdfExtensionId;
+#else
+    Q_UNUSED(origin);
+    return false;
+#endif
+}
+
+bool IsPdfInternalPluginAllowedOrigin(const url::Origin &origin)
+{
+    if (IsPdfExtensionOrigin(origin))
+        return true;
+
+    // Allow embedding the internal PDF plugin in chrome://print.
+    if (origin == url::Origin::Create(GURL(chrome::kChromeUIPrintURL)))
+        return true;
+
+    // Only allow the PDF plugin in the known, trustworthy origins that are
+    // allowlisted above.  See also https://crbug.com/520422 and
+    // https://crbug.com/1027173.
+    return false;
+}
+
+content::RenderFrameHost *GetFullPagePlugin(content::WebContents *contents)
+{
+    content::RenderFrameHost *full_page_plugin = nullptr;
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    contents->ForEachRenderFrameHostWithAction([&full_page_plugin](content::RenderFrameHost *rfh) {
+        auto* guest_view = extensions::MimeHandlerViewGuest::FromRenderFrameHost(rfh);
+        if (guest_view && guest_view->is_full_page_plugin()) {
+            DCHECK_EQ(guest_view->GetGuestMainFrame(), rfh);
+            full_page_plugin = rfh;
+            return content::RenderFrameHost::FrameIterationAction::kStop;
+        }
+        return content::RenderFrameHost::FrameIterationAction::kContinue;
+    });
+#endif  // BUILDFLAG(ENABLE_EXTENSIONS)
+    return full_page_plugin;
+}
+
+content::RenderFrameHost *FindPdfChildFrame(content::RenderFrameHost *rfh)
+{
+    if (!rfh)
+        return nullptr;
+
+    if (!IsPdfExtensionOrigin(rfh->GetLastCommittedOrigin()))
+        return nullptr;
+
+    content::RenderFrameHost *pdf_rfh = nullptr;
+    rfh->ForEachRenderFrameHost([&pdf_rfh](content::RenderFrameHost *rfh) {
+        if (!rfh->GetProcess()->IsPdf())
+            return;
+
+        DCHECK(IsPdfExtensionOrigin(rfh->GetParent()->GetLastCommittedOrigin()));
+        DCHECK(!pdf_rfh);
+        pdf_rfh = rfh;
+    });
+
+    return pdf_rfh;
+}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/pdf_util_qt.h b/src/core/pdf_util_qt.h
new file mode 100644
index 00000000000..5ee211800d1
--- /dev/null
+++ b/src/core/pdf_util_qt.h
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 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 2021 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE.Chromium file.
+
+#ifndef PDF_UTIL_QT_H
+#define PDF_UTIL_QT_H
+
+namespace content {
+class RenderFrameHost;
+class WebContents;
+}  // namespace content
+
+namespace url {
+class Origin;
+}  // namespace url
+
+namespace QtWebEngineCore {
+
+// from chrome/common/pdf_util.cc:
+constexpr char kPDFMimeType[] = "application/pdf";
+
+bool IsPdfExtensionOrigin(const url::Origin &origin);
+bool IsPdfInternalPluginAllowedOrigin(const url::Origin &origin);
+
+// from chrome/browser/pdf/pdf_frame_util.cc:
+content::RenderFrameHost *GetFullPagePlugin(content::WebContents *contents);
+content::RenderFrameHost *FindPdfChildFrame(content::RenderFrameHost *rfh);
+
+} // namespace QtWebEngineCore
+
+#endif // PDF_UTIL_QT_H
diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp
index 28e1c981d9b..b44fb430092 100644
--- a/src/core/permission_manager_qt.cpp
+++ b/src/core/permission_manager_qt.cpp
@@ -33,7 +33,7 @@ static ProfileAdapter::PermissionType toQt(blink::PermissionType type)
         return ProfileAdapter::NotificationPermission;
     case blink::PermissionType::ACCESSIBILITY_EVENTS:
     case blink::PermissionType::CAMERA_PAN_TILT_ZOOM:
-    case blink::PermissionType::WINDOW_PLACEMENT:
+    case blink::PermissionType::WINDOW_MANAGEMENT:
         return ProfileAdapter::UnsupportedPermission;
     case blink::PermissionType::MIDI_SYSEX:
     case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
@@ -53,6 +53,7 @@ static ProfileAdapter::PermissionType toQt(blink::PermissionType type)
     case blink::PermissionType::STORAGE_ACCESS_GRANT:
     case blink::PermissionType::LOCAL_FONTS:
     case blink::PermissionType::DISPLAY_CAPTURE:
+    case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS:
     case blink::PermissionType::NUM:
         LOG(INFO) << "Unexpected unsupported permission type: " << static_cast<int>(type);
         break;
diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h
index 8778c538d5c..6cfeb874e4d 100644
--- a/src/core/permission_manager_qt.h
+++ b/src/core/permission_manager_qt.h
@@ -4,7 +4,7 @@
 #ifndef PERMISSION_MANAGER_QT_H
 #define PERMISSION_MANAGER_QT_H
 
-#include "base/callback.h"
+#include "base/functional/callback.h"
 #include "content/public/browser/permission_controller_delegate.h"
 
 #include "profile_adapter.h"
diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp
index b6cfc27145f..dcc7401c07d 100644
--- a/src/core/pref_service_adapter.cpp
+++ b/src/core/pref_service_adapter.cpp
@@ -87,8 +87,6 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter)
     registry->RegisterIntegerPref(prefs::kNotificationNextPersistentId, 10000);
     registry->RegisterDictionaryPref(prefs::kPushMessagingAppIdentifierMap);
     registry->RegisterListPref(prefs::kAccountInfo);
-    registry->RegisterStringPref(prefs::kGoogleServicesLastAccountId,
-                               std::string());
     registry->RegisterStringPref(prefs::kGoogleServicesLastUsername,
                                std::string());
     registry->RegisterStringPref(prefs::kGoogleServicesAccountId, std::string());
@@ -113,6 +111,7 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter)
     registry->RegisterListPref(extensions::pref_names::kNativeMessagingBlocklist);
     registry->RegisterListPref(extensions::pref_names::kNativeMessagingAllowlist);
     registry->RegisterBooleanPref(extensions::pref_names::kNativeMessagingUserLevelHosts, true);
+    registry->RegisterListPref(extensions::pref_names::kExtendedBackgroundLifetimeForPortConnectionsToUrls);
 #endif // BUILDFLAG(ENABLE_EXTENSIONS)
 
     // Media device salt id key
diff --git a/src/core/printing/pdf_web_contents_helper_client_qt.cpp b/src/core/printing/pdf_web_contents_helper_client_qt.cpp
index 4deb398c6ee..0ff7499c353 100644
--- a/src/core/printing/pdf_web_contents_helper_client_qt.cpp
+++ b/src/core/printing/pdf_web_contents_helper_client_qt.cpp
@@ -9,33 +9,7 @@
 #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h"
 #include "extensions/common/constants.h"
 
-namespace {
-bool IsPdfExtensionOrigin(const url::Origin &origin)
-{
-    return origin.scheme() == extensions::kExtensionScheme &&
-           origin.host() == extension_misc::kPdfExtensionId;
-}
-
-// from chrome/browser/pdf/pdf_frame_util.cc:
-content::RenderFrameHost *FindPdfChildFrame(content::RenderFrameHost *rfh)
-{
-    if (!IsPdfExtensionOrigin(rfh->GetLastCommittedOrigin()))
-        return nullptr;
-
-    content::RenderFrameHost *pdf_rfh = nullptr;
-    rfh->ForEachRenderFrameHost(
-                    [&pdf_rfh](content::RenderFrameHost *rfh) {
-                        if (!rfh->GetProcess()->IsPdf())
-                            return;
-
-                        DCHECK(IsPdfExtensionOrigin(rfh->GetParent()->GetLastCommittedOrigin()));
-                        DCHECK(!pdf_rfh);
-                        pdf_rfh = rfh;
-                    });
-
-    return pdf_rfh;
-}
-}  // namespace
+#include "pdf_util_qt.h"
 
 PDFWebContentsHelperClientQt::PDFWebContentsHelperClientQt() = default;
 PDFWebContentsHelperClientQt::~PDFWebContentsHelperClientQt() = default;
@@ -43,7 +17,7 @@ PDFWebContentsHelperClientQt::~PDFWebContentsHelperClientQt() = default;
 content::RenderFrameHost *PDFWebContentsHelperClientQt::FindPdfFrame(content::WebContents *contents)
 {
     content::RenderFrameHost *main_frame = contents->GetPrimaryMainFrame();
-    content::RenderFrameHost *pdf_frame = FindPdfChildFrame(main_frame);
+    content::RenderFrameHost *pdf_frame = QtWebEngineCore::FindPdfChildFrame(main_frame);
     return pdf_frame ? pdf_frame : main_frame;
 }
 
diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp
index f071b59ad2f..d6113ecd944 100644
--- a/src/core/printing/print_view_manager_base_qt.cpp
+++ b/src/core/printing/print_view_manager_base_qt.cpp
@@ -65,8 +65,6 @@ void OnDidGetDefaultPrintSettings(scoped_refptr<printing::PrintQueriesQueue> que
         // If user hasn't cancelled.
         if (printer_query->cookie() && printer_query->settings().dpi()) {
             queue->QueuePrinterQuery(std::move(printer_query));
-        } else {
-            printer_query->StopWorker();
         }
     }
 }
@@ -109,8 +107,6 @@ void OnDidUpdatePrintSettings(scoped_refptr<printing::PrintQueriesQueue> queue,
 
     if (printer_query->cookie() && printer_query->settings().dpi()) {
         queue->QueuePrinterQuery(std::move(printer_query));
-    } else {
-        printer_query->StopWorker();
     }
 }
 
@@ -132,8 +128,6 @@ void OnDidScriptedPrint(scoped_refptr<printing::PrintQueriesQueue> queue,
 
     if (has_dpi && has_valid_cookie) {
         queue->QueuePrinterQuery(std::move(printer_query));
-    } else {
-        printer_query->StopWorker();
     }
 }
 
@@ -145,9 +139,6 @@ PrintViewManagerBaseQt::PrintViewManagerBaseQt(content::WebContents *contents)
     , m_didPrintingSucceed(false)
     , m_printerQueriesQueue(WebEngineContext::current()->getPrintJobManager()->queue())
 {
-    // FIXME: Check if this needs to be executed async:
-    // TODO: Add isEnabled to profile
-    PrintViewManagerBaseQt::UpdatePrintingEnabled();
 }
 
 PrintViewManagerBaseQt::~PrintViewManagerBaseQt()
@@ -181,18 +172,6 @@ void PrintViewManagerBaseQt::ScriptedPrintReply(ScriptedPrintCallback callback,
     std::move(callback).Run(std::move(params));
 }
 
-void PrintViewManagerBaseQt::UpdatePrintingEnabled()
-{
-    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
-    bool enabled = false;
-#if QT_CONFIG(webengine_printing_and_pdf)
-    enabled = true;
-#endif
-    web_contents()->ForEachRenderFrameHost([this, enabled](content::RenderFrameHost *rfh) {
-        SendPrintingEnabled(enabled, rfh);
-    });
-}
-
 void PrintViewManagerBaseQt::NavigationStopped()
 {
     // Cancel the current job, wait for the worker to finish.
@@ -284,6 +263,7 @@ void PrintViewManagerBaseQt::GetDefaultPrintSettings(GetDefaultPrintSettingsCall
      printer_query_ptr->GetDefaultSettings(
                  base::BindOnce(&OnDidGetDefaultPrintSettings, m_printerQueriesQueue,
                                 std::move(printer_query), std::move(callback_wrapper)),
+                 false,
                  !render_process_host->IsPdf());
 }
 
@@ -298,6 +278,15 @@ void PrintViewManagerBaseQt::PrintingFailed(int32_t cookie, printing::mojom::Pri
 
     ReleasePrinterQuery();
 }
+void PrintViewManagerBaseQt::IsPrintingEnabled(IsPrintingEnabledCallback callback)
+{
+    DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+    bool enabled = false;
+#if QT_CONFIG(webengine_printing_and_pdf)
+    enabled = true;
+#endif
+    std::move(callback).Run(enabled);
+}
 
 void PrintViewManagerBaseQt::ScriptedPrint(printing::mojom::ScriptedPrintParamsPtr params,
                                            printing::mojom::PrintManagerHost::ScriptedPrintCallback callback)
@@ -324,15 +313,6 @@ void PrintViewManagerBaseQt::ScriptedPrint(printing::mojom::ScriptedPrintParamsP
                 base::BindOnce(&OnDidScriptedPrint, m_printerQueriesQueue, std::move(printer_query), std::move(callback_wrapper)));
 }
 
-void PrintViewManagerBaseQt::ShowInvalidPrinterSettingsError()
-{
-}
-
-void PrintViewManagerBaseQt::DidStartLoading()
-{
-    UpdatePrintingEnabled();
-}
-
 // Note: In PrintViewManagerQt we always initiate printing with
 // printing::mojom::PrintRenderFrame::InitiatePrintPreview()
 // so m_printingRFH is never set and used at the moment.
@@ -536,11 +516,10 @@ bool PrintViewManagerBaseQt::RunInnerMessageLoop()
 
   m_quitInnerLoop = run_loop.QuitClosure();
 
-  // Need to enable recursive task.
-  {
-      base::CurrentThread::ScopedNestableTaskAllower allow;
-      run_loop.Run();
-  }
+  auto weak_this = weak_ptr_factory_.GetWeakPtr();
+  run_loop.Run();
+  if (!weak_this)
+      return false;
 
   bool success = !m_quitInnerLoop;
   m_quitInnerLoop.Reset();
@@ -591,11 +570,8 @@ void PrintViewManagerBaseQt::ReleasePrinterQuery()
     if (!printJobManager)
         return;
 
-    std::unique_ptr<printing::PrinterQuery> printerQuery;
-    printerQuery = m_printerQueriesQueue->PopPrinterQuery(cookie);
-    if (!printerQuery)
-        return;
-    printerQuery->StopWorker();
+    std::unique_ptr<printing::PrinterQuery> printerQuery =
+            m_printerQueriesQueue->PopPrinterQuery(cookie);
 }
 
 // Originally from print_preview_message_handler.cc:
@@ -605,15 +581,6 @@ void PrintViewManagerBaseQt::StopWorker(int documentCookie)
         return;
     std::unique_ptr<printing::PrinterQuery> printerQuery =
             m_printerQueriesQueue->PopPrinterQuery(documentCookie);
-    if (!printerQuery)
-        return;
-    printerQuery->StopWorker();
-}
-
-void PrintViewManagerBaseQt::SendPrintingEnabled(bool enabled, content::RenderFrameHost* rfh)
-{
-    if (rfh->IsRenderFrameLive())
-        GetPrintRenderFrame(rfh)->SetPrintingEnabled(enabled);
 }
 
 void PrintViewManagerBaseQt::UpdatePrintSettings(int32_t cookie, base::Value::Dict job_settings,
diff --git a/src/core/printing/print_view_manager_base_qt.h b/src/core/printing/print_view_manager_base_qt.h
index 8201a42253c..e8e59f8a5e4 100644
--- a/src/core/printing/print_view_manager_base_qt.h
+++ b/src/core/printing/print_view_manager_base_qt.h
@@ -36,9 +36,6 @@ class PrintViewManagerBaseQt : public printing::PrintManager
 public:
     ~PrintViewManagerBaseQt() override;
 
-    // Whether printing is enabled or not.
-    void UpdatePrintingEnabled();
-
     std::u16string RenderSourceName();
 
     // mojom::PrintManagerHost:
@@ -48,9 +45,9 @@ class PrintViewManagerBaseQt : public printing::PrintManager
     void GetDefaultPrintSettings(GetDefaultPrintSettingsCallback callback) override;
     void UpdatePrintSettings(int32_t cookie, base::Value::Dict job_settings,
                              UpdatePrintSettingsCallback callback) override;
+    void IsPrintingEnabled(IsPrintingEnabledCallback callback) override;
     void ScriptedPrint(printing::mojom::ScriptedPrintParamsPtr,
                        printing::mojom::PrintManagerHost::ScriptedPrintCallback) override;
-    void ShowInvalidPrinterSettingsError() override;
     void PrintingFailed(int32_t cookie,
                         printing::mojom::PrintFailureReason reason) override;
 
@@ -83,9 +80,6 @@ class PrintViewManagerBaseQt : public printing::PrintManager
     void StopWorker(int documentCookie);
 
 private:
-    // content::WebContentsObserver implementation.
-    void DidStartLoading() override;
-
     // Requests the RenderView to render all the missing pages for the print job.
     // No-op if no print job is pending. Returns true if at least one page has
     // been requested to the renderer.
@@ -136,9 +130,6 @@ class PrintViewManagerBaseQt : public printing::PrintManager
     // Release the PrinterQuery associated with our |cookie_|.
     void ReleasePrinterQuery();
 
-    // Helper method for UpdatePrintingEnabled().
-    void SendPrintingEnabled(bool enabled, content::RenderFrameHost* rfh);
-
 private:
     content::NotificationRegistrar m_registrar;
     scoped_refptr<printing::PrintJob> m_printJob;
diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp
index 7d8a796f773..060417e5b78 100644
--- a/src/core/printing/print_view_manager_qt.cpp
+++ b/src/core/printing/print_view_manager_qt.cpp
@@ -8,6 +8,7 @@
 
 #include "print_view_manager_qt.h"
 
+#include "pdf_util_qt.h"
 #include "type_conversion.h"
 #include "web_contents_adapter_client.h"
 #include "web_contents_view_qt.h"
@@ -238,7 +239,11 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout,
     if (web_contents()->IsCrashed())
         return false;
 
-    content::RenderFrameHost* rfh = web_contents()->GetPrimaryMainFrame();
+    content::RenderFrameHost *rfh = web_contents()->GetPrimaryMainFrame();
+    // Use the plugin frame for printing if web_contents() is a PDF viewer guest
+    content::RenderFrameHost *full_page_plugin = GetFullPagePlugin(web_contents());
+    if (content::RenderFrameHost *pdf_rfh = FindPdfChildFrame(full_page_plugin ? full_page_plugin : rfh))
+        rfh = pdf_rfh;
     GetPrintRenderFrame(rfh)->InitiatePrintPreview(mojo::PendingAssociatedRemote<printing::mojom::PrintRenderer>(), false);
 
     DCHECK(!m_printPreviewRfh);
@@ -336,12 +341,23 @@ void PrintViewManagerQt::ShowScriptedPrintPreview(bool /*source_is_modifiable*/)
     // ignore for now
 }
 
-void PrintViewManagerQt::RequestPrintPreview(printing::mojom::RequestPrintPreviewParamsPtr /*params*/)
+void PrintViewManagerQt::RequestPrintPreview(printing::mojom::RequestPrintPreviewParamsPtr params)
 {
+    if (!m_printPreviewRfh && params->webnode_only) {
+        // The preview was requested by the print button of PDF viewer plugin. The code path ends up here, because
+        // Chromium automatically initiated a preview generation. We don't want that, just notify our embedder
+        // like we do in SetupScriptedPrintPreview() after window.print() and let them decide what to do.
+        content::WebContentsView *view = static_cast<content::WebContentsImpl*>(web_contents()->GetOutermostWebContents())->GetView();
+        if (WebContentsAdapterClient *client = WebContentsViewQt::from(view)->client())
+            client->printRequested();
+        return;
+    }
+
     if (m_printSettings.empty()) {
         PrintPreviewDone();
         return;
     }
+
     mojo::AssociatedRemote<printing::mojom::PrintRenderFrame> printRenderFrame;
     m_printPreviewRfh->GetRemoteAssociatedInterfaces()->GetInterface(&printRenderFrame);
     printRenderFrame->PrintPreview(m_printSettings.Clone());
diff --git a/src/core/printing/printer_worker.cpp b/src/core/printing/printer_worker.cpp
index da71656236d..6032f221118 100644
--- a/src/core/printing/printer_worker.cpp
+++ b/src/core/printing/printer_worker.cpp
@@ -27,22 +27,8 @@ void PrinterWorker::print()
 
     PdfiumDocumentWrapperQt pdfiumWrapper(m_data->constData(), m_data->size());
 
-    const QPageRanges ranges = m_device->pageRanges();
-    int toPage = ranges.firstPage();
-    int fromPage = ranges.lastPage();
-    bool ascendingOrder = true;
-
-    if (fromPage == 0 && toPage == 0) {
-        fromPage = 1;
-        toPage = pdfiumWrapper.pageCount();
-    }
-    fromPage = qMax(1, fromPage);
-    toPage = qMin(pdfiumWrapper.pageCount(), toPage);
-
-    if (!m_firstPageFirst) {
-        qSwap(fromPage, toPage);
-        ascendingOrder = false;
-    }
+    const int fromPage = m_firstPageFirst ? 0 : pdfiumWrapper.pageCount() - 1;
+    const int toPage = m_firstPageFirst ? pdfiumWrapper.pageCount() : -1;
 
     int pageCopies = 1;
     if (m_collateCopies) {
@@ -58,10 +44,8 @@ void PrinterWorker::print()
         if (printedDocuments > 0)
             m_device->newPage();
 
-        int currentPageIndex = fromPage;
-
-        for (int i = 0; true; i++) {
-            QSizeF documentSize = (pdfiumWrapper.pageSize(currentPageIndex - 1) * resolution);
+        for (int i = fromPage; i != toPage; m_firstPageFirst ? i++ : i--) {
+            QSizeF documentSize = (pdfiumWrapper.pageSize(i) * resolution);
             bool isLandscape = documentSize.width() > documentSize.height();
             m_device->setPageOrientation(isLandscape ? QPageLayout::Landscape
                                                       : QPageLayout::Portrait);
@@ -77,29 +61,21 @@ void PrinterWorker::print()
                 return;
             }
 
-            if (i > 0)
+            if (i != fromPage)
                 m_device->newPage();
 
             for (int printedPages = 0; printedPages < pageCopies; printedPages++) {
                 if (printedPages > 0)
                     m_device->newPage();
 
-                QImage currentImage = pdfiumWrapper.pageAsQImage(
-                        currentPageIndex - 1, documentSize.width(), documentSize.height());
+                QImage currentImage =
+                        pdfiumWrapper.pageAsQImage(i, documentSize.width(), documentSize.height());
                 if (currentImage.isNull()) {
                     Q_EMIT resultReady(false);
                     return;
                 }
                 painter.drawImage(0, 0, currentImage);
             }
-
-            if (currentPageIndex == toPage)
-                break;
-
-            if (ascendingOrder)
-                currentPageIndex++;
-            else
-                currentPageIndex--;
         }
     }
     painter.end();
diff --git a/src/core/process_main.cpp b/src/core/process_main.cpp
index ce92db0834b..6a7d26ffd0f 100644
--- a/src/core/process_main.cpp
+++ b/src/core/process_main.cpp
@@ -39,7 +39,6 @@ int processMain(int argc, const char **argv)
     CHECK(seatbelt.server->InitializeSandbox());
   }
 #endif  // IS_MAC
-
     return content::ContentMain(std::move(params));
 }
 
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 1b71744c999..fdb01d4edab 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -191,16 +191,6 @@ void ProfileAdapter::setRequestInterceptor(QWebEngineUrlRequestInterceptor *inte
     m_requestInterceptor = interceptor;
 }
 
-QWebEngineUrlResponseInterceptor *ProfileAdapter::responseInterceptor()
-{
-    return m_responseInterceptor.data();
-}
-
-void ProfileAdapter::setResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor)
-{
-    m_responseInterceptor = interceptor;
-}
-
 void ProfileAdapter::addClient(ProfileAdapterClient *adapterClient)
 {
     m_clients.append(adapterClient);
@@ -211,9 +201,9 @@ void ProfileAdapter::removeClient(ProfileAdapterClient *adapterClient)
     m_clients.removeOne(adapterClient);
 }
 
-void ProfileAdapter::cancelDownload(quint32 downloadId)
+bool ProfileAdapter::cancelDownload(quint32 downloadId)
 {
-    downloadManagerDelegate()->cancelDownload(downloadId);
+    return downloadManagerDelegate()->cancelDownload(downloadId);
 }
 
 void ProfileAdapter::pauseDownload(quint32 downloadId)
@@ -332,7 +322,7 @@ void ProfileAdapter::setHttpUserAgent(const QString &userAgent)
         if (web_contents->GetBrowserContext() == m_profile.data())
             web_contents->SetUserAgentOverride(blink::UserAgentOverride::UserAgentOnly(stdUserAgent), true);
 
-    m_profile->ForEachStoragePartition(
+    m_profile->ForEachLoadedStoragePartition(
                 base::BindRepeating([](const std::string &user_agent, content::StoragePartition *storage_partition) {
                     storage_partition->GetNetworkContext()->SetUserAgent(user_agent);
                 }, stdUserAgent));
@@ -355,8 +345,6 @@ void ProfileAdapter::setHttpCacheType(ProfileAdapter::HttpCacheType newhttpCache
         return;
     if (!m_offTheRecord && !m_profile->m_profileIOData->isClearHttpCacheInProgress()) {
         m_profile->m_profileIOData->resetNetworkContext();
-        if (m_httpCacheType == NoCache)
-            clearHttpCache();
     }
 }
 
@@ -474,7 +462,7 @@ const QList<QByteArray> ProfileAdapter::customUrlSchemes() const
 
 void ProfileAdapter::updateCustomUrlSchemeHandlers()
 {
-    m_profile->ForEachStoragePartition(
+    m_profile->ForEachLoadedStoragePartition(
         base::BindRepeating([](content::StoragePartition *storage_partition) {
             storage_partition->ResetURLLoaderFactories();
         }));
@@ -596,7 +584,7 @@ void ProfileAdapter::setHttpAcceptLanguage(const QString &httpAcceptLanguage)
         }
     }
 
-    m_profile->ForEachStoragePartition(
+    m_profile->ForEachLoadedStoragePartition(
         base::BindRepeating([](std::string accept_language, content::StoragePartition *storage_partition) {
             storage_partition->GetNetworkContext()->SetAcceptLanguage(accept_language);
         }, http_accept_language));
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index a45a12e5c80..317364ac088 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -27,7 +27,6 @@
 #include <QtWebEngineCore/qwebengineclientcertificatestore.h>
 #include <QtWebEngineCore/qwebenginecookiestore.h>
 #include <QtWebEngineCore/qwebengineurlrequestinterceptor.h>
-#include <QtWebEngineCore/qwebengineurlresponseinterceptor.h>
 #include <QtWebEngineCore/qwebengineurlschemehandler.h>
 #include "net/qrc_url_scheme_handler.h"
 
@@ -65,14 +64,11 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT ProfileAdapter : public QObject
     QWebEngineUrlRequestInterceptor* requestInterceptor();
     void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
 
-    QWebEngineUrlResponseInterceptor *responseInterceptor();
-    void setResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor);
-
     QList<ProfileAdapterClient*> clients() { return m_clients; }
     void addClient(ProfileAdapterClient *adapterClient);
     void removeClient(ProfileAdapterClient *adapterClient);
 
-    void cancelDownload(quint32 downloadId);
+    bool cancelDownload(quint32 downloadId);
     void pauseDownload(quint32 downloadId);
     void resumeDownload(quint32 downloadId);
     void removeDownload(quint32 downloadId);
@@ -213,7 +209,6 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT ProfileAdapter : public QObject
     QWebEngineClientCertificateStore *m_clientCertificateStore = nullptr;
 #endif
     QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor;
-    QPointer<QWebEngineUrlResponseInterceptor> m_responseInterceptor;
 
     QString m_dataPath;
     QString m_downloadPath;
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
index c11d35c950e..822c923a26a 100644
--- a/src/core/profile_io_data_qt.cpp
+++ b/src/core/profile_io_data_qt.cpp
@@ -161,7 +161,7 @@ void ProfileIODataQt::resetNetworkContext()
 {
     Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
     setFullConfiguration();
-    m_profile->ForEachStoragePartition(
+    m_profile->ForEachLoadedStoragePartition(
             base::BindRepeating([](content::StoragePartition *storage) {
                 auto storage_impl = static_cast<content::StoragePartitionImpl *>(storage);
                 storage_impl->ResetURLLoaderFactories();
diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp
index 410340fb804..c912c989841 100644
--- a/src/core/profile_qt.cpp
+++ b/src/core/profile_qt.cpp
@@ -46,7 +46,12 @@
 #endif
 
 #if BUILDFLAG(ENABLE_EXTENSIONS)
+#include "base/command_line.h"
 #include "components/guest_view/browser/guest_view_manager.h"
+#include "extensions/browser/extension_pref_value_map_factory.h"
+#include "extensions/browser/extension_prefs.h"
+#include "extensions/browser/extension_prefs_factory.h"
+#include "extensions/browser/extensions_browser_client.h"
 #include "extensions/browser/pref_names.h"
 #include "extensions/browser/process_manager.h"
 #include "extensions/common/constants.h"
@@ -246,6 +251,7 @@ content::FileSystemAccessPermissionContext *ProfileQt::GetFileSystemAccessPermis
 
 void ProfileQt::setupPrefService()
 {
+    const bool recreation = m_prefServiceAdapter.prefService() != nullptr;
     profile_metrics::SetBrowserProfileType(this,
                                            IsOffTheRecord()
                                                ? profile_metrics::BrowserProfileType::kIncognito
@@ -253,12 +259,28 @@ void ProfileQt::setupPrefService()
 
     // Remove previous handler before we set a new one or we will assert
     // TODO: Remove in Qt6
-    if (m_prefServiceAdapter.prefService() != nullptr) {
+    if (recreation) {
         user_prefs::UserPrefs::Remove(this);
         m_prefServiceAdapter.commit();
     }
     m_prefServiceAdapter.setup(*m_profileAdapter);
     user_prefs::UserPrefs::Set(this, m_prefServiceAdapter.prefService());
+
+#if BUILDFLAG(ENABLE_EXTENSIONS)
+    if (recreation) {
+        // Recreate ExtensionPrefs to update its pointer to the new PrefService
+        extensions::ExtensionsBrowserClient *client = extensions::ExtensionsBrowserClient::Get();
+        std::vector<extensions::EarlyExtensionPrefsObserver *> prefsObservers;
+        client->GetEarlyExtensionPrefsObservers(this, &prefsObservers);
+        extensions::ExtensionPrefs *extensionPrefs = extensions::ExtensionPrefs::Create(
+            this, client->GetPrefServiceForContext(this),
+            this->GetPath().AppendASCII(extensions::kInstallDirectoryName),
+            ExtensionPrefValueMapFactory::GetForBrowserContext(this),
+            client->AreExtensionsDisabled(*base::CommandLine::ForCurrentProcess(), this),
+            prefsObservers);
+        extensions::ExtensionPrefsFactory::GetInstance()->SetInstanceForTesting(this, base::WrapUnique(extensionPrefs));
+    }
+#endif
 }
 
 PrefServiceAdapter &ProfileQt::prefServiceAdapter()
diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp
index 3d4e5bbc2cd..4e52041d4ae 100644
--- a/src/core/render_widget_host_view_qt.cpp
+++ b/src/core/render_widget_host_view_qt.cpp
@@ -12,7 +12,6 @@
 #include "web_contents_adapter_client.h"
 #include "web_event_factory.h"
 
-#include "base/threading/thread_task_runner_handle.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"
@@ -47,7 +46,7 @@
 #endif
 
 #if defined(USE_AURA)
-#include "ui/wm/core/cursors_aura.h"
+#include "ui/wm/core/cursor_util.h"
 #include "ui/base/cursor/cursor_size.h"
 #endif
 
@@ -145,7 +144,7 @@ class FlingingCompositor : public ui::Compositor
 
 RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget)
     : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget)
-    , m_taskRunner(base::ThreadTaskRunnerHandle::Get())
+    , m_taskRunner(base::SingleThreadTaskRunner::GetCurrentDefault())
     , m_gestureProvider(QtGestureProviderConfig(), this)
     , m_frameSinkId(host()->GetFrameSinkId())
     , m_delegateClient(new RenderWidgetHostViewQtDelegateClient(this))
@@ -368,6 +367,9 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds()
 
 void RenderWidgetHostViewQt::UpdateBackgroundColor()
 {
+    if (!m_delegate)
+        return;
+
     DCHECK(GetBackgroundColor());
     SkColor color = *GetBackgroundColor();
 
@@ -478,14 +480,13 @@ bool RenderWidgetHostViewQt::updateCursorFromResource(ui::mojom::CursorType type
     return true;
 }
 
-void RenderWidgetHostViewQt::UpdateCursor(const content::WebCursor &webCursor)
+void RenderWidgetHostViewQt::UpdateCursor(const ui::Cursor &webCursor)
 {
     DisplayCursor(webCursor);
 }
 
-void RenderWidgetHostViewQt::DisplayCursor(const content::WebCursor &webCursor)
+void RenderWidgetHostViewQt::DisplayCursor(const ui::Cursor &cursorInfo)
 {
-    const ui::Cursor &cursorInfo = webCursor.cursor();
     Qt::CursorShape shape = Qt::ArrowCursor;
     switch (cursorInfo.type()) {
     case ui::mojom::CursorType::kNull:
@@ -682,9 +683,11 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana
 
     // In case of text selection, the update is expected in RenderWidgetHostViewQt::selectionChanged().
     if (GetSelectedText().empty()) {
-        // At this point it is unknown whether the text input state has been updated due to a text selection.
-        // Keep the cursor position updated for cursor movements too.
-        delegateClient()->setCursorPosition(state->selection.start());
+        if (state->composition.has_value()) {
+            delegateClient()->setCursorPosition(state->composition->start());
+        } else {
+            delegateClient()->setCursorPosition(state->selection.start());
+        }
         m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE, type == ui::TEXT_INPUT_TYPE_PASSWORD);
     }
 
diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h
index 25fd201157d..d2bd8aaf7d2 100644
--- a/src/core/render_widget_host_view_qt.h
+++ b/src/core/render_widget_host_view_qt.h
@@ -77,8 +77,8 @@ class RenderWidgetHostViewQt
     blink::mojom::PointerLockResult LockMouse(bool) override;
     blink::mojom::PointerLockResult ChangeMouseLock(bool) override;
     void UnlockMouse() override;
-    void UpdateCursor(const content::WebCursor&) override;
-    void DisplayCursor(const content::WebCursor&) override;
+    void UpdateCursor(const ui::Cursor&) override;
+    void DisplayCursor(const ui::Cursor&) override;
     content::CursorManager *GetCursorManager() override;
     void SetIsLoading(bool) override;
     void ImeCancelComposition() override;
@@ -132,9 +132,8 @@ class RenderWidgetHostViewQt
     void SetWindowFrameInScreen(const gfx::Rect&) override { QT_NOT_YET_IMPLEMENTED }
 #endif // BUILDFLAG(IS_MAC)
     void NotifyHostAndDelegateOnWasShown(blink::mojom::RecordContentToVisibleTimeRequestPtr) override { QT_NOT_YET_IMPLEMENTED }
-    void RequestPresentationTimeFromHostOrDelegate(blink::mojom::RecordContentToVisibleTimeRequestPtr) override { QT_NOT_YET_IMPLEMENTED }
-    void CancelPresentationTimeRequestForHostAndDelegate() override { QT_NOT_YET_IMPLEMENTED }
-
+    void RequestSuccessfulPresentationTimeFromHostOrDelegate(blink::mojom::RecordContentToVisibleTimeRequestPtr) override {}
+    void CancelSuccessfulPresentationTimeRequestForHostAndDelegate() override {}
 
     // Overridden from ui::GestureProviderClient.
     void OnGestureEvent(const ui::GestureEventData& gesture) override;
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 1b30e995332..a1fb81a29b5 100644
--- a/src/core/render_widget_host_view_qt_delegate_client.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_client.cpp
@@ -16,9 +16,7 @@
 
 #include <QEvent>
 #include <QInputMethodEvent>
-#include <QScopeGuard>
 #include <QSet>
-#include <QSGNode>
 #include <QStyleHints>
 #include <QTextFormat>
 #include <QVariant>
@@ -346,6 +344,7 @@ QVariant RenderWidgetHostViewQtDelegateClient::inputMethodQuery(Qt::InputMethodQ
         }
         return QVariant();
     }
+    case Qt::ImAbsolutePosition:
     case Qt::ImCursorPosition:
         return m_cursorPosition;
     case Qt::ImAnchorPosition:
@@ -528,7 +527,7 @@ void RenderWidgetHostViewQtDelegateClient::handleTouchEvent(QTouchEvent *event)
         m_eventsToNowDelta = (base::TimeTicks::Now() - eventTimestamp).InMicroseconds();
     eventTimestamp += base::Microseconds(m_eventsToNowDelta);
 
-    auto touchPoints = mapTouchPointIds(event->touchPoints());
+    auto touchPoints = mapTouchPointIds(event->points());
     // Make sure that POINTER_DOWN action is delivered before MOVE, and MOVE before POINTER_UP
     std::sort(touchPoints.begin(), touchPoints.end(), [] (const TouchPoint &l, const TouchPoint &r) {
         return l.second.state() < r.second.state();
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 8579ce51d94..78ec06bb8ce 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.cpp
+++ b/src/core/render_widget_host_view_qt_delegate_item.cpp
@@ -22,8 +22,10 @@ RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWid
 {
     setFlag(ItemHasContents);
     setAcceptedMouseButtons(Qt::AllButtons);
+    setKeepMouseGrab(true);
     setAcceptHoverEvents(true);
     setAcceptTouchEvents(true);
+    setKeepTouchGrab(true);
     if (!isPopup) {
         setFocus(true);
         setActiveFocusOnTab(true);
@@ -33,7 +35,7 @@ RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWid
 
 RenderWidgetHostViewQtDelegateItem::~RenderWidgetHostViewQtDelegateItem()
 {
-    releaseVulkanResources();
+    releaseTextureResources();
     if (m_widgetDelegate) {
         m_widgetDelegate->Unbind();
         m_widgetDelegate->Destroy();
@@ -321,14 +323,15 @@ void RenderWidgetHostViewQtDelegateItem::itemChange(ItemChange change, const Ite
         if (value.window) {
             m_windowConnections.append(connect(value.window, &QQuickWindow::beforeRendering,
                                                this, &RenderWidgetHostViewQtDelegateItem::onBeforeRendering, Qt::DirectConnection));
-            m_windowConnections.append(connect(value.window, &QQuickWindow::afterFrameEnd,
-                                               this, &RenderWidgetHostViewQtDelegateItem::onAfterRendering, Qt::DirectConnection));
+            m_windowConnections.append(connect(value.window, &QQuickWindow::afterFrameEnd, this,
+                                               &RenderWidgetHostViewQtDelegateItem::onAfterFrameEnd,
+                                               Qt::DirectConnection));
             m_windowConnections.append(connect(value.window, SIGNAL(xChanged(int)), SLOT(onWindowPosChanged())));
             m_windowConnections.append(connect(value.window, SIGNAL(yChanged(int)), SLOT(onWindowPosChanged())));
 #if QT_CONFIG(webengine_vulkan)
             m_windowConnections.append(
                     connect(value.window, &QQuickWindow::sceneGraphAboutToStop, this,
-                            &RenderWidgetHostViewQtDelegateItem::releaseVulkanResources,
+                            &RenderWidgetHostViewQtDelegateItem::releaseTextureResources,
                             Qt::DirectConnection));
 #endif
             if (!m_isPopup)
@@ -402,7 +405,7 @@ void RenderWidgetHostViewQtDelegateItem::onBeforeRendering()
     comp->waitForTexture();
 }
 
-void RenderWidgetHostViewQtDelegateItem::onAfterRendering()
+void RenderWidgetHostViewQtDelegateItem::onAfterFrameEnd()
 {
     auto comp = compositor();
     if (!comp || comp->type() != Compositor::Type::NativeBuffer)
@@ -421,15 +424,13 @@ void RenderWidgetHostViewQtDelegateItem::onHide()
     m_client->forwardEvent(&event);
 }
 
-void RenderWidgetHostViewQtDelegateItem::releaseVulkanResources()
+void RenderWidgetHostViewQtDelegateItem::releaseTextureResources()
 {
-#if QT_CONFIG(webengine_vulkan)
     auto comp = compositor();
-    if (!comp || comp->type() != Compositor::Type::Vulkan)
+    if (!comp || (comp->type() != Compositor::Type::Vulkan && comp->type() != Compositor::Type::NativeBuffer))
         return;
 
-    comp->releaseVulkanResources(QQuickItem::window());
-#endif
+    comp->releaseResources(QQuickItem::window());
 }
 
 void RenderWidgetHostViewQtDelegateItem::adapterClientChanged(WebContentsAdapterClient *client)
@@ -448,10 +449,8 @@ void RenderWidgetHostViewQtDelegateItem::updateAdapterClientIfNeeded(WebContents
 
 void RenderWidgetHostViewQtDelegateItem::unhandledWheelEvent(QWheelEvent *ev)
 {
-    if (QWindow *w = Window()) {
-        if (QWindow *p = w->parent())
-            qApp->sendEvent(p, ev);
-    }
+    if (m_widgetDelegate)
+        m_widgetDelegate->unhandledWheelEvent(ev);
 }
 
 } // namespace QtWebEngineCore
diff --git a/src/core/render_widget_host_view_qt_delegate_item.h b/src/core/render_widget_host_view_qt_delegate_item.h
index 6af81fea38b..55f243eab59 100644
--- a/src/core/render_widget_host_view_qt_delegate_item.h
+++ b/src/core/render_widget_host_view_qt_delegate_item.h
@@ -35,6 +35,7 @@ class WidgetDelegate
     virtual void Destroy() = 0;
     virtual void Resize(int, int) { }
     virtual QWindow *Window() { return nullptr; }
+    virtual void unhandledWheelEvent(QWheelEvent *) { }
 };
 
 // Useful information keyboard and mouse QEvent propagation.
@@ -100,9 +101,9 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT RenderWidgetHostViewQtDelegateItem
 
 private Q_SLOTS:
     void onBeforeRendering();
-    void onAfterRendering();
+    void onAfterFrameEnd();
     void onWindowPosChanged();
-    void releaseVulkanResources();
+    void releaseTextureResources();
     void onHide();
 
 private:
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index 80bbabf6304..6b3df4a2791 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -10,8 +10,8 @@
 #include "renderer/web_engine_page_render_frame.h"
 #include "web_engine_library_info.h"
 
+#include "base/task/sequenced_task_runner.h"
 #include "components/autofill/content/renderer/autofill_agent.h"
-#include "components/autofill/content/renderer/autofill_assistant_agent.h"
 #include "components/autofill/content/renderer/password_autofill_agent.h"
 #include "components/autofill/content/renderer/password_generation_agent.h"
 #include "components/cdm/renderer/external_clear_key_key_system_info.h"
@@ -131,12 +131,12 @@ void ContentRendererClientQt::RenderThreadStarted()
 void ContentRendererClientQt::ExposeInterfacesToBrowser(mojo::BinderMap* binders)
 {
     binders->Add<visitedlink::mojom::VisitedLinkNotificationSink>(
-                m_visitedLinkReader->GetBindCallback(), base::SequencedTaskRunnerHandle::Get());
+                m_visitedLinkReader->GetBindCallback(), base::SingleThreadTaskRunner::GetCurrentDefault());
 
     binders->Add<web_cache::mojom::WebCache>(
                 base::BindRepeating(&web_cache::WebCacheImpl::BindReceiver,
                                     base::Unretained(m_webCacheImpl.get())),
-                base::SequencedTaskRunnerHandle::Get());
+                base::SingleThreadTaskRunner::GetCurrentDefault());
 
 #if QT_CONFIG(webengine_spellchecker)
     binders->Add<spellcheck::mojom::SpellChecker>(
@@ -147,7 +147,7 @@ void ContentRendererClientQt::ExposeInterfacesToBrowser(mojo::BinderMap* binders
                                  client->InitSpellCheck();
                              client->m_spellCheck->BindReceiver(std::move(receiver));
                          }, this),
-                 base::SequencedTaskRunnerHandle::Get());
+                 base::SingleThreadTaskRunner::GetCurrentDefault());
 #endif
 
 #if QT_CONFIG(webengine_webrtc) && QT_CONFIG(webengine_extensions)
@@ -157,7 +157,7 @@ void ContentRendererClientQt::ExposeInterfacesToBrowser(mojo::BinderMap* binders
                             mojo::PendingReceiver<chrome::mojom::WebRtcLoggingAgent> receiver) {
                                 client->GetWebRtcLoggingAgent()->AddReceiver(std::move(receiver));
                          }, this),
-                 base::SequencedTaskRunnerHandle::Get());
+                 base::SingleThreadTaskRunner::GetCurrentDefault());
 #endif
 }
 
@@ -195,8 +195,6 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr
     ExtensionsRendererClientQt::GetInstance()->RenderFrameCreated(render_frame, render_frame_observer->registry());
 #endif
 
-    autofill::AutofillAssistantAgent *autofill_assistant_agent =
-            new autofill::AutofillAssistantAgent(render_frame);
     autofill::PasswordAutofillAgent *password_autofill_agent =
             new autofill::PasswordAutofillAgent(render_frame, associated_interfaces);
     autofill::PasswordGenerationAgent *password_generation_agent =
@@ -204,7 +202,7 @@ void ContentRendererClientQt::RenderFrameCreated(content::RenderFrame *render_fr
                                                   associated_interfaces);
 
     new autofill::AutofillAgent(render_frame, password_autofill_agent, password_generation_agent,
-                                autofill_assistant_agent, associated_interfaces);
+                                associated_interfaces);
 }
 
 void ContentRendererClientQt::WebViewCreated(blink::WebView *web_view,
@@ -290,11 +288,12 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF
         // TODO(elproxy): We could potentially get better diagnostics here by first calling
         // NetErrorHelper::GetErrorStringsForDnsProbe, but that one is harder to untangle.
 
+        base::Value::Dict error_page_params;
         error_page::LocalizedError::PageState errorPageState =
                 error_page::LocalizedError::GetPageState(
                         error.reason(), error.domain(), error.url(), isPost, false,
                         error.stale_copy_in_cache(), false,
-                        RenderConfiguration::is_incognito_process(), false, false, false, locale, false);
+                        RenderConfiguration::is_incognito_process(), false, false, false, locale, false, &error_page_params);
 
         resourceId = IDR_NET_ERROR_HTML;
 
@@ -477,7 +476,7 @@ static const char kExternalClearKeyKeySystem[] = "org.chromium.externalclearkey"
 
 // External Clear Key (used for testing).
 static void AddExternalClearKey(const media::mojom::KeySystemCapabilityPtr &capability,
-                                media::KeySystemInfoVector *key_systems)
+                                media::KeySystemInfos* key_systems)
 {
     Q_UNUSED(capability);
     if (!base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting)) {
@@ -486,7 +485,7 @@ static void AddExternalClearKey(const media::mojom::KeySystemCapabilityPtr &capa
     }
 
     // TODO(xhwang): Actually use `capability` to determine capabilities.
-    key_systems->push_back(std::make_unique<cdm::ExternalClearKeyProperties>());
+    key_systems->push_back(std::make_unique<cdm::ExternalClearKeyKeySystemInfo>());
 }
 
 #if BUILDFLAG(ENABLE_WIDEVINE)
@@ -603,7 +602,7 @@ static media::SupportedCodecs GetSupportedCodecs(const media::CdmCapability& cap
 }
 
 static void AddWidevine(const media::mojom::KeySystemCapabilityPtr &capability,
-                        media::KeySystemInfoVector *key_systems)
+                        media::KeySystemInfos *key_systems)
 {
     // Codecs and encryption schemes.
     media::SupportedCodecs codecs = media::EME_CODEC_NONE;
@@ -658,11 +657,11 @@ static void AddWidevine(const media::mojom::KeySystemCapabilityPtr &capability,
 void OnKeySystemSupportUpdated(media::GetSupportedKeySystemsCB cb,
                                content::KeySystemCapabilityPtrMap key_system_capabilities)
 {
-    media::KeySystemInfoVector key_systems;
+    media::KeySystemInfos key_systems;
     for (const auto &entry : key_system_capabilities) {
+#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
         const auto &key_system = entry.first;
         const auto &capability = entry.second;
-#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
 #if BUILDFLAG(ENABLE_WIDEVINE)
         if (key_system == kWidevineKeySystem) {
             AddWidevine(capability, &key_systems);
@@ -674,9 +673,9 @@ void OnKeySystemSupportUpdated(media::GetSupportedKeySystemsCB cb,
             AddExternalClearKey(capability, &key_systems);
             continue;
         }
-#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
 
         DLOG(ERROR) << "Unrecognized key system: " << key_system;
+#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
     }
 
     cb.Run(std::move(key_systems));
diff --git a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.h b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.h
index fd808f766b2..9b9d1bca855 100644
--- a/src/core/renderer/plugins/loadable_plugin_placeholder_qt.h
+++ b/src/core/renderer/plugins/loadable_plugin_placeholder_qt.h
@@ -31,8 +31,6 @@ class LoadablePluginPlaceholderQt final : public plugins::LoadablePluginPlacehol
 
     // content::LoadablePluginPlaceholder overrides.
     blink::WebPlugin* CreatePlugin() override;
-    void OnBlockedContent(content::RenderFrame::PeripheralContentStatus status,
-                          bool is_same_origin) override {}
 
     // WebViewPlugin::Delegate (via PluginPlaceholder) methods:
     v8::Local<v8::Value> GetV8Handle(v8::Isolate* isolate) override;
diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.cpp b/src/core/renderer/print_web_view_helper_delegate_qt.cpp
index f77b6fbbc2c..f01568e6584 100644
--- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp
+++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp
@@ -15,8 +15,10 @@
 #include "chrome/common/webui_url_constants.h"
 #include "extensions/common/constants.h"
 #include "third_party/blink/public/web/web_document.h"
+#include "extensions/renderer/guest_view/mime_handler_view/post_message_support.h"
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
 
+#include "pdf_util_qt.h"
 #include "print_web_view_helper_delegate_qt.h"
 #include "web_engine_library_info.h"
 
@@ -24,33 +26,13 @@ namespace QtWebEngineCore {
 
 PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() {}
 
-bool IsPdfExtensionOrigin(const url::Origin& origin)
-{
-#if BUILDFLAG(ENABLE_EXTENSIONS)
-    return origin.scheme() == extensions::kExtensionScheme
-        && origin.host() == extension_misc::kPdfExtensionId;
-#else
-    Q_UNUSED(origin);
-    return false;
-#endif
-}
-
 blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame *frame)
 {
 #if BUILDFLAG(ENABLE_EXTENSIONS)
-    const url::Origin origin = frame->GetDocument().GetSecurityOrigin();
-    bool inside_print_preview = origin == url::Origin::Create(GURL(chrome::kChromeUIPrintURL));
-    bool inside_pdf_extension = IsPdfExtensionOrigin(origin);
-    if (inside_print_preview || inside_pdf_extension) {
-        // <object> with id="plugin" is created in
-        // chrome/browser/resources/pdf/pdf_viewer_base.js.
-        auto viewer_element = frame->GetDocument().GetElementById("viewer");
-        if (!viewer_element.IsNull() && !viewer_element.ShadowRoot().IsNull()) {
-            auto plugin_element = viewer_element.ShadowRoot().QuerySelector("#plugin");
-            if (!plugin_element.IsNull())
-                return plugin_element;
-        }
-        NOTREACHED();
+    if (frame->Parent() && IsPdfInternalPluginAllowedOrigin(frame->Parent()->GetSecurityOrigin())) {
+        auto plugin_element = frame->GetDocument().QuerySelector("embed");
+        DCHECK(!plugin_element.IsNull());
+        return plugin_element;
     }
 #endif  // BUILDFLAG(ENABLE_EXTENSIONS)
     return blink::WebElement();
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index ce942e0c817..eff304981c5 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -5,6 +5,7 @@
 
 #include "base/memory/weak_ptr.h"
 #include "base/strings/pattern.h"
+#include "base/task/single_thread_task_runner.h"
 #include "content/public/renderer/render_frame.h"
 #include "content/public/renderer/render_frame_observer.h"
 #include "extensions/common/url_pattern.h"
@@ -203,7 +204,7 @@ void UserResourceController::RenderFrameObserverHelper::DidCommitProvisionalLoad
 
     m_runner.reset(new Runner(render_frame()->GetWebFrame(), m_userResourceController));
 
-    base::ThreadTaskRunnerHandle::Get()->PostTask(
+    base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
             FROM_HERE,
             base::BindOnce(&Runner::run, m_runner->AsWeakPtr(),
                            QtWebEngineCore::UserScriptData::DocumentElementCreation));
@@ -214,7 +215,7 @@ void UserResourceController::RenderFrameObserverHelper::DidDispatchDOMContentLoa
     // Don't run scripts if provisional load failed (DidFailProvisionalLoad
     // called instead of DidCommitProvisionalLoad).
     if (m_runner)
-        base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+        base::SingleThreadTaskRunner::GetCurrentDefault()->PostDelayedTask(
                 FROM_HERE,
                 base::BindOnce(&Runner::run, m_runner->AsWeakPtr(),
                                QtWebEngineCore::UserScriptData::AfterLoad),
@@ -224,7 +225,7 @@ void UserResourceController::RenderFrameObserverHelper::DidDispatchDOMContentLoa
 void UserResourceController::RenderFrameObserverHelper::DidFinishLoad()
 {
     if (m_runner)
-        base::ThreadTaskRunnerHandle::Get()->PostTask(
+        base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
                 FROM_HERE,
                 base::BindOnce(&Runner::run, m_runner->AsWeakPtr(),
                                QtWebEngineCore::UserScriptData::AfterLoad));
diff --git a/src/core/renderer/web_channel_ipc_transport.cpp b/src/core/renderer/web_channel_ipc_transport.cpp
index 04a4ce70500..89b20c7d11c 100644
--- a/src/core/renderer/web_channel_ipc_transport.cpp
+++ b/src/core/renderer/web_channel_ipc_transport.cpp
@@ -43,8 +43,6 @@ void WebChannelTransport::Install(blink::WebLocalFrame *frame, uint worldId)
 {
     v8::Isolate *isolate = blink::MainThreadIsolate();
     v8::HandleScope handleScope(isolate);
-    v8::MicrotasksScope microtasks_scope(
-        isolate, v8::MicrotasksScope::kDoNotRunMicrotasks);
     v8::Local<v8::Context> context;
     if (worldId == 0)
         context = frame->MainWorldScriptContext();
@@ -59,15 +57,14 @@ void WebChannelTransport::Install(blink::WebLocalFrame *frame, uint worldId)
         return;
 
     v8::Local<v8::Object> global = context->Global();
-    v8::Local<v8::Value> qtObjectValue;
     v8::Local<v8::Object> qtObject;
-    if (!global->Get(context, gin::StringToV8(isolate, "qt")).ToLocal(&qtObjectValue) || !qtObjectValue->IsObject()) {
-        qtObject = v8::Object::New(isolate);
-        global->Set(context, gin::StringToV8(isolate, "qt"), qtObject).Check();
-    } else {
-        qtObject = v8::Local<v8::Object>::Cast(qtObjectValue);
-    }
-    qtObject->Set(context, gin::StringToV8(isolate, "webChannelTransport"), transport.ToV8()).Check();
+    qtObject = v8::Object::New(isolate);
+    global->CreateDataProperty(context,
+                               gin::StringToSymbol(isolate, "qt"),
+                               qtObject).Check();
+    qtObject->CreateDataProperty(context,
+                                 gin::StringToSymbol(isolate, "webChannelTransport"),
+                                 transport.ToV8()).Check();
 }
 
 void WebChannelTransport::Uninstall(blink::WebLocalFrame *frame, uint worldId)
diff --git a/src/core/select_file_dialog_factory_qt.cpp b/src/core/select_file_dialog_factory_qt.cpp
index 9da27a4cf1c..1f897a805c3 100644
--- a/src/core/select_file_dialog_factory_qt.cpp
+++ b/src/core/select_file_dialog_factory_qt.cpp
@@ -137,7 +137,7 @@ SelectFileDialogFactoryQt::Create(ui::SelectFileDialog::Listener *listener,
                                   std::unique_ptr<ui::SelectFilePolicy> policy)
 {
     content::WebContents *webContents =
-            static_cast<SelectFilePolicyQt *>(policy.get())->webContents();
+            static_cast<SelectFilePolicyQt *>(policy.get())->webContents()->GetOutermostWebContents();
     WebContentsAdapterClient *client =
             WebContentsViewQt::from(static_cast<content::WebContentsImpl *>(webContents)->GetView())
                     ->client();
diff --git a/src/core/tools/CMakeLists.txt b/src/core/tools/CMakeLists.txt
index 9029b60a1ff..b332e96f8b3 100644
--- a/src/core/tools/CMakeLists.txt
+++ b/src/core/tools/CMakeLists.txt
@@ -22,7 +22,7 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING)
     qt_skip_warnings_are_errors(${dict_target_name})
     add_dependencies(${dict_target_name} WebEngineCore)
     qt_internal_extend_target(${dict_target_name} CONDITION WIN32
-        DEFINES WIN32_LEAN_AND_MEAN NOMINMAX
+        DEFINES WIN32_LEAN_AND_MEAN
     )
     qt_internal_extend_target(${dict_target_name} CONDITION GCC OR CLANG
         COMPILE_OPTIONS -Wno-unused-parameter
diff --git a/src/core/tools/main.cpp b/src/core/tools/main.cpp
index 4b6c82997d6..a82947ddc35 100644
--- a/src/core/tools/main.cpp
+++ b/src/core/tools/main.cpp
@@ -111,7 +111,7 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words,
         }
 
         base::span<const int> expectedAffixes(org_words[i].second);
-        base::span<const int> actualAffixes(affix_ids, affix_matches);
+        base::span<const int> actualAffixes(affix_ids, (size_t)affix_matches);
 
         if (!std::equal(expectedAffixes.begin(), expectedAffixes.end(),
                         actualAffixes.begin(), actualAffixes.end(),
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index 54f6e2e4fb9..2d4fb323dc4 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -103,6 +103,7 @@ QImage toQImage(const SkBitmap &bitmap)
         }
         break;
     case kBGR_101010x_SkColorType:
+    case kBGR_101010x_XR_SkColorType:
     case kBGRA_1010102_SkColorType:
         switch (bitmap.alphaType()) {
         case kUnknown_SkAlphaType:
diff --git a/src/core/version_ui_qt.cpp b/src/core/version_ui_qt.cpp
new file mode 100644
index 00000000000..0208299ebc3
--- /dev/null
+++ b/src/core/version_ui_qt.cpp
@@ -0,0 +1,57 @@
+// Copyright (C) 2023 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 "version_ui_qt.h"
+#include "api/qtwebenginecoreglobal.h"
+#include "build/build_config.h"
+#include "base/command_line.h"
+#include "chrome/common/url_constants.h"
+#include "chrome/browser/profiles/profile.h"
+#include "qtwebengine/grit/qt_webengine_resources.h"
+#include "services/network/public/cpp/content_security_policy/content_security_policy.h"
+
+namespace {
+const char kQtWebEngineVersion[] = "qtwebengine_version";
+const char kQtWebEngineChromiumVersion[] = "qtwebengine_chromium_version";
+const char kQtWebEngineChromiumSecurityPatchVersion[] =
+        "qtwebengine_chromium_security_patch_version";
+const char kCommandLine[] = "command_line";
+const char kQtVersionCSS[] = "qt_version.css";
+const char kQtLogo[] = "images/qt.png";
+const char kQtWebEngineLogo[] = "images/qtwebengine.png";
+}
+
+VersionUIQt::VersionUIQt(content::WebUI *web_ui) : content::WebUIController(web_ui)
+{
+
+    Profile *profile = Profile::FromWebUI(web_ui);
+    content::WebUIDataSource *html_source =
+            content::WebUIDataSource::Create(chrome::kChromeUIVersionQtHost);
+    html_source->OverrideContentSecurityPolicy(
+            network::mojom::CSPDirectiveName::ScriptSrc,
+            "script-src chrome://resources 'self' 'unsafe-inline';");
+    html_source->SetDefaultResource(IDR_VERSION_UI_QT_HTML);
+    html_source->AddResourcePath(kQtVersionCSS, IDR_VERSION_UI_QT_CSS);
+    html_source->AddResourcePath(kQtLogo, IDR_QT_LOGO);
+    html_source->AddResourcePath(kQtWebEngineLogo, IDR_QTWEBENGINE_LOGO);
+
+    html_source->AddString(kQtWebEngineVersion, qWebEngineVersion());
+    html_source->AddString(kQtWebEngineChromiumVersion, qWebEngineChromiumVersion());
+    html_source->AddString(kQtWebEngineChromiumSecurityPatchVersion,
+                           qWebEngineChromiumSecurityPatchVersion());
+#if BUILDFLAG(IS_WIN)
+    html_source->AddString(
+            kCommandLine,
+            base::AsString16(base::CommandLine::ForCurrentProcess()->GetCommandLineString()));
+#else
+    std::string command_line;
+    typedef std::vector<std::string> ArgvList;
+    const ArgvList &argv = base::CommandLine::ForCurrentProcess()->argv();
+    for (auto iter = argv.begin(); iter != argv.end(); iter++)
+        command_line += " " + *iter;
+    html_source->AddString(kCommandLine, command_line);
+#endif
+    content::WebUIDataSource::Add(profile, html_source);
+}
+
+VersionUIQt::~VersionUIQt() { }
diff --git a/src/core/version_ui_qt.h b/src/core/version_ui_qt.h
new file mode 100644
index 00000000000..1fe8ef9e0a6
--- /dev/null
+++ b/src/core/version_ui_qt.h
@@ -0,0 +1,32 @@
+// Copyright (C) 2023 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
+
+//
+//  W A R N I N G
+//  -------------
+//
+// This file is not part of the Qt API.  It exists purely as an
+// implementation detail.  This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#ifndef VERSION_UI_QT_H_
+#define VERSION_UI_QT_H_
+
+#include "build/build_config.h"
+#include "content/public/browser/web_ui_controller.h"
+#include "content/public/browser/web_ui_data_source.h"
+
+class VersionUIQt : public content::WebUIController
+{
+public:
+    explicit VersionUIQt(content::WebUI *web_ui);
+    ~VersionUIQt() override;
+
+    VersionUIQt(const VersionUIQt &) = delete;
+    VersionUIQt &operator=(const VersionUIQt &) = delete;
+};
+
+#endif // VERSION_UI_QT_H
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index f1bdb07c0e7..f4467517183 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -15,6 +15,7 @@
 #include "favicon_service_factory_qt.h"
 #include "find_text_helper.h"
 #include "media_capture_devices_dispatcher.h"
+#include "pdf_util_qt.h"
 #include "profile_adapter.h"
 #include "profile_qt.h"
 #include "qwebengineloadinginfo.h"
@@ -152,7 +153,7 @@ static QVariant fromJSValue(const base::Value *result)
         }
         break;
     }
-    case base::Value::Type::DICTIONARY:
+    case base::Value::Type::DICT:
     {
         if (const auto dict = result->GetIfDict()) {
             QVariantMap map;
@@ -210,10 +211,28 @@ static std::unique_ptr<content::WebContents> createBlankWebContents(WebContentsA
     return webContents;
 }
 
+static int navigationListSize(content::NavigationController &controller) {
+    // If we're currently on the initial NavigationEntry, no navigation has
+    // committed, so the initial NavigationEntry should not be part of the
+    // "Navigation List", and we should return 0 as the navigation list size.
+    if (controller.GetLastCommittedEntry()->IsInitialEntry())
+        return 0;
+    return controller.GetEntryCount();
+}
+
+static int navigationListCurrentIndex(content::NavigationController &controller) {
+    // If we're currently on the initial NavigationEntry, no navigation has
+    // committed, so the initial NavigationEntry should not be part of the
+    // "Navigation List", and we should return -1 as the current index.
+    if (controller.GetLastCommittedEntry()->IsInitialEntry())
+        return -1;
+    return controller.GetCurrentEntryIndex();
+}
+
 static void serializeNavigationHistory(content::NavigationController &controller, QDataStream &output)
 {
-    const int currentIndex = controller.GetCurrentEntryIndex();
-    const int count = controller.GetEntryCount();
+    const int currentIndex = navigationListCurrentIndex(controller);
+    const int count = navigationListSize(controller);
     const int pendingIndex = controller.GetPendingEntryIndex();
 
     output << kHistoryStreamVersion;
@@ -304,6 +323,7 @@ static void deserializeNavigationHistory(QDataStream &input, int *currentIndex,
             toGurl(virtualUrl),
             content::Referrer(toGurl(referrerUrl), static_cast<network::mojom::ReferrerPolicy>(referrerPolicy)),
             absl::nullopt, // optional initiator_origin
+            absl::nullopt, // optional initiator_base_url
             // Use a transition type of reload so that we don't incorrectly
             // increase the typed count.
             ui::PAGE_TRANSITION_RELOAD,
@@ -535,6 +555,8 @@ void WebContentsAdapter::initializeRenderPrefs()
                 ? blink::kWebRTCIPHandlingDefaultPublicInterfaceOnly
                 : blink::kWebRTCIPHandlingDefault;
 #endif
+    rendererPrefs->can_accept_load_drops = m_adapterClient->webEngineSettings()->testAttribute(QWebEngineSettings::NavigateOnDropEnabled);
+
     // Set web-contents font settings to the default font settings as Chromium constantly overrides
     // the global font defaults with the font settings of the latest web-contents created.
     static const gfx::FontRenderParams params = gfx::GetFontRenderParams(gfx::FontRenderParamsQuery(), nullptr);
@@ -753,7 +775,7 @@ void WebContentsAdapter::save(const QString &filePath, int savePageFormat)
 {
     CHECK_INITIALIZED();
     base::RecordAction(base::UserMetricsAction("SavePage"));
-    m_webContentsDelegate->setSavePageInfo(SavePageInfo(filePath, savePageFormat));
+    m_webContentsDelegate->setSavePageInfo(new SavePageInfo(filePath, savePageFormat));
     m_webContents->OnSavePage();
 }
 
@@ -909,13 +931,13 @@ void WebContentsAdapter::navigateToOffset(int offset)
 int WebContentsAdapter::navigationEntryCount()
 {
     CHECK_INITIALIZED(0);
-    return m_webContents->GetController().GetEntryCount();
+    return navigationListSize(m_webContents->GetController());
 }
 
 int WebContentsAdapter::currentNavigationEntryIndex()
 {
     CHECK_INITIALIZED(0);
-    return m_webContents->GetController().GetCurrentEntryIndex();
+    return navigationListCurrentIndex(m_webContents->GetController());
 }
 
 QUrl WebContentsAdapter::getNavigationEntryOriginalUrl(int index)
@@ -979,9 +1001,8 @@ void WebContentsAdapter::setZoomFactor(qreal factor)
     content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(m_webContents.get());
 
     if (zoomMap) {
-        int render_process_id = m_webContents->GetPrimaryMainFrame()->GetProcess()->GetID();
-        int render_view_id = m_webContents->GetRenderViewHost()->GetRoutingID();
-        zoomMap->SetTemporaryZoomLevel(render_process_id, render_view_id, zoomLevel);
+        const content::GlobalRenderFrameHostId global_id = m_webContents->GetPrimaryMainFrame()->GetGlobalId();
+        zoomMap->SetTemporaryZoomLevel(global_id, zoomLevel);
     }
 }
 
@@ -1013,16 +1034,6 @@ QWebEngineUrlRequestInterceptor* WebContentsAdapter::requestInterceptor() const
     return m_requestInterceptor;
 }
 
-void WebContentsAdapter::setResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor)
-{
-    m_responseInterceptor = interceptor;
-}
-
-QWebEngineUrlResponseInterceptor *WebContentsAdapter::responseInterceptor() const
-{
-    return m_responseInterceptor;
-}
-
 #if QT_CONFIG(accessibility)
 QAccessibleInterface *WebContentsAdapter::browserAccessible()
 {
@@ -1546,7 +1557,7 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD
     }
 
     {
-        base::CurrentThread::ScopedNestableTaskAllower allow;
+        base::CurrentThread::ScopedAllowApplicationTasksInNativeNestedLoop allow;
         drag->exec(allowedActions);
     }
 
@@ -1964,7 +1975,7 @@ WebContentsAdapter::LifecycleState WebContentsAdapter::determineRecommendedState
     // Do not discard PDFs as they might contain entry that is not saved and they
     // don't remember their scrolling positions. See crbug.com/547286 and
     // crbug.com/65244.
-    if (m_webContents->GetContentsMimeType() == "application/pdf")
+    if (m_webContents->GetContentsMimeType() == kPDFMimeType)
         return LifecycleState::Frozen;
 
     return LifecycleState::Discarded;
diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h
index 6a4e296a1fc..807806973bb 100644
--- a/src/core/web_contents_adapter.h
+++ b/src/core/web_contents_adapter.h
@@ -211,8 +211,6 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT WebContentsAdapter : public QEnableSharedFr
     void updateRecommendedState();
     void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
     QWebEngineUrlRequestInterceptor* requestInterceptor() const;
-    void setResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor);
-    QWebEngineUrlResponseInterceptor *responseInterceptor() const;
 
 private:
     Q_DISABLE_COPY(WebContentsAdapter)
@@ -254,7 +252,6 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT WebContentsAdapter : public QEnableSharedFr
     LifecycleState m_recommendedState = LifecycleState::Active;
     bool m_inspector = false;
     QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor;
-    QPointer<QWebEngineUrlResponseInterceptor> m_responseInterceptor;
 };
 
 } // namespace QtWebEngineCore
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 7470e5cc2d8..d00f66335c2 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -311,6 +311,9 @@ void WebContentsDelegateQt::RenderViewHostChanged(content::RenderViewHost *, con
         Q_ASSERT(rwhv->delegate());
         rwhv->delegate()->adapterClientChanged(m_viewClient);
         m_viewClient->zoomUpdateIsNeeded();
+        auto backgroundColor = m_viewClient->backgroundColor();
+        if (backgroundColor != Qt::white)
+            m_viewClient->webContentsAdapter()->setBackgroundColor(backgroundColor);
     }
 }
 
@@ -413,7 +416,6 @@ void WebContentsDelegateQt::DidFinishNavigation(content::NavigationHandle *navig
     }
 
     const net::HttpResponseHeaders * const responseHeaders = navigation_handle->GetResponseHeaders();
-    QHash<QByteArray, QByteArray> responseHeadersMap;
     if (responseHeaders != nullptr) {
         m_loadingInfo.responseHeaders.clear();
         std::size_t iter = 0;
@@ -641,12 +643,6 @@ void WebContentsDelegateQt::UpdateTargetURL(content::WebContents* source, const
     m_viewClient->didUpdateTargetURL(toQt(url));
 }
 
-void WebContentsDelegateQt::OnVisibilityChanged(content::Visibility visibility)
-{
-    if (visibility != content::Visibility::HIDDEN)
-        web_cache::WebCacheManager::GetInstance()->ObserveActivity(web_contents()->GetPrimaryMainFrame()->GetProcess()->GetID());
-}
-
 void WebContentsDelegateQt::ActivateContents(content::WebContents* contents)
 {
     QWebEngineSettings *settings = m_viewClient->webEngineSettings();
@@ -751,12 +747,6 @@ void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool pr
         m_viewClient->windowCloseRejected();
 }
 
-void WebContentsDelegateQt::BeforeUnloadFired(bool proceed, const base::TimeTicks &proceed_time)
-{
-    Q_UNUSED(proceed);
-    Q_UNUSED(proceed_time);
-}
-
 bool WebContentsDelegateQt::CheckMediaAccessPermission(content::RenderFrameHost *, const GURL& security_origin, blink::mojom::MediaStreamType type)
 {
     switch (type) {
@@ -827,6 +817,15 @@ void WebContentsDelegateQt::ResourceLoadComplete(content::RenderFrameHost* rende
     }
 }
 
+void WebContentsDelegateQt::InnerWebContentsAttached(content::WebContents *inner_web_contents,
+                                        content::RenderFrameHost *render_frame_host,
+                                        bool is_full_page)
+{
+    blink::web_pref::WebPreferences guestPrefs = inner_web_contents->GetOrCreateWebPreferences();
+    webEngineSettings()->overrideWebPreferences(inner_web_contents, &guestPrefs);
+    inner_web_contents->SetWebPreferences(guestPrefs);
+}
+
 FindTextHelper *WebContentsDelegateQt::findTextHelper()
 {
     return m_findTextHelper.data();
diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h
index 37c2c73418c..51004878d65 100644
--- a/src/core/web_contents_delegate_qt.h
+++ b/src/core/web_contents_delegate_qt.h
@@ -12,6 +12,7 @@
 #include "web_contents_adapter_client.h"
 
 #include <QtCore/qlist.h>
+#include <QtCore/qmap.h>
 
 namespace blink {
     namespace web_pref {
@@ -123,12 +124,13 @@ class WebContentsDelegateQt : public content::WebContentsDelegate
     void DidStopLoading() override;
     void DidFailLoad(content::RenderFrameHost* render_frame_host, const GURL& validated_url, int error_code) override;
     void DidFinishLoad(content::RenderFrameHost *render_frame_host, const GURL &validated_url) override;
-    void BeforeUnloadFired(bool proceed, const base::TimeTicks& proceed_time) override;
-    void OnVisibilityChanged(content::Visibility visibility) override;
     void ActivateContents(content::WebContents* contents) override;
     void ResourceLoadComplete(content::RenderFrameHost* render_frame_host,
                               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;
 
     void didFailLoad(const QUrl &url, int errorCode, const QString &errorDescription);
     void overrideWebPreferences(content::WebContents *, blink::web_pref::WebPreferences*);
@@ -138,8 +140,8 @@ class WebContentsDelegateQt : public content::WebContentsDelegate
     void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture);
     FindTextHelper *findTextHelper();
 
-    void setSavePageInfo(const SavePageInfo &spi) { m_savePageInfo = spi; }
-    const SavePageInfo &savePageInfo() { return m_savePageInfo; }
+    void setSavePageInfo(SavePageInfo *spi) { m_savePageInfo.reset(spi); }
+    SavePageInfo *savePageInfo() { return m_savePageInfo.get(); }
 
     WebEngineSettings *webEngineSettings() const;
     WebContentsAdapter *webContentsAdapter() const;
@@ -179,7 +181,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate
 
     WebContentsAdapterClient *m_viewClient;
     QScopedPointer<FindTextHelper> m_findTextHelper;
-    SavePageInfo m_savePageInfo;
+    std::unique_ptr<SavePageInfo> m_savePageInfo;
     QSharedPointer<FilePickerController> m_filePickerController;
     LoadingState m_loadingState;
     FrameFocusedObserver m_frameFocusedObserver;
@@ -200,7 +202,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate
         int errorCode = 0, errorDomain = 0;
         QString errorDescription;
         bool triggersErrorPage = false;
-        QHash<QByteArray, QByteArray> responseHeaders;
+        QMultiMap<QByteArray, QByteArray> responseHeaders;
         void clear() { *this = LoadingInfo(); }
     } m_loadingInfo;
 
diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h
index 15528b41d16..8754250e641 100644
--- a/src/core/web_contents_view_qt.h
+++ b/src/core/web_contents_view_qt.h
@@ -73,6 +73,7 @@ class WebContentsViewQt
     void FocusThroughTabTraversal(bool reverse) override;
     void OnCapturerCountChanged() override { QT_NOT_YET_IMPLEMENTED }
     void FullscreenStateChanged(bool) override { }
+    void UpdateWindowControlsOverlay(const gfx::Rect &) override { QT_NOT_YET_IMPLEMENTED }
 
 #if BUILDFLAG(IS_MAC)
     bool CloseTabAfterEventTrackingIfNeeded() override { QT_NOT_YET_IMPLEMENTED return false; }
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index fab0501bed8..81de7833fdf 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -4,9 +4,10 @@
 #include "web_engine_context.h"
 
 #include <math.h>
+#include <QtGui/private/qrhi_p.h>
 
 #include "base/base_switches.h"
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/command_line.h"
 #include "base/files/file_path.h"
 #include "base/power_monitor/power_monitor.h"
@@ -104,6 +105,7 @@
 #include <qopenglcontext_platform.h>
 #endif
 #include <QQuickWindow>
+#include <QRegularExpression>
 #include <QStringList>
 #include <QSurfaceFormat>
 #include <QNetworkProxy>
@@ -193,9 +195,9 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
         return glType;
 
 #if defined(Q_OS_MACOS)
-    if (QQuickWindow::graphicsApi() == QSGRendererInterface::Metal)
-        return gl::kGLImplementationANGLEName;
-#elif defined(Q_OS_WIN)
+    return gl::kGLImplementationANGLEName;
+#else
+#if defined(Q_OS_WIN)
     if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11)
         return gl::kGLImplementationANGLEName;
 #endif
@@ -211,15 +213,10 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
     switch (sharedFormat.renderableType()) {
     case QSurfaceFormat::OpenGL:
         if (sharedFormat.profile() == QSurfaceFormat::CoreProfile) {
-#if defined(Q_OS_MACOS)
-            // Chromium supports core profile only on mac
-            glType = gl::kGLImplementationCoreProfileName;
-#else
             glType = gl::kGLImplementationDesktopName;
             qWarning("An OpenGL Core Profile was requested, but it is not supported "
                      "on the current platform. Falling back to a non-Core profile. "
                      "Note that this might cause rendering issues.");
-#endif
         } else {
             glType = gl::kGLImplementationDesktopName;
         }
@@ -235,6 +232,7 @@ static const char *getGLType(bool enableGLSoftwareRendering, bool disableGpu)
                  "https://bugreports.qt.io");
     }
     return glType;
+#endif // defined(Q_OS_MACOS)
 }
 #else
 static const char *getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu)
@@ -242,8 +240,7 @@ static const char *getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu
     if (disableGpu)
         return gl::kGLImplementationDisabledName;
 #if defined(Q_OS_MACOS)
-    if (QQuickWindow::graphicsApi() == QSGRendererInterface::Metal)
-        return gl::kGLImplementationANGLEName;
+    return gl::kGLImplementationANGLEName;
 #elif defined(Q_OS_WIN)
     if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11)
         return gl::kGLImplementationANGLEName;
@@ -252,6 +249,31 @@ static const char *getGLType(bool /*enableGLSoftwareRendering*/, bool disableGpu
 }
 #endif // QT_CONFIG(opengl)
 
+#if defined(Q_OS_WIN)
+static QString getAdapterLuid() {
+    static const bool preferSoftwareDevice = qEnvironmentVariableIntValue("QSG_RHI_PREFER_SOFTWARE_RENDERER");
+    QRhiD3D11InitParams rhiParams;
+    QRhi::Flags flags;
+    if (preferSoftwareDevice) {
+        flags |= QRhi::PreferSoftwareRenderer;
+    }
+    QScopedPointer<QRhi> rhi(QRhi::create(QRhi::D3D11,&rhiParams,flags,nullptr));
+    // mimic what QSGRhiSupport and QBackingStoreRhi does
+    if (!rhi && !preferSoftwareDevice) {
+        flags |= QRhi::PreferSoftwareRenderer;
+        rhi.reset(QRhi::create(QRhi::D3D11, &rhiParams, flags));
+    }
+    if (rhi) {
+        const QRhiD3D11NativeHandles *handles =
+                static_cast<const QRhiD3D11NativeHandles *>(rhi->nativeHandles());
+        Q_ASSERT(handles);
+        return QString("%1,%2").arg(handles->adapterLuidHigh).arg(handles->adapterLuidLow);
+    } else {
+        return QString();
+    }
+}
+#endif
+
 #if QT_CONFIG(webengine_pepper_plugins)
 void dummyGetPluginCallback(const std::vector<content::WebPluginInfo>&)
 {
@@ -579,9 +601,6 @@ const static char kDisableInProcGpuThread[] = "QTWEBENGINE_DISABLE_GPU_THREAD";
 bool WebEngineContext::isGpuServiceOnUIThread()
 {
     static bool threadedGpu =
-#if QT_CONFIG(opengl) && !defined(Q_OS_MACOS)
-            QOpenGLContext::supportsThreadedOpenGL() &&
-#endif
             !qEnvironmentVariableIsSet(kDisableInProcGpuThread);
     return !threadedGpu;
 }
@@ -694,6 +713,9 @@ WebEngineContext::WebEngineContext()
     enableFeatures.push_back(features::kNetworkServiceInProcess.name);
     enableFeatures.push_back(features::kTracingServiceInProcess.name);
 
+#if QT_CONFIG(webengine_webrtc_pipewire)
+    enableFeatures.push_back(features::kWebRtcPipeWireCapturer.name);
+#endif
     // When enabled, event.movement is calculated in blink instead of in browser.
     disableFeatures.push_back(features::kConsolidatedMovementXY.name);
 
@@ -710,7 +732,6 @@ WebEngineContext::WebEngineContext()
     disableFeatures.push_back(features::kWebOTP.name);
     disableFeatures.push_back(features::kWebPayments.name);
     disableFeatures.push_back(features::kWebUsb.name);
-    disableFeatures.push_back(media::kPictureInPicture.name);
 
     if (useEmbeddedSwitches) {
         // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc
@@ -727,6 +748,14 @@ WebEngineContext::WebEngineContext()
     }
 #endif
 
+#if defined(Q_OS_WIN)
+    if (QQuickWindow::graphicsApi() == QSGRendererInterface::Direct3D11) {
+        const QString luid = getAdapterLuid();
+        if (!luid.isEmpty())
+            parsedCommandLine->AppendSwitchASCII(switches::kUseAdapterLuid, luid.toStdString());
+    }
+#endif
+
     initializeFeatureList(parsedCommandLine, enableFeatures, disableFeatures);
 
     GLContextHelper::initialize();
@@ -898,6 +927,22 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches,
     appArgs.removeAll(QStringLiteral("--disable-embedded-switches"));
     appArgs.removeAll(QStringLiteral("--enable-embedded-switches"));
 
+    bool isRemoteDebugPort =
+            (-1
+             != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-debugging-port=.*"),
+                                                   QRegularExpression::CaseInsensitiveOption)))
+            || !qEnvironmentVariable("QTWEBENGINE_REMOTE_DEBUGGING").isEmpty();
+    bool isRemoteAllowOrigins =
+            (-1
+             != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-allow-origins=.*"),
+                                                   QRegularExpression::CaseInsensitiveOption)));
+
+    if (isRemoteDebugPort && !isRemoteAllowOrigins) {
+        appArgs.append(QStringLiteral("--remote-allow-origins=*"));
+        qWarning("Added {--remote-allow-origins=*} to command-line arguments "
+                 "to avoid web socket connection errors during remote debugging.");
+    }
+
     base::CommandLine::StringVector argv;
     argv.resize(appArgs.size());
 #if defined(Q_OS_WIN)
@@ -937,7 +982,7 @@ const char *qWebEngineChromiumVersion() noexcept
 
 const char *qWebEngineChromiumSecurityPatchVersion() noexcept
 {
-    return "113.0.5672.126"; // FIXME: Remember to update
+    return "124.0.6367.208"; // FIXME: Remember to update
 }
 
 QT_END_NAMESPACE
diff --git a/src/core/web_engine_context_threads.cpp b/src/core/web_engine_context_threads.cpp
index f62e2074e28..ce39b198bdd 100644
--- a/src/core/web_engine_context_threads.cpp
+++ b/src/core/web_engine_context_threads.cpp
@@ -3,7 +3,7 @@
 
 #include "web_engine_context.h"
 
-#include "base/bind.h"
+#include "base/functional/bind.h"
 #include "base/task/thread_pool.h"
 #include "base/threading/platform_thread.h"
 #include "base/threading/thread_restrictions.h"
diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp
index c03c9a3b232..e7115389962 100644
--- a/src/core/web_engine_library_info.cpp
+++ b/src/core/web_engine_library_info.cpp
@@ -284,6 +284,12 @@ QString dictionariesPath()
                 break;
             }
         }
+
+        if (potentialDictionariesPath.isEmpty()) {
+            // return path for error message
+            potentialDictionariesPath = QCoreApplication::applicationDirPath() % QDir::separator()
+                    % QLatin1String("qtwebengine_dictionaries");
+        }
     }
 
     return potentialDictionariesPath;
diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp
index 11adc8d19d4..2dc7c5e32de 100644
--- a/src/core/web_engine_settings.cpp
+++ b/src/core/web_engine_settings.cpp
@@ -9,7 +9,6 @@
 
 #include "base/command_line.h"
 #include "chrome/common/chrome_switches.h"
-#include "content/browser/gpu/gpu_process_host.h"
 #include "content/public/browser/render_view_host.h"
 #include "content/public/browser/web_contents.h"
 #include "content/public/common/content_switches.h"
@@ -262,9 +261,9 @@ void WebEngineSettings::initDefaults()
         s_defaultAttributes.insert(QWebEngineSettings::PdfViewerEnabled, false);
 #endif
         s_defaultAttributes.insert(QWebEngineSettings::NavigateOnDropEnabled, true);
-        bool readingFromCanvas =
+        bool noReadingFromCanvas =
                 commandLine->HasSwitch(switches::kDisableReadingFromCanvas);
-        s_defaultAttributes.insert(QWebEngineSettings::DisableReadingFromCanvas, readingFromCanvas);
+        s_defaultAttributes.insert(QWebEngineSettings::ReadingFromCanvasEnabled, !noReadingFromCanvas);
     }
 
     if (s_defaultFontFamilies.isEmpty()) {
@@ -324,6 +323,9 @@ void WebEngineSettings::doApply()
 
 void WebEngineSettings::applySettingsToWebPreferences(blink::web_pref::WebPreferences *prefs)
 {
+    // Not supported
+    prefs->picture_in_picture_enabled = false;
+
     // Override for now
     prefs->touch_event_feature_detection_enabled = isTouchEventsAPIEnabled();
 #if !QT_CONFIG(webengine_embedded_build)
@@ -373,7 +375,7 @@ void WebEngineSettings::applySettingsToWebPreferences(blink::web_pref::WebPrefer
     prefs->dom_paste_enabled = testAttribute(QWebEngineSettings::JavascriptCanPaste);
     prefs->dns_prefetching_enabled = testAttribute(QWebEngineSettings::DnsPrefetchEnabled);
     prefs->navigate_on_drag_drop = testAttribute(QWebEngineSettings::NavigateOnDropEnabled);
-    prefs->disable_reading_from_canvas = testAttribute(QWebEngineSettings::DisableReadingFromCanvas);
+    prefs->disable_reading_from_canvas = !testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled);
 
     // Fonts settings.
     prefs->standard_font_family_map[blink::web_pref::kCommonScript] =
@@ -445,6 +447,11 @@ bool WebEngineSettings::applySettingsToRendererPreferences(blink::RendererPrefer
         }
     }
 #endif
+    bool canNavigateOnDrop = testAttribute(QWebEngineSettings::NavigateOnDropEnabled);
+    if (canNavigateOnDrop != prefs->can_accept_load_drops) {
+        prefs->can_accept_load_drops = canNavigateOnDrop;
+        changed = true;
+    }
     return changed;
 }
 
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index 986c2fe9189..f4b37e83844 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -558,6 +558,8 @@ static int windowsKeyCodeForQtKey(int qtKey, bool isKeypad)
         case Qt::Key_QuoteDbl:
             return VK_OEM_7; // case '\'': case '"': return 0xDE;
             // VK_OEM_8 (DF) Used for miscellaneous characters; it can vary by keyboard.
+        case Qt::Key_AltGr:
+            return 0xE1; // (E1) VK_OEM_AX = ui::VKEY_ALTGR see ui/events/keycodes/keyboard_codes_win.h
             // VK_OEM_102 (E2) Windows 2000/XP: Either the angle bracket key or the backslash key on the RT 102-key keyboard
 
         case Qt::Key_AudioRewind:
@@ -1541,8 +1543,9 @@ static QPoint getWheelEventDelta(const blink::WebGestureEvent &webEvent)
 {
     static const float cDefaultQtScrollStep = 20.f;
     static const int wheelScrollLines = QGuiApplication::styleHints()->wheelScrollLines();
-    return QPoint(webEvent.data.scroll_update.delta_x * QWheelEvent::DefaultDeltasPerStep / (wheelScrollLines * cDefaultQtScrollStep),
-                  webEvent.data.scroll_update.delta_y * QWheelEvent::DefaultDeltasPerStep / (wheelScrollLines * cDefaultQtScrollStep));
+    static const float deltasPerStep = static_cast<float>(QWheelEvent::DefaultDeltasPerStep);
+    return QPoint(webEvent.data.scroll_update.delta_x * deltasPerStep / (wheelScrollLines * cDefaultQtScrollStep),
+                  webEvent.data.scroll_update.delta_y * deltasPerStep / (wheelScrollLines * cDefaultQtScrollStep));
 }
 
 blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev)
@@ -1589,8 +1592,8 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev)
     webEvent.SetPositionInScreen(static_cast<float>(ev->globalPosition().x()),
                                  static_cast<float>(ev->globalPosition().y()));
 
-    webEvent.wheel_ticks_x = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep;
-    webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep;
+    webEvent.wheel_ticks_x = ev->angleDelta().x() / static_cast<float>(QWheelEvent::DefaultDeltasPerStep);
+    webEvent.wheel_ticks_y = ev->angleDelta().y() / static_cast<float>(QWheelEvent::DefaultDeltasPerStep);
     webEvent.phase = toBlinkPhase(ev);
 #if defined(Q_OS_DARWIN)
     // PrecisePixel is a macOS term meaning it is a system scroll gesture, see qnsview_mouse.mm
@@ -1627,8 +1630,8 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent,
     webEvent.SetPositionInScreen(static_cast<float>(ev->globalPosition().x()),
                                  static_cast<float>(ev->globalPosition().y()));
 
-    webEvent.wheel_ticks_x += static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep;
-    webEvent.wheel_ticks_y += static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep;
+    webEvent.wheel_ticks_x = ev->angleDelta().x() / static_cast<float>(QWheelEvent::DefaultDeltasPerStep);
+    webEvent.wheel_ticks_y = ev->angleDelta().y() / static_cast<float>(QWheelEvent::DefaultDeltasPerStep);
     setBlinkWheelEventDelta(webEvent);
 
     return true;
@@ -1697,10 +1700,12 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e
                 ui::DomCodeToUsLayoutKeyboardCode(static_cast<ui::DomCode>(webKitEvent.dom_code));
 
     const ushort* text = qtText.utf16();
-    size_t textSize = std::min(sizeof(webKitEvent.text), size_t(qtText.length() * 2));
-    memcpy(&webKitEvent.text, text, textSize);
-    memcpy(&webKitEvent.unmodified_text, text, textSize);
-
+    size_t size = std::char_traits<char16_t>::length((char16_t *)text);
+    if (size <= blink::WebKeyboardEvent::kTextLengthCap - 1) { // should be null terminated
+        size_t textSize = std::min(sizeof(webKitEvent.text), size * sizeof(char16_t));
+        memcpy(&webKitEvent.text, text, textSize);
+        memcpy(&webKitEvent.unmodified_text, text, textSize);
+    }
     if (webKitEvent.windows_key_code == VK_RETURN) {
         // This is the same behavior as GTK:
         // We need to treat the enter key as a key press of character \r. This
diff --git a/src/gn/CMakeLists.txt b/src/gn/CMakeLists.txt
index 6f73e29c7b7..0fe3e4e05b8 100644
--- a/src/gn/CMakeLists.txt
+++ b/src/gn/CMakeLists.txt
@@ -11,7 +11,12 @@ project(Gn
 )
 
 if(NOT DEFINED WEBENGINE_ROOT_SOURCE_DIR)
-    get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." REALPATH)
+    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})
 endif()
 
 include(${WEBENGINE_ROOT_SOURCE_DIR}/.cmake.conf)
@@ -26,7 +31,7 @@ find_package(Ninja 1.7.2 REQUIRED)
 
 if(WIN32)
     set(GN_EXECUTABLE gn.exe)
-    if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
+    if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND NOT MINGW)
         # Use lld-link instead of clang-cl.
         set(GN_LINKER ${CMAKE_LINKER})
     endif()
diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt
index 08da14c1d5a..2f7642593b3 100644
--- a/src/host/CMakeLists.txt
+++ b/src/host/CMakeLists.txt
@@ -19,16 +19,21 @@ project(QtWebEngineConfigure
     VERSION "${QT_REPO_MODULE_VERSION}"
     LANGUAGES CXX C)
 
-find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core)
-qt_internal_project_setup()
+find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core)
+
+if(COMMAND qt_internal_project_setup)
+    qt_internal_project_setup()
+endif()
+get_gn_arch(target_arch ${GN_TARGET_CPU})
+get_gn_arch(host_arch ${TEST_architecture_arch})
+get_v8_arch(v8_arch ${target_arch} ${host_arch})
 
 set(buildDir ${CMAKE_CURRENT_BINARY_DIR})
-configure_gn_toolchain(host ${TEST_architecture_arch} ${TEST_architecture_arch}
+configure_gn_toolchain(host ${host_arch} ${host_arch}
     ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
     ${buildDir}/host_toolchain
 )
-get_v8_arch(GN_V8_HOST_CPU ${GN_TARGET_CPU} ${TEST_architecture_arch})
-configure_gn_toolchain(v8 ${GN_V8_HOST_CPU} ${GN_TARGET_CPU}
+configure_gn_toolchain(v8 ${v8_arch} ${target_arch}
     ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in
     ${buildDir}/v8_toolchain)
 
@@ -49,3 +54,17 @@ if(QT_FEATURE_qtpdf_build)
     )
 endif()
 
+# TODO: this could be run as part of main configure with execute_process
+
+if(CMAKE_CXX_COMPILER_ID STREQUAL GNU AND TEST_architecture_arch STREQUAL "x86_64"
+AND GN_TARGET_CPU STREQUAL "arm")
+    try_compile(
+        has32HostCompiler
+        "${CMAKE_CURRENT_BINARY_DIR}/config.tests/hostcompiler"
+        "${CMAKE_CURRENT_SOURCE_DIR}/config.tests/hostcompiler"
+        hostcompiler
+    )
+    if(NOT has32HostCompiler)
+        MESSAGE(FATAL_ERROR "Compiler does not support 32bit compilation")
+    endif()
+endif()
diff --git a/src/host/config.tests/hostcompiler/CMakeLists.txt b/src/host/config.tests/hostcompiler/CMakeLists.txt
new file mode 100644
index 00000000000..f36886d0a55
--- /dev/null
+++ b/src/host/config.tests/hostcompiler/CMakeLists.txt
@@ -0,0 +1,11 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+cmake_minimum_required(VERSION 3.16)
+project(arch LANGUAGES CXX)
+
+add_executable(host_compiler_test)
+set_property(TARGET host_compiler_test PROPERTY MACOSX_BUNDLE FALSE)
+target_sources(host_compiler_test PRIVATE main.cpp)
+target_compile_options(host_compiler_test PRIVATE -m32)
+target_link_options(host_compiler_test PRIVATE -m32)
diff --git a/config.tests/hostcompiler/main.cpp b/src/host/config.tests/hostcompiler/main.cpp
similarity index 100%
rename from config.tests/hostcompiler/main.cpp
rename to src/host/config.tests/hostcompiler/main.cpp
diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt
index 563aa9d433a..1775d598c1c 100644
--- a/src/pdf/CMakeLists.txt
+++ b/src/pdf/CMakeLists.txt
@@ -3,7 +3,7 @@
 
 cmake_minimum_required(VERSION 3.19)
 find_package(Ninja 1.7.2 REQUIRED)
-find_package(Nodejs 12 REQUIRED)
+find_package(Nodejs 14.19 REQUIRED)
 find_package(PkgConfig)
 if(PkgConfig_FOUND)
     create_pkg_config_host_wrapper(${CMAKE_CURRENT_BINARY_DIR})
@@ -32,13 +32,14 @@ qt_internal_add_module(Pdf
         ../3rdparty/chromium
     DEFINES
         QT_BUILD_PDF_LIB
-        NOMINMAX
     LIBRARIES
         Qt::CorePrivate
         Qt::Network
     PUBLIC_LIBRARIES
         Qt::Core
         Qt::Gui
+    GENERATE_CPP_EXPORTS
+    GENERATE_PRIVATE_CPP_EXPORTS
 )
 
 add_subdirectory(plugins/imageformats/pdf)
@@ -64,7 +65,7 @@ add_code_attributions_target(
     BUILDDIR ${buildDir}/${config}/${arch}
 )
 add_dependencies(generate_pdf_attributions run_pdf_GnDone)
-add_dependencies(docs generate_pdf_attributions)
+add_dependencies(prepare_docs_Pdf generate_pdf_attributions)
 
 ##
 #   TOOLCHAIN SETUP
@@ -120,6 +121,11 @@ 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"
+          enable_swiftshader=false
+          enable_swiftshader_vulkan=false
+          angle_enable_swiftshader=false
+          dawn_use_swiftshader=false
+          use_dawn=false
           enable_ipc_fuzzer=false
           enable_remoting=false
           enable_resource_allowlist_generation=false
@@ -134,6 +140,7 @@ foreach(arch ${archs})
                 ozone_auto_platforms=false
                 use_gnome_keyring=false
                 enable_vr=false
+                use_ml_inliner=false
             )
             extend_gn_list(gnArgArg
                 ARGS use_system_icu
@@ -189,7 +196,7 @@ foreach(arch ${archs})
             CONDITION QT_FEATURE_pdf_xfa_tiff
         )
         extend_gn_list(gnArgArg
-            ARGS pdfium_use_system_zlib
+            ARGS pdfium_use_system_zlib use_system_zlib
             CONDITION QT_FEATURE_webengine_system_zlib
         )
         extend_gn_list(gnArgArg
@@ -238,7 +245,7 @@ endforeach()
 get_architectures(archs)
 list(GET archs 0 arch)
 target_include_directories(Pdf PRIVATE ${buildDir}/$<CONFIG>/${arch}/gen)
-add_gn_build_aritfacts_to_target(
+add_gn_build_artifacts_to_target(
     CMAKE_TARGET Pdf
     NINJA_TARGET QtPdf
     MODULE pdf
diff --git a/src/pdf/configure/BUILD.root.gn.in b/src/pdf/configure/BUILD.root.gn.in
index 71358756523..44481923d1c 100644
--- a/src/pdf/configure/BUILD.root.gn.in
+++ b/src/pdf/configure/BUILD.root.gn.in
@@ -51,7 +51,7 @@ config("cpp17_config") {
 
 static_library("QtPdf") {
   complete_static_lib = true
-  rsp_types = [ "objects", "archives", "libs", "lflags" ]
+  rsp_types = [ "objects", "archives", "libs", "ldir" ]
   configs += [
     ":cpp17_config",
     ":QtPdf_config"
@@ -63,6 +63,7 @@ static_library("QtPdf") {
     libs = [
       "dloadhelper.lib",
       "winmm.lib",
+      "usp10.lib",
     ]
   }
   if (is_mingw) {
diff --git a/src/pdf/doc/src/qtpdf-examples.qdoc b/src/pdf/doc/src/qtpdf-examples.qdoc
index 0ebad3c825c..02dc23dc210 100644
--- a/src/pdf/doc/src/qtpdf-examples.qdoc
+++ b/src/pdf/doc/src/qtpdf-examples.qdoc
@@ -3,7 +3,6 @@
 
 /*!
     \group qtpdf-examples
-    \ingroup all-examples
 
     \title Qt PDF Examples
     \brief Using the classes and types in the Qt PDF module.
diff --git a/src/pdf/doc/src/qtpdf-index.qdoc b/src/pdf/doc/src/qtpdf-index.qdoc
index 055a36b4fba..b72619fbf94 100644
--- a/src/pdf/doc/src/qtpdf-index.qdoc
+++ b/src/pdf/doc/src/qtpdf-index.qdoc
@@ -65,6 +65,11 @@
         \li \l{Qt Quick PDF QML Types}
     \endlist
 
+    \section1 Articles and Guides
+    \list
+        \li {Qt PDF Platform Notes} {Platform Notes}
+    \endlist
+
     \section1 Licenses and Attributions
 
     Qt PDF is available under commercial licenses from \l{The Qt Company}.
diff --git a/src/pdf/doc/src/qtpdf-platformnotes.qdoc b/src/pdf/doc/src/qtpdf-platformnotes.qdoc
new file mode 100644
index 00000000000..f50be120dca
--- /dev/null
+++ b/src/pdf/doc/src/qtpdf-platformnotes.qdoc
@@ -0,0 +1,11 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+    \page qtpdf-platformnotes.html
+    \title Qt PDF Platform Notes
+
+    Building Qt PDF for Android is currently
+    \l{https://bugreports.qt.io/browse/QTBUG-83459} {not supported} on Windows host platforms.
+*/
+
diff --git a/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp b/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp
index 19575902864..bb3e7c92930 100644
--- a/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp
+++ b/src/pdf/plugins/imageformats/pdf/qpdfiohandler.cpp
@@ -62,7 +62,7 @@ int QPdfIOHandler::imageCount() const
 bool QPdfIOHandler::read(QImage *image)
 {
     if (load(device())) {
-        if (m_page >= m_doc->pageCount())
+        if (m_doc.isNull() || m_page >= m_doc->pageCount())
             return false;
         if (m_page < 0)
             m_page = 0;
@@ -110,9 +110,11 @@ bool QPdfIOHandler::read(QImage *image)
             options.setScaledSize(pageSize);
             image->fill(m_backColor.rgba());
             QPainter p(image);
-            QImage pageImage = m_doc->render(m_page, finalSize, options);
-            p.drawImage(0, 0, pageImage);
-            p.end();
+            if (!m_doc.isNull()) {
+                QImage pageImage = m_doc->render(m_page, finalSize, options);
+                p.drawImage(0, 0, pageImage);
+                p.end();
+            }
         }
         return true;
     }
diff --git a/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h b/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h
index 5918c03282b..c4d8e0f9a26 100644
--- a/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h
+++ b/src/pdf/plugins/imageformats/pdf/qpdfiohandler_p.h
@@ -41,7 +41,7 @@ class QPdfIOHandler : public QImageIOHandler
     bool load(QIODevice *device);
 
 private:
-    QPdfDocument *m_doc = nullptr;
+    QPointer<QPdfDocument> m_doc;
     int m_page = -1;
 
     QRect m_clipRect;
diff --git a/src/pdf/qpdfbookmarkmodel.cpp b/src/pdf/qpdfbookmarkmodel.cpp
index c9035f21ace..93dbf5d1f9a 100644
--- a/src/pdf/qpdfbookmarkmodel.cpp
+++ b/src/pdf/qpdfbookmarkmodel.cpp
@@ -176,17 +176,7 @@ struct QPdfBookmarkModelPrivate
 
             const FPDF_DEST dest = FPDFBookmark_GetDest(document, bookmark);
             const int pageNumber = FPDFDest_GetDestPageIndex(document, dest);
-            double pageHeight = 11.69 * 72; // A4 height
-            {
-                // get actual page height
-                const QPdfMutexLocker lock;
-                FPDF_PAGE pdfPage = FPDF_LoadPage(document, pageNumber);
-                if (pdfPage)
-                    pageHeight = FPDF_GetPageHeight(pdfPage);
-                else
-                    qCWarning(qLcBM) << "failed to load page" << pageNumber;
-            }
-
+            const qreal pageHeight = m_document->pagePointSize(pageNumber).height();
             FPDF_BOOL hasX, hasY, hasZoom;
             FS_FLOAT x, y, zoom;
             bool ok = FPDFDest_GetLocationInPage(dest, &hasX, &hasY, &hasZoom, &x, &y, &zoom);
@@ -270,6 +260,10 @@ QPdfDocument* QPdfBookmarkModel::document() const
     return d->m_document;
 }
 
+/*!
+    \property QPdfBookmarkModel::document
+    \brief the PDF document in which bookmarks are to be found.
+*/
 void QPdfBookmarkModel::setDocument(QPdfDocument *document)
 {
     if (d->m_document == document)
diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp
index 695b30c59ba..17fdb29b98e 100644
--- a/src/pdf/qpdfdocument.cpp
+++ b/src/pdf/qpdfdocument.cpp
@@ -446,7 +446,7 @@ void QPdfDocumentPrivate::fpdf_AddSegment(_FX_DOWNLOADHINTS *pThis, size_t offse
     Q_UNUSED(size);
 }
 
-QString QPdfDocumentPrivate::getText(FPDF_TEXTPAGE textPage, int startIndex, int count)
+QString QPdfDocumentPrivate::getText(FPDF_TEXTPAGE textPage, int startIndex, int count) const
 {
     QList<ushort> buf(count + 1);
     // TODO is that enough space in case one unicode character is more than one in utf-16?
@@ -455,23 +455,73 @@ QString QPdfDocumentPrivate::getText(FPDF_TEXTPAGE textPage, int startIndex, int
     return QString::fromUtf16(reinterpret_cast<const char16_t *>(buf.constData()), len - 1);
 }
 
-QPointF QPdfDocumentPrivate::getCharPosition(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex)
+QPointF QPdfDocumentPrivate::getCharPosition(FPDF_PAGE pdfPage, FPDF_TEXTPAGE textPage, int charIndex) const
 {
     double x, y;
-    int count = FPDFText_CountChars(textPage);
-    bool ok = FPDFText_GetCharOrigin(textPage, qMin(count - 1, charIndex), &x, &y);
-    if (!ok)
-        return QPointF();
-    return QPointF(x, pageHeight - y);
+    const int count = FPDFText_CountChars(textPage);
+    if (FPDFText_GetCharOrigin(textPage, qMin(count - 1, charIndex), &x, &y))
+        return mapPageToView(pdfPage, x, y);
+    return {};
 }
 
-QRectF QPdfDocumentPrivate::getCharBox(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex)
+QRectF QPdfDocumentPrivate::getCharBox(FPDF_PAGE pdfPage, FPDF_TEXTPAGE textPage, int charIndex) const
 {
     double l, t, r, b;
-    bool ok = FPDFText_GetCharBox(textPage, charIndex, &l, &r, &b, &t);
-    if (!ok)
-        return QRectF();
-    return QRectF(l, pageHeight - t, r - l, t - b);
+    if (FPDFText_GetCharBox(textPage, charIndex, &l, &r, &b, &t))
+        return mapPageToView(pdfPage, l, t, r, b);
+    return {};
+}
+
+/*! \internal
+    Convert the point \a x , \a y to the usual 1x (pixels = points)
+    4th-quadrant "view" coordinate system relative to the top-left corner of
+    the rendered page. Some PDF files have internal transforms that make this
+    coordinate system different from "page coordinates", so we cannot just
+    subtract from page height to invert the y coordinates, in general.
+ */
+QPointF QPdfDocumentPrivate::mapPageToView(FPDF_PAGE pdfPage, double x, double y) const
+{
+    const auto pageHeight = FPDF_GetPageHeight(pdfPage);
+    const auto pageWidth = FPDF_GetPageWidth(pdfPage);
+    int rx, ry;
+    if (FPDF_PageToDevice(pdfPage, 0, 0, qRound(pageWidth), qRound(pageHeight), 0, x, y, &rx, &ry))
+        return QPointF(rx, ry);
+    return {};
+}
+
+/*! \internal
+    Convert the bounding box defined by \a left \a top \a right and \a bottom
+    to the usual 1x (pixels = points) 4th-quadrant "view" coordinate system
+    that we use for rendering things on top of the page image.
+    Some PDF files have internal transforms that make this coordinate
+    system different from "page coordinates", so we cannot just
+    subtract from page height to invert the y coordinates, in general.
+ */
+QRectF QPdfDocumentPrivate::mapPageToView(FPDF_PAGE pdfPage, double left, double top, double right, double bottom) const
+{
+    const auto pageHeight = FPDF_GetPageHeight(pdfPage);
+    const auto pageWidth = FPDF_GetPageWidth(pdfPage);
+    int xfmLeft, xfmTop, xfmRight, xfmBottom;
+    if ( FPDF_PageToDevice(pdfPage, 0, 0, qRound(pageWidth), qRound(pageHeight), 0, left, top, &xfmLeft, &xfmTop) &&
+         FPDF_PageToDevice(pdfPage, 0, 0, qRound(pageWidth), qRound(pageHeight), 0, right, bottom, &xfmRight, &xfmBottom) )
+        return QRectF(xfmLeft, xfmTop, xfmRight - xfmLeft, xfmBottom - xfmTop);
+    return {};
+}
+
+/*! \internal
+    Convert the point \a x , \a y \a from the usual 1x (pixels = points)
+    4th-quadrant "view" coordinate system relative to the top-left corner of
+    the rendered page, to "page coordinates" suited to the given \a pdfPage,
+    which may have arbitrary internal transforms.
+ */
+QPointF QPdfDocumentPrivate::mapViewToPage(FPDF_PAGE pdfPage, QPointF position) const
+{
+    const auto pageHeight = FPDF_GetPageHeight(pdfPage);
+    const auto pageWidth = FPDF_GetPageWidth(pdfPage);
+    double rx, ry;
+    if (FPDF_DeviceToPage(pdfPage, 0, 0, qRound(pageWidth), qRound(pageHeight), 0, position.x(), position.y(), &rx, &ry))
+        return QPointF(rx, ry);
+    return {};
 }
 
 QPdfDocumentPrivate::TextPosition QPdfDocumentPrivate::hitTest(int page, QPointF position)
@@ -480,14 +530,14 @@ QPdfDocumentPrivate::TextPosition QPdfDocumentPrivate::hitTest(int page, QPointF
 
     TextPosition result;
     FPDF_PAGE pdfPage = FPDF_LoadPage(doc, page);
-    double pageHeight = FPDF_GetPageHeight(pdfPage);
     FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
-    int hitIndex = FPDFText_GetCharIndexAtPos(textPage, position.x(), pageHeight - position.y(),
+    const QPointF pagePos = mapViewToPage(pdfPage, position);
+    int hitIndex = FPDFText_GetCharIndexAtPos(textPage, pagePos.x(), pagePos.y(),
                                               CharacterHitTolerance, CharacterHitTolerance);
     if (hitIndex >= 0) {
-        QPointF charPos = getCharPosition(textPage, pageHeight, hitIndex);
+        QPointF charPos = getCharPosition(pdfPage, textPage, hitIndex);
         if (!charPos.isNull()) {
-            QRectF charBox = getCharBox(textPage, pageHeight, hitIndex);
+            QRectF charBox = getCharBox(pdfPage, textPage, hitIndex);
             // If the given position is past the end of the line, i.e. if the right edge of the found character's
             // bounding box is closer to it than the left edge is, we say that we "hit" the next character index after
             if (qAbs(charBox.right() - position.x()) < qAbs(charPos.x() - position.x())) {
@@ -828,12 +878,12 @@ QString QPdfDocument::pageLabel(int page)
     Returns the index of the page that has the \a label, or \c -1 if not found.
 
     \sa pageLabel()
+    \since 6.6
 */
 int QPdfDocument::pageIndexForLabel(const QString &label)
 {
-    const auto trimmed = label.trimmed();
     for (int i = 0; i < d->pageCount; ++i) {
-        if (pageLabel(i) == trimmed)
+        if (pageLabel(i) == label)
             return i;
     }
     return -1;
@@ -931,11 +981,12 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end)
 {
     const QPdfMutexLocker lock;
     FPDF_PAGE pdfPage = FPDF_LoadPage(d->doc, page);
-    double pageHeight = FPDF_GetPageHeight(pdfPage);
+    const QPointF pageStart = d->mapViewToPage(pdfPage, start);
+    const QPointF pageEnd = d->mapViewToPage(pdfPage, end);
     FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
-    int startIndex = FPDFText_GetCharIndexAtPos(textPage, start.x(), pageHeight - start.y(),
+    int startIndex = FPDFText_GetCharIndexAtPos(textPage, pageStart.x(), pageStart.y(),
                                                 CharacterHitTolerance, CharacterHitTolerance);
-    int endIndex = FPDFText_GetCharIndexAtPos(textPage, end.x(), pageHeight - end.y(),
+    int endIndex = FPDFText_GetCharIndexAtPos(textPage, pageEnd.x(), pageEnd.y(),
                                               CharacterHitTolerance, CharacterHitTolerance);
 
     QPdfSelection result;
@@ -946,7 +997,7 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end)
 
         // If the given end position is past the end of the line, i.e. if the right edge of the last character's
         // bounding box is closer to it than the left edge is, then extend the char range by one
-        QRectF endCharBox = d->getCharBox(textPage, pageHeight, endIndex);
+        QRectF endCharBox = d->getCharBox(pdfPage, textPage, endIndex);
         if (qAbs(endCharBox.right() - end.x()) < qAbs(endCharBox.x() - end.x()))
             ++endIndex;
 
@@ -958,7 +1009,7 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end)
         for (int i = 0; i < rectCount; ++i) {
             double l, r, b, t;
             FPDFText_GetRect(textPage, i, &l, &t, &r, &b);
-            QRectF rect(l, pageHeight - t, r - l, t - b);
+            const QRectF rect = d->mapPageToView(pdfPage, l, t, r, b);
             if (hull.isNull())
                 hull = rect;
             else
@@ -988,7 +1039,6 @@ QPdfSelection QPdfDocument::getSelectionAtIndex(int page, int startIndex, int ma
         return {};
     const QPdfMutexLocker lock;
     FPDF_PAGE pdfPage = FPDF_LoadPage(d->doc, page);
-    double pageHeight = FPDF_GetPageHeight(pdfPage);
     FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
     int pageCount = FPDFText_CountChars(textPage);
     if (startIndex >= pageCount)
@@ -1003,7 +1053,7 @@ QPdfSelection QPdfDocument::getSelectionAtIndex(int page, int startIndex, int ma
         for (int i = 0; i < rectCount; ++i) {
             double l, r, b, t;
             FPDFText_GetRect(textPage, i, &l, &t, &r, &b);
-            QRectF rect(l, pageHeight - t, r - l, t - b);
+            const QRectF rect = d->mapPageToView(pdfPage, l, t, r, b);
             if (hull.isNull())
                 hull = rect;
             else
@@ -1012,7 +1062,7 @@ QPdfSelection QPdfDocument::getSelectionAtIndex(int page, int startIndex, int ma
         }
     }
     if (bounds.isEmpty())
-        hull = QRectF(d->getCharPosition(textPage, pageHeight, startIndex), QSizeF());
+        hull = QRectF(d->getCharPosition(pdfPage, textPage, startIndex), QSizeF());
     qCDebug(qLcDoc) << "on page" << page << "at index" << startIndex << "maxLength" << maxLength
                     << "got" << text.size() << "chars," << rectCount << "rects within" << hull;
 
@@ -1029,7 +1079,6 @@ QPdfSelection QPdfDocument::getAllText(int page)
 {
     const QPdfMutexLocker lock;
     FPDF_PAGE pdfPage = FPDF_LoadPage(d->doc, page);
-    double pageHeight = FPDF_GetPageHeight(pdfPage);
     FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
     int count = FPDFText_CountChars(textPage);
     if (count < 1)
@@ -1041,7 +1090,7 @@ QPdfSelection QPdfDocument::getAllText(int page)
     for (int i = 0; i < rectCount; ++i) {
         double l, r, b, t;
         FPDFText_GetRect(textPage, i, &l, &t, &r, &b);
-        QRectF rect(l, pageHeight - t, r - l, t - b);
+        const QRectF rect = d->mapPageToView(pdfPage, l, t, r, b);
         if (hull.isNull())
             hull = rect;
         else
diff --git a/src/pdf/qpdfdocument_p.h b/src/pdf/qpdfdocument_p.h
index d52aabe4bb1..12092c4ad26 100644
--- a/src/pdf/qpdfdocument_p.h
+++ b/src/pdf/qpdfdocument_p.h
@@ -16,6 +16,7 @@
 //
 
 #include "qpdfdocument.h"
+#include "private/qtpdfexports_p.h"
 
 #include "third_party/pdfium/public/fpdfview.h"
 #include "third_party/pdfium/public/fpdf_dataavail.h"
@@ -77,9 +78,12 @@ class Q_PDF_PRIVATE_EXPORT QPdfDocumentPrivate: public FPDF_FILEACCESS, public F
     static int fpdf_GetBlock(void* param, unsigned long position, unsigned char* pBuf, unsigned long size);
     static void fpdf_AddSegment(struct _FX_DOWNLOADHINTS* pThis, size_t offset, size_t size);
     void updateLastError();
-    QString getText(FPDF_TEXTPAGE textPage, int startIndex, int count);
-    QPointF getCharPosition(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex);
-    QRectF getCharBox(FPDF_TEXTPAGE textPage, double pageHeight, int charIndex);
+    QString getText(FPDF_TEXTPAGE textPage, int startIndex, int count) const;
+    QPointF getCharPosition(FPDF_PAGE pdfPage, FPDF_TEXTPAGE textPage, int charIndex) const;
+    QRectF getCharBox(FPDF_PAGE pdfPage, FPDF_TEXTPAGE textPage, int charIndex) const;
+    QPointF mapPageToView(FPDF_PAGE pdfPage, double x, double y) const;
+    QRectF mapPageToView(FPDF_PAGE pdfPage, double left, double top, double right, double bottom) const;
+    QPointF mapViewToPage(FPDF_PAGE pdfPage, QPointF position) const;
 
     // FPDF takes the rotation parameter as an int.
     // This enum is mapping the int values defined in fpdfview.h:956.
diff --git a/src/pdf/qpdflinkmodel.cpp b/src/pdf/qpdflinkmodel.cpp
index 5fae579d351..645dff21a4d 100644
--- a/src/pdf/qpdflinkmodel.cpp
+++ b/src/pdf/qpdflinkmodel.cpp
@@ -44,11 +44,13 @@ Q_LOGGING_CATEGORY(qLcLink, "qt.pdf.links")
     Constructs a new link model with parent object \a parent.
 */
 QPdfLinkModel::QPdfLinkModel(QObject *parent)
-    : QAbstractListModel(*(new QPdfLinkModelPrivate()), parent)
+    : QAbstractListModel(parent),
+      d_ptr{std::make_unique<QPdfLinkModelPrivate>(this)}
 {
+    Q_D(QPdfLinkModel);
     QMetaEnum rolesMetaEnum = metaObject()->enumerator(metaObject()->indexOfEnumerator("Role"));
     for (int r = Qt::UserRole; r < int(Role::NRoles); ++r)
-        m_roleNames.insert(r, QByteArray(rolesMetaEnum.valueToKey(r)).toLower());
+        d->roleNames.insert(r, QByteArray(rolesMetaEnum.valueToKey(r)).toLower());
 }
 
 /*!
@@ -58,7 +60,8 @@ QPdfLinkModel::~QPdfLinkModel() {}
 
 QHash<int, QByteArray> QPdfLinkModel::roleNames() const
 {
-    return m_roleNames;
+    Q_D(const QPdfLinkModel);
+    return d->roleNames;
 }
 
 /*!
@@ -152,7 +155,7 @@ void QPdfLinkModel::setPage(int page)
     not found. In other words, this function is useful for picking, to handle
     mouse click or hover.
 */
-QPdfLink QPdfLinkModel::linkAt(const QPointF &point) const
+QPdfLink QPdfLinkModel::linkAt(QPointF point) const
 {
     Q_D(const QPdfLinkModel);
     for (const auto &link : std::as_const(d->links)) {
@@ -164,10 +167,6 @@ QPdfLink QPdfLinkModel::linkAt(const QPointF &point) const
     return {};
 }
 
-QPdfLinkModelPrivate::QPdfLinkModelPrivate() : QAbstractItemModelPrivate()
-{
-}
-
 void QPdfLinkModelPrivate::update()
 {
     Q_Q(QPdfLinkModel);
@@ -180,7 +179,6 @@ void QPdfLinkModelPrivate::update()
         qCWarning(qLcLink) << "failed to load page" << page;
         return;
     }
-    double pageHeight = FPDF_GetPageHeight(pdfPage);
     q->beginResetModel();
     links.clear();
 
@@ -205,8 +203,7 @@ void QPdfLinkModelPrivate::update()
             std::swap(rect.bottom, rect.top);
 
         QPdfLink linkData;
-        linkData.d->rects << QRectF(rect.left, pageHeight - rect.top,
-                               rect.right - rect.left, rect.top - rect.bottom);
+        linkData.d->rects << document->d->mapPageToView(pdfPage, rect.left, rect.top, rect.right, rect.bottom);
         FPDF_DEST dest = FPDFLink_GetDest(doc, linkAnnot);
         FPDF_ACTION action = FPDFLink_GetAction(linkAnnot);
         switch (FPDFAction_GetType(action)) {
@@ -225,7 +222,7 @@ void QPdfLinkModelPrivate::update()
                 break; // at least we got a page number, so the link will jump there
             }
             if (hasX && hasY)
-                linkData.d->location = QPointF(x, pageHeight - y);
+                linkData.d->location = document->d->mapPageToView(pdfPage, x, y);
             if (hasZoom)
                 linkData.d->zoom = zoom;
             break;
@@ -288,7 +285,7 @@ void QPdfLinkModelPrivate::update()
                     double left, top, right, bottom;
                     bool success = FPDFLink_GetRect(webLinks, i, r, &left, &top, &right, &bottom);
                     if (success) {
-                        linkData.d->rects << QRectF(left, pageHeight - top, right - left, top - bottom);
+                        linkData.d->rects << document->d->mapPageToView(pdfPage, left, top, right, bottom);
                         links << linkData;
                     }
                 }
diff --git a/src/pdf/qpdflinkmodel.h b/src/pdf/qpdflinkmodel.h
index 73cc23d1f74..be2ce890c19 100644
--- a/src/pdf/qpdflinkmodel.h
+++ b/src/pdf/qpdflinkmodel.h
@@ -10,6 +10,8 @@
 
 #include <QtCore/QAbstractListModel>
 
+#include <memory>
+
 QT_BEGIN_NAMESPACE
 
 class QPdfLinkModelPrivate;
@@ -21,7 +23,7 @@ class Q_PDF_EXPORT QPdfLinkModel : public QAbstractListModel
     Q_PROPERTY(int page READ page WRITE setPage NOTIFY pageChanged)
 
 public:
-    enum class Role : int {
+    enum class Role {
         Link = Qt::UserRole,
         Rectangle,
         Url,
@@ -32,7 +34,7 @@ class Q_PDF_EXPORT QPdfLinkModel : public QAbstractListModel
     };
     Q_ENUM(Role)
     explicit QPdfLinkModel(QObject *parent = nullptr);
-    ~QPdfLinkModel();
+    ~QPdfLinkModel() override;
 
     QPdfDocument *document() const;
 
@@ -42,7 +44,7 @@ class Q_PDF_EXPORT QPdfLinkModel : public QAbstractListModel
 
     int page() const;
 
-    QPdfLink linkAt(const QPointF &point) const;
+    QPdfLink linkAt(QPointF point) const;
 
 public Q_SLOTS:
     void setDocument(QPdfDocument *document);
@@ -56,8 +58,8 @@ private Q_SLOTS:
     void onStatusChanged(QPdfDocument::Status status);
 
 private:
-    QHash<int, QByteArray> m_roleNames;
     Q_DECLARE_PRIVATE(QPdfLinkModel)
+    const std::unique_ptr<QPdfLinkModelPrivate> d_ptr;
 };
 
 QT_END_NAMESPACE
diff --git a/src/pdf/qpdflinkmodel_p.h b/src/pdf/qpdflinkmodel_p.h
index 99bd5f1730a..ba46a6e00a6 100644
--- a/src/pdf/qpdflinkmodel_p.h
+++ b/src/pdf/qpdflinkmodel_p.h
@@ -20,15 +20,18 @@
 
 QT_BEGIN_NAMESPACE
 
-class QPdfLinkModelPrivate: public QAbstractItemModelPrivate
+class QPdfLinkModelPrivate
 {
+    QPdfLinkModel *q_ptr;
     Q_DECLARE_PUBLIC(QPdfLinkModel)
 
 public:
-    QPdfLinkModelPrivate();
+    explicit QPdfLinkModelPrivate(QPdfLinkModel *qq)
+        : q_ptr(qq) {}
 
     void update();
 
+    QHash<int, QByteArray> roleNames;
     QPdfDocument *document = nullptr;
     QList<QPdfLink> links;
     int page = 0;
diff --git a/src/pdf/qpdfsearchmodel.cpp b/src/pdf/qpdfsearchmodel.cpp
index 3109430f0d6..abe0122bfc2 100644
--- a/src/pdf/qpdfsearchmodel.cpp
+++ b/src/pdf/qpdfsearchmodel.cpp
@@ -3,12 +3,11 @@
 
 #include "qpdfdocument_p.h"
 #include "qpdflink.h"
-#include "qpdflink_p.h"
 #include "qpdfsearchmodel.h"
 #include "qpdfsearchmodel_p.h"
 
-#include "third_party/pdfium/public/fpdf_doc.h"
 #include "third_party/pdfium/public/fpdf_text.h"
+#include "third_party/pdfium/public/fpdfview.h"
 
 #include <QtCore/qelapsedtimer.h>
 #include <QtCore/qloggingcategory.h>
@@ -173,7 +172,7 @@ QPdfLink QPdfSearchModel::resultAtIndex(int index) const
 {
     Q_D(const QPdfSearchModel);
     const auto pi = const_cast<QPdfSearchModelPrivate*>(d)->pageAndIndexForResult(index);
-    if (pi.page < 0)
+    if (pi.page < 0 || index < 0)
         return {};
     return d->searchResults[pi.page][pi.index];
 }
@@ -196,21 +195,13 @@ void QPdfSearchModel::setDocument(QPdfDocument *document)
 
     disconnect(d->documentConnection);
     d->documentConnection = connect(document, &QPdfDocument::pageCountChanged, this,
-                                    &QPdfSearchModel::onDocumentPageCountChanged);
+                                    [this]() { d_func()->clearResults(); });
 
     d->document = document;
     d->clearResults();
     emit documentChanged();
 }
 
-void QPdfSearchModel::onDocumentPageCountChanged(int count)
-{
-    Q_UNUSED(count);
-
-    Q_D(QPdfSearchModel);
-    d->clearResults();
-}
-
 void QPdfSearchModel::timerEvent(QTimerEvent *event)
 {
     Q_D(QPdfSearchModel);
@@ -259,7 +250,6 @@ bool QPdfSearchModelPrivate::doSearch(int page)
         qWarning() << "failed to load page" << page;
         return false;
     }
-    double pageHeight = FPDF_GetPageHeight(pdfPage);
     FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage);
     if (!textPage) {
         qWarning() << "failed to load text of page" << page;
@@ -277,9 +267,12 @@ bool QPdfSearchModelPrivate::doSearch(int page)
         int startIndex = -1;
         int endIndex = -1;
         for (int r = 0; r < rectCount; ++r) {
+            // get bounding box of search result in page coordinates
             double left, top, right, bottom;
             FPDFText_GetRect(textPage, r, &left, &top, &right, &bottom);
-            rects << QRectF(left, pageHeight - top, right - left, top - bottom);
+            // deal with any internal PDF transforms and
+            // convert to the 1x (pixels = points) 4th-quadrant coordinate system
+            rects << document->d->mapPageToView(pdfPage, left, top, right, bottom);
             if (r == 0) {
                 startIndex = FPDFText_GetCharIndexAtPos(textPage, left, top,
                         CharacterHitTolerance, CharacterHitTolerance);
@@ -288,7 +281,8 @@ bool QPdfSearchModelPrivate::doSearch(int page)
                 endIndex = FPDFText_GetCharIndexAtPos(textPage, right, top,
                         CharacterHitTolerance, CharacterHitTolerance);
             }
-            qCDebug(qLcS) << rects.last() << "char idx" << startIndex << "->" << endIndex;
+            qCDebug(qLcS) << rects.last() << "char idx" << startIndex << "->" << endIndex
+                          << "from page rect" << left << top << right << bottom;
         }
         QString contextBefore, contextAfter;
         if (startIndex >= 0 || endIndex >= 0) {
diff --git a/src/pdf/qpdfsearchmodel.h b/src/pdf/qpdfsearchmodel.h
index b1094b67b5b..c1e4e64ece6 100644
--- a/src/pdf/qpdfsearchmodel.h
+++ b/src/pdf/qpdfsearchmodel.h
@@ -55,7 +55,6 @@ public Q_SLOTS:
 protected:
     void updatePage(int page);
     void timerEvent(QTimerEvent *event) override;
-    void onDocumentPageCountChanged(int count);
 
 private:
     QHash<int, QByteArray> m_roleNames;
diff --git a/src/pdf/qtpdfglobal.h b/src/pdf/qtpdfglobal.h
index d38eafaab24..2d0900029e6 100644
--- a/src/pdf/qtpdfglobal.h
+++ b/src/pdf/qtpdfglobal.h
@@ -5,24 +5,7 @@
 #define QTPDFGLOBAL_H
 
 #include <QtCore/qglobal.h>
-
-QT_BEGIN_NAMESPACE
-
-#ifndef Q_PDF_EXPORT
-#  ifndef QT_STATIC
-#    if defined(QT_BUILD_PDF_LIB)
-#      define Q_PDF_EXPORT Q_DECL_EXPORT
-#    else
-#      define Q_PDF_EXPORT Q_DECL_IMPORT
-#    endif
-#  else
-#    define Q_PDF_EXPORT
-#  endif
-#endif
-
-#define Q_PDF_PRIVATE_EXPORT Q_PDF_EXPORT
-
-QT_END_NAMESPACE
+#include <QtPdf/qtpdfexports.h>
 
 #endif // QTPDFGLOBAL_H
 
diff --git a/src/pdfquick/PdfMultiPageView.qml b/src/pdfquick/PdfMultiPageView.qml
index 0f62a229d5a..cfc19c28ba8 100644
--- a/src/pdfquick/PdfMultiPageView.qml
+++ b/src/pdfquick/PdfMultiPageView.qml
@@ -159,6 +159,13 @@ Item {
         \sa PdfPageNavigator::jump(), currentPage
     */
     function goToLocation(page, location, zoom) {
+        if (tableView.rows === 0) {
+            // save this request for later
+            tableView.pendingRow = page
+            tableView.pendingLocation = location
+            tableView.pendingZoom = zoom
+            return
+        }
         if (zoom > 0) {
             pageNavigator.jumping = true // don't call pageNavigator.update() because we will jump() instead
             root.renderScale = zoom
@@ -298,14 +305,7 @@ Item {
         property point jumpLocationMargin: Qt.point(10, 10)  // px away from viewport edges
         anchors.fill: parent
         anchors.leftMargin: 2
-        model: modelInUse && root.document ? root.document.pageCount : 0
-        // workaround to make TableView do scheduleRebuildTable(RebuildOption::All) in cases when forceLayout() doesn't
-        property bool modelInUse: true
-        function rebuild() {
-            modelInUse = false
-            modelInUse = true
-        }
-        // end workaround
+        model: root.document ? root.document.pageCount : 0
         rowSpacing: 6
         property real rotationNorm: Math.round((360 + (root.pageRotation % 360)) % 360)
         property bool rot90: rotationNorm == 90 || rotationNorm == 270
@@ -316,6 +316,21 @@ Item {
         property real pageHolderWidth: Math.max(root.width, ((rot90 ? document?.maxPageHeight : document?.maxPageWidth) ?? 0) * root.renderScale)
         columnWidthProvider: function(col) { return document ? pageHolderWidth + vscroll.width + 2 : 0 }
         rowHeightProvider: function(row) { return (rot90 ? document.pagePointSize(row).width : document.pagePointSize(row).height) * root.renderScale }
+
+        // delayed-jump feature in case the user called goToPage() or goToLocation() too early
+        property int pendingRow: -1
+        property point pendingLocation
+        property real pendingZoom: -1
+        onRowsChanged: {
+            if (rows > 0 && tableView.pendingRow >= 0) {
+                console.log(lcMPV, "initiating delayed jump to page", tableView.pendingRow, "loc", tableView.pendingLocation, "zoom", tableView.pendingZoom)
+                root.goToLocation(tableView.pendingRow, tableView.pendingLocation, tableView.pendingZoom)
+                tableView.pendingRow = -1
+                tableView.pendingLocation = Qt.point(-1, -1)
+                tableView.pendingZoom = -1
+            }
+        }
+
         delegate: Rectangle {
             id: pageHolder
             color: tableView.debug ? "beige" : "transparent"
@@ -415,12 +430,16 @@ Item {
                             const centroidInFlickable = tableView.mapFromItem(paper, pinch.centroid.position.x, pinch.centroid.position.y)
                             const newSourceWidth = image.sourceSize.width * paper.scale
                             const ratio = newSourceWidth / image.sourceSize.width
-                            console.log(lcMPV, "pinch ended on page", index, "with centroid", pinch.centroid.position, centroidInPoints, "wrt flickable", centroidInFlickable,
+                            console.log(lcMPV, "pinch ended on page", index,
+                                        "with scale", paper.scale.toFixed(3), "ratio", ratio.toFixed(3),
+                                        "centroid", pinch.centroid.position, centroidInPoints,
+                                        "wrt flickable", centroidInFlickable,
                                         "page at", pageHolder.x.toFixed(2), pageHolder.y.toFixed(2),
                                         "contentX/Y were", tableView.contentX.toFixed(2), tableView.contentY.toFixed(2))
                             if (ratio > 1.1 || ratio < 0.9) {
                                 const centroidOnPage = Qt.point(centroidInPoints.x * root.renderScale * ratio, centroidInPoints.y * root.renderScale * ratio)
                                 paper.scale = 1
+                                pinch.persistentScale = 1
                                 paper.x = 0
                                 paper.y = 0
                                 root.renderScale *= ratio
@@ -528,8 +547,8 @@ Item {
         // and don't force layout either, because positionViewAtCell() will do that
         if (pageNavigator.jumping)
             return
-        // make TableView rebuild from scratch, because otherwise it doesn't know the delegates are changing size
-        tableView.rebuild()
+        // page size changed: TableView needs to redo layout to avoid overlapping delegates or gaps between them
+        tableView.forceLayout()
         const cell = tableView.cellAtPos(root.width / 2, root.height / 2)
         const currentItem = tableView.itemAtCell(cell)
         if (currentItem) {
diff --git a/src/pdfquick/PdfScrollablePageView.qml b/src/pdfquick/PdfScrollablePageView.qml
index 5295db7f8c5..afebdd080a6 100644
--- a/src/pdfquick/PdfScrollablePageView.qml
+++ b/src/pdfquick/PdfScrollablePageView.qml
@@ -302,9 +302,6 @@ Flickable {
     }
 
     onRenderScaleChanged: {
-        image.sourceSize.width = document.pagePointSize(pageNavigator.currentPage).width *
-                renderScale * Screen.devicePixelRatio
-        image.sourceSize.height = 0
         paper.scale = 1
         const currentLocation = Qt.point((root.contentX + root.width / 2) / root.renderScale,
                                          (root.contentY + root.height / 2) / root.renderScale)
@@ -365,6 +362,10 @@ Flickable {
             rotation: root.pageRotation
             anchors.centerIn: parent
             property real pageScale: image.paintedWidth / document.pagePointSize(pageNavigator.currentPage).width
+            width: document.pagePointSize(pageNavigator.currentPage).width * root.renderScale
+            height: document.pagePointSize(pageNavigator.currentPage).height * root.renderScale
+            sourceSize.width: width * Screen.devicePixelRatio
+            sourceSize.height: 0
 
             Shape {
                 anchors.fill: parent
diff --git a/src/pdfquick/doc/src/qtquickpdf-module.qdoc b/src/pdfquick/doc/src/qtquickpdf-module.qdoc
index 1d31f6148cb..a4ca0d9e8b0 100644
--- a/src/pdfquick/doc/src/qtquickpdf-module.qdoc
+++ b/src/pdfquick/doc/src/qtquickpdf-module.qdoc
@@ -12,7 +12,7 @@
 
     To use the types in this module, import the module with the following line:
 
-    \code
+    \qml
     import QtQuick.Pdf
-    \endcode
+    \endqml
 */
diff --git a/src/pdfquick/qquickpdfdocument.cpp b/src/pdfquick/qquickpdfdocument.cpp
index 492c320d6ac..9770900db57 100644
--- a/src/pdfquick/qquickpdfdocument.cpp
+++ b/src/pdfquick/qquickpdfdocument.cpp
@@ -36,7 +36,10 @@ QQuickPdfDocument::QQuickPdfDocument(QObject *parent)
 /*!
     \internal
 */
-QQuickPdfDocument::~QQuickPdfDocument() = default;
+QQuickPdfDocument::~QQuickPdfDocument()
+{
+    delete m_carrierFile;
+};
 
 void QQuickPdfDocument::classBegin()
 {
@@ -69,7 +72,8 @@ void QQuickPdfDocument::setSource(QUrl source)
 
     m_source = source;
     m_maxPageWidthHeight = QSizeF();
-    m_carrierFile->deleteLater();
+    if (m_carrierFile)
+        m_carrierFile->deleteLater();
     m_carrierFile = nullptr;
     emit sourceChanged();
     const QQmlContext *context = qmlContext(this);
diff --git a/src/pdfquick/qquickpdfpageimage.cpp b/src/pdfquick/qquickpdfpageimage.cpp
index 2ea8ebc12ca..f2da067f1b5 100644
--- a/src/pdfquick/qquickpdfpageimage.cpp
+++ b/src/pdfquick/qquickpdfpageimage.cpp
@@ -76,6 +76,18 @@ QQuickPdfDocument *QQuickPdfPageImage::document() const
 void QQuickPdfPageImage::load()
 {
     Q_D(QQuickPdfPageImage);
+    QUrl url = source();
+    if (!d->doc || !d->doc->carrierFile()) {
+        if (!url.isEmpty()) {
+            qmlWarning(this) << "document property not set: falling back to inefficient loading of " << url;
+            QQuickImageBase::load();
+        }
+        return;
+    }
+    if (url != d->doc->resolvedSource()) {
+        url = d->doc->resolvedSource();
+        qmlWarning(this) << "document and source properties in conflict: preferring document source " << url;
+    }
     auto carrierFile = d->doc->carrierFile();
     static int thisRequestProgress = -1;
     static int thisRequestFinished = -1;
@@ -86,7 +98,7 @@ void QQuickPdfPageImage::load()
             QQuickImageBase::staticMetaObject.indexOfSlot("requestFinished()");
     }
 
-    d->pix.loadImageFromDevice(qmlEngine(this), carrierFile, d->url,
+    d->pix.loadImageFromDevice(qmlEngine(this), carrierFile, url,
                                d->sourceClipRect.toRect(), d->sourcesize * d->devicePixelRatio,
                                QQuickImageProviderOptions(), d->currentFrame, d->frameCount);
 
diff --git a/src/pdfquick/qquickpdfsearchmodel.cpp b/src/pdfquick/qquickpdfsearchmodel.cpp
index ca33a6dc624..21fa1a70bb5 100644
--- a/src/pdfquick/qquickpdfsearchmodel.cpp
+++ b/src/pdfquick/qquickpdfsearchmodel.cpp
@@ -199,7 +199,7 @@ QList<QPolygonF> QQuickPdfSearchModel::boundingPolygonsOnPage(int page)
 */
 void QQuickPdfSearchModel::setCurrentPage(int currentPage)
 {
-    if (m_currentPage == currentPage)
+    if (m_currentPage == currentPage || !document())
         return;
 
     const auto pageCount = document()->document()->pageCount();
diff --git a/src/pdfwidgets/qpdfpageselector.cpp b/src/pdfwidgets/qpdfpageselector.cpp
index 72ab283555a..0c42573d8c8 100644
--- a/src/pdfwidgets/qpdfpageselector.cpp
+++ b/src/pdfwidgets/qpdfpageselector.cpp
@@ -6,29 +6,20 @@
 
 #include <QPdfDocument>
 
-QT_BEGIN_NAMESPACE
+#include <QtWidgets/qboxlayout.h>
 
-QPdfPageSelectorPrivate::QPdfPageSelectorPrivate(QPdfPageSelector *q)
-    : q_ptr(q)
-{
-}
+using namespace Qt::StringLiterals;
 
-void QPdfPageSelectorPrivate::documentStatusChanged()
-{
-    Q_Q(QPdfPageSelector);
-    if (!document.isNull() && document->status() == QPdfDocument::Status::Ready) {
-        q->setMaximum(document->pageCount());
-        q->setValue(0);
-    }
-}
+QT_BEGIN_NAMESPACE
 
 /*!
     \class QPdfPageSelector
     \inmodule QtPdf
-    \brief A QSpinBox for selecting a PDF page.
+    \since 6.6
+    \brief A widget for selecting a PDF page.
 
-    QPdfPageSelector is a QSpinBox specialized for selecting a page label
-    from a QPdfDocument.
+    QPdfPageSelector is a widget for selecting a page label from a
+    QPdfDocument.
 
     \sa QPdfDocument::pageLabel()
 */
@@ -37,69 +28,144 @@ void QPdfPageSelectorPrivate::documentStatusChanged()
     Constructs a PDF page selector with parent widget \a parent.
 */
 QPdfPageSelector::QPdfPageSelector(QWidget *parent)
-    : QSpinBox(parent)
-    , d_ptr(new QPdfPageSelectorPrivate(this))
+    : QWidget(parent), d_ptr(new QPdfPageSelectorPrivate)
 {
+    Q_D(QPdfPageSelector);
+    d->spinBox = new QPdfPageSelectorSpinBox(this);
+    d->spinBox->setObjectName(u"_q_spinBox"_s);
+    auto vlay = new QVBoxLayout(this);
+    vlay->setContentsMargins({});
+    vlay->addWidget(d->spinBox);
+
+    connect(d->spinBox, &QPdfPageSelectorSpinBox::_q_documentChanged,
+            this, &QPdfPageSelector::documentChanged);
+    connect(d->spinBox, &QSpinBox::valueChanged, this, &QPdfPageSelector::currentPageChanged);
+    connect(d->spinBox, &QSpinBox::textChanged, this, &QPdfPageSelector::currentPageLabelChanged);
 }
 
 /*!
     Destroys the page selector.
 */
 QPdfPageSelector::~QPdfPageSelector()
-{
-}
+    = default;
 
 /*!
     \property QPdfPageSelector::document
 
     This property holds the document to be viewed.
 */
-void QPdfPageSelector::setDocument(QPdfDocument *document)
+
+void QPdfPageSelector::setDocument(QPdfDocument *doc)
 {
     Q_D(QPdfPageSelector);
+    d->spinBox->setDocument(doc);
+}
 
-    if (d->document == document)
-        return;
+QPdfDocument *QPdfPageSelector::document() const
+{
+    Q_D(const QPdfPageSelector);
+    return d->spinBox->document();
+}
 
-    if (d->document)
-        disconnect(d->documentStatusChangedConnection);
+/*!
+    \property QPdfPageSelector::currentPage
 
-    d->document = document;
-    emit documentChanged(d->document);
+    This property holds the index (\c{0}-based) of the current page in the
+    document.
+*/
 
-    if (d->document)
-        d->documentStatusChangedConnection =
-                connect(d->document.data(), &QPdfDocument::statusChanged, this,
-                        [d](){ d->documentStatusChanged(); });
+int QPdfPageSelector::currentPage() const
+{
+    Q_D(const QPdfPageSelector);
+    return d->spinBox->value();
+}
 
-    d->documentStatusChanged();
+void QPdfPageSelector::setCurrentPage(int index)
+{
+    Q_D(QPdfPageSelector);
+    d->spinBox->setValue(index);
 }
 
-QPdfDocument *QPdfPageSelector::document() const
+/*!
+    \property QPdfPageSelector::currentPageIndex
+
+    This property holds the page label corresponding to the current page index
+    in the document.
+
+    This is the text presented to the user.
+
+    \sa QPdfDocument::pageLabel()
+*/
+
+QString QPdfPageSelector::currentPageLabel() const
 {
     Q_D(const QPdfPageSelector);
+    return d->spinBox->text();
+}
+
+//
+// QPdfPageSelectorSpinBox:
+//
 
-    return d->document;
+void QPdfPageSelectorSpinBox::documentStatusChanged()
+{
+    if (m_document && m_document->status() == QPdfDocument::Status::Ready) {
+        setMaximum(m_document->pageCount());
+        setValue(0);
+    }
 }
 
-int QPdfPageSelector::valueFromText(const QString &text) const
+void QPdfPageSelectorSpinBox::setDocument(QPdfDocument *document)
 {
-    Q_D(const QPdfPageSelector);
-    if (d->document.isNull())
+    if (m_document == document)
+        return;
+
+    if (m_document)
+        disconnect(m_documentStatusChangedConnection);
+
+    m_document = document;
+    emit _q_documentChanged(document);
+
+    if (m_document) {
+        m_documentStatusChangedConnection =
+                connect(m_document.get(), &QPdfDocument::statusChanged,
+                        this, &QPdfPageSelectorSpinBox::documentStatusChanged);
+    }
+
+    documentStatusChanged();
+}
+
+QPdfPageSelectorSpinBox::QPdfPageSelectorSpinBox(QWidget *parent)
+    : QSpinBox(parent)
+{
+}
+
+QPdfPageSelectorSpinBox::~QPdfPageSelectorSpinBox()
+    = default;
+
+int QPdfPageSelectorSpinBox::valueFromText(const QString &text) const
+{
+    if (!m_document)
         return 0;
 
-    return d->document->pageIndexForLabel(text);
+    return m_document->pageIndexForLabel(text.trimmed());
 }
 
-QString QPdfPageSelector::textFromValue(int value) const
+QString QPdfPageSelectorSpinBox::textFromValue(int value) const
 {
-    Q_D(const QPdfPageSelector);
-    if (d->document.isNull())
+    if (!m_document)
         return {};
 
-    return d->document->pageLabel(value);
+    return m_document->pageLabel(value);
+}
+
+QValidator::State QPdfPageSelectorSpinBox::validate(QString &text, int &pos) const
+{
+    Q_UNUSED(pos);
+    return valueFromText(text) >= 0 ? QValidator::Acceptable : QValidator::Intermediate;
 }
 
 QT_END_NAMESPACE
 
+#include "moc_qpdfpageselector_p.cpp"
 #include "moc_qpdfpageselector.cpp"
diff --git a/src/pdfwidgets/qpdfpageselector.h b/src/pdfwidgets/qpdfpageselector.h
index bc2e352f771..d779f54cd3c 100644
--- a/src/pdfwidgets/qpdfpageselector.h
+++ b/src/pdfwidgets/qpdfpageselector.h
@@ -5,38 +5,45 @@
 #define QPDFPAGESELECTOR_H
 
 #include <QtPdfWidgets/qtpdfwidgetsglobal.h>
-#include <QtWidgets/qspinbox.h>
+
+#include <QtWidgets/qwidget.h>
+
+#include <memory>
 
 QT_BEGIN_NAMESPACE
 
 class QPdfDocument;
-class QPdfPageNavigator;
 class QPdfPageSelectorPrivate;
 
-class Q_PDF_WIDGETS_EXPORT QPdfPageSelector : public QSpinBox
+class Q_PDF_WIDGETS_EXPORT QPdfPageSelector : public QWidget
 {
     Q_OBJECT
 
     Q_PROPERTY(QPdfDocument* document READ document WRITE setDocument NOTIFY documentChanged)
-
+    Q_PROPERTY(int currentPage READ currentPage WRITE setCurrentPage NOTIFY currentPageChanged USER true)
+    Q_PROPERTY(QString currentPageLabel READ currentPageLabel NOTIFY currentPageLabelChanged)
 public:
     QPdfPageSelector() : QPdfPageSelector(nullptr) {}
     explicit QPdfPageSelector(QWidget *parent);
-    ~QPdfPageSelector();
+    ~QPdfPageSelector() override;
 
     void setDocument(QPdfDocument *document);
     QPdfDocument *document() const;
 
+    int currentPage() const;
+    QString currentPageLabel() const;
+
+public Q_SLOTS:
+    void setCurrentPage(int index);
+
 Q_SIGNALS:
     void documentChanged(QPdfDocument *document);
-
-protected:
-    int valueFromText(const QString &text) const override;
-    QString textFromValue(int value) const override;
+    void currentPageChanged(int index);
+    void currentPageLabelChanged(const QString &label);
 
 private:
     Q_DECLARE_PRIVATE(QPdfPageSelector)
-    QScopedPointer<QPdfPageSelectorPrivate> d_ptr;
+    const std::unique_ptr<QPdfPageSelectorPrivate> d_ptr;
 };
 
 QT_END_NAMESPACE
diff --git a/src/pdfwidgets/qpdfpageselector_p.h b/src/pdfwidgets/qpdfpageselector_p.h
index b2cd6ecf721..8e961f1d287 100644
--- a/src/pdfwidgets/qpdfpageselector_p.h
+++ b/src/pdfwidgets/qpdfpageselector_p.h
@@ -17,24 +17,42 @@
 
 #include "qpdfpageselector.h"
 
+#include <QtWidgets/qspinbox.h>
+
 #include <QPointer>
 
 QT_BEGIN_NAMESPACE
 
-class QPdfPageRenderer;
-
-class QPdfPageSelectorPrivate
+class QPdfPageSelectorSpinBox : public QSpinBox
 {
-    Q_DECLARE_PUBLIC(QPdfPageSelector)
-
+    Q_OBJECT
 public:
-    QPdfPageSelectorPrivate(QPdfPageSelector *q);
+    QPdfPageSelectorSpinBox() : QPdfPageSelectorSpinBox(nullptr) {}
+    explicit QPdfPageSelectorSpinBox(QWidget *parent);
+    ~QPdfPageSelectorSpinBox();
+
+    void setDocument(QPdfDocument *document);
+    QPdfDocument *document() const { return m_document.get(); }
+
+Q_SIGNALS:
+    void _q_documentChanged(QPdfDocument *document);
 
+protected:
+    int valueFromText(const QString &text) const override;
+    QString textFromValue(int value) const override;
+    QValidator::State validate(QString &text, int &pos) const override;
+
+private:
     void documentStatusChanged();
+private:
+    QPointer<QPdfDocument> m_document;
+    QMetaObject::Connection m_documentStatusChangedConnection;
+};
 
-    QPdfPageSelector *q_ptr;
-    QPointer<QPdfDocument> document;
-    QMetaObject::Connection documentStatusChangedConnection;
+class QPdfPageSelectorPrivate
+{
+public:
+    QPdfPageSelectorSpinBox *spinBox;
 };
 
 QT_END_NAMESPACE
diff --git a/src/pdfwidgets/qpdfview.cpp b/src/pdfwidgets/qpdfview.cpp
index 8295fd57b36..a67667fedb8 100644
--- a/src/pdfwidgets/qpdfview.cpp
+++ b/src/pdfwidgets/qpdfview.cpp
@@ -16,7 +16,6 @@
 #include <QPdfSearchModel>
 #include <QScreen>
 #include <QScrollBar>
-#include <QScroller>
 
 QT_BEGIN_NAMESPACE
 
@@ -107,8 +106,9 @@ void QPdfViewPrivate::setViewport(QRect viewport)
         const QRect currentPageLine(m_viewport.x(), m_viewport.y() + m_viewport.height() * 0.4, m_viewport.width(), 2);
 
         int currentPage = 0;
-        for (auto it = m_documentLayout.pageGeometries.cbegin(); it != m_documentLayout.pageGeometries.cend(); ++it) {
-            const QRect pageGeometry = it.value();
+        for (auto it = m_documentLayout.pageGeometryAndScale.cbegin();
+             it != m_documentLayout.pageGeometryAndScale.cend(); ++it) {
+            const QRect pageGeometry = it.value().first;
             if (pageGeometry.intersects(currentPageLine)) {
                 currentPage = it.key();
                 break;
@@ -183,7 +183,7 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const
     if (!m_document || m_document->status() != QPdfDocument::Status::Ready)
         return documentLayout;
 
-    QHash<int, QRect> pageGeometries;
+    QHash<int, QPair<QRect, qreal>> pageGeometryAndScale;
 
     const int pageCount = m_document->pageCount();
 
@@ -195,24 +195,28 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const
     // calculate page sizes
     for (int page = startPage; page < endPage; ++page) {
         QSize pageSize;
+        qreal pageScale = m_zoomFactor;
         if (m_zoomMode == QPdfView::ZoomMode::Custom) {
             pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution * m_zoomFactor).toSize();
         } else if (m_zoomMode == QPdfView::ZoomMode::FitToWidth) {
             pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution).toSize();
-            const qreal factor = (qreal(m_viewport.width() - m_documentMargins.left() - m_documentMargins.right()) /
-                                  qreal(pageSize.width()));
-            pageSize *= factor;
+            pageScale = (qreal(m_viewport.width() - m_documentMargins.left() - m_documentMargins.right()) /
+                         qreal(pageSize.width()));
+            pageSize *= pageScale;
         } else if (m_zoomMode == QPdfView::ZoomMode::FitInView) {
             const QSize viewportSize(m_viewport.size() +
                                      QSize(-m_documentMargins.left() - m_documentMargins.right(), -m_pageSpacing));
 
             pageSize = QSizeF(m_document->pagePointSize(page) * m_screenResolution).toSize();
-            pageSize = pageSize.scaled(viewportSize, Qt::KeepAspectRatio);
+            QSize scaledSize = pageSize.scaled(viewportSize, Qt::KeepAspectRatio);
+            // because of KeepAspectRatio, the ratio of widths should be the same as the ratio of heights
+            pageScale = qreal(scaledSize.width()) / qreal(pageSize.width());
+            pageSize = scaledSize;
         }
 
         totalWidth = qMax(totalWidth, pageSize.width());
 
-        pageGeometries[page] = QRect(QPoint(0, 0), pageSize);
+        pageGeometryAndScale[page] = {QRect(QPoint(0, 0), pageSize), pageScale};
     }
 
     totalWidth += m_documentMargins.left() + m_documentMargins.right();
@@ -221,19 +225,19 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const
 
     // calculate page positions
     for (int page = startPage; page < endPage; ++page) {
-        const QSize pageSize = pageGeometries[page].size();
+        const QSize pageSize = pageGeometryAndScale[page].first.size();
 
         // center horizontal inside the viewport
         const int pageX = (qMax(totalWidth, m_viewport.width()) - pageSize.width()) / 2;
 
-        pageGeometries[page].moveTopLeft(QPoint(pageX, pageY));
+        pageGeometryAndScale[page].first.moveTopLeft(QPoint(pageX, pageY));
 
         pageY += pageSize.height() + m_pageSpacing;
     }
 
     pageY += m_documentMargins.bottom();
 
-    documentLayout.pageGeometries = pageGeometries;
+    documentLayout.pageGeometryAndScale = pageGeometryAndScale;
 
     // calculate overall document size
     documentLayout.documentSize = QSize(totalWidth, pageY);
@@ -243,16 +247,25 @@ QPdfViewPrivate::DocumentLayout QPdfViewPrivate::calculateDocumentLayout() const
 
 qreal QPdfViewPrivate::yPositionForPage(int pageNumber) const
 {
-    const auto it = m_documentLayout.pageGeometries.constFind(pageNumber);
-    if (it == m_documentLayout.pageGeometries.cend())
+    const auto it = m_documentLayout.pageGeometryAndScale.constFind(pageNumber);
+    if (it == m_documentLayout.pageGeometryAndScale.cend())
         return 0.0;
 
-    return (*it).y();
+    return (*it).first.y();
 }
 
-QTransform QPdfViewPrivate::screenScaleTransform() const
+QTransform QPdfViewPrivate::screenScaleTransform(int page) const
 {
-    const qreal scale = m_screenResolution * m_zoomFactor;
+    qreal scale = m_screenResolution * m_zoomFactor;
+    switch (m_zoomMode) {
+    case QPdfView::ZoomMode::FitToWidth:
+    case QPdfView::ZoomMode::FitInView:
+        scale = m_screenResolution * m_documentLayout.pageGeometryAndScale[page].second;
+        break;
+    default:
+        break;
+    }
+
     return QTransform::fromScale(scale, scale);
 }
 
@@ -296,7 +309,6 @@ QPdfView::QPdfView(QWidget *parent)
     verticalScrollBar()->setSingleStep(20);
     horizontalScrollBar()->setSingleStep(20);
 
-    QScroller::grabGesture(this);
     setMouseTracking(true);
     d->calculateViewport();
 }
@@ -368,7 +380,7 @@ void QPdfView::setSearchModel(QPdfSearchModel *searchModel)
         connect(searchModel, &QPdfSearchModel::dataChanged, this,
                 [this](const QModelIndex &, const QModelIndex &, const QList<int> &) { update(); });
     }
-    setCurrentSearchResult(-1);
+    setCurrentSearchResultIndex(-1);
 }
 
 QPdfSearchModel *QPdfView::searchModel() const
@@ -379,7 +391,7 @@ QPdfSearchModel *QPdfView::searchModel() const
 
 /*!
     \since 6.6
-    \property QPdfView::currentSearchResult
+    \property QPdfView::currentSearchResultIndex
 
     If this property is set to a positive number, and \l searchModel is set,
     QPdfView draws a frame around the search result provided by
@@ -390,21 +402,21 @@ QPdfSearchModel *QPdfView::searchModel() const
 
     By default it is \c -1, so that no search results are framed.
 */
-void QPdfView::setCurrentSearchResult(int currentResult)
+void QPdfView::setCurrentSearchResultIndex(int currentResult)
 {
     Q_D(QPdfView);
-    if (d->m_currentSearchResult == currentResult)
+    if (d->m_currentSearchResultIndex == currentResult)
         return;
 
-    d->m_currentSearchResult = currentResult;
-    emit currentSearchResultChanged(currentResult);
+    d->m_currentSearchResultIndex = currentResult;
+    emit currentSearchResultIndexChanged(currentResult);
     viewport()->update(); //update();
 }
 
-int QPdfView::currentSearchResult() const
+int QPdfView::currentSearchResultIndex() const
 {
     Q_D(const QPdfView);
-    return d->m_currentSearchResult;
+    return d->m_currentSearchResultIndex;
 }
 
 /*!
@@ -575,9 +587,9 @@ void QPdfView::paintEvent(QPaintEvent *event)
     painter.fillRect(event->rect(), palette().brush(QPalette::Dark));
     painter.translate(-d->m_viewport.x(), -d->m_viewport.y());
 
-    for (auto it = d->m_documentLayout.pageGeometries.cbegin();
-         it != d->m_documentLayout.pageGeometries.cend(); ++it) {
-        const QRect pageGeometry = it.value();
+    for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin();
+         it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) {
+        const QRect pageGeometry = it.value().first;
         if (pageGeometry.intersects(d->m_viewport)) { // page needs to be painted
             painter.fillRect(pageGeometry, Qt::white);
 
@@ -590,7 +602,7 @@ void QPdfView::paintEvent(QPaintEvent *event)
                 d->m_pageRenderer->requestPage(page, pageGeometry.size() * devicePixelRatioF());
             }
 
-            const QTransform scaleTransform = d->screenScaleTransform();
+            const QTransform scaleTransform = d->screenScaleTransform(page);
 #ifdef DEBUG_LINKS
             const QString fmt = u"page %1 @ %2, %3"_s;
             d->m_linkModel.setPage(page);
@@ -618,8 +630,8 @@ void QPdfView::paintEvent(QPaintEvent *event)
                         painter.fillRect(scaleTransform.mapRect(rect).translated(pageGeometry.topLeft()), SearchResultHighlight);
                 }
 
-                if (d->m_currentSearchResult >= 0 && d->m_currentSearchResult < d->m_searchModel->rowCount({})) {
-                    const QPdfLink &cur = d->m_searchModel->resultAtIndex(d->m_currentSearchResult);
+                if (d->m_currentSearchResultIndex >= 0 && d->m_currentSearchResultIndex < d->m_searchModel->rowCount({})) {
+                    const QPdfLink &cur = d->m_searchModel->resultAtIndex(d->m_currentSearchResultIndex);
                     if (cur.page() == page) {
                         painter.setPen({CurrentSearchResultHighlight, CurrentSearchResultWidth});
                         for (const auto &rect : cur.rectangles())
@@ -658,10 +670,11 @@ void QPdfView::mousePressEvent(QMouseEvent *event)
 void QPdfView::mouseMoveEvent(QMouseEvent *event)
 {
     Q_D(QPdfView);
-    const QTransform screenInvTransform = d->screenScaleTransform().inverted();
-    for (auto it = d->m_documentLayout.pageGeometries.cbegin(); it != d->m_documentLayout.pageGeometries.cend(); ++it) {
+    for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin();
+         it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) {
         const int page = it.key();
-        const QRect pageGeometry = it.value();
+        const QTransform screenInvTransform = d->screenScaleTransform(page).inverted();
+        const QRect pageGeometry = it.value().first;
         if (pageGeometry.contains(event->position().toPoint())) {
             const QPointF posInPoints = screenInvTransform.map(event->position() - pageGeometry.topLeft());
             d->m_linkModel.setPage(page);
@@ -676,10 +689,11 @@ void QPdfView::mouseMoveEvent(QMouseEvent *event)
 void QPdfView::mouseReleaseEvent(QMouseEvent *event)
 {
     Q_D(QPdfView);
-    const QTransform screenInvTransform = d->screenScaleTransform().inverted();
-    for (auto it = d->m_documentLayout.pageGeometries.cbegin(); it != d->m_documentLayout.pageGeometries.cend(); ++it) {
+    for (auto it = d->m_documentLayout.pageGeometryAndScale.cbegin();
+         it != d->m_documentLayout.pageGeometryAndScale.cend(); ++it) {
         const int page = it.key();
-        const QRect pageGeometry = it.value();
+        const QTransform screenInvTransform = d->screenScaleTransform(page).inverted();
+        const QRect pageGeometry = it.value().first;
         if (pageGeometry.contains(event->position().toPoint())) {
             const QPointF posInPoints = screenInvTransform.map(event->position() - pageGeometry.topLeft());
             d->m_linkModel.setPage(page);
diff --git a/src/pdfwidgets/qpdfview.h b/src/pdfwidgets/qpdfview.h
index 54e9ddfd5ba..7f1d014deba 100644
--- a/src/pdfwidgets/qpdfview.h
+++ b/src/pdfwidgets/qpdfview.h
@@ -5,8 +5,6 @@
 #ifndef QPDFVIEW_H
 #define QPDFVIEW_H
 
-#include <QtPdf/qpdfdocument.h>
-#include <QtPdf/qpdflink.h>
 #include <QtPdfWidgets/qtpdfwidgetsglobal.h>
 #include <QtWidgets/qabstractscrollarea.h>
 
@@ -31,7 +29,7 @@ class Q_PDF_WIDGETS_EXPORT QPdfView : public QAbstractScrollArea
     Q_PROPERTY(QMargins documentMargins READ documentMargins WRITE setDocumentMargins NOTIFY documentMarginsChanged)
 
     Q_PROPERTY(QPdfSearchModel* searchModel READ searchModel WRITE setSearchModel NOTIFY searchModelChanged)
-    Q_PROPERTY(int currentSearchResult READ currentSearchResult WRITE setCurrentSearchResult NOTIFY currentSearchResultChanged)
+    Q_PROPERTY(int currentSearchResultIndex READ currentSearchResultIndex WRITE setCurrentSearchResultIndex NOTIFY currentSearchResultIndexChanged)
 
 public:
     enum class PageMode
@@ -59,7 +57,7 @@ class Q_PDF_WIDGETS_EXPORT QPdfView : public QAbstractScrollArea
     QPdfSearchModel *searchModel() const;
     void setSearchModel(QPdfSearchModel *searchModel);
 
-    int currentSearchResult() const;
+    int currentSearchResultIndex() const;
 
     QPdfPageNavigator *pageNavigator() const;
 
@@ -77,7 +75,7 @@ public Q_SLOTS:
     void setPageMode(QPdfView::PageMode mode);
     void setZoomMode(QPdfView::ZoomMode mode);
     void setZoomFactor(qreal factor);
-    void setCurrentSearchResult(int currentResult);
+    void setCurrentSearchResultIndex(int currentResult);
 
 Q_SIGNALS:
     void documentChanged(QPdfDocument *document);
@@ -87,7 +85,7 @@ public Q_SLOTS:
     void pageSpacingChanged(int pageSpacing);
     void documentMarginsChanged(QMargins documentMargins);
     void searchModelChanged(QPdfSearchModel *searchModel);
-    void currentSearchResultChanged(int currentResult);
+    void currentSearchResultIndexChanged(int currentResult);
 
 protected:
     void paintEvent(QPaintEvent *event) override;
diff --git a/src/pdfwidgets/qpdfview_p.h b/src/pdfwidgets/qpdfview_p.h
index 37222ce8c55..d349cc2eee8 100644
--- a/src/pdfwidgets/qpdfview_p.h
+++ b/src/pdfwidgets/qpdfview_p.h
@@ -16,6 +16,7 @@
 //
 
 #include "qpdfview.h"
+#include "qpdfdocument.h"
 #include "qpdflinkmodel.h"
 
 #include <QHash>
@@ -45,12 +46,12 @@ class QPdfViewPrivate
 
     qreal yPositionForPage(int page) const;
 
-    QTransform screenScaleTransform() const; // points to pixels
+    QTransform screenScaleTransform(int page) const; // points to pixels
 
     struct DocumentLayout
     {
         QSize documentSize;
-        QHash<int, QRect> pageGeometries;
+        QHash<int, QPair<QRect, qreal>> pageGeometryAndScale;
     };
 
     DocumentLayout calculateDocumentLayout() const;
@@ -67,7 +68,7 @@ class QPdfViewPrivate
     QPdfView::ZoomMode m_zoomMode;
     qreal m_zoomFactor;
 
-    int m_currentSearchResult = -1;
+    int m_currentSearchResultIndex = -1;
 
     int m_pageSpacing;
     QMargins m_documentMargins;
diff --git a/src/process/CMakeLists.txt b/src/process/CMakeLists.txt
index 63783af696c..630ba42a8b0 100644
--- a/src/process/CMakeLists.txt
+++ b/src/process/CMakeLists.txt
@@ -2,7 +2,9 @@
 # SPDX-License-Identifier: BSD-3-Clause
 
 if(NOT DEFINED WEBENGINE_ROOT_SOURCE_DIR)
-    get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." REALPATH)
+    qt_internal_get_filename_path_mode(path_mode)
+
+    get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/../.." ${path_mode})
 endif()
 include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/Functions.cmake)
 
@@ -23,7 +25,7 @@ if(WIN32)
     set_property(TARGET ${qtWebEngineProcessName} PROPERTY WIN32_EXECUTABLE TRUE)
     # get libs rsp file, since cmake is not aware of PUBLIC libs for WebEngineCore
     get_target_property(libs_rsp WebEngineCore LIBS_RSP)
-    target_link_options(${qtWebEngineProcessName} PRIVATE "@${libs_rsp}")
+    target_link_options(${qtWebEngineProcessName} PRIVATE "@${libs_rsp}" "/STACK:0x800000")
 endif()
 
 if(MACOS)
@@ -57,13 +59,13 @@ foreach(config ${configs})
     set_target_properties(${qtWebEngineProcessName} PROPERTIES
         RUNTIME_OUTPUT_DIRECTORY_${config_upper} "${outputPath}"
     )
-endforeach()
 
-if(QT_FEATURE_debug_and_release)
-    set_target_properties(${qtWebEngineProcessName} PROPERTIES
-        OUTPUT_NAME_DEBUG ${qtWebEngineProcessName}${CMAKE_DEBUG_POSTFIX}
-    )
-endif()
+    if("${config}" STREQUAL "Debug")
+        set_target_properties(${qtWebEngineProcessName} PROPERTIES
+            OUTPUT_NAME_DEBUG ${qtWebEngineProcessName}${CMAKE_DEBUG_POSTFIX}
+        )
+    endif()
+endforeach()
 
 if(isFramework)
     set_target_properties(${qtWebEngineProcessName} PROPERTIES
@@ -88,7 +90,8 @@ if(isFramework)
         COMPONENT Runtime
     )
     qt_enable_separate_debug_info(${qtWebEngineProcessName}
-         "${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers" QT_EXECUTABLE
+        "${INSTALL_LIBDIR}" QT_EXECUTABLE
+        DSYM_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${INSTALL_LIBDIR}"
     )
 else()
     qt_apply_rpaths(TARGET ${qtWebEngineProcessName} INSTALL_PATH "${INSTALL_LIBEXECDIR}" RELATIVE_RPATH)
diff --git a/src/webenginequick/CMakeLists.txt b/src/webenginequick/CMakeLists.txt
index 867a388ebb5..0081edb7f4f 100644
--- a/src/webenginequick/CMakeLists.txt
+++ b/src/webenginequick/CMakeLists.txt
@@ -57,11 +57,6 @@ qt_internal_add_qml_module(WebEngineQuick
         Qt::WebEngineCore
 )
 
-qt_internal_extend_target(WebEngineQuick CONDITION QT_FEATURE_webengine_webchannel
-    PUBLIC_LIBRARIES
-        Qt::WebChannelQuick
-)
-
 qt_internal_extend_target(WebEngineQuick CONDITION QT_FEATURE_accessibility
     SOURCES
         qquickwebengine_accessible.cpp qquickwebengine_accessible.h
diff --git a/src/webenginequick/api/qquickwebengineforeigntypes_p.h b/src/webenginequick/api/qquickwebengineforeigntypes_p.h
index 1591e596f8c..e9a8c791c0f 100644
--- a/src/webenginequick/api/qquickwebengineforeigntypes_p.h
+++ b/src/webenginequick/api/qquickwebengineforeigntypes_p.h
@@ -34,10 +34,17 @@
 
 QT_BEGIN_NAMESPACE
 
+// To prevent the same type from being exported twice into qmltypes
+// (for value type and for the enums)
+struct QWebEngineLoadingInfoDerived : public QWebEngineLoadingInfo
+{
+    Q_GADGET
+};
+
 namespace ForeignWebEngineLoadingInfoNamespace
 {
     Q_NAMESPACE
-    QML_FOREIGN_NAMESPACE(QWebEngineLoadingInfo)
+    QML_FOREIGN_NAMESPACE(QWebEngineLoadingInfoDerived)
     QML_NAMED_ELEMENT(WebEngineLoadingInfo)
     QML_ADDED_IN_VERSION(1, 1)
     QML_EXTRA_VERSION(2, 0)
@@ -53,10 +60,17 @@ struct ForeignWebEngineLoadingInfo
     QML_UNCREATABLE("")
 };
 
+// To prevent the same type from being exported twice into qmltypes
+// (for value type and for the enums)
+struct QWebEngineCertificateErrorDerived : public QWebEngineCertificateError
+{
+    Q_GADGET
+};
+
 namespace ForeignWebEngineCertificateErrorNamespace
 {
     Q_NAMESPACE
-    QML_FOREIGN_NAMESPACE(QWebEngineCertificateError)
+    QML_FOREIGN_NAMESPACE(QWebEngineCertificateErrorDerived)
     QML_NAMED_ELEMENT(WebEngineCertificateError)
     QML_ADDED_IN_VERSION(1, 1)
     QML_EXTRA_VERSION(2, 0)
@@ -141,6 +155,7 @@ struct ForeignWebEngineContextMenuRequest
     QML_UNCREATABLE("")
 };
 
+#if QT_DEPRECATED_SINCE(6, 5)
 struct ForeignWebEngineQuotaRequest
 {
     Q_GADGET
@@ -150,6 +165,7 @@ struct ForeignWebEngineQuotaRequest
     QML_EXTRA_VERSION(2, 0)
     QML_UNCREATABLE("")
 };
+#endif
 
 struct ForeignWebEngineRegisterProtocolHandlerRequest
 {
@@ -190,10 +206,17 @@ struct ForeginWebEngineFileSystemAccessRequest
     QML_UNCREATABLE("")
 };
 
+// To prevent the same type from being exported twice into qmltypes
+// (for value type and for the enums)
+struct QWebEngineFileSystemAccessRequestDerived : public QWebEngineFileSystemAccessRequest
+{
+    Q_GADGET
+};
+
 namespace ForeginWebEngineFileSystemAccessRequestNamespace
 {
     Q_NAMESPACE
-    QML_FOREIGN_NAMESPACE(QWebEngineFileSystemAccessRequest)
+    QML_FOREIGN_NAMESPACE(QWebEngineFileSystemAccessRequestDerived)
     QML_NAMED_ELEMENT(WebEngineFileSystemAccessRequest)
     QML_ADDED_IN_VERSION(6, 4)
 };
diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp
index 92ab9dc2586..270f9cd53bc 100644
--- a/src/webenginequick/api/qquickwebengineprofile.cpp
+++ b/src/webenginequick/api/qquickwebengineprofile.cpp
@@ -325,16 +325,16 @@ QQuickWebEngineScriptCollection *QQuickWebEngineProfilePrivate::getUserScripts()
 */
 
 /*!
-    \qmlsignal WebEngineProfile::downloadRequested(WebEngineDownloadItem download)
+    \qmlsignal WebEngineProfile::downloadRequested(WebEngineDownloadRequest download)
 
     This signal is emitted whenever a download has been triggered.
     The \a download argument holds the state of the download.
-    The download has to be explicitly accepted with WebEngineDownloadItem::accept() or the
+    The download has to be explicitly accepted with WebEngineDownloadRequest::accept() or the
     download will be cancelled by default.
 */
 
 /*!
-    \qmlsignal WebEngineProfile::downloadFinished(WebEngineDownloadItem download)
+    \qmlsignal WebEngineProfile::downloadFinished(WebEngineDownloadRequest download)
 
     This signal is emitted whenever downloading stops, because it finished successfully, was
     cancelled, or was interrupted (for example, because connectivity was lost).
@@ -903,19 +903,6 @@ void QQuickWebEngineProfile::setUrlRequestInterceptor(QWebEngineUrlRequestInterc
     d->profileAdapter()->setRequestInterceptor(interceptor);
 }
 
-/*!
-    Registers a response interceptor singleton \a interceptor to intercept URL responses.
-
-    The profile does not take ownership of the pointer.
-
-    \sa QWebEngineUrlResponseInterceptor
-*/
-void QQuickWebEngineProfile::setUrlResponseInterceptor(
-        QWebEngineUrlResponseInterceptor *interceptor)
-{
-    Q_D(QQuickWebEngineProfile);
-    d->profileAdapter()->setResponseInterceptor(interceptor);
-}
 
 /*!
     Returns the custom URL scheme handler register for the URL scheme \a scheme.
diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h
index 43b02e45a64..29d6ee0b267 100644
--- a/src/webenginequick/api/qquickwebengineprofile.h
+++ b/src/webenginequick/api/qquickwebengineprofile.h
@@ -8,7 +8,6 @@
 #include <QtCore/qobject.h>
 #include <QtCore/qscopedpointer.h>
 #include <QtCore/qstring.h>
-#include <QtWebEngineCore/qwebengineurlresponseinterceptor.h>
 #include <QtQml/qqmlregistration.h>
 
 QT_BEGIN_NAMESPACE
@@ -91,7 +90,6 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject {
     QWebEngineCookieStore *cookieStore() const;
 
     void setUrlRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor);
-    void setUrlResponseInterceptor(QWebEngineUrlResponseInterceptor *interceptor);
 
     const QWebEngineUrlSchemeHandler *urlSchemeHandler(const QByteArray &) const;
     void installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *);
diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp
index 54407cc2f1d..2686a577439 100644
--- a/src/webenginequick/api/qquickwebenginesettings.cpp
+++ b/src/webenginequick/api/qquickwebenginesettings.cpp
@@ -433,17 +433,19 @@ bool QQuickWebEngineSettings::navigateOnDropEnabled() const
 }
 
 /*!
-    \qmlproperty bool WebEngineSettings::disableReadingFromCanvas
+    \qmlproperty bool WebEngineSettings::readingFromCanvasEnabled
     \since QtWebEngine 6.6
 
-    Disables JavaScript reading from canvas elements.
-    This setting will have impact on all HTML5 canvas elements irrespective of origin.
+    Specifies that reading from all canvas elements is enabled.
 
-    Disabled by default.
+    This setting will have impact on all HTML5 canvas elements irrespective of origin, and can be disabled
+    to prevent canvas fingerprinting.
+
+    Enabled by default.
  */
-bool QQuickWebEngineSettings::disableReadingFromCanvas() const
+bool QQuickWebEngineSettings::readingFromCanvasEnabled() const
 {
-    return d_ptr->testAttribute(QWebEngineSettings::DisableReadingFromCanvas);
+    return d_ptr->testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled);
 }
 
 /*!
@@ -729,12 +731,12 @@ void QQuickWebEngineSettings::setNavigateOnDropEnabled(bool on)
         Q_EMIT navigateOnDropEnabledChanged();
 }
 
-void QQuickWebEngineSettings::setDisableReadingFromCanvas(bool on)
+void QQuickWebEngineSettings::setReadingFromCanvasEnabled(bool on)
 {
-    bool wasOn = d_ptr->testAttribute(QWebEngineSettings::DisableReadingFromCanvas);
-    d_ptr->setAttribute(QWebEngineSettings::DisableReadingFromCanvas, on);
+    bool wasOn = d_ptr->testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled);
+    d_ptr->setAttribute(QWebEngineSettings::ReadingFromCanvasEnabled, on);
     if (wasOn != on)
-        Q_EMIT disableReadingFromCanvasChanged();
+        Q_EMIT readingFromCanvasEnabledChanged();
 }
 
 void QQuickWebEngineSettings::setUnknownUrlSchemePolicy(QQuickWebEngineSettings::UnknownUrlSchemePolicy policy)
diff --git a/src/webenginequick/api/qquickwebenginesettings_p.h b/src/webenginequick/api/qquickwebenginesettings_p.h
index 2fed034c126..53156da0221 100644
--- a/src/webenginequick/api/qquickwebenginesettings_p.h
+++ b/src/webenginequick/api/qquickwebenginesettings_p.h
@@ -57,7 +57,7 @@ class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
     Q_PROPERTY(bool dnsPrefetchEnabled READ dnsPrefetchEnabled WRITE setDnsPrefetchEnabled NOTIFY dnsPrefetchEnabledChanged REVISION(1,7) FINAL)
     Q_PROPERTY(bool pdfViewerEnabled READ pdfViewerEnabled WRITE setPdfViewerEnabled NOTIFY pdfViewerEnabledChanged REVISION(1,8) FINAL)
     Q_PROPERTY(bool navigateOnDropEnabled READ navigateOnDropEnabled WRITE setNavigateOnDropEnabled NOTIFY navigateOnDropEnabledChanged REVISION(6,4) FINAL)
-    Q_PROPERTY(bool disableReadingFromCanvas READ disableReadingFromCanvas WRITE setDisableReadingFromCanvas NOTIFY disableReadingFromCanvasChanged REVISION(6,6) FINAL)
+    Q_PROPERTY(bool readingFromCanvasEnabled READ readingFromCanvasEnabled WRITE setReadingFromCanvasEnabled NOTIFY readingFromCanvasEnabledChanged REVISION(6,6) FINAL)
     QML_NAMED_ELEMENT(WebEngineSettings)
     QML_ADDED_IN_VERSION(1, 1)
     QML_EXTRA_VERSION(2, 0)
@@ -105,7 +105,7 @@ class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
     bool dnsPrefetchEnabled() const;
     bool pdfViewerEnabled() const;
     bool navigateOnDropEnabled() const;
-    bool disableReadingFromCanvas() const;
+    bool readingFromCanvasEnabled() const;
 
     void setAutoLoadImages(bool on);
     void setJavascriptEnabled(bool on);
@@ -139,7 +139,7 @@ class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
     void setDnsPrefetchEnabled(bool on);
     void setPdfViewerEnabled(bool on);
     void setNavigateOnDropEnabled(bool on);
-    void setDisableReadingFromCanvas(bool on);
+    void setReadingFromCanvasEnabled(bool on);
 
 signals:
     void autoLoadImagesChanged();
@@ -174,7 +174,7 @@ class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
     Q_REVISION(1,7) void dnsPrefetchEnabledChanged();
     Q_REVISION(1,8) void pdfViewerEnabledChanged();
     Q_REVISION(6,4) void navigateOnDropEnabledChanged();
-    Q_REVISION(6,6) void disableReadingFromCanvasChanged();
+    Q_REVISION(6,6) void readingFromCanvasEnabledChanged();
 
 private:
     explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = nullptr);
diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp
index d20cde3056b..4be484cd004 100644
--- a/src/webenginequick/api/qquickwebengineview.cpp
+++ b/src/webenginequick/api/qquickwebengineview.cpp
@@ -36,12 +36,14 @@
 #include <QtWebEngineCore/qwebenginefullscreenrequest.h>
 #include <QtWebEngineCore/qwebengineloadinginfo.h>
 #include <QtWebEngineCore/qwebenginenavigationrequest.h>
+#include <QtWebEngineCore/qwebenginepage.h>
 #include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h>
 #include <QtWebEngineCore/qwebenginescriptcollection.h>
 #include <QtWebEngineCore/private/qwebenginecontextmenurequest_p.h>
 #include <QtWebEngineCore/private/qwebenginehistory_p.h>
 #include <QtWebEngineCore/private/qwebenginenewwindowrequest_p.h>
 #include <QtWebEngineCore/private/qwebenginescriptcollection_p.h>
+#include <QtWebEngineCore/private/qwebenginepage_p.h>
 #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
 
 #include <QtCore/qloggingcategory.h>
@@ -71,12 +73,15 @@
 #endif
 
 #if QT_CONFIG(webengine_webchannel)
-#include <QtWebChannelQuick/qqmlwebchannel.h>
+#include <QtWebChannel/qqmlwebchannel.h>
 #endif
 
 QT_BEGIN_NAMESPACE
 using namespace QtWebEngineCore;
 
+Q_STATIC_ASSERT(int(QQuickWebEngineView::WebActionCount) == int(QWebEnginePage::WebActionCount));
+using LoadStatus = QWebEngineLoadingInfo::LoadStatus;
+using ErrorDomain = QWebEngineLoadingInfo::ErrorDomain;
 #if QT_DEPRECATED_SINCE(6, 2)
 QT_WARNING_PUSH QT_WARNING_DISABLE_DEPRECATED
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::AcceptRequest)            == static_cast<int>(QWebEngineNavigationRequest::AcceptRequest));
@@ -92,9 +97,6 @@ Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInWindow)
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInTab)             == static_cast<int>(QWebEngineNewWindowRequest::InNewTab));
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInDialog)          == static_cast<int>(QWebEngineNewWindowRequest::InNewDialog));
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NewViewInBackgroundTab)   == static_cast<int>(QWebEngineNewWindowRequest::InNewBackgroundTab));
-
-using LoadStatus = QWebEngineLoadingInfo::LoadStatus;
-using ErrorDomain = QWebEngineLoadingInfo::ErrorDomain;
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::NoErrorDomain)          == static_cast<int>(ErrorDomain::NoErrorDomain));
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::InternalErrorDomain)    == static_cast<int>(ErrorDomain::InternalErrorDomain));
 Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::ConnectionErrorDomain)  == static_cast<int>(ErrorDomain::ConnectionErrorDomain));
@@ -109,6 +111,134 @@ Q_STATIC_ASSERT(static_cast<int>(QQuickWebEngineView::LoadSucceededStatus) == st
 QT_WARNING_POP
 #endif
 
+#if QT_CONFIG(webengine_printing_and_pdf)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Letter, QQuickWebEngineView::PrintedPageSizeId::Letter)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Legal, QQuickWebEngineView::PrintedPageSizeId::Legal)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Executive, QQuickWebEngineView::PrintedPageSizeId::Executive)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A0, QQuickWebEngineView::PrintedPageSizeId::A0)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A1, QQuickWebEngineView::PrintedPageSizeId::A1)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A2, QQuickWebEngineView::PrintedPageSizeId::A2)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A3, QQuickWebEngineView::PrintedPageSizeId::A3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4, QQuickWebEngineView::PrintedPageSizeId::A4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A5, QQuickWebEngineView::PrintedPageSizeId::A5)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A6, QQuickWebEngineView::PrintedPageSizeId::A6)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A7, QQuickWebEngineView::PrintedPageSizeId::A7)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A8, QQuickWebEngineView::PrintedPageSizeId::A8)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A9, QQuickWebEngineView::PrintedPageSizeId::A9)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A10, QQuickWebEngineView::PrintedPageSizeId::A10)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B0, QQuickWebEngineView::PrintedPageSizeId::B0)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B1, QQuickWebEngineView::PrintedPageSizeId::B1)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B2, QQuickWebEngineView::PrintedPageSizeId::B2)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B3, QQuickWebEngineView::PrintedPageSizeId::B3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B4, QQuickWebEngineView::PrintedPageSizeId::B4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B5, QQuickWebEngineView::PrintedPageSizeId::B5)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B6, QQuickWebEngineView::PrintedPageSizeId::B6)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B7, QQuickWebEngineView::PrintedPageSizeId::B7)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B8, QQuickWebEngineView::PrintedPageSizeId::B8)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B9, QQuickWebEngineView::PrintedPageSizeId::B9)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B10, QQuickWebEngineView::PrintedPageSizeId::B10)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::C5E, QQuickWebEngineView::PrintedPageSizeId::C5E)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Comm10E, QQuickWebEngineView::PrintedPageSizeId::Comm10E)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::DLE, QQuickWebEngineView::PrintedPageSizeId::DLE)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Folio, QQuickWebEngineView::PrintedPageSizeId::Folio)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Ledger, QQuickWebEngineView::PrintedPageSizeId::Ledger)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Tabloid, QQuickWebEngineView::PrintedPageSizeId::Tabloid)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Custom, QQuickWebEngineView::PrintedPageSizeId::Custom)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A3Extra, QQuickWebEngineView::PrintedPageSizeId::A3Extra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4Extra, QQuickWebEngineView::PrintedPageSizeId::A4Extra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4Plus, QQuickWebEngineView::PrintedPageSizeId::A4Plus)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A4Small, QQuickWebEngineView::PrintedPageSizeId::A4Small)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::A5Extra, QQuickWebEngineView::PrintedPageSizeId::A5Extra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::B5Extra, QQuickWebEngineView::PrintedPageSizeId::B5Extra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB0, QQuickWebEngineView::PrintedPageSizeId::JisB0)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB1, QQuickWebEngineView::PrintedPageSizeId::JisB1)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB2, QQuickWebEngineView::PrintedPageSizeId::JisB2)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB3, QQuickWebEngineView::PrintedPageSizeId::JisB3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB4, QQuickWebEngineView::PrintedPageSizeId::JisB4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB5, QQuickWebEngineView::PrintedPageSizeId::JisB5)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB6, QQuickWebEngineView::PrintedPageSizeId::JisB6)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB7, QQuickWebEngineView::PrintedPageSizeId::JisB7)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB8, QQuickWebEngineView::PrintedPageSizeId::JisB8)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB9, QQuickWebEngineView::PrintedPageSizeId::JisB9)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::JisB10, QQuickWebEngineView::PrintedPageSizeId::JisB10)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiC, QQuickWebEngineView::PrintedPageSizeId::AnsiC)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiD, QQuickWebEngineView::PrintedPageSizeId::AnsiD)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiE, QQuickWebEngineView::PrintedPageSizeId::AnsiE)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LegalExtra, QQuickWebEngineView::PrintedPageSizeId::LegalExtra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LetterExtra, QQuickWebEngineView::PrintedPageSizeId::LetterExtra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LetterPlus, QQuickWebEngineView::PrintedPageSizeId::LetterPlus)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LetterSmall, QQuickWebEngineView::PrintedPageSizeId::LetterSmall)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::TabloidExtra, QQuickWebEngineView::PrintedPageSizeId::TabloidExtra)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchA, QQuickWebEngineView::PrintedPageSizeId::ArchA)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchB, QQuickWebEngineView::PrintedPageSizeId::ArchB)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchC, QQuickWebEngineView::PrintedPageSizeId::ArchC)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchD, QQuickWebEngineView::PrintedPageSizeId::ArchD)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ArchE, QQuickWebEngineView::PrintedPageSizeId::ArchE)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial7x9, QQuickWebEngineView::PrintedPageSizeId::Imperial7x9)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial8x10, QQuickWebEngineView::PrintedPageSizeId::Imperial8x10)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial9x11, QQuickWebEngineView::PrintedPageSizeId::Imperial9x11)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial9x12, QQuickWebEngineView::PrintedPageSizeId::Imperial9x12)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial10x11, QQuickWebEngineView::PrintedPageSizeId::Imperial10x11)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial10x13, QQuickWebEngineView::PrintedPageSizeId::Imperial10x13)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial10x14, QQuickWebEngineView::PrintedPageSizeId::Imperial10x14)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial12x11, QQuickWebEngineView::PrintedPageSizeId::Imperial12x11)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Imperial15x11, QQuickWebEngineView::PrintedPageSizeId::Imperial15x11)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::ExecutiveStandard, QQuickWebEngineView::PrintedPageSizeId::ExecutiveStandard)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Note, QQuickWebEngineView::PrintedPageSizeId::Note)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Quarto, QQuickWebEngineView::PrintedPageSizeId::Quarto)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Statement, QQuickWebEngineView::PrintedPageSizeId::Statement)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::SuperA, QQuickWebEngineView::PrintedPageSizeId::SuperA)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::SuperB, QQuickWebEngineView::PrintedPageSizeId::SuperB)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Postcard, QQuickWebEngineView::PrintedPageSizeId::Postcard)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::DoublePostcard, QQuickWebEngineView::PrintedPageSizeId::DoublePostcard)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Prc16K, QQuickWebEngineView::PrintedPageSizeId::Prc16K)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Prc32K, QQuickWebEngineView::PrintedPageSizeId::Prc32K)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Prc32KBig, QQuickWebEngineView::PrintedPageSizeId::Prc32KBig)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::FanFoldUS, QQuickWebEngineView::PrintedPageSizeId::FanFoldUS)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::FanFoldGerman, QQuickWebEngineView::PrintedPageSizeId::FanFoldGerman)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::FanFoldGermanLegal, QQuickWebEngineView::PrintedPageSizeId::FanFoldGermanLegal)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeB4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeB4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeB5, QQuickWebEngineView::PrintedPageSizeId::EnvelopeB5)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeB6, QQuickWebEngineView::PrintedPageSizeId::EnvelopeB6)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC0, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC0)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC1, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC1)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC2, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC2)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC3, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC6, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC6)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC65, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC65)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC7, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC7)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope9, QQuickWebEngineView::PrintedPageSizeId::Envelope9)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope11, QQuickWebEngineView::PrintedPageSizeId::Envelope11)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope12, QQuickWebEngineView::PrintedPageSizeId::Envelope12)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope14, QQuickWebEngineView::PrintedPageSizeId::Envelope14)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeMonarch, QQuickWebEngineView::PrintedPageSizeId::EnvelopeMonarch)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePersonal, QQuickWebEngineView::PrintedPageSizeId::EnvelopePersonal)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeChou3, QQuickWebEngineView::PrintedPageSizeId::EnvelopeChou3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeChou4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeChou4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeInvite, QQuickWebEngineView::PrintedPageSizeId::EnvelopeInvite)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeItalian, QQuickWebEngineView::PrintedPageSizeId::EnvelopeItalian)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeKaku2, QQuickWebEngineView::PrintedPageSizeId::EnvelopeKaku2)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeKaku3, QQuickWebEngineView::PrintedPageSizeId::EnvelopeKaku3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc1, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc1)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc2, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc2)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc3, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc3)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc4, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc5, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc5)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc6, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc6)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc7, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc7)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc8, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc8)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc9, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc9)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopePrc10, QQuickWebEngineView::PrintedPageSizeId::EnvelopePrc10)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeYou4, QQuickWebEngineView::PrintedPageSizeId::EnvelopeYou4)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::LastPageSize, QQuickWebEngineView::PrintedPageSizeId::LastPageSize)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiA, QQuickWebEngineView::PrintedPageSizeId::AnsiA)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::AnsiB, QQuickWebEngineView::PrintedPageSizeId::AnsiB)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeC5, QQuickWebEngineView::PrintedPageSizeId::EnvelopeC5)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::EnvelopeDL, QQuickWebEngineView::PrintedPageSizeId::EnvelopeDL)
+ASSERT_ENUMS_MATCH(QPageSize::PageSizeId::Envelope10, QQuickWebEngineView::PrintedPageSizeId::Envelope10)
+#endif
+
 class WebEngineQuickWidgetDelegate : public QtWebEngineCore::WidgetDelegate
 {
 public:
@@ -592,7 +722,7 @@ bool QQuickWebEngineViewPrivate::isFullScreenMode() const
 void QQuickWebEngineViewPrivate::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID)
 {
     Q_Q(QQuickWebEngineView);
-    if (q->receivers(SIGNAL(javaScriptConsoleMessage(JavaScriptConsoleMessageLevel,QString,int,QString))) > 0) {
+    if (q->receivers(SIGNAL(javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel,QString,int,QString))) > 0) {
         Q_EMIT q->javaScriptConsoleMessage(static_cast<QQuickWebEngineView::JavaScriptConsoleMessageLevel>(level), message, lineNumber, sourceID);
         return;
     }
@@ -2000,171 +2130,113 @@ QQuickWebEngineAction *QQuickWebEngineView::action(WebAction action)
         return d->actions[action];
     }
 
-    QString text;
+    const QString text = QWebEnginePagePrivate::actionText(action);
     QString iconName;
 
     switch (action) {
     case Back:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Back);
         iconName = QStringLiteral("go-previous");
         break;
     case Forward:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Forward);
         iconName = QStringLiteral("go-next");
         break;
     case Stop:
-        text = tr("Stop");
         iconName = QStringLiteral("process-stop");
         break;
     case Reload:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Reload);
         iconName = QStringLiteral("view-refresh");
         break;
     case ReloadAndBypassCache:
-        text = tr("Reload and Bypass Cache");
         iconName = QStringLiteral("view-refresh");
         break;
     case Cut:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Cut);
         iconName = QStringLiteral("edit-cut");
         break;
     case Copy:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Copy);
         iconName = QStringLiteral("edit-copy");
         break;
     case Paste:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Paste);
         iconName = QStringLiteral("edit-paste");
         break;
     case Undo:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Undo);
         iconName = QStringLiteral("edit-undo");
         break;
     case Redo:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::Redo);
         iconName = QStringLiteral("edit-redo");
         break;
     case SelectAll:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SelectAll);
         iconName = QStringLiteral("edit-select-all");
         break;
     case PasteAndMatchStyle:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::PasteAndMatchStyle);
         iconName = QStringLiteral("edit-paste");
         break;
     case OpenLinkInThisWindow:
-        text = tr("Open link in this window");
-        break;
     case OpenLinkInNewWindow:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewWindow);
-        break;
     case OpenLinkInNewTab:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::OpenLinkInNewTab);
-        break;
     case CopyLinkToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyLinkToClipboard);
-        break;
     case DownloadLinkToDisk:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadLinkToDisk);
-        break;
     case CopyImageToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageToClipboard);
-        break;
     case CopyImageUrlToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyImageUrlToClipboard);
-        break;
     case DownloadImageToDisk:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadImageToDisk);
-        break;
     case CopyMediaUrlToClipboard:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::CopyMediaUrlToClipboard);
-        break;
     case ToggleMediaControls:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaControls);
-        break;
     case ToggleMediaLoop:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ToggleMediaLoop);
         break;
     case ToggleMediaPlayPause:
-        text = tr("Toggle Play/Pause");
         iconName = QStringLiteral("media-playback-start");
         break;
     case ToggleMediaMute:
-        text = tr("Toggle Mute");
         iconName = QStringLiteral("audio-volume-muted");
         break;
     case DownloadMediaToDisk:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::DownloadMediaToDisk);
-        break;
     case InspectElement:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::InspectElement);
         break;
     case ExitFullScreen:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ExitFullScreen);
         iconName = QStringLiteral("view-fullscreen");
         break;
     case RequestClose:
-        text = tr("Close Page");
         iconName = QStringLiteral("window-close");
         break;
     case Unselect:
-        text = tr("Unselect");
         iconName = QStringLiteral("edit-select-none");
         break;
     case SavePage:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::SavePage);
         iconName = QStringLiteral("document-save");
         break;
+    case OpenLinkInNewBackgroundTab:
+        break;
     case ViewSource:
-        text = RenderViewContextMenuQt::getMenuItemName(RenderViewContextMenuQt::ContextMenuItem::ViewSource);
         break;
     case ToggleBold:
-        text = tr("&Bold");
         iconName = QStringLiteral("format-text-bold");
         break;
     case ToggleItalic:
-        text = tr("&Italic");
         iconName = QStringLiteral("format-text-italic");
         break;
     case ToggleUnderline:
-        text = tr("&Underline");
         iconName = QStringLiteral("format-text-underline");
         break;
     case ToggleStrikethrough:
-        text = tr("&Strikethrough");
         iconName = QStringLiteral("format-text-strikethrough");
         break;
     case AlignLeft:
-        text = tr("Align &Left");
         break;
     case AlignCenter:
-        text = tr("Align &Center");
         break;
     case AlignRight:
-        text = tr("Align &Right");
         break;
     case AlignJustified:
-        text = tr("Align &Justified");
         break;
     case Indent:
-        text = tr("&Indent");
         iconName = QStringLiteral("format-indent-more");
         break;
     case Outdent:
-        text = tr("&Outdent");
         iconName = QStringLiteral("format-indent-less");
         break;
     case InsertOrderedList:
-        text = tr("Insert &Ordered List");
-        break;
     case InsertUnorderedList:
-        text = tr("Insert &Unordered List");
-        break;
     case ChangeTextDirectionLTR:
-        text = tr("Change text direction left to right");
-        break;
     case ChangeTextDirectionRTL:
-        text = tr("Change text direction right to left");
         break;
     case NoWebAction:
     case WebActionCount:
diff --git a/src/webenginequick/api/qquickwebengineview_p.h b/src/webenginequick/api/qquickwebengineview_p.h
index 5b8e183d56a..7e982094e74 100644
--- a/src/webenginequick/api/qquickwebengineview_p.h
+++ b/src/webenginequick/api/qquickwebengineview_p.h
@@ -81,7 +81,7 @@ class Q_WEBENGINEQUICK_PRIVATE_EXPORT QQuickWebEngineView : public QQuickItem {
 
     Q_PROPERTY(QQuickWebEngineView *inspectedView READ inspectedView WRITE setInspectedView NOTIFY inspectedViewChanged REVISION(1,7) FINAL)
     Q_PROPERTY(QQuickWebEngineView *devToolsView READ devToolsView WRITE setDevToolsView NOTIFY devToolsViewChanged REVISION(1,7) FINAL)
-    Q_PROPERTY(QString devToolsId READ devToolsId CONSTANT REVISION(0) FINAL)
+    Q_PROPERTY(QString devToolsId READ devToolsId CONSTANT REVISION(6,6) FINAL)
 
     Q_PROPERTY(LifecycleState lifecycleState READ lifecycleState WRITE setLifecycleState NOTIFY lifecycleStateChanged REVISION(1,10) FINAL)
     Q_PROPERTY(LifecycleState recommendedState READ recommendedState NOTIFY recommendedStateChanged REVISION(1,10) FINAL)
@@ -214,6 +214,7 @@ QT_WARNING_POP
         RequestClose,
         Unselect,
         SavePage,
+        OpenLinkInNewBackgroundTab, // Not supported in QML
         ViewSource,
 
         ToggleBold,
@@ -265,8 +266,6 @@ QT_WARNING_POP
     // must match QPageSize::PageSizeId
     enum PrintedPageSizeId {
         // Existing Qt sizes
-        A4,
-        B5,
         Letter,
         Legal,
         Executive,
@@ -274,21 +273,24 @@ QT_WARNING_POP
         A1,
         A2,
         A3,
+        A4,
         A5,
         A6,
         A7,
         A8,
         A9,
+        A10,
         B0,
         B1,
-        B10,
         B2,
         B3,
         B4,
+        B5,
         B6,
         B7,
         B8,
         B9,
+        B10,
         C5E,
         Comm10E,
         DLE,
@@ -298,7 +300,6 @@ QT_WARNING_POP
         Custom,
 
         // New values derived from PPD standard
-        A10,
         A3Extra,
         A4Extra,
         A4Plus,
@@ -401,10 +402,8 @@ QT_WARNING_POP
         EnvelopePrc10,
         EnvelopeYou4,
 
-        // Last item, with commonly used synynoms from QPagedPrintEngine / QPrinter
+        // Last item
         LastPageSize = EnvelopeYou4,
-        NPageSize = LastPageSize,
-        NPaperSize = LastPageSize,
 
         // Convenience overloads for naming consistency
         AnsiA = Letter,
@@ -468,10 +467,6 @@ QT_WARNING_POP
 
     QQmlComponent *touchHandleDelegate() const;
     void setTouchHandleDelegate(QQmlComponent *delegagte);
-    Q_REVISION(6, 6)
-    Q_INVOKABLE void save(const QString &filePath,
-                          QWebEngineDownloadRequest::SavePageFormat format =
-                                  QWebEngineDownloadRequest::MimeHtmlSaveFormat) const;
 
 public Q_SLOTS:
     void runJavaScript(const QString&, const QJSValue & = QJSValue());
@@ -485,12 +480,15 @@ public Q_SLOTS:
     void stop();
     Q_REVISION(1,1) void findText(const QString &subString, FindFlags options = { }, const QJSValue &callback = QJSValue());
     Q_REVISION(1,1) void fullScreenCancelled();
-    Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, Feature, bool granted);
+    Q_REVISION(1,1) void grantFeaturePermission(const QUrl &securityOrigin, QQuickWebEngineView::Feature, bool granted);
     Q_REVISION(1,2) void setActiveFocusOnPress(bool arg);
     Q_REVISION(1,2) void triggerWebAction(WebAction action);
     Q_REVISION(1,3) void printToPdf(const QString &filePath, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait);
     Q_REVISION(1,3) void printToPdf(const QJSValue &callback, PrintedPageSizeId pageSizeId = PrintedPageSizeId::A4, PrintedPageOrientation orientation = PrintedPageOrientation::Portrait);
     Q_REVISION(1,4) void replaceMisspelledWord(const QString &replacement);
+    Q_REVISION(6, 6) void save(const QString &filePath,
+                               QWebEngineDownloadRequest::SavePageFormat format =
+                                       QWebEngineDownloadRequest::MimeHtmlSaveFormat) const;
 
 private Q_SLOTS:
     void lazyInitialize();
@@ -503,17 +501,22 @@ private Q_SLOTS:
     void loadProgressChanged();
     void linkHovered(const QUrl &hoveredUrl);
     void navigationRequested(QWebEngineNavigationRequest *request);
-    void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID);
+    void javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel level,
+                                  const QString &message, int lineNumber, const QString &sourceID);
     Q_REVISION(1,1) void certificateError(const QWebEngineCertificateError &error);
     Q_REVISION(1,1) void fullScreenRequested(const QWebEngineFullScreenRequest &request);
     Q_REVISION(1,1) void isFullScreenChanged();
-    Q_REVISION(1,1) void featurePermissionRequested(const QUrl &securityOrigin, Feature feature);
+    Q_REVISION(1, 1)
+    void featurePermissionRequested(const QUrl &securityOrigin,
+                                    QQuickWebEngineView::Feature feature);
     Q_REVISION(1,1) void zoomFactorChanged(qreal arg);
     Q_REVISION(1,1) void profileChanged();
     Q_REVISION(1,1) void webChannelChanged();
     Q_REVISION(1,2) void activeFocusOnPressChanged(bool);
     Q_REVISION(1,2) void backgroundColorChanged();
-    Q_REVISION(1,2) void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode);
+    Q_REVISION(1, 2)
+    void renderProcessTerminated(QQuickWebEngineView::RenderProcessTerminationStatus terminationStatus,
+                            int exitCode);
     Q_REVISION(1,2) void windowCloseRequested();
     Q_REVISION(1,3) void contentsSizeChanged(const QSizeF& size);
     Q_REVISION(1,3) void scrollPositionChanged(const QPointF& position);
@@ -537,8 +540,8 @@ private Q_SLOTS:
     Q_REVISION(1,8) void printRequested();
     Q_REVISION(1,9) void selectClientCertificate(QQuickWebEngineClientCertificateSelection *clientCertSelection);
     Q_REVISION(1,10) void tooltipRequested(QQuickWebEngineTooltipRequest *request);
-    Q_REVISION(1,10) void lifecycleStateChanged(LifecycleState state);
-    Q_REVISION(1,10) void recommendedStateChanged(LifecycleState state);
+    Q_REVISION(1, 10) void lifecycleStateChanged(QQuickWebEngineView::LifecycleState state);
+    Q_REVISION(1, 10) void recommendedStateChanged(QQuickWebEngineView::LifecycleState state);
     Q_REVISION(1,10) void findTextFinished(const QWebEngineFindTextResult &result);
     Q_REVISION(1,11) void renderProcessPidChanged(qint64 pid);
     Q_REVISION(1,11) void canGoBackChanged();
diff --git a/src/webenginequick/api/qtwebenginequickglobal.cpp b/src/webenginequick/api/qtwebenginequickglobal.cpp
index f8f520a05cb..e24ef643b01 100644
--- a/src/webenginequick/api/qtwebenginequickglobal.cpp
+++ b/src/webenginequick/api/qtwebenginequickglobal.cpp
@@ -37,16 +37,19 @@ namespace QtWebEngineQuick {
 */
 void initialize()
 {
+    auto api = QQuickWindow::graphicsApi();
     if (!QCoreApplication::startingUp()) {
-        qWarning("QtWebEngineQuick::initialize() called with QCoreApplication object already created and should be call before. "\
-                 "This is depreciated and may fail in the future.");
+        if (api == QSGRendererInterface::OpenGL || (api != QSGRendererInterface::Vulkan
+                && api != QSGRendererInterface::Metal && api != QSGRendererInterface::Direct3D11)) {
+            qWarning("QtWebEngineQuick::initialize() called with QCoreApplication object already created and should be call before. "\
+                     "This is depreciated and may fail in the future.");
+        }
         QtWebEngineCore::initialize();
         return;
     }
 
     // call initialize the same way as widgets do
     qAddPreRoutine(QtWebEngineCore::initialize);
-    auto api = QQuickWindow::graphicsApi();
     if (api != QSGRendererInterface::OpenGL && api != QSGRendererInterface::Vulkan
             && api != QSGRendererInterface::Metal && api != QSGRendererInterface::Direct3D11)
         QQuickWindow::setGraphicsApi(QSGRendererInterface::OpenGL);
diff --git a/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc b/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc
index 76dea97cfbd..f8fbbd669c2 100644
--- a/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc
+++ b/src/webenginequick/doc/snippets/qtwebengine_build_snippet.qdoc
@@ -7,5 +7,5 @@ QT += webenginequick
 
 //! [2]
 find_package(Qt6 REQUIRED COMPONENTS WebEngineQuick)
-target_link_libraries(target PRIVATE Qt::WebEngineQuick)
+target_link_libraries(target PRIVATE Qt6::WebEngineQuick)
 //! [2]
diff --git a/src/webenginequick/doc/src/qtwebengine-examples.qdoc b/src/webenginequick/doc/src/qtwebengine-examples.qdoc
index b3eb548e58a..eebf18ba110 100644
--- a/src/webenginequick/doc/src/qtwebengine-examples.qdoc
+++ b/src/webenginequick/doc/src/qtwebengine-examples.qdoc
@@ -5,7 +5,6 @@
     \group webengine-examples
     \title Qt WebEngine Quick Examples
     \brief Examples demonstrating the \QWE usage.
-    \ingroup all-examples
 
     These examples and demonstrations show a range of different uses for \l{Qt WebEngine},
     from displaying Web pages within a QML user interface to an implementation of
diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
index 16c5b07f647..cbbec9fd80d 100644
--- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc
+++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc
@@ -356,9 +356,8 @@
     This method offers a lower-level alternative to the \c{url} property,
     which references HTML pages via URL.
 
-    External objects, such as stylesheets or images referenced in the HTML
-    document, should be located relative to \a baseUrl. For external objects to
-    be loaded, \c baseUrl cannot be empty. For example, if \a html
+    \a baseUrl is optional and used to resolve relative URLs in the document,
+    such as referenced images or stylesheets. For example, if \a html
     is retrieved from \c http://www.example.com/documents/overview.html, which
     is the base URL, then an image referenced with the relative URL, \c diagram.png,
     should be at \c{http://www.example.com/documents/diagram.png}.
@@ -787,6 +786,7 @@
             Exit the fullscreen mode. (Added in Qt 5.6)
     \value  WebEngineView.SavePage
             Save the current web page to disk. (Added in Qt 5.7)
+    \omitvalue WebEngineView.OpenLinkInNewBackgroundTab
     \value  WebEngineView.ViewSource
             Show the source of the current page in a new tab. Requires a handler for the
             \l newWindowRequested() signal. (Added in Qt 5.8)
@@ -1000,8 +1000,6 @@
     \value WebEngineView.EnvelopePrc10
     \value WebEngineView.EnvelopeYou4
     \value WebEngineView.LastPageSize = \c EnvelopeYou4
-    \omitvalue NPageSize
-    \omitvalue NPaperSize
 
     \sa WebEngineView::printToPdf()
 */
@@ -1304,7 +1302,7 @@
 */
 
 /*!
-    \qmlproperty WebEngineView WebEngineView::devToolsView
+    \qmlproperty WebEngineView WebEngineView::devToolsId
     \since QtWebEngine 6.6
     \readonly
 
@@ -1333,10 +1331,11 @@
 */
 
 /*!
-    \qmlsignal WebEngineView::printRequest
+    \qmlsignal WebEngineView::printRequested
     \since QtWebEngine 1.8
 
-    This signal is emitted when the JavaScript \c{window.print()} method is called.
+    This signal is emitted when the JavaScript \c{window.print()} method is called or the user pressed the print
+    button of PDF viewer plugin.
     Typically, the signal handler can simply call printToPdf().
 
     \sa printToPdf
diff --git a/src/webenginequick/ui/AlertDialog.qml b/src/webenginequick/ui/AlertDialog.qml
index 53911f0bca3..e4c17b05621 100644
--- a/src/webenginequick/ui/AlertDialog.qml
+++ b/src/webenginequick/ui/AlertDialog.qml
@@ -49,6 +49,7 @@ Dialog {
                 id: message
                 Layout.fillWidth: true
                 color: palette.windowText
+                textFormat: Text.PlainText
             }
         }
         Item {
diff --git a/src/webenginequick/ui/AuthenticationDialog.qml b/src/webenginequick/ui/AuthenticationDialog.qml
index f9de8d79fc3..d0611b84f51 100644
--- a/src/webenginequick/ui/AuthenticationDialog.qml
+++ b/src/webenginequick/ui/AuthenticationDialog.qml
@@ -50,6 +50,7 @@ Dialog {
         Label {
             id: message
             color: palette.windowText
+            textFormat: Text.PlainText
         }
         GridLayout {
             columns: 2
diff --git a/src/webenginequick/ui/ConfirmDialog.qml b/src/webenginequick/ui/ConfirmDialog.qml
index 7b5f1f5cf75..cfffe7c4d54 100644
--- a/src/webenginequick/ui/ConfirmDialog.qml
+++ b/src/webenginequick/ui/ConfirmDialog.qml
@@ -55,6 +55,7 @@ Dialog {
                 id: message
                 Layout.fillWidth: true
                 color: palette.windowText
+                textFormat: Text.PlainText
             }
         }
         Item {
diff --git a/src/webenginequick/ui/PromptDialog.qml b/src/webenginequick/ui/PromptDialog.qml
index f3a15d48d16..275deace862 100644
--- a/src/webenginequick/ui/PromptDialog.qml
+++ b/src/webenginequick/ui/PromptDialog.qml
@@ -52,6 +52,7 @@ Dialog {
             id: message
             Layout.fillWidth: true
             color: palette.windowText
+            textFormat: Text.PlainText
         }
         TextField {
             id:field
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 35fb9813879..e28f70b5f5f 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -1,6 +1,7 @@
 // Copyright (C) 2021 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 "qapplication.h"
 #include "qwebenginenotificationpresenter_p.h"
 #include "qwebengineview.h"
 #include "qwebengineview_p.h"
@@ -68,6 +69,14 @@
 #include <QThread>
 #endif
 
+QT_BEGIN_NAMESPACE
+class QSpontaneKeyEvent
+{
+public:
+    static inline void makeSpontaneous(QEvent *ev) { ev->setSpontaneous(); }
+};
+QT_END_NAMESPACE
+
 namespace QtWebEngineCore {
 class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate
 {
@@ -148,6 +157,7 @@ class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate
     }
     void SetClearColor(const QColor &color) override
     {
+        setUpdatesEnabled(false);
         QQuickWidget::setClearColor(color);
         // QQuickWidget is usually blended by punching holes into widgets
         // above it to simulate the visual stacking order. If we want it to be
@@ -156,7 +166,8 @@ class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate
         bool isTranslucent = color.alpha() < 255;
         setAttribute(Qt::WA_AlwaysStackOnTop, isTranslucent);
         setAttribute(Qt::WA_OpaquePaintEvent, !isTranslucent);
-        update();
+        setUpdatesEnabled(true);
+        window()->update();
     }
     void MoveWindow(const QPoint &screenPos) override
     {
@@ -172,6 +183,14 @@ class WebEngineQuickWidget : public QQuickWidget, public WidgetDelegate
             return root->windowHandle();
         return nullptr;
     }
+    void unhandledWheelEvent(QWheelEvent *ev) override
+    {
+        auto parentWidget = QQuickWidget::parentWidget();
+        if (parentWidget) {
+            QSpontaneKeyEvent::makeSpontaneous(ev);
+            qApp->notify(parentWidget, ev);
+        }
+    }
 
 protected:
     void closeEvent(QCloseEvent *event) override
@@ -425,6 +444,8 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget
 #endif
         q->layout()->addWidget(newWidget);
         q->setFocusProxy(newWidget);
+        if (oldWidget && oldWidget == QApplication::focusWidget())
+            newWidget->setFocus();
         newWidget->show();
     }
 }
@@ -537,8 +558,10 @@ bool QWebEngineViewPrivate::showAuthorizationDialog(const QString &title, const
 {
 #if QT_CONFIG(messagebox)
     Q_Q(QWebEngineView);
-    return QMessageBox::question(q, title, message, QMessageBox::Yes, QMessageBox::No)
-            == QMessageBox::Yes;
+    QMessageBox msgBox(QMessageBox::Question, title, message, QMessageBox::Yes | QMessageBox::No,
+                       q, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
+    msgBox.setTextFormat(Qt::PlainText);
+    return msgBox.exec() == QMessageBox::Yes;
 #else
     return false;
 #endif // QT_CONFIG(messagebox)
@@ -548,8 +571,12 @@ void QWebEngineViewPrivate::javaScriptAlert(const QUrl &url, const QString &msg)
 {
 #if QT_CONFIG(messagebox)
     Q_Q(QWebEngineView);
-    QMessageBox::information(q, QStringLiteral("Javascript Alert - %1").arg(url.toString()),
-                             msg.toHtmlEscaped());
+    QMessageBox msgBox(QMessageBox::Information,
+                       QStringLiteral("Javascript Alert - %1").arg(url.toString()),
+                       msg, QMessageBox::Ok, q,
+                       Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
+    msgBox.setTextFormat(Qt::PlainText);
+    msgBox.exec();
 #else
     Q_UNUSED(msg);
 #endif // QT_CONFIG(messagebox)
@@ -559,10 +586,12 @@ bool QWebEngineViewPrivate::javaScriptConfirm(const QUrl &url, const QString &ms
 {
 #if QT_CONFIG(messagebox)
     Q_Q(QWebEngineView);
-    return (QMessageBox::information(q,
-                                     QStringLiteral("Javascript Confirm - %1").arg(url.toString()),
-                                     msg.toHtmlEscaped(), QMessageBox::Ok, QMessageBox::Cancel)
-            == QMessageBox::Ok);
+    QMessageBox msgBox(QMessageBox::Information,
+                       QStringLiteral("Javascript Confirm - %1").arg(url.toString()),
+                       msg, QMessageBox::Ok | QMessageBox::Cancel, q,
+                       Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint);
+    msgBox.setTextFormat(Qt::PlainText);
+    return msgBox.exec() == QMessageBox::Ok;
 #else
     Q_UNUSED(msg);
     return false;
@@ -575,10 +604,16 @@ bool QWebEngineViewPrivate::javaScriptPrompt(const QUrl &url, const QString &msg
 #if QT_CONFIG(inputdialog)
     Q_Q(QWebEngineView);
     bool ret = false;
+
+    // Workaround: Do not interpret text as Qt::RichText
+    // QInputDialog uses Qt::AutoText that interprets the text string as
+    // Qt::RichText if Qt::mightBeRichText() returns true, otherwise as Qt::PlainText.
+    const QString message = Qt::mightBeRichText(msg) ? msg.toHtmlEscaped() : msg;
+
     if (result)
         *result = QInputDialog::getText(
                 q, QStringLiteral("Javascript Prompt - %1").arg(url.toString()),
-                msg.toHtmlEscaped(), QLineEdit::Normal, defaultValue.toHtmlEscaped(), &ret);
+                message, QLineEdit::Normal, defaultValue, &ret);
     return ret;
 #else
     Q_UNUSED(msg);
@@ -731,9 +766,9 @@ void QWebEngineViewPrivate::bindPageAndWidget(QWebEnginePagePrivate *pagePrivate
     }
 }
 
-QIcon QWebEngineViewPrivate::webActionIcon(QWebEnginePage::WebAction action)
+QIcon QWebEngineViewPrivate::webActionIcon(QWebEnginePage::WebAction action) const
 {
-    Q_Q(QWebEngineView);
+    Q_Q(const QWebEngineView);
     QIcon icon;
     QStyle *style = q->style();
 
@@ -1105,7 +1140,16 @@ QString QWebEngineView::selectedText() const
 #if QT_CONFIG(action)
 QAction* QWebEngineView::pageAction(QWebEnginePage::WebAction action) const
 {
-    return page()->action(action);
+    Q_D(const QWebEngineView);
+    QAction *pageAction = page()->action(action);
+
+    if (pageAction->icon().isNull()) {
+        auto icon = d->webActionIcon(action);
+        if (!icon.isNull())
+            pageAction->setIcon(icon);
+    }
+
+    return pageAction;
 }
 #endif
 
@@ -1379,7 +1423,8 @@ void QWebEngineView::printToPdf(const std::function<void(const QByteArray&)> &re
     \fn void QWebEngineView::printRequested()
     \since 6.2
 
-    This signal is emitted when the JavaScript \c{window.print()} method is called.
+    This signal is emitted when the JavaScript \c{window.print()} method is called or the user pressed the print
+    button of PDF viewer plugin.
     Typically, the signal handler can simply call print().
 
     \sa print()
@@ -1462,79 +1507,79 @@ void QContextMenuBuilder::addMenuItem(ContextMenuItem menuItem)
 
     switch (menuItem) {
     case ContextMenuItem::Back:
-        action = thisRef->action(QWebEnginePage::Back);
+        action = m_view->pageAction(QWebEnginePage::Back);
         break;
     case ContextMenuItem::Forward:
-        action = thisRef->action(QWebEnginePage::Forward);
+        action = m_view->pageAction(QWebEnginePage::Forward);
         break;
     case ContextMenuItem::Reload:
-        action = thisRef->action(QWebEnginePage::Reload);
+        action = m_view->pageAction(QWebEnginePage::Reload);
         break;
     case ContextMenuItem::Cut:
-        action = thisRef->action(QWebEnginePage::Cut);
+        action = m_view->pageAction(QWebEnginePage::Cut);
         break;
     case ContextMenuItem::Copy:
-        action = thisRef->action(QWebEnginePage::Copy);
+        action = m_view->pageAction(QWebEnginePage::Copy);
         break;
     case ContextMenuItem::Paste:
-        action = thisRef->action(QWebEnginePage::Paste);
+        action = m_view->pageAction(QWebEnginePage::Paste);
         break;
     case ContextMenuItem::Undo:
-        action = thisRef->action(QWebEnginePage::Undo);
+        action = m_view->pageAction(QWebEnginePage::Undo);
         break;
     case ContextMenuItem::Redo:
-        action = thisRef->action(QWebEnginePage::Redo);
+        action = m_view->pageAction(QWebEnginePage::Redo);
         break;
     case ContextMenuItem::SelectAll:
-        action = thisRef->action(QWebEnginePage::SelectAll);
+        action = m_view->pageAction(QWebEnginePage::SelectAll);
         break;
     case ContextMenuItem::PasteAndMatchStyle:
-        action = thisRef->action(QWebEnginePage::PasteAndMatchStyle);
+        action = m_view->pageAction(QWebEnginePage::PasteAndMatchStyle);
         break;
     case ContextMenuItem::OpenLinkInNewWindow:
-        action = thisRef->action(QWebEnginePage::OpenLinkInNewWindow);
+        action = m_view->pageAction(QWebEnginePage::OpenLinkInNewWindow);
         break;
     case ContextMenuItem::OpenLinkInNewTab:
-        action = thisRef->action(QWebEnginePage::OpenLinkInNewTab);
+        action = m_view->pageAction(QWebEnginePage::OpenLinkInNewTab);
         break;
     case ContextMenuItem::CopyLinkToClipboard:
-        action = thisRef->action(QWebEnginePage::CopyLinkToClipboard);
+        action = m_view->pageAction(QWebEnginePage::CopyLinkToClipboard);
         break;
     case ContextMenuItem::DownloadLinkToDisk:
-        action = thisRef->action(QWebEnginePage::DownloadLinkToDisk);
+        action = m_view->pageAction(QWebEnginePage::DownloadLinkToDisk);
         break;
     case ContextMenuItem::CopyImageToClipboard:
-        action = thisRef->action(QWebEnginePage::CopyImageToClipboard);
+        action = m_view->pageAction(QWebEnginePage::CopyImageToClipboard);
         break;
     case ContextMenuItem::CopyImageUrlToClipboard:
-        action = thisRef->action(QWebEnginePage::CopyImageUrlToClipboard);
+        action = m_view->pageAction(QWebEnginePage::CopyImageUrlToClipboard);
         break;
     case ContextMenuItem::DownloadImageToDisk:
-        action = thisRef->action(QWebEnginePage::DownloadImageToDisk);
+        action = m_view->pageAction(QWebEnginePage::DownloadImageToDisk);
         break;
     case ContextMenuItem::CopyMediaUrlToClipboard:
-        action = thisRef->action(QWebEnginePage::CopyMediaUrlToClipboard);
+        action = m_view->pageAction(QWebEnginePage::CopyMediaUrlToClipboard);
         break;
     case ContextMenuItem::ToggleMediaControls:
-        action = thisRef->action(QWebEnginePage::ToggleMediaControls);
+        action = m_view->pageAction(QWebEnginePage::ToggleMediaControls);
         break;
     case ContextMenuItem::ToggleMediaLoop:
-        action = thisRef->action(QWebEnginePage::ToggleMediaLoop);
+        action = m_view->pageAction(QWebEnginePage::ToggleMediaLoop);
         break;
     case ContextMenuItem::DownloadMediaToDisk:
-        action = thisRef->action(QWebEnginePage::DownloadMediaToDisk);
+        action = m_view->pageAction(QWebEnginePage::DownloadMediaToDisk);
         break;
     case ContextMenuItem::InspectElement:
-        action = thisRef->action(QWebEnginePage::InspectElement);
+        action = m_view->pageAction(QWebEnginePage::InspectElement);
         break;
     case ContextMenuItem::ExitFullScreen:
-        action = thisRef->action(QWebEnginePage::ExitFullScreen);
+        action = m_view->pageAction(QWebEnginePage::ExitFullScreen);
         break;
     case ContextMenuItem::SavePage:
-        action = thisRef->action(QWebEnginePage::SavePage);
+        action = m_view->pageAction(QWebEnginePage::SavePage);
         break;
     case ContextMenuItem::ViewSource:
-        action = thisRef->action(QWebEnginePage::ViewSource);
+        action = m_view->pageAction(QWebEnginePage::ViewSource);
         break;
     case ContextMenuItem::SpellingSuggestions:
         for (int i = 0; i < m_contextData->spellCheckerSuggestions().size() && i < 4; i++) {
diff --git a/src/webenginewidgets/api/qwebengineview.h b/src/webenginewidgets/api/qwebengineview.h
index f93d61b12c7..d594c825419 100644
--- a/src/webenginewidgets/api/qwebengineview.h
+++ b/src/webenginewidgets/api/qwebengineview.h
@@ -26,6 +26,7 @@ class QWebEngineHttpRequest;
 class QWebEngineSettings;
 class QWebEngineViewAccessible;
 class QWebEngineViewPrivate;
+class QMenu;
 
 class QWEBENGINEWIDGETS_EXPORT QWebEngineView : public QWidget
 {
diff --git a/src/webenginewidgets/api/qwebengineview_p.h b/src/webenginewidgets/api/qwebengineview_p.h
index 7c0f3fe60c2..9d5a0ad219a 100644
--- a/src/webenginewidgets/api/qwebengineview_p.h
+++ b/src/webenginewidgets/api/qwebengineview_p.h
@@ -85,7 +85,7 @@ class QWebEngineViewPrivate : public PageView
     static void bindPageAndView(QWebEnginePage *page, QWebEngineView *view);
     static void bindPageAndWidget(QWebEnginePagePrivate *pagePrivate,
                                   QtWebEngineCore::WebEngineQuickWidget *widget);
-    QIcon webActionIcon(QWebEnginePage::WebAction action);
+    QIcon webActionIcon(QWebEnginePage::WebAction action) const;
     void unhandledKeyEvent(QKeyEvent *event) override;
     void focusContainer() override;
     bool passOnFocus(bool reverse) override;
diff --git a/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc b/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
index 4ab54a2ba83..f11f550ffe0 100644
--- a/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
+++ b/src/webenginewidgets/doc/snippets/qtwebenginewidgets_build_snippet.qdoc
@@ -7,5 +7,5 @@ QT += webenginewidgets
 
 //! [2]
 find_package(Qt6 REQUIRED COMPONENTS WebEngineWidgets)
-target_link_libraries(target PRIVATE Qt::WebEngineWidgets)
+target_link_libraries(target PRIVATE Qt6::WebEngineWidgets)
 //! [2]
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
index 15f6d08f4da..c9bd76bf4e3 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
@@ -5,7 +5,6 @@
     \group webengine-widgetexamples
     \title Qt WebEngine Widgets Examples
     \brief Examples demonstrating the \QWE Widgets usage.
-    \ingroup all-examples
 
     Qt provides an integrated Web browser component based on Chromium, the popular
     open source browser engine.
diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
index 9b8ee29eb91..3153ec95223 100644
--- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
@@ -108,9 +108,8 @@
     \fn void QWebEngineView::setHtml(const QString &html, const QUrl &baseUrl)
     Sets the content of the web view to the specified \a html content.
 
-    External objects, such as stylesheets or images referenced in the HTML
-    document, are located relative to \a baseUrl. For external objects to
-    be loaded, \c baseUrl cannot be empty. For example, if \a html
+    \a baseUrl is optional and used to resolve relative URLs in the document,
+    such as referenced images or stylesheets. For example, if \a html
     is retrieved from \c http://www.example.com/documents/overview.html, which
     is the base URL, then an image referenced with the relative URL, \c diagram.png,
     should be at \c{http://www.example.com/documents/diagram.png}.
@@ -144,7 +143,7 @@
     is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}.
 
     External objects referenced in the content are located relative to \a baseUrl.
-    For external objects to be loaded, \c baseUrl cannot be empty.
+    For external objects with relative URLs to be loaded, \c baseUrl cannot be empty.
 
     The data is loaded immediately; external objects are loaded asynchronously.
 
@@ -210,6 +209,7 @@
 /*!
     \fn QAction *QWebEngineView::pageAction(QWebEnginePage::WebAction action) const
     Returns a pointer to a QAction that encapsulates the specified web action \a action.
+    This function will also set a default styled icon to the QAction if it lacks one.
 */
 
 /*!
diff --git a/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp b/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp
index 2ff1de1690b..6ba64a1783e 100644
--- a/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp
+++ b/src/webenginewidgets/plugins/qwebengineview/qwebengineview_plugin.cpp
@@ -79,14 +79,6 @@ void QWebEngineViewPlugin::initialize(QDesignerFormEditorInterface * /*core*/)
 
 QString QWebEngineViewPlugin::domXml() const
 {
-    const auto graphicsApi = QQuickWindow::graphicsApi();
-    if (graphicsApi != QSGRendererInterface::OpenGLRhi
-        && graphicsApi != QSGRendererInterface::Software) {
-        qWarning("Qt Designer: The QWebEngineView custom widget plugin is disabled because it requires OpenGL/Software RHI (current: %d).",
-                 int(graphicsApi));
-        return {};
-    }
-
     return QStringLiteral("\
     <ui language=\"c++\">\
         <widget class=\"QWebEngineView\" name=\"webEngineView\">\
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index a8f031a5d25..9e02c40caac 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -1 +1,3 @@
-qt_build_tests()
+if(Qt6Core_VERSION VERSION_GREATER_EQUAL "6.5")
+   qt_build_tests()
+endif()
diff --git a/tests/auto/CMakeLists.txt b/tests/auto/CMakeLists.txt
index 6fff2b35c21..ad69710b116 100644
--- a/tests/auto/CMakeLists.txt
+++ b/tests/auto/CMakeLists.txt
@@ -13,5 +13,7 @@ if(TARGET Qt::WebEngineWidgets)
 endif()
 if(TARGET Qt::Pdf)
     add_subdirectory(pdf)
+endif()
+if(TARGET Qt::PdfQuick)
     add_subdirectory(pdfquick)
 endif()
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt
index 9981d4950dd..4ed41d94755 100644
--- a/tests/auto/core/CMakeLists.txt
+++ b/tests/auto/core/CMakeLists.txt
@@ -4,13 +4,16 @@
 add_subdirectory(qwebenginecookiestore)
 add_subdirectory(qwebengineloadinginfo)
 add_subdirectory(qwebenginesettings)
-add_subdirectory(qwebengineglobalsettings)
+if(QT_FEATURE_ssl)
+    # only tests doh, and requires ssl
+    add_subdirectory(qwebengineglobalsettings)
+endif()
 add_subdirectory(qwebengineurlrequestinterceptor)
-add_subdirectory(qwebengineurlresponseinterceptor)
 add_subdirectory(qwebengineurlrequestjob)
 add_subdirectory(origins)
 add_subdirectory(devtools)
 add_subdirectory(getdomainandregistry)
+add_subdirectory(qtversion)
 
 if(QT_FEATURE_ssl)
     add_subdirectory(qwebengineclientcertificatestore)
diff --git a/tests/auto/core/origins/tst_origins.cpp b/tests/auto/core/origins/tst_origins.cpp
index c77a4bc26a6..091ce865119 100644
--- a/tests/auto/core/origins/tst_origins.cpp
+++ b/tests/auto/core/origins/tst_origins.cpp
@@ -1692,11 +1692,11 @@ void tst_Origins::fetchApiCustomUrl()
     }
 
     page.load(url);
-    QVERIFY(loadSpy.wait());
+    QTRY_VERIFY(loadSpy.count() > 0);
     QTRY_COMPARE(handler.fetchWasAllowed, expectedFetchWasAllowed);
 
     if (fetchApiScheme == "fetchapi-not-allowed") {
-        QVERIFY(jsSpy.wait());
+        QTRY_VERIFY(jsSpy.count() > 0);
     }
 }
 
@@ -1722,8 +1722,8 @@ void tst_Origins::fetchApiHttpUrl()
             + httpServer.url("/somepage.html").toEncoded();
     page.load(QUrl(fullUrl));
 
-    QVERIFY(loadSpy.wait());
-    QVERIFY(jsSpy.wait());
+    QTRY_VERIFY(loadSpy.count() > 0);
+    QTRY_VERIFY(jsSpy.count() > 0);
     QVERIFY(httpServer.stop());
 }
 
diff --git a/tests/auto/core/qtversion/CMakeLists.txt b/tests/auto/core/qtversion/CMakeLists.txt
new file mode 100644
index 00000000000..9a5e892666c
--- /dev/null
+++ b/tests/auto/core/qtversion/CMakeLists.txt
@@ -0,0 +1,10 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+qt_internal_add_test(tst_qtversion
+    SOURCES
+        tst_qtversion.cpp
+    LIBRARIES
+        Qt::WebEngineCore
+)
+
diff --git a/tests/auto/core/qtversion/tst_qtversion.cpp b/tests/auto/core/qtversion/tst_qtversion.cpp
new file mode 100644
index 00000000000..44c2d4e5c90
--- /dev/null
+++ b/tests/auto/core/qtversion/tst_qtversion.cpp
@@ -0,0 +1,34 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtTest/QtTest>
+#include <QtWebEngineCore/qwebenginepage.h>
+
+class tst_QtVersion : public QObject
+{
+    Q_OBJECT
+signals:
+    void done();
+private Q_SLOTS:
+    void checkVersion();
+};
+
+void tst_QtVersion::checkVersion()
+{
+    QWebEnginePage page;
+    QSignalSpy loadSpy(&page, &QWebEnginePage::loadFinished);
+    QSignalSpy doneSpy(this, &tst_QtVersion::done);
+    page.load(QUrl("chrome://qt"));
+    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 12000);
+    page.toPlainText([this](const QString &result) {
+        QVERIFY(result.contains(qWebEngineVersion()));
+        QVERIFY(result.contains(qWebEngineChromiumVersion()));
+        QVERIFY(result.contains(qWebEngineChromiumSecurityPatchVersion()));
+        emit done();
+    });
+    QTRY_VERIFY(doneSpy.size());
+}
+
+QTEST_MAIN(tst_QtVersion)
+
+#include "tst_qtversion.moc"
diff --git a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
index 409b0eb0cbd..0af85a7114e 100644
--- a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
+++ b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
@@ -34,17 +34,23 @@ Q_LOGGING_CATEGORY(lc, "qt.webengine.tests")
 
 void tst_QWebEngineGlobalSettings::dnsOverHttps_data()
 {
-    QTest::addColumn<QWebEngineGlobalSettings::DnsMode>("dnsMode");
+    QTest::addColumn<QWebEngineGlobalSettings::SecureDnsMode>("dnsMode");
     QTest::addColumn<QString>("uriTemplate");
-    QTest::addColumn<bool>("isWithCustomDnsServer");
+    QTest::addColumn<bool>("isMockDnsServerCalledExpected");
     QTest::addColumn<bool>("isDnsResolutionSuccessExpected");
-    QTest::newRow("DnsMode::Secure (mock DNS)")
-            << QWebEngineGlobalSettings::DnsMode::Secure
-            << QStringLiteral("https://127.0.0.1:3000/dns-query{?dns}") << true << false;
-    QTest::newRow("DnsMode::Secure (real DNS)")
-            << QWebEngineGlobalSettings::DnsMode::Secure
-            << QStringLiteral("https://dns.google/dns-query{?dns}") << false << true;
-
+    QTest::addColumn<bool>("isConfigurationSuccessExpected");
+    QTest::newRow("DnsMode::SystemOnly (no DoH server)")
+            << QWebEngineGlobalSettings::SecureDnsMode::SystemOnly << QStringLiteral("") << false
+            << true << true;
+    QTest::newRow("DnsMode::SecureOnly (mock DoH server)")
+            << QWebEngineGlobalSettings::SecureDnsMode::SecureOnly
+            << QStringLiteral("https://127.0.0.1:3000/dns-query{?dns}") << true << false << true;
+    QTest::newRow("DnsMode::SecureOnly (real DoH server)")
+            << QWebEngineGlobalSettings::SecureDnsMode::SecureOnly
+            << QStringLiteral("https://dns.google/dns-query{?dns}") << false << true << true;
+    QTest::newRow("DnsMode::SecureOnly (Empty URI Templates)")
+            << QWebEngineGlobalSettings::SecureDnsMode::SecureOnly << QStringLiteral("") << false
+            << false << false;
     // Note: In the following test, we can't verify that the DoH server is called first and
     // afterwards insecure DNS is tried, because for the DoH server to ever be used when the DNS
     // mode is set to DnsMode::WithFallback, Chromium starts an asynchronous DoH server DnsProbe and
@@ -52,33 +58,45 @@ void tst_QWebEngineGlobalSettings::dnsOverHttps_data()
     // DNS response, which in turn requires that certificate errors aren't ignored and
     // non-self-signed certificates are used for correct encryption. Instead of implementing
     // all of that, this test verifies that Chromium tries probing the configured DoH server only.
-    QTest::newRow("DnsMode::WithFallback (mock DNS)")
-            << QWebEngineGlobalSettings::DnsMode::WithFallback
-            << QStringLiteral("https://127.0.0.1:3000/dns-query{?dns}") << true << true;
+    QTest::newRow("DnsMode::SecureWithFallback (mock DoH server)")
+            << QWebEngineGlobalSettings::SecureDnsMode::SecureWithFallback
+            << QStringLiteral("https://127.0.0.1:3000/dns-query{?dns}") << true << true << true;
+    QTest::newRow("DnsMode::SecureWithFallback (Empty URI Templates)")
+            << QWebEngineGlobalSettings::SecureDnsMode::SecureWithFallback << QStringLiteral("")
+            << false << false << false;
 }
 
 void tst_QWebEngineGlobalSettings::dnsOverHttps()
 {
-    QFETCH(QWebEngineGlobalSettings::DnsMode, dnsMode);
+    QFETCH(QWebEngineGlobalSettings::SecureDnsMode, dnsMode);
     QFETCH(QString, uriTemplate);
-    QFETCH(bool, isWithCustomDnsServer);
+    QFETCH(bool, isMockDnsServerCalledExpected);
     QFETCH(bool, isDnsResolutionSuccessExpected);
-    bool isDnsServerCalled = false;
+    QFETCH(bool, isConfigurationSuccessExpected);
+    bool isMockDnsServerCalled = false;
     bool isLoadSuccessful = false;
 
+    bool configurationSuccess =
+            QWebEngineGlobalSettings::setDnsMode({ dnsMode, QStringList{ uriTemplate } });
+    QCOMPARE(configurationSuccess, isConfigurationSuccessExpected);
+
+    if (!configurationSuccess) {
+        // In this case, DNS has invalid configuration, so the DNS change transaction is not
+        // triggered and the result of the DNS resolution depends on the current DNS mode, which is
+        // set by the previous run of this function.
+        return;
+    }
     HttpsServer httpsServer(":/cert/localhost.crt", ":/cert/localhost.key", ":/cert/RootCA.pem",
                             3000, this);
-    if (isWithCustomDnsServer) {
-        QObject::connect(
-                &httpsServer, &HttpsServer::newRequest, this, [&isDnsServerCalled](HttpReqRep *rr) {
-                    QVERIFY(rr->requestPath().contains(QByteArrayLiteral("/dns-query?dns=")));
-                    isDnsServerCalled = true;
-                    rr->close();
-                });
-        QVERIFY(httpsServer.start());
-        httpsServer.setExpectError(true);
-        httpsServer.setVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
-    }
+    QObject::connect(&httpsServer, &HttpsServer::newRequest, this,
+                     [&isMockDnsServerCalled](HttpReqRep *rr) {
+                         QVERIFY(rr->requestPath().contains(QByteArrayLiteral("/dns-query?dns=")));
+                         isMockDnsServerCalled = true;
+                         rr->close();
+                     });
+    QVERIFY(httpsServer.start());
+    httpsServer.setExpectError(isMockDnsServerCalledExpected);
+    httpsServer.setVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
 
     QWebEngineProfile profile;
     QWebEnginePage page(&profile);
@@ -87,15 +105,12 @@ void tst_QWebEngineGlobalSettings::dnsOverHttps()
     connect(&page, &QWebEnginePage::loadFinished, this,
             [&isLoadSuccessful](bool ok) { isLoadSuccessful = ok; });
 
-    QWebEngineGlobalSettings *globalSettings = QWebEngineGlobalSettings::GetInstance();
-    globalSettings->configureDnsOverHttps(dnsMode, uriTemplate);
-
     page.load(QUrl("https://google.com/"));
-    if (!loadSpy.wait(10000)) {
+    if (!loadSpy.wait(20000)) {
         QSKIP("Couldn't load page from network, skipping test.");
     }
 
-    QTRY_COMPARE(isDnsServerCalled, isWithCustomDnsServer);
+    QTRY_COMPARE(isMockDnsServerCalled, isMockDnsServerCalledExpected);
     QCOMPARE(isLoadSuccessful, isDnsResolutionSuccessExpected);
     QVERIFY(httpsServer.stop());
 }
diff --git a/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp b/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp
index 064abe816f1..ccae7436bdd 100644
--- a/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp
+++ b/tests/auto/core/qwebengineloadinginfo/tst_qwebengineloadinginfo.cpp
@@ -6,11 +6,12 @@
 #include <QtWebEngineCore/qwebenginepage.h>
 #include <QtWebEngineCore/qwebengineloadinginfo.h>
 #include <QtWebEngineCore/qwebenginehttprequest.h>
+#include <QtWebEngineCore/qwebenginesettings.h>
 
 #include <httpserver.h>
 #include <httpreqrep.h>
 
-typedef QHash<QByteArray, QByteArray> Map;
+typedef QMultiMap<QByteArray, QByteArray> Map;
 
 class tst_QWebEngineLoadingInfo : public QObject
 {
@@ -75,6 +76,7 @@ private Q_SLOTS:
 
         QWebEngineProfile profile;
         QWebEnginePage page(&profile);
+        page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
         QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
         QObject::connect(&page, &QWebEnginePage::loadingChanged, this, &tst_QWebEngineLoadingInfo::loadingInfoChanged);
 
@@ -82,7 +84,7 @@ private Q_SLOTS:
         QWebEngineHttpRequest request(httpServer.url("/somepage.html"));
         page.load(request);
 
-        QVERIFY(spy.wait());
+        QTRY_VERIFY(spy.count() > 0);
         QVERIFY(httpServer.stop());
     }
 };
diff --git a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
index f63a333c296..14492c728bc 100644
--- a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
+++ b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp
@@ -211,15 +211,15 @@ void tst_QWebEngineSettings::disableReadingFromCanvas()
     QWebEnginePage page;
     QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
     page.settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true);
-    page.settings()->setAttribute(QWebEngineSettings::DisableReadingFromCanvas,
-                                  disableReadingFromCanvas);
+    page.settings()->setAttribute(QWebEngineSettings::ReadingFromCanvasEnabled,
+                                  !disableReadingFromCanvas);
     page.setHtml("<html><body>"
                  "<canvas id='myCanvas' width='200' height='40' style='border:1px solid "
                  "#000000;'></canvas>"
                  "</body></html>");
     QVERIFY(loadFinishedSpy.wait());
-    QCOMPARE(page.settings()->testAttribute(QWebEngineSettings::DisableReadingFromCanvas),
-             disableReadingFromCanvas);
+    QCOMPARE(page.settings()->testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled),
+             !disableReadingFromCanvas);
 
     const QString jsCode("(function(){"
                          "   var canvas = document.getElementById(\"myCanvas\");"
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index 73185837a16..6774a51f0b6 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -48,6 +48,8 @@ private Q_SLOTS:
     void replaceInterceptor();
     void replaceOnIntercept();
     void multipleRedirects();
+    void profilePreventsPageInterception_data();
+    void profilePreventsPageInterception();
 };
 
 tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor()
@@ -134,7 +136,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor
 
         // MEMO avoid unintentionally changing request when it is not needed for test logic
         //      since api behavior depends on 'changed' state of the info object
-        Q_ASSERT(info.changed() == (block || redirect || !headers.empty()));
+        Q_ASSERT(info.changed() == (block || redirect));
     }
 
     bool shouldSkipRequest(const RequestInfo &requestInfo)
@@ -935,5 +937,62 @@ void tst_QWebEngineUrlRequestInterceptor::multipleRedirects()
     QTRY_COMPARE(multiInterceptor.requestInfos.size(), 2);
 }
 
+class PageOrProfileInterceptor : public QWebEngineUrlRequestInterceptor
+{
+public:
+    PageOrProfileInterceptor(const QString &profileAction)
+        : profileAction(profileAction)
+    {
+    }
+
+    void interceptRequest(QWebEngineUrlRequestInfo &info) override
+    {
+        if (profileAction == "block")
+            info.block(true);
+        else if (profileAction == "redirect")
+            info.redirect(QUrl("data:text/html,<p>redirected"));
+        else if (profileAction == "add header")
+            info.setHttpHeader("Custom-Header", "Value");
+        else
+            QVERIFY(info.httpHeaders().contains("Custom-Header"));
+        ran = true;
+    }
+
+    QString profileAction;
+    bool ran = false;
+};
+
+void tst_QWebEngineUrlRequestInterceptor::profilePreventsPageInterception_data()
+{
+    QTest::addColumn<QString>("profileAction");
+    QTest::addColumn<bool>("interceptInProfile");
+    QTest::addColumn<bool>("interceptInPage");
+    QTest::newRow("block") << "block" << true << false;
+    QTest::newRow("redirect") << "redirect" << true << false;
+    QTest::newRow("add header") << "add header" << true << true;
+}
+
+void tst_QWebEngineUrlRequestInterceptor::profilePreventsPageInterception()
+{
+    QFETCH(QString, profileAction);
+    QFETCH(bool, interceptInProfile);
+    QFETCH(bool, interceptInPage);
+
+    QWebEngineProfile profile;
+    PageOrProfileInterceptor profileInterceptor(profileAction);
+    profile.setUrlRequestInterceptor(&profileInterceptor);
+    profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+
+    QWebEnginePage page(&profile);
+    PageOrProfileInterceptor pageInterceptor("");
+    page.setUrlRequestInterceptor(&pageInterceptor);
+    QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+
+    page.load(QUrl("qrc:///resources/index.html"));
+    QTRY_COMPARE(loadSpy.size(), 1);
+    QCOMPARE(profileInterceptor.ran, interceptInProfile);
+    QCOMPARE(pageInterceptor.ran, interceptInPage);
+}
+
 QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor)
 #include "tst_qwebengineurlrequestinterceptor.moc"
diff --git a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp
index 034bda2910e..6839eab06dd 100644
--- a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp
+++ b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp
@@ -22,7 +22,7 @@ class AdditionalResponseHeadersHandler : public QWebEngineUrlSchemeHandler
     {
         QCOMPARE(job->requestUrl(), QUrl(schemeName + ":about"));
 
-        QMap<QByteArray, QByteArray> additionalResponseHeaders;
+        QMultiMap<QByteArray, QByteArray> additionalResponseHeaders;
         if (m_addAdditionalResponseHeaders) {
             additionalResponseHeaders.insert(QByteArray::fromStdString("test1"),
                                              QByteArray::fromStdString("test1VALUE"));
diff --git a/tests/auto/core/qwebengineurlresponseinterceptor/CMakeLists.txt b/tests/auto/core/qwebengineurlresponseinterceptor/CMakeLists.txt
deleted file mode 100644
index 08a5b9699a9..00000000000
--- a/tests/auto/core/qwebengineurlresponseinterceptor/CMakeLists.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-# Copyright (C) 2023 The Qt Company Ltd.
-# SPDX-License-Identifier: BSD-3-Clause
-
-include(../../httpserver/httpserver.cmake)
-
-qt_internal_add_test(tst_qwebengineurlresponseinterceptor
-    SOURCES
-        tst_qwebengineurlresponseinterceptor.cpp
-    LIBRARIES
-        Qt::WebEngineCore
-        Test::HttpServer
-)
diff --git a/tests/auto/core/qwebengineurlresponseinterceptor/tst_qwebengineurlresponseinterceptor.cpp b/tests/auto/core/qwebengineurlresponseinterceptor/tst_qwebengineurlresponseinterceptor.cpp
deleted file mode 100644
index 4d08853eff4..00000000000
--- a/tests/auto/core/qwebengineurlresponseinterceptor/tst_qwebengineurlresponseinterceptor.cpp
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (C) 2023 The Qt Company Ltd.
-// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
-
-#include <QtTest/QtTest>
-#include <QtWebEngineCore/QWebEngineUrlResponseInterceptor>
-#include <QtWebEngineCore/QWebEngineProfile>
-#include <QtWebEngineCore/QWebEnginePage>
-#include <QtWebEngineCore/QWebEngineLoadingInfo>
-#include <QtWebEngineCore/QWebEngineUrlResponseInfo>
-
-#include <httpserver.h>
-#include <httpreqrep.h>
-
-class tst_QWebEngineUrlResponseInterceptor : public QObject
-{
-    Q_OBJECT
-
-public:
-    tst_QWebEngineUrlResponseInterceptor() { }
-    ~tst_QWebEngineUrlResponseInterceptor() { }
-
-public Q_SLOTS:
-    void init() { }
-    void cleanup() { }
-
-private Q_SLOTS:
-    void initTestCase() { }
-    void cleanupTestCase() { }
-    void interceptRequest_data();
-    void interceptRequest();
-};
-
-Q_LOGGING_CATEGORY(lc, "qt.webengine.tests")
-
-class Interceptor : public QWebEngineUrlResponseInterceptor
-{
-    Q_OBJECT
-
-    QUrl m_receivedRequestUrl;
-    QHash<QByteArray, QByteArray> m_receivedRequestHeaders;
-
-public:
-    void interceptResponseHeaders(QWebEngineUrlResponseInfo &info) override
-    {
-        m_receivedRequestUrl = info.requestUrl();
-        m_receivedRequestHeaders = info.requestHeaders();
-        QHash<QByteArray, QByteArray> responseHeaders = info.responseHeaders();
-
-        responseHeaders.insert(QByteArrayLiteral("ADDEDHEADER"), QByteArrayLiteral("ADDEDVALUE"));
-        *(responseHeaders.find(QByteArrayLiteral("content-length"))) = QByteArrayLiteral("57");
-
-        info.setResponseHeaders(responseHeaders);
-    }
-
-    void getReceivedRequest(QUrl *receivedRequestUrl,
-                            QHash<QByteArray, QByteArray> *receivedRequestHeaders)
-    {
-        *receivedRequestUrl = m_receivedRequestUrl;
-        *receivedRequestHeaders = m_receivedRequestHeaders;
-    }
-};
-
-void tst_QWebEngineUrlResponseInterceptor::interceptRequest_data()
-{
-    QTest::addColumn<bool>("withProfileInterceptor");
-    QTest::newRow("with profile interceptor") << true;
-    QTest::newRow("with page interceptor") << false;
-}
-
-void tst_QWebEngineUrlResponseInterceptor::interceptRequest()
-{
-    QFETCH(bool, withProfileInterceptor);
-
-    HttpServer httpServer;
-    QObject::connect(&httpServer, &HttpServer::newRequest, this, [&](HttpReqRep *rr) {
-        if (rr->requestPath() == QByteArrayLiteral("/okay.html")) {
-            rr->setResponseBody(QByteArrayLiteral(
-                    "<html><script>console.log('hello world js!');</script></html>"));
-            rr->sendResponse();
-        }
-    });
-    QVERIFY(httpServer.start());
-
-    const QUrl requestUrl = httpServer.url(QStringLiteral("/okay.html"));
-
-    Interceptor interceptor;
-    QWebEngineProfile profile;
-    QWebEnginePage page(&profile);
-    if (withProfileInterceptor)
-        profile.setUrlResponseInterceptor(&interceptor);
-    else
-        page.setUrlResponseInterceptor(&interceptor);
-
-    QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
-
-    bool headersWereChanged = false;
-    QObject::connect(
-            &page, &QWebEnginePage::loadingChanged, this, [&](QWebEngineLoadingInfo loadingInfo) {
-                const QHash<QByteArray, QByteArray> responseHeaders = loadingInfo.responseHeaders();
-                bool contentLengthSizeChanged = false;
-                bool additionalHeaderAdded = false;
-                for (auto it = responseHeaders.constBegin(); it != responseHeaders.constEnd();
-                     ++it) {
-                    if (it.key() == QByteArrayLiteral("content-length")
-                        && it.value() == QByteArrayLiteral("57"))
-                        contentLengthSizeChanged = true;
-                    if (it.key() == QByteArrayLiteral("ADDEDHEADER")
-                        && it.value() == QByteArrayLiteral("ADDEDVALUE"))
-                        additionalHeaderAdded = true;
-                }
-
-                if (contentLengthSizeChanged && additionalHeaderAdded)
-                    headersWereChanged = true;
-            });
-
-    page.load(requestUrl);
-
-    QVERIFY(loadSpy.wait());
-
-    QUrl receivedRequestUrl;
-    QHash<QByteArray, QByteArray> receivedRequestHeaders;
-    interceptor.getReceivedRequest(&receivedRequestUrl, &receivedRequestHeaders);
-
-    bool receivedRequestHeadersContainsQtWebEngine = false;
-    for (auto it = receivedRequestHeaders.cbegin(); it != receivedRequestHeaders.cend(); ++it) {
-        if (it.value().contains("QtWebEngine/")) {
-            receivedRequestHeadersContainsQtWebEngine = true;
-            break;
-        }
-    }
-
-    QVERIFY(headersWereChanged);
-    QCOMPARE_EQ(receivedRequestUrl, requestUrl);
-    QVERIFY(receivedRequestHeaders.size() != 0);
-    QVERIFY(receivedRequestHeadersContainsQtWebEngine);
-    QVERIFY(httpServer.stop());
-}
-
-QTEST_MAIN(tst_QWebEngineUrlResponseInterceptor)
-#include "tst_qwebengineurlresponseinterceptor.moc"
diff --git a/tests/auto/pdf/qpdfdocument/CMakeLists.txt b/tests/auto/pdf/qpdfdocument/CMakeLists.txt
index aadc192b384..b8300ef27e7 100644
--- a/tests/auto/pdf/qpdfdocument/CMakeLists.txt
+++ b/tests/auto/pdf/qpdfdocument/CMakeLists.txt
@@ -12,5 +12,7 @@ qt_internal_add_test(tst_qpdfdocument
     TESTDATA
         pdf-sample.protected.pdf
         pdf-sample.metadata.pdf
+        rotated_text.pdf
+        tagged_mcr_multipage.pdf
         test.pdf
 )
diff --git a/tests/auto/pdf/qpdfdocument/rotated_text.pdf b/tests/auto/pdf/qpdfdocument/rotated_text.pdf
new file mode 100644
index 00000000000..d6d8db84ed3
Binary files /dev/null and b/tests/auto/pdf/qpdfdocument/rotated_text.pdf differ
diff --git a/tests/auto/pdf/qpdfdocument/tagged_mcr_multipage.pdf b/tests/auto/pdf/qpdfdocument/tagged_mcr_multipage.pdf
new file mode 100644
index 00000000000..fcc5fafda4d
Binary files /dev/null and b/tests/auto/pdf/qpdfdocument/tagged_mcr_multipage.pdf differ
diff --git a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp
index 6bb007e7fbd..d222bff0cd2 100644
--- a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp
+++ b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp
@@ -36,6 +36,10 @@ private slots:
     void passwordClearedOnClose();
     void metaData();
     void pageLabels();
+    void getSelection_data();
+    void getSelection();
+    void getSelectionAtIndex_data();
+    void getSelectionAtIndex();
 
 private:
     void consistencyCheck(QPdfDocument &doc) const;
@@ -394,6 +398,86 @@ void tst_QPdfDocument::pageLabels()
     QCOMPARE(doc.pageLabel(2), "i"); // i of the tiger!
 }
 
+void tst_QPdfDocument::getSelection_data()
+{
+    QTest::addColumn<QString>("pdfPath");
+    QTest::addColumn<int>("page");
+    QTest::addColumn<QPointF>("start");
+    QTest::addColumn<QPointF>("end");
+    QTest::addColumn<QString>("expectedText");
+    QTest::addColumn<int>("expectedStartIndex");
+    QTest::addColumn<int>("expectedEndIndex");
+    QTest::addColumn<QRect>("expectedBounds");
+    QTest::addColumn<int>("expectedPolygonCount");
+
+    QTest::newRow("raid") << QFINDTESTDATA("test.pdf")
+            << 1 << QPointF(316.4, 206) << QPointF(339, 201)
+            << "raid" << 80 << 84 << QRect(316, 201, 21, 12) << 1;
+    QTest::newRow("rotated text") << QFINDTESTDATA("rotated_text.pdf")
+            << 0 << QPointF(102, 94) << QPointF(125, 73)
+            << "world!" << 25 << 31 << QRect(98, 70, 26, 28) << 1;
+}
+
+void tst_QPdfDocument::getSelection()
+{
+    QFETCH(QString, pdfPath);
+    QFETCH(int, page);
+    QFETCH(QPointF, start);
+    QFETCH(QPointF, end);
+    QFETCH(QString, expectedText);
+    QFETCH(int, expectedStartIndex);
+    QFETCH(int, expectedEndIndex);
+    QFETCH(QRect, expectedBounds);
+    QFETCH(int, expectedPolygonCount);
+
+    QPdfDocument doc;
+    QCOMPARE(doc.load(pdfPath), QPdfDocument::Error::None);
+
+    QPdfSelection sel = doc.getSelection(page, start, end);
+    QCOMPARE(sel.text(), expectedText);
+    QCOMPARE(sel.startIndex(), expectedStartIndex);
+    QCOMPARE(sel.endIndex(), expectedEndIndex);
+    QCOMPARE(sel.boundingRectangle().toRect(), expectedBounds);
+    QCOMPARE(sel.bounds().size(), expectedPolygonCount);
+}
+
+void tst_QPdfDocument::getSelectionAtIndex_data()
+{
+    QTest::addColumn<QString>("pdfPath");
+    QTest::addColumn<int>("page");
+    QTest::addColumn<int>("start");
+    QTest::addColumn<int>("maxLen");
+    QTest::addColumn<QString>("expectedText");
+    QTest::addColumn<QRect>("expectedBounds");
+    QTest::addColumn<int>("expectedPolygonCount");
+
+    QTest::newRow("raid") << QFINDTESTDATA("test.pdf")
+            << 1 << 80 << 4 << "raid" << QRect(316, 201, 21, 12) << 1;
+    QTest::newRow("rotated text") << QFINDTESTDATA("rotated_text.pdf")
+            << 0 << 7 << 6 << "world!" << QRect(76, 102, 26, 28) << 1;
+    QTest::newRow("displaced text") << QFINDTESTDATA("tagged_mcr_multipage.pdf")
+            << 0 << 0 << 10 << "1" << QRect(34, 22, 3, 8) << 1;
+}
+
+void tst_QPdfDocument::getSelectionAtIndex()
+{
+    QFETCH(QString, pdfPath);
+    QFETCH(int, page);
+    QFETCH(int, start);
+    QFETCH(int, maxLen);
+    QFETCH(QString, expectedText);
+    QFETCH(QRect, expectedBounds);
+    QFETCH(int, expectedPolygonCount);
+
+    QPdfDocument doc;
+    QCOMPARE(doc.load(pdfPath), QPdfDocument::Error::None);
+
+    QPdfSelection sel = doc.getSelectionAtIndex(page, start, maxLen);
+    QCOMPARE(sel.text(), expectedText);
+    QCOMPARE(sel.boundingRectangle().toRect(), expectedBounds);
+    QCOMPARE(sel.bounds().size(), expectedPolygonCount);
+}
+
 QTEST_MAIN(tst_QPdfDocument)
 
 #include "tst_qpdfdocument.moc"
diff --git a/tests/auto/pdfquick/CMakeLists.txt b/tests/auto/pdfquick/CMakeLists.txt
index 9f79459b2be..e6a3a460c32 100644
--- a/tests/auto/pdfquick/CMakeLists.txt
+++ b/tests/auto/pdfquick/CMakeLists.txt
@@ -1 +1,2 @@
 add_subdirectory(multipageview)
+add_subdirectory(pdfpageimage)
diff --git a/tests/auto/pdfquick/multipageview/data/jumpOnDocumentReady.qml b/tests/auto/pdfquick/multipageview/data/jumpOnDocumentReady.qml
new file mode 100644
index 00000000000..ce74f5ed82c
--- /dev/null
+++ b/tests/auto/pdfquick/multipageview/data/jumpOnDocumentReady.qml
@@ -0,0 +1,18 @@
+import QtQuick
+import QtQuick.Pdf
+
+PdfMultiPageView {
+    id: view
+    width: 480
+    height: 480
+
+    document: PdfDocument {
+        id: document
+        onStatusChanged: {
+            if(status === PdfDocument.Ready)
+                view.goToPage(2)
+        }
+    }
+
+    Component.onCompleted: document.source = "bookmarksAndLinks.pdf"
+}
diff --git a/tests/auto/pdfquick/multipageview/tst_multipageview.cpp b/tests/auto/pdfquick/multipageview/tst_multipageview.cpp
index 9cd8e3e2d8b..c5e0b30dbba 100644
--- a/tests/auto/pdfquick/multipageview/tst_multipageview.cpp
+++ b/tests/auto/pdfquick/multipageview/tst_multipageview.cpp
@@ -6,6 +6,7 @@
 #include <QtCore/QLoggingCategory>
 #include <QtGui/QClipboard>
 #include <QtGui/QPointingDevice>
+#include <QtGui/QStyleHints>
 #include <QtQuick/QQuickView>
 #include <QtPdfQuick/private/qquickpdflinkmodel_p.h>
 #include <QtPdfQuick/private/qquickpdfsearchmodel_p.h>
@@ -28,6 +29,8 @@ private Q_SLOTS:
     void password();
     void selectionAndClipboard();
     void search();
+    void pinchDragPinch();
+    void jumpOnDocumentReady();
 
 public:
     enum NavigationAction {
@@ -59,7 +62,7 @@ void tst_MultiPageView::internalLink_data()
     QTest::addColumn<qreal>("expectedZoom");
     QTest::addColumn<QPoint>("expectedScroll");
 
-    QTest::newRow("first link") << 0 << 1 << qreal(1) << QPoint(134, 1276);
+    QTest::newRow("first link") << 0 << 1 << qreal(1) << QPoint(134, 1286);
     // TODO fails because it zooms out, and the view leaves gaps between pages currently
 //    QTest::newRow("second link") << 1 << 2 << qreal(0.5) << QPoint(0, 717);
 }
@@ -355,5 +358,89 @@ void tst_MultiPageView::search()
     QVERIFY(movements > 4);
 }
 
+void tst_MultiPageView::pinchDragPinch()
+{
+    qputenv("QML_NO_TOUCH_COMPRESSION", "1");
+    QQuickView window;
+    QVERIFY(showView(window, testFileUrl("multiPageView.qml")));
+    QQuickItem *pdfView = window.rootObject();
+    QVERIFY(pdfView);
+    pdfView->setProperty("source", testFileUrl("bookmarksAndLinks.pdf"));
+    QTRY_COMPARE(pdfView->property("currentPageRenderingStatus").toInt(), QQuickPdfPageImage::Ready);
+    QQuickItem *table = static_cast<QQuickItem *>(findFirstChild(pdfView, "QQuickTableView"));
+    QVERIFY(table);
+    QQuickItem *firstPage = tableViewItemAtCell(table, 0, 0);
+    QVERIFY(firstPage);
+    QQuickItem *paper = firstPage->childAt(10, 10);
+    QVERIFY(paper);
+    QQuickPdfPageImage *image = firstPage->findChild<QQuickPdfPageImage *>();
+    QVERIFY(image);
+
+    auto pinch = [&window, paper, this]() {
+        const int threshold = QGuiApplication::styleHints()->startDragDistance();
+        const int movement = 100;
+        QCOMPARE_GT(movement, threshold);
+        const qreal initialScale = paper->scale();
+        QPoint p0(100, 200);
+        QPoint p1(200, 200);
+        QTest::QTouchEventSequence seq = QTest::touchEvent(&window, touchscreen.get());
+        seq.press(0, p0, &window).commit();
+        seq.stationary(0).press(1, p1, &window).commit();
+        p1.setX(p1.x() + movement);
+        QSignalSpy frameSwappedSpy(&window, &QQuickWindow::frameSwapped);
+        seq.stationary(0).move(1, p1, &window).commit();
+        // after a frame is rendered, the PinchHandler ought to be active
+        // (but verifying it would require private API)
+        QTRY_VERIFY(frameSwappedSpy.size() > 0);
+        QTRY_COMPARE(paper->scale(), initialScale);
+
+        for (int i = 1; i <= 2; ++i) {
+            p1.setX(p1.x() + movement);
+            seq.stationary(0).move(1, p1, &window).commit();
+            QTRY_COMPARE(paper->scale(), initialScale + i * 0.5);
+        }
+        seq.release(0, p0, &window).release(1, p1, &window).commit();
+    };
+
+    auto drag = [&window, table, this]() {
+        const int movement = 100;
+        QPoint p0(200, 200);
+        QTest::QTouchEventSequence seq = QTest::touchEvent(&window, touchscreen.get());
+        seq.press(0, p0, &window).commit();
+        p0.setY(p0.y() + movement);
+        seq.move(0, p0, &window).commit();
+        p0.setY(p0.y() + movement);
+        seq.move(0, p0, &window).commit();
+        seq.release(0, p0, &window).commit();
+        QTRY_COMPARE(table->property("moving"), false);
+    };
+
+    pinch();
+    qCDebug(lcTests) << "new scale" << pdfView->property("renderScale").toReal();
+    QTRY_COMPARE(pdfView->property("renderScale").toReal(), 2);
+
+    drag();
+    QCOMPARE(pdfView->property("renderScale").toReal(), 2);
+
+    pinch();
+    qCDebug(lcTests) << "new scale" << pdfView->property("renderScale").toReal();
+    QTRY_COMPARE(pdfView->property("renderScale").toReal(), 4);
+
+    // wait for rendering to be done before we exit: if we delete the document
+    // prematurely, QPdfIOHandler might access a dangling pointer
+    QTRY_COMPARE(image->status(), QQuickPdfPageImage::Ready);
+}
+
+void tst_MultiPageView::jumpOnDocumentReady() // QTBUG-119416
+{
+    QQuickView window;
+    QVERIFY(showView(window, testFileUrl("jumpOnDocumentReady.qml")));
+    QQuickItem *pdfView = window.rootObject();
+    QVERIFY(pdfView);
+
+    // QML calls view.goToPage(2): verify that it eventually happens
+    QTRY_COMPARE(pdfView->property("currentPage").toInt(), 2);
+}
+
 QTEST_MAIN(tst_MultiPageView)
 #include "tst_multipageview.moc"
diff --git a/tests/auto/pdfquick/pdfpageimage/CMakeLists.txt b/tests/auto/pdfquick/pdfpageimage/CMakeLists.txt
new file mode 100644
index 00000000000..da67d872100
--- /dev/null
+++ b/tests/auto/pdfquick/pdfpageimage/CMakeLists.txt
@@ -0,0 +1,30 @@
+# Collect test data
+file(GLOB_RECURSE test_data_glob
+    RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}
+    data/*)
+list(APPEND test_data ${test_data_glob})
+
+qt_internal_add_test(tst_pdfpageimage
+    SOURCES
+        tst_pdfpageimage.cpp
+        ../shared/util.cpp ../shared/util.h
+    LIBRARIES
+        Qt::Gui
+        Qt::Quick
+        Qt::PdfQuickPrivate
+    TESTDATA ${test_data}
+)
+
+## Scopes:
+#####################################################################
+
+qt_internal_extend_target(tst_pdfpageimage CONDITION ANDROID OR IOS
+    DEFINES
+        QT_QMLTEST_DATADIR=":/data"
+)
+
+qt_internal_extend_target(tst_pdfpageimage CONDITION NOT ANDROID AND NOT IOS
+    DEFINES
+        QT_QMLTEST_DATADIR="${CMAKE_CURRENT_SOURCE_DIR}/data"
+)
+
diff --git a/tests/auto/pdfquick/pdfpageimage/data/bookmarksAndLinks.pdf b/tests/auto/pdfquick/pdfpageimage/data/bookmarksAndLinks.pdf
new file mode 100644
index 00000000000..aa0b9903982
Binary files /dev/null and b/tests/auto/pdfquick/pdfpageimage/data/bookmarksAndLinks.pdf differ
diff --git a/tests/auto/pdfquick/pdfpageimage/data/pdfPageImage.qml b/tests/auto/pdfquick/pdfpageimage/data/pdfPageImage.qml
new file mode 100644
index 00000000000..a268bf14b96
--- /dev/null
+++ b/tests/auto/pdfquick/pdfpageimage/data/pdfPageImage.qml
@@ -0,0 +1,16 @@
+import QtQuick
+import QtQuick.Pdf
+
+Item {
+    width: 320
+    height: 320
+
+    PdfDocument {
+        id: doc
+        source: "bookmarksAndLinks.pdf"
+    }
+
+    PdfPageImage {
+        anchors.centerIn: parent
+    }
+}
diff --git a/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp b/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp
new file mode 100644
index 00000000000..d2c9c8709f6
--- /dev/null
+++ b/tests/auto/pdfquick/pdfpageimage/tst_pdfpageimage.cpp
@@ -0,0 +1,131 @@
+// Copyright (C) 2024 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 <QRegularExpression>
+#include <QSignalSpy>
+#include <QTest>
+#include <QtQuick/QQuickView>
+#include <QtPdfQuick/private/qquickpdfdocument_p.h>
+#include <QtPdfQuick/private/qquickpdfpageimage_p.h>
+#include "../shared/util.h"
+
+using namespace Qt::StringLiterals;
+
+Q_LOGGING_CATEGORY(lcTests, "qt.pdf.tests")
+
+// #define DEBUG_WRITE_OUTPUT
+
+class tst_PdfPageImage : public QQuickDataTest
+{
+    Q_OBJECT
+
+private Q_SLOTS:
+    void settableProperties_data();
+    void settableProperties();
+
+public:
+    enum Property {
+        Source = 0x01,
+        Document = 0x02,
+        SourceSize = 0x04,
+        SourceClipRect = 0x08,
+        MipMap = 0x10,
+        AutoTransform = 0x20,
+        Asynchronous = 0x40,
+        NoCache = 0x80,
+        Mirror = 0x100,
+        MirrorVertically = 0x200,
+        ColorSpace = 0x400,
+    };
+    Q_DECLARE_FLAGS(Properties, Property)
+    Q_FLAG(Properties)
+
+private:
+#ifdef DEBUG_WRITE_OUTPUT
+    QTemporaryDir m_tmpDir;
+#endif
+};
+
+void tst_PdfPageImage::settableProperties_data()
+{
+    QTest::addColumn<tst_PdfPageImage::Properties>("toSet");
+    QTest::addColumn<QSize>("expectedSize");
+    QTest::addColumn<QRegularExpression>("expectedWarning");
+
+    const QRegularExpression NoWarning;
+    const qreal dpr = qGuiApp->devicePixelRatio();
+
+    QTest::newRow("source") << Properties(Source) << (QSizeF(600, 790) * dpr).toSize()
+        << QRegularExpression("document property not set: falling back to inefficient loading"); // QTBUG-104767
+    QTest::newRow("document") << Properties(Document) << QSize(600, 790) << NoWarning;
+    QTest::newRow("source and document") << Properties(Source | Document) << QSize(600, 790)
+        << QRegularExpression("document and source properties in conflict");
+    QTest::newRow("document and sourceSize") << Properties(Document | SourceSize) << QSize(100, 100) << NoWarning;
+    QTest::newRow("document and sourceClipRect") << Properties(Document | SourceClipRect) << QSize(100, 100) << NoWarning;
+    QTest::newRow("document and autoTransform") << Properties(Document | AutoTransform) << QSize(600, 790) << NoWarning;
+    QTest::newRow("document and async") << Properties(Document | Asynchronous) << QSize(600, 790) << NoWarning;
+    QTest::newRow("document and nocache") << Properties(Document | NoCache) << QSize(600, 790) << NoWarning;
+    QTest::newRow("document and mirror") << Properties(Document | Mirror) << QSize(600, 790) << NoWarning;
+    QTest::newRow("document and mirrorVertically") << Properties(Document | MirrorVertically) << QSize(600, 790) << NoWarning;
+    QTest::newRow("document and colorSpace") << Properties(Document | ColorSpace) << QSize(600, 790) << NoWarning;
+}
+
+void tst_PdfPageImage::settableProperties()
+{
+    QFETCH(tst_PdfPageImage::Properties, toSet);
+    QFETCH(QSize, expectedSize);
+    QFETCH(QRegularExpression, expectedWarning);
+
+    QQuickView window;
+    if (!expectedWarning.pattern().isEmpty())
+        QTest::ignoreMessage(QtWarningMsg, expectedWarning);
+    QVERIFY(showView(window, testFileUrl("pdfPageImage.qml")));
+    QQuickPdfPageImage *pdfImage = window.rootObject()->findChild<QQuickPdfPageImage *>();
+    QVERIFY(pdfImage);
+    QQuickPdfDocument *doc = window.rootObject()->findChild<QQuickPdfDocument *>();
+    QVERIFY(doc);
+    if (toSet.testFlag(Document))
+        pdfImage->setDocument(doc);
+    if (toSet.testFlag(Source))
+        pdfImage->setSource(doc->source());
+    if (toSet.testFlag(SourceSize))
+        pdfImage->setSourceSize({100, 100});
+    if (toSet.testFlag(SourceClipRect))
+        pdfImage->setSourceClipRect({100, 100, 100, 100});
+    if (toSet.testFlag(MipMap))
+        pdfImage->setMipmap(true);
+    if (toSet.testFlag(AutoTransform))
+        pdfImage->setAutoTransform(true);
+    if (toSet.testFlag(Asynchronous)) {
+        QCOMPARE(pdfImage->asynchronous(), false);
+        // test the opposite of the default
+        pdfImage->setAsynchronous(true);
+    }
+    if (toSet.testFlag(NoCache)) {
+        QCOMPARE(pdfImage->cache(), true);
+        // test the opposite of the default
+        pdfImage->setCache(false);
+    }
+    if (toSet.testFlag(Mirror)) {
+        QCOMPARE(pdfImage->mirror(), false);
+        pdfImage->setMirror(true);
+    }
+    if (toSet.testFlag(MirrorVertically)) {
+        QCOMPARE(pdfImage->mirrorVertically(), false);
+        pdfImage->setMirrorVertically(true);
+    }
+    if (toSet.testFlag(ColorSpace))
+        pdfImage->setColorSpace(QColorSpace::ProPhotoRgb);
+    QTRY_COMPARE(pdfImage->status(), QQuickPdfPageImage::Ready);
+    const QImage img = pdfImage->image();
+    QCOMPARE(img.size(), expectedSize);
+#ifdef DEBUG_WRITE_OUTPUT
+    m_tmpDir.setAutoRemove(false);
+    const auto path = m_tmpDir.filePath(QString::fromLocal8Bit(QTest::currentDataTag()) + ".png");
+    qCDebug(lcTests) << "saving to" << path;
+    img.save(path);
+#endif
+}
+
+QTEST_MAIN(tst_PdfPageImage)
+#include "tst_pdfpageimage.moc"
diff --git a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp
index 8b80c1a5f04..667f923bbd2 100644
--- a/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp
+++ b/tests/auto/quick/inspectorserver/tst_inspectorserver.cpp
@@ -38,6 +38,7 @@ private Q_SLOTS:
 
 tst_InspectorServer::tst_InspectorServer()
 {
+    qputenv("QTWEBENGINE_CHROMIUM_FLAGS", "--remote-allow-origins=*");
     qputenv("QTWEBENGINE_REMOTE_DEBUGGING", INSPECTOR_SERVER_PORT);
     QtWebEngineQuick::initialize();
     QQuickWebEngineProfile::defaultProfile()->setOffTheRecord(true);
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index a388886a525..12733b89085 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -87,7 +87,7 @@ static const QStringList hardcodedTypes = QStringList()
     << "Qt::LayoutDirection"
     << "QQuickWebEngineScriptCollection*"
     << "QQmlComponent*"
-    << "QHash<QByteArray,QByteArray>";
+    << "QMultiMap<QByteArray,QByteArray>";
 
 static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineAction.text --> QString"
@@ -296,7 +296,7 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineJavaScriptDialogRequest.title --> QString"
     << "QQuickWebEngineJavaScriptDialogRequest.type --> QQuickWebEngineJavaScriptDialogRequest::DialogType"
     << "QWebEngineLoadingInfo.errorCode --> int"
-    << "QWebEngineLoadingInfo.responseHeaders --> QHash<QByteArray,QByteArray>"
+    << "QWebEngineLoadingInfo.responseHeaders --> QMultiMap<QByteArray,QByteArray>"
     << "QWebEngineLoadingInfo.errorDomain --> QWebEngineLoadingInfo::ErrorDomain"
     << "QWebEngineLoadingInfo.errorString --> QString"
     << "QWebEngineLoadingInfo.status --> QWebEngineLoadingInfo::LoadStatus"
@@ -443,8 +443,8 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineSettings.webGLEnabledChanged() --> void"
     << "QQuickWebEngineSettings.webRTCPublicInterfacesOnly --> bool"
     << "QQuickWebEngineSettings.webRTCPublicInterfacesOnlyChanged() --> void"
-    << "QQuickWebEngineSettings.disableReadingFromCanvas --> bool"
-    << "QQuickWebEngineSettings.disableReadingFromCanvasChanged() --> void"
+    << "QQuickWebEngineSettings.readingFromCanvasEnabled --> bool"
+    << "QQuickWebEngineSettings.readingFromCanvasEnabledChanged() --> void"
     << "QQuickWebEngineSingleton.defaultProfile --> QQuickWebEngineProfile*"
     << "QQuickWebEngineSingleton.settings --> QQuickWebEngineSettings*"
     << "QQuickWebEngineSingleton.script() --> QWebEngineScript"
@@ -469,7 +469,6 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.action(WebAction) --> QQuickWebEngineAction*"
     << "QQuickWebEngineView.A0 --> PrintedPageSizeId"
     << "QQuickWebEngineView.A1 --> PrintedPageSizeId"
-    << "QQuickWebEngineView.A10 --> PrintedPageSizeId"
     << "QQuickWebEngineView.A2 --> PrintedPageSizeId"
     << "QQuickWebEngineView.A3 --> PrintedPageSizeId"
     << "QQuickWebEngineView.A3Extra --> PrintedPageSizeId"
@@ -483,6 +482,7 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.A7 --> PrintedPageSizeId"
     << "QQuickWebEngineView.A8 --> PrintedPageSizeId"
     << "QQuickWebEngineView.A9 --> PrintedPageSizeId"
+    << "QQuickWebEngineView.A10 --> PrintedPageSizeId"
     << "QQuickWebEngineView.AbnormalTerminationStatus --> RenderProcessTerminationStatus"
     << "QQuickWebEngineView.AlignCenter --> WebAction"
     << "QQuickWebEngineView.AlignJustified --> WebAction"
@@ -500,7 +500,6 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.ArchE --> PrintedPageSizeId"
     << "QQuickWebEngineView.B0 --> PrintedPageSizeId"
     << "QQuickWebEngineView.B1 --> PrintedPageSizeId"
-    << "QQuickWebEngineView.B10 --> PrintedPageSizeId"
     << "QQuickWebEngineView.B2 --> PrintedPageSizeId"
     << "QQuickWebEngineView.B3 --> PrintedPageSizeId"
     << "QQuickWebEngineView.B4 --> PrintedPageSizeId"
@@ -510,6 +509,7 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.B7 --> PrintedPageSizeId"
     << "QQuickWebEngineView.B8 --> PrintedPageSizeId"
     << "QQuickWebEngineView.B9 --> PrintedPageSizeId"
+    << "QQuickWebEngineView.B10 --> PrintedPageSizeId"
     << "QQuickWebEngineView.Back --> WebAction"
     << "QQuickWebEngineView.C5E --> PrintedPageSizeId"
     << "QQuickWebEngineView.CertificateErrorDomain --> ErrorDomain"
@@ -630,8 +630,6 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.MediaAudioCapture --> Feature"
     << "QQuickWebEngineView.MediaAudioVideoCapture --> Feature"
     << "QQuickWebEngineView.MediaVideoCapture --> Feature"
-    << "QQuickWebEngineView.NPageSize --> PrintedPageSizeId"
-    << "QQuickWebEngineView.NPaperSize --> PrintedPageSizeId"
     << "QQuickWebEngineView.NoErrorDomain --> ErrorDomain"
     << "QQuickWebEngineView.Notifications --> Feature"
     << "QQuickWebEngineView.NoWebAction --> WebAction"
@@ -671,6 +669,7 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.ToggleUnderline --> WebAction"
     << "QQuickWebEngineView.Undo --> WebAction"
     << "QQuickWebEngineView.Unselect --> WebAction"
+    << "QQuickWebEngineView.OpenLinkInNewBackgroundTab --> WebAction"
     << "QQuickWebEngineView.ViewSource --> WebAction"
     << "QQuickWebEngineView.WarningMessageLevel --> JavaScriptConsoleMessageLevel"
     << "QQuickWebEngineView.WebActionCount --> WebAction"
@@ -693,7 +692,7 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.devToolsId --> QString"
     << "QQuickWebEngineView.devToolsView --> QQuickWebEngineView*"
     << "QQuickWebEngineView.devToolsViewChanged() --> void"
-    << "QQuickWebEngineView.featurePermissionRequested(QUrl,Feature) --> void"
+    << "QQuickWebEngineView.featurePermissionRequested(QUrl,QQuickWebEngineView::Feature) --> void"
     << "QQuickWebEngineView.fileDialogRequested(QQuickWebEngineFileDialogRequest*) --> void"
     << "QQuickWebEngineView.fileSystemAccessRequested(QWebEngineFileSystemAccessRequest) --> void"
     << "QQuickWebEngineView.findText(QString) --> void"
@@ -706,7 +705,7 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.goBack() --> void"
     << "QQuickWebEngineView.goBackOrForward(int) --> void"
     << "QQuickWebEngineView.goForward() --> void"
-    << "QQuickWebEngineView.grantFeaturePermission(QUrl,Feature,bool) --> void"
+    << "QQuickWebEngineView.grantFeaturePermission(QUrl,QQuickWebEngineView::Feature,bool) --> void"
     << "QQuickWebEngineView.history --> QWebEngineHistory*"
     << "QQuickWebEngineView.icon --> QUrl"
     << "QQuickWebEngineView.iconChanged() --> void"
@@ -714,10 +713,10 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.inspectedViewChanged() --> void"
     << "QQuickWebEngineView.isFullScreen --> bool"
     << "QQuickWebEngineView.isFullScreenChanged() --> void"
-    << "QQuickWebEngineView.javaScriptConsoleMessage(JavaScriptConsoleMessageLevel,QString,int,QString) --> void"
+    << "QQuickWebEngineView.javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel,QString,int,QString) --> void"
     << "QQuickWebEngineView.javaScriptDialogRequested(QQuickWebEngineJavaScriptDialogRequest*) --> void"
     << "QQuickWebEngineView.lifecycleState --> QQuickWebEngineView::LifecycleState"
-    << "QQuickWebEngineView.lifecycleStateChanged(LifecycleState) --> void"
+    << "QQuickWebEngineView.lifecycleStateChanged(QQuickWebEngineView::LifecycleState) --> void"
     << "QQuickWebEngineView.linkHovered(QUrl) --> void"
     << "QQuickWebEngineView.loadHtml(QString) --> void"
     << "QQuickWebEngineView.loadHtml(QString,QUrl) --> void"
@@ -756,11 +755,11 @@ static const QStringList expectedAPI = QStringList()
     << "QQuickWebEngineView.renderProcessPid --> qlonglong"
     << "QQuickWebEngineView.renderProcessPidChanged(qlonglong) --> void"
     << "QQuickWebEngineView.recommendedState --> QQuickWebEngineView::LifecycleState"
-    << "QQuickWebEngineView.recommendedStateChanged(LifecycleState) --> void"
+    << "QQuickWebEngineView.recommendedStateChanged(QQuickWebEngineView::LifecycleState) --> void"
     << "QQuickWebEngineView.registerProtocolHandlerRequested(QWebEngineRegisterProtocolHandlerRequest) --> void"
     << "QQuickWebEngineView.reload() --> void"
     << "QQuickWebEngineView.reloadAndBypassCache() --> void"
-    << "QQuickWebEngineView.renderProcessTerminated(RenderProcessTerminationStatus,int) --> void"
+    << "QQuickWebEngineView.renderProcessTerminated(QQuickWebEngineView::RenderProcessTerminationStatus,int) --> void"
     << "QQuickWebEngineView.replaceMisspelledWord(QString) --> void"
     << "QQuickWebEngineView.runJavaScript(QString) --> void"
     << "QQuickWebEngineView.runJavaScript(QString,QJSValue) --> void"
diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST
index 36c7376939f..ef580a636cb 100644
--- a/tests/auto/quick/qmltests/BLACKLIST
+++ b/tests/auto/quick/qmltests/BLACKLIST
@@ -4,14 +4,42 @@ macos
 [WebEngineViewContextMenu::test_contextMenuLinkAndSelectedText]
 macos
 
+[WebEngineFavicon::test_bestFavicon]
+macos
+
+[WebEngineFavicon::test_dynamicFavicon]
+macos
+
+[WebEngineFavicon::test_faviconLoad]
+macos
+
+[WebEngineFavicon::test_faviconLoadAfterHistoryNavigation]
+macos
+
+[WebEngineFavicon::test_faviconLoadEncodedUrl]
+macos
+
+[WebEngineFavicon::test_faviconLoadPushState]
+macos
+
+[WebEngineFavicon::test_multiIcon]
+macos
+
+[WebEngineFavicon::test_touchIcon]
+macos
+
+[WebEngineFavicon::test_touchIconWithSameURL]
+macos
+
+[WebEngineFaviconDatabase::test_iconDatabase]
+macos
+
+[WebEngineFaviconDatabase::test_iconDatabaseMultiView]
+macos
+
 [CertificateError::test_fatalError]
 *
 
 [CertificateError::test_error]
 *
 
-[WebViewFindText::test_findTextInterruptedByLoad]
-b2qt arm 64bit
-
-[WebEngineViewLoadUrl::test_loadStartedAfterInPageNavigation]
-b2qt
diff --git a/tests/auto/quick/qmltests/CMakeLists.txt b/tests/auto/quick/qmltests/CMakeLists.txt
index acd783bd598..daae6d60dcd 100644
--- a/tests/auto/quick/qmltests/CMakeLists.txt
+++ b/tests/auto/quick/qmltests/CMakeLists.txt
@@ -1,4 +1,4 @@
-# Copyright (C) 2022 The Qt Company Ltd.
+# Copyright (C) 2023 The Qt Company Ltd.
 # SPDX-License-Identifier: BSD-3-Clause
 
 include(../../httpserver/httpserver.cmake)
@@ -25,6 +25,7 @@ set(testList
     tst_datalist.qml
     tst_desktopBehaviorLoadHtml.qml
     tst_download.qml
+    tst_dragHandlerUnderView.qml
     tst_favicon.qml
     tst_faviconDatabase.qml
     tst_filePicker.qml
@@ -32,7 +33,6 @@ set(testList
     tst_findText.qml
     tst_focusOnNavigation.qml
     tst_fullScreenRequest.qml
-    tst_geopermission.qml
     tst_getUserMedia.qml
     tst_inputMethod.qml
     tst_inputTextDirection.qml
@@ -71,6 +71,10 @@ if(QT_FEATURE_ssl)
     list(APPEND testList tst_certificateError.qml)
 endif()
 
+if (NOT APPLE)
+   list(APPEND testList tst_geopermission.qml)
+endif()
+
 set(content "")
 foreach(test ${testList})
    set(contents "${contents}${CMAKE_CURRENT_LIST_DIR}/data/${test}\n")
diff --git a/tests/auto/quick/qmltests/data/test4.html b/tests/auto/quick/qmltests/data/test4.html
index cf570899455..82830668a68 100644
--- a/tests/auto/quick/qmltests/data/test4.html
+++ b/tests/auto/quick/qmltests/data/test4.html
@@ -9,7 +9,6 @@
                  font-size: 50px;
             }
         </style>
-        <meta name="viewport" content="initial-scale=2.0"/>
     </head>
     <body>
         <button onclick="scrollWin()" id="scroll">Click me to scroll!</button><br><br>
diff --git a/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml b/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml
new file mode 100644
index 00000000000..c22bd44c285
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_dragHandlerUnderView.qml
@@ -0,0 +1,67 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtTest
+import QtWebEngine
+
+Item {
+    id: parentItem
+    width: 400
+    height: 300
+
+    Rectangle {
+        id: draggableDownUnder
+        color: "wheat"
+        width: 350
+        height: 250
+
+        DragHandler { id: dragHandler }
+    }
+
+    TestWebEngineView {
+        id: webEngineView
+        width: 300
+        height: 250
+
+        property var testUrl: Qt.resolvedUrl("test4.html")
+
+        SignalSpy {
+            id: scrollPositionSpy
+            target: webEngineView
+            signalName: "onScrollPositionChanged"
+        }
+
+        SignalSpy {
+            id: dragActiveSpy
+            target: dragHandler
+            signalName: "activeChanged"
+        }
+
+        TestCase {
+            id: testCase
+            name: "KeepMouseGrabDuringScrolling"
+            when: windowShown
+
+            function test_scroll() {
+                webEngineView.url = Qt.resolvedUrl("test4.html");
+                verify(webEngineView.waitForLoadSucceeded());
+
+                mousePress(webEngineView, 295, 20);
+                mouseMove(webEngineView, 295, 200);
+                mouseRelease(webEngineView, 295, 200);
+
+                // WebEngineView scrolled if the scrollbar was visible.
+                // But on macOS, the scrollbar is hidden, so text gets selected.
+                tryVerify(function() {
+                    return (scrollPositionSpy.count === 1 && webEngineView.scrollPosition.y > 100)
+                            || webEngineView.getTextSelection().length > 0;
+                });
+
+                // DragHandler didn't take over and drag
+                compare(dragActiveSpy.count, 0);
+                compare(draggableDownUnder.y, 0);
+            }
+        }
+    }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_filePicker.qml b/tests/auto/quick/qmltests/data/tst_filePicker.qml
index a557369edb3..a7b59b2e9bb 100644
--- a/tests/auto/quick/qmltests/data/tst_filePicker.qml
+++ b/tests/auto/quick/qmltests/data/tst_filePicker.qml
@@ -11,7 +11,6 @@ TestWebEngineView {
     id: webEngineView
     width: 400
     height: 300
-    property var titleChanges: []
 
     function driveLetter() {
         if (Qt.platform.os !== "windows")
@@ -30,8 +29,6 @@ TestWebEngineView {
         signalName: "renderProcessTerminated"
     }
 
-    onTitleChanged: { titleChanges.push(webEngineView.title) }
-
     TestCase {
         id: testCase
         name: "WebEngineViewSingleFileUpload"
@@ -44,7 +41,6 @@ TestWebEngineView {
             FilePickerParams.nameFilters = []
             titleSpy.clear()
             terminationSpy.clear()
-            titleChanges = []
         }
 
         function cleanup() {
@@ -87,10 +83,10 @@ TestWebEngineView {
 
             keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
             tryCompare(FilePickerParams, "filePickerOpened", true);
+            tryCompare(webEngineView, "title", row.expected);
             webEngineView.url = Qt.resolvedUrl("about:blank");
             verify(webEngineView.waitForLoadSucceeded());
             tryCompare(webEngineView, "title", "about:blank");
-            compare(titleChanges[titleChanges.length-2], row.expected);
 
 
             // Custom dialog
@@ -98,7 +94,7 @@ TestWebEngineView {
 
             function acceptedFileHandler(request) {
                 request.accepted = true;
-                request.dialogAccept(row.input);
+                request.dialogAccept([row.input]);
                 finished = true;
             }
 
@@ -108,10 +104,10 @@ TestWebEngineView {
 
             keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
             tryVerify(function() { return finished; });
+            tryCompare(webEngineView, "title", row.expected);
             webEngineView.url = Qt.resolvedUrl("about:blank");
             verify(webEngineView.waitForLoadSucceeded());
             tryCompare(webEngineView, "title", "about:blank");
-            compare(titleChanges[titleChanges.length-2], row.expected);
             webEngineView.fileDialogRequested.disconnect(acceptedFileHandler);
         }
 
@@ -242,10 +238,10 @@ TestWebEngineView {
 
             keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
             tryCompare(FilePickerParams, "filePickerOpened", true);
+            tryCompare(webEngineView, "title", row.expected);
             webEngineView.url = Qt.resolvedUrl("about:blank");
             verify(webEngineView.waitForLoadSucceeded());
             tryCompare(webEngineView, "title", "about:blank");
-            compare(titleChanges[titleChanges.length-2], row.expected);
 
 
             // Custom dialog
@@ -253,7 +249,7 @@ TestWebEngineView {
 
             function acceptedFileHandler(request) {
                 request.accepted = true;
-                request.dialogAccept(row.input);
+                request.dialogAccept([row.input]);
                 finished = true;
             }
 
@@ -263,10 +259,10 @@ TestWebEngineView {
 
             keyClick(Qt.Key_Enter); // Focus is on the button. Open FileDialog.
             tryVerify(function() { return finished; });
+            tryCompare(webEngineView, "title", row.expected);
             webEngineView.url = Qt.resolvedUrl("about:blank");
             verify(webEngineView.waitForLoadSucceeded());
             tryCompare(webEngineView, "title", "about:blank");
-            compare(titleChanges[titleChanges.length-2], row.expected);
             webEngineView.fileDialogRequested.disconnect(acceptedFileHandler);
         }
 
diff --git a/tests/auto/quick/qmltests/data/tst_findText.qml b/tests/auto/quick/qmltests/data/tst_findText.qml
index 392ce5dcafa..597cff73e97 100644
--- a/tests/auto/quick/qmltests/data/tst_findText.qml
+++ b/tests/auto/quick/qmltests/data/tst_findText.qml
@@ -206,8 +206,7 @@ TestWebEngineView {
 
             var listItemText = '';
             for (var i = 0; i < 100000; ++i)
-                listItemText += "bla ";
-            listItemText = listItemText.trim();
+                listItemText += "bla";
 
             webEngineView.loadHtml(
                         "<html><body>" +
diff --git a/tests/auto/quick/qmltests/data/tst_save.qml b/tests/auto/quick/qmltests/data/tst_save.qml
index 9757f8fac6d..3289dbd8b90 100644
--- a/tests/auto/quick/qmltests/data/tst_save.qml
+++ b/tests/auto/quick/qmltests/data/tst_save.qml
@@ -14,8 +14,10 @@ TestWebEngineView {
     property int receivedBytes: 0
     property string downloadDir: ""
     property string downloadFileName: ""
+    property bool isSavePageDownload: false
     property var downloadState: []
     property int savePageFormat: WebEngineDownloadRequest.MimeHtmlSaveFormat;
+    property bool autoCancel: false
 
     TempDir {
         id: tempDir
@@ -42,6 +44,10 @@ TestWebEngineView {
             savePageFormat = download.savePageFormat
             downloadDir = download.downloadDirectory;
             downloadFileName = download.downloadFileName
+            isSavePageDownload = download.isSavePageDownload
+
+            if (autoCancel)
+                download.cancel()
         }
         onDownloadFinished: function(download) {
             receivedBytes = download.receivedBytes
@@ -73,8 +79,10 @@ TestWebEngineView {
             receivedBytes = 0
             downloadDir = ""
             downloadFileName = ""
+            isSavePageDownload = false
             downloadState = []
             downloadUrl = ""
+            autoCancel = false
         }
 
         function test_savePage_data() {
@@ -104,6 +112,7 @@ TestWebEngineView {
             compare(savePageFormat, saveFormat)
             compare(downloadDir, fileDir)
             compare(downloadFileName, fileName)
+            compare(isSavePageDownload, true)
             compare(downloadState[0], WebEngineDownloadRequest.DownloadInProgress)
             downloadFinishedSpy.wait()
             compare(downloadFinishedSpy.count, 1)
@@ -119,5 +128,58 @@ TestWebEngineView {
             verify(webEngineView.waitForLoadSucceeded())
             verify(verifyData())
         }
+
+        function test_saveImage_data() {
+            return [
+                   { tag: "Auto accept", autoCancel: false },
+                   { tag: "Cancel", autoCancel: true },
+            ];
+        }
+
+        function test_saveImage(row) {
+            autoCancel = row.autoCancel
+
+            var fileDir = tempDir.path()
+            var fileName = "favicon.png"
+            var filePath = fileDir + "/"+ fileName
+
+            // Load an image
+            webEngineView.url = Qt.resolvedUrl("icons/favicon.png")
+            verify(webEngineView.waitForLoadSucceeded())
+
+            webEngineView.save(filePath)
+            downLoadRequestedSpy.wait()
+            compare(downLoadRequestedSpy.count, 1)
+            compare(downloadUrl, webEngineView.url)
+            compare(downloadDir, fileDir)
+            compare(downloadFileName, fileName)
+            compare(isSavePageDownload, true)
+            compare(downloadState[0], WebEngineDownloadRequest.DownloadInProgress)
+            downloadFinishedSpy.wait()
+            compare(downloadFinishedSpy.count, 1)
+            if (autoCancel) {
+                compare(receivedBytes, 0)
+                compare(downloadState[1], WebEngineDownloadRequest.DownloadCancelled)
+            } else {
+                compare(totalBytes, receivedBytes)
+                compare(downloadState[1], WebEngineDownloadRequest.DownloadCompleted)
+            }
+        }
+
+        function test_saveWebAction() {
+            // Load an image
+            webEngineView.url = Qt.resolvedUrl("icons/favicon.png")
+            verify(webEngineView.waitForLoadSucceeded())
+
+            // Saving without specifying path shouldn't be auto accepted
+            webEngineView.triggerWebAction(WebEngineView.SavePage)
+            downLoadRequestedSpy.wait()
+            compare(downLoadRequestedSpy.count, 1)
+            compare(downloadUrl, webEngineView.url)
+            compare(isSavePageDownload, true)
+            // The initial download request starts from DownloadRequested state,
+            // which means it wasn't automatically accepted.
+            compare(downloadState[0], WebEngineDownloadRequest.DownloadRequested)
+        }
     }
 }
diff --git a/tests/auto/quick/qmltests/data/tst_settings.qml b/tests/auto/quick/qmltests/data/tst_settings.qml
index 2f71407cf1b..6b351a29315 100644
--- a/tests/auto/quick/qmltests/data/tst_settings.qml
+++ b/tests/auto/quick/qmltests/data/tst_settings.qml
@@ -87,12 +87,12 @@ TestWebEngineView {
         }
 
         function test_disableReadingFromCanvas(data) {
-            webEngineView.settings.disableReadingFromCanvas = data.disableReadingFromCanvas;
+            webEngineView.settings.readingFromCanvasEnabled = !data.disableReadingFromCanvas;
             webEngineView.loadHtml("<html><body>" +
                                    "<canvas id='myCanvas' width='200' height='40' style='border:1px solid #000000;'></canvas>" +
                                    "</body></html>");
             verify(webEngineView.waitForLoadSucceeded());
-            verify(webEngineView.settings.disableReadingFromCanvas === data.disableReadingFromCanvas )
+            verify(webEngineView.settings.readingFromCanvasEnabled === !data.disableReadingFromCanvas )
 
             var jsCode = "(function(){" +
                        "   var canvas = document.getElementById(\"myCanvas\");" +
diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
index f82c5826470..1e79466a3ce 100644
--- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
+++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp
@@ -3,6 +3,7 @@
 
 #include "testwindow.h"
 #include "quickutil.h"
+#include "util.h"
 
 #include <QScopedPointer>
 #include <QtCore/qelapsedtimer.h>
@@ -692,8 +693,8 @@ void tst_QQuickWebEngineView::inputContextQueryInput()
         QGuiApplication::sendEvent(qApp->focusObject(), &event);
     }
     QTRY_COMPARE(testContext.infos.size(), 1);
-    QCOMPARE(testContext.infos[0].cursorPosition, 3);
-    QCOMPARE(testContext.infos[0].anchorPosition, 3);
+    QCOMPARE(testContext.infos[0].cursorPosition, 0);
+    QCOMPARE(testContext.infos[0].anchorPosition, 0);
     QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
     QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
     QCOMPARE(evaluateJavaScriptSync(view, "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!"));
@@ -1295,7 +1296,10 @@ void tst_QQuickWebEngineView::savePage()
     const QString filePath = tempDir.path() + "/saved_page.html";
 
     QQuickWebEngineView *view = webEngineView();
-    connect(view->profile(), &QQuickWebEngineProfile::downloadRequested,
+    int acceptedCount = 0;
+    int finishedCount = 0;
+    ScopedConnection sc1 = connect(
+            view->profile(), &QQuickWebEngineProfile::downloadRequested,
             [&](QQuickWebEngineDownloadRequest *downloadRequest) {
                 QCOMPARE(downloadRequest->state(),
                          QQuickWebEngineDownloadRequest::DownloadInProgress);
@@ -1320,8 +1324,9 @@ void tst_QQuickWebEngineView::savePage()
                                              .filePath(downloadRequest->downloadFileName()),
                                      filePath);
                             QCOMPARE(downloadRequest->url(), view->url());
-                            QTestEventLoop::instance().exitLoop();
+                            finishedCount++;
                         });
+                acceptedCount++;
             });
 
     const QString originalData = QStringLiteral("Basic page");
@@ -1333,7 +1338,8 @@ void tst_QQuickWebEngineView::savePage()
 
     // Save the loaded page as HTML.
     view->save(filePath, savePageFormat);
-    QTestEventLoop::instance().enterLoop(10);
+    QTRY_COMPARE(acceptedCount, 1);
+    QTRY_COMPARE(finishedCount, 1);
     QFile file(filePath);
     QVERIFY(file.exists());
 
diff --git a/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp b/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp
index 71c3a1cf2ff..3644ac48187 100644
--- a/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp
+++ b/tests/auto/quick/qquickwebengineviewgraphics/tst_qquickwebengineviewgraphics.cpp
@@ -124,6 +124,7 @@ void tst_QQuickWebEngineViewGraphics::reparentToOtherWindow()
 
     m_view->rootObject()->setParentItem(window.contentItem());
     window.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&window));
     verifyGreenSquare(&window);
 }
 
diff --git a/tests/auto/widgets/accessibility/CMakeLists.txt b/tests/auto/widgets/accessibility/CMakeLists.txt
index 4c0bb17eeb9..f6a08c9d38d 100644
--- a/tests/auto/widgets/accessibility/CMakeLists.txt
+++ b/tests/auto/widgets/accessibility/CMakeLists.txt
@@ -8,5 +8,6 @@ qt_internal_add_test(tst_webengine_accessibility
         tst_accessibility.cpp
     LIBRARIES
         Qt::WebEngineWidgets
+        Qt::WebEngineCorePrivate
         Test::Util
 )
diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp
index 68566c0827c..1579b61e2fe 100644
--- a/tests/auto/widgets/accessibility/tst_accessibility.cpp
+++ b/tests/auto/widgets/accessibility/tst_accessibility.cpp
@@ -17,6 +17,7 @@
     Boston, MA 02110-1301, USA.
 */
 
+#include <QtWebEngineCore/private/qtwebenginecore-config_p.h>
 #include <qtest.h>
 #include <widgetutil.h>
 
@@ -50,6 +51,7 @@ private Q_SLOTS:
     void roles();
     void objectName();
     void crossTreeParent();
+    void tableCellInterface();
 };
 
 // This will be called before the first test function is executed.
@@ -605,9 +607,65 @@ void tst_Accessibility::crossTreeParent()
     QCOMPARE(p->object()->objectName(), QStringLiteral("my_id"));
 }
 
+void tst_Accessibility::tableCellInterface()
+{
+    QWebEngineView webView;
+    webView.resize(400, 400);
+    webView.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&webView));
+
+    QSignalSpy spyFinished(&webView, &QWebEngineView::loadFinished);
+    webView.setHtml(QLatin1String(
+            "<html><body>"
+            "  <ul>"
+            "    <li><a href='#link1' id='link1'>Link in ListItem</a></li>"
+            "  </ul>"
+            ""
+            "  <div role='rowgroup'>"
+            "    <div role='row'>"
+            "      <span role='cell'><a href='#link2' id='link2'>Link in Cell</a></span>"
+            "    </div>"
+            "  </div>"
+            "</body></html>"));
+    QTRY_COMPARE(spyFinished.size(), 1);
+
+    QAccessibleInterface *view = QAccessible::queryAccessibleInterface(&webView);
+    QAccessibleInterface *document = view->child(0);
+    QTRY_COMPARE(document->childCount(), 2);
+
+    // ListItem without Table parent.
+    {
+        QAccessibleInterface *list = document->child(0);
+        QAccessibleInterface *listItem = list->child(0);
+        QVERIFY(!listItem->tableCellInterface());
+
+        // Should not crash.
+        QPoint linkCenter = elementCenter(webView.page(), QLatin1String("link1"));
+        QTest::mouseClick(webView.focusProxy(), Qt::LeftButton, {}, linkCenter);
+        QTRY_COMPARE(webView.url().fragment(), QLatin1String("link1"));
+    }
+
+    // Cell without Table parent.
+    {
+        QAccessibleInterface *rowgroup = document->child(1);
+        QAccessibleInterface *row = rowgroup->child(0);
+        QAccessibleInterface *cell = row->child(0);
+        QVERIFY(!cell->tableCellInterface());
+
+        // Should not crash.
+        QPoint linkCenter = elementCenter(webView.page(), QLatin1String("link2"));
+        QTest::mouseClick(webView.focusProxy(), Qt::LeftButton, {}, linkCenter);
+        QTRY_COMPARE(webView.url().fragment(), QLatin1String("link2"));
+    }
+}
+
 static QByteArrayList params = QByteArrayList()
     << "--force-renderer-accessibility"
-    << "--enable-features=AccessibilityExposeARIAAnnotations";
+    << "--enable-features=AccessibilityExposeARIAAnnotations"
+#if QT_CONFIG(webengine_embedded_build)
+    << "--disable-features=TimedHTMLParserBudget"
+#endif
+    ;
 
 W_QTEST_MAIN(tst_Accessibility, params)
 #include "tst_accessibility.moc"
diff --git a/tests/auto/widgets/printing/tst_printing.cpp b/tests/auto/widgets/printing/tst_printing.cpp
index 1f9b5059c58..605fb57b5c7 100644
--- a/tests/auto/widgets/printing/tst_printing.cpp
+++ b/tests/auto/widgets/printing/tst_printing.cpp
@@ -3,6 +3,7 @@
 
 #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h>
 #include <QtWebEngineCore/qtwebenginecore-config.h>
+#include <QWebEngineSettings>
 #include <QWebEngineView>
 #include <QTemporaryDir>
 #include <QTest>
@@ -22,6 +23,7 @@ private slots:
     void printRequest();
 #if QT_CONFIG(webengine_system_poppler)
     void printToPdfPoppler();
+    void printFromPdfViewer();
 #endif
     void interruptPrinting();
 };
@@ -116,6 +118,50 @@ void tst_Printing::printToPdfPoppler()
     QVERIFY2(pdfPage->search(ustring::from_latin1("Hello Paper World"), rect, page::search_from_top,
                      case_sensitive ), "Could not find text");
 }
+
+void tst_Printing::printFromPdfViewer()
+{
+    using namespace poppler;
+
+    QWebEngineView view;
+    view.page()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true);
+    view.page()->settings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, true);
+
+    // Load a basic HTML
+    QSignalSpy spy(&view, &QWebEngineView::loadFinished);
+    view.load(QUrl("qrc:///resources/basic_printing_page.html"));
+    QTRY_COMPARE(spy.size(), 1);
+
+    // Create a PDF
+    QTemporaryDir tempDir(QDir::tempPath() + "/tst_printing-XXXXXX");
+    QVERIFY(tempDir.isValid());
+    QString path = tempDir.path() + "/basic_page.pdf";
+    QSignalSpy savePdfSpy(view.page(), &QWebEnginePage::pdfPrintingFinished);
+    view.page()->printToPdf(path);
+    QTRY_COMPARE(savePdfSpy.size(), 1);
+
+    // Open the new file with the PDF viewer plugin
+    view.load(QUrl("file://" + path));
+    QTRY_COMPARE(spy.size(), 2);
+
+    // Print from the plugin
+    // loadFinished signal is not reliable when loading a PDF file, because it has multiple phases.
+    // Workaround: Try to print it a couple of times until the result matches the expected.
+    CallbackSpy<QByteArray> resultSpy;
+    bool ok = QTest::qWaitFor([&]() -> bool {
+        view.printToPdf(resultSpy.ref());
+        QByteArray data = resultSpy.waitForResult();
+
+        // Check if the result contains text from the original basic HTML
+        // This catches all the typical issues: empty result or printing the WebUI without PDF content.
+        QScopedPointer<document> pdf(document::load_from_raw_data(data.constData(), data.length()));
+        QScopedPointer<page> pdfPage(pdf->create_page(0));
+        rectf rect;
+        return pdfPage->search(ustring::from_latin1("Hello Paper World"), rect, page::search_from_top,
+                            case_sensitive);
+    }, 10000);
+    QVERIFY(ok);
+}
 #endif
 
 void tst_Printing::interruptPrinting()
diff --git a/tests/auto/widgets/proxy/tst_proxy.cpp b/tests/auto/widgets/proxy/tst_proxy.cpp
index f378ae22f5c..3dc72618c9b 100644
--- a/tests/auto/widgets/proxy/tst_proxy.cpp
+++ b/tests/auto/widgets/proxy/tst_proxy.cpp
@@ -8,7 +8,7 @@
 #include <QWebEnginePage>
 #include <QWebEngineView>
 #include <QWebEngineUrlRequestInterceptor>
-
+#include <QWebEngineLoadingInfo>
 
 struct Interceptor : public QWebEngineUrlRequestInterceptor
 {
@@ -28,6 +28,7 @@ class tst_Proxy : public QObject {
 private slots:
     void proxyAuthentication();
     void forwardCookie();
+    void invalidHostName();
 };
 
 
@@ -72,6 +73,19 @@ void tst_Proxy::forwardCookie()
     QTRY_VERIFY2(cookieSpy.size() > 0, "Could not get cookie");
 }
 
+// Crash test ( https://bugreports.qt.io/browse/QTBUG-113992 )
+void tst_Proxy::invalidHostName()
+{
+    QNetworkProxy proxy;
+    proxy.setType(QNetworkProxy::HttpProxy);
+    proxy.setHostName("999.0.0.0");
+    QNetworkProxy::setApplicationProxy(proxy);
+    QWebEnginePage page;
+    QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+    page.load(QUrl("http://www.qt.io"));
+    QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000);
+}
+
 #include "tst_proxy.moc"
 QTEST_MAIN(tst_Proxy)
 
diff --git a/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp b/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp
index 1389682da1b..9453ae9b845 100644
--- a/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp
+++ b/tests/auto/widgets/qtbug_110287/tst_qtbug_110287.cpp
@@ -22,7 +22,7 @@ void tst_qtbug_110287::getAddrInfo()
     QNetworkAccessManager nam;
     QSignalSpy namSpy(&nam, &QNetworkAccessManager::finished);
 
-    QString address("http://www.qt.io");
+    QString address("http://www.example.com");
     QScopedPointer<QNetworkReply> reply(nam.get(QNetworkRequest(address)));
 
     if (!namSpy.wait(25000) || reply->error() != QNetworkReply::NoError)
diff --git a/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp b/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp
index 6ddc031d5be..ad66e972c61 100644
--- a/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp
+++ b/tests/auto/widgets/qwebenginehistory/tst_qwebenginehistory.cpp
@@ -487,9 +487,9 @@ void tst_QWebEngineHistory::clear()
 
     QWebEnginePage page2(this);
     QWebEngineHistory* hist2 = page2.history();
-    QCOMPARE(hist2->count(), 1);
+    QCOMPARE(hist2->count(), 0);
     hist2->clear();
-    QCOMPARE(hist2->count(), 1); // Do not change anything.
+    QCOMPARE(hist2->count(), 0); // Do not change anything.
 }
 
 void tst_QWebEngineHistory::historyItemFromDeletedPage()
diff --git a/tests/auto/widgets/qwebenginepage/resources/reload.html b/tests/auto/widgets/qwebenginepage/resources/reload.html
index d9c33dfcd57..6fc570caeb2 100644
--- a/tests/auto/widgets/qwebenginepage/resources/reload.html
+++ b/tests/auto/widgets/qwebenginepage/resources/reload.html
@@ -1,6 +1,6 @@
 <html>
 <head>
-<meta http-equiv="refresh" content="2">
+<meta http-equiv="refresh" content="2;url=">
 </head>
 <body>
 This is test content
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 43d29d12a4c..538195854bb 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2016 The Qt Company Ltd.
+    Copyright (C) 2023 The Qt Company Ltd.
     Copyright (C) 2009 Girish Ramakrishnan <girish@forwardbias.in>
     Copyright (C) 2010 Holger Hans Peter Freyther
 
@@ -65,6 +65,7 @@
 #include <qwebenginescript.h>
 #include <qwebenginescriptcollection.h>
 #include <qwebenginesettings.h>
+#include <qwebengineurlrequestinterceptor.h>
 #include <qwebengineurlrequestjob.h>
 #include <qwebengineurlscheme.h>
 #include <qwebengineurlschemehandler.h>
@@ -116,8 +117,10 @@ private Q_SLOTS:
     void acceptNavigationRequest();
     void acceptNavigationRequestNavigationType();
     void acceptNavigationRequestRelativeToNothing();
+#ifndef Q_OS_MACOS
     void geolocationRequestJS_data();
     void geolocationRequestJS();
+#endif
     void loadFinished();
     void actionStates();
     void pasteImage();
@@ -269,6 +272,7 @@ private Q_SLOTS:
     void childFrameInput();
     void openLinkInNewPageWithWebWindowType_data();
     void openLinkInNewPageWithWebWindowType();
+    void keepInterceptorAfterNewWindowRequested();
 
 private:
     static bool isFalseJavaScriptResult(QWebEnginePage *page, const QString &javaScript);
@@ -277,6 +281,9 @@ private Q_SLOTS:
 
     QWebEngineView* m_view;
     QWebEnginePage* m_page;
+    QScopedPointer<QPointingDevice> s_touchDevice =
+            QScopedPointer<QPointingDevice>(QTest::createTouchDevice());
+
     QString tmpDirPath() const
     {
         static QString tmpd = QDir::tempPath() + "/tst_qwebenginepage-"
@@ -284,13 +291,13 @@ private Q_SLOTS:
         return tmpd;
     }
 
-    QScopedPointer<QPointingDevice> s_touchDevice;
-    void makeClick(QWindow *window, bool withTouch = false, const QPoint &p = QPoint()) {
+    void makeClick(const QPointer<QWindow> window, bool withTouch = false,
+                   const QPoint &p = QPoint())
+    {
+        QVERIFY2(window, "window is gone");
         if (!withTouch) {
             QTest::mouseClick(window, Qt::LeftButton, Qt::KeyboardModifiers(), p);
         } else {
-            if (!s_touchDevice)
-                s_touchDevice.reset(QTest::createTouchDevice());
             QTest::touchEvent(window, s_touchDevice.get()).press(1, p);
             QTest::touchEvent(window, s_touchDevice.get()).release(1, p);
         }
@@ -451,6 +458,7 @@ public Q_SLOTS:
     bool m_allowGeolocation;
 };
 
+#ifndef Q_OS_MACOS
 void tst_QWebEnginePage::geolocationRequestJS_data()
 {
     QTest::addColumn<bool>("allowed");
@@ -490,6 +498,7 @@ void tst_QWebEnginePage::geolocationRequestJS()
         QEXPECT_FAIL("", "No location service available.", Continue);
     QCOMPARE(result, errorCode);
 }
+#endif
 
 void tst_QWebEnginePage::loadFinished()
 {
@@ -1357,8 +1366,11 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterMove_data()
 
 void tst_QWebEnginePage::comboBoxPopupPositionAfterMove()
 {
+#if defined(Q_OS_MACOS) && (defined(__arm64__) || defined(__aarch64__))
+    QSKIP("This test crashes for Apple M1");
+#endif
     QWebEngineView view;
-    Q_ASSERT(QGuiApplication::primaryScreen());
+    QTRY_VERIFY(QGuiApplication::primaryScreen());
     view.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
     view.resize(640, 480);
     view.show();
@@ -1370,7 +1382,7 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterMove()
     QTRY_COMPARE(spyLoadFinished.size(), 1);
     const auto oldTlws = QGuiApplication::topLevelWindows();
     QFETCH(bool, withTouch);
-    QWindow *window = view.windowHandle();
+    QPointer<QWindow> window = view.windowHandle();
     auto pos = elementCenter(view.page(), "foo");
     makeClick(window, withTouch, pos);
     QWindow *popup = nullptr;
@@ -1420,6 +1432,9 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterChildMove_data()
 
 void tst_QWebEnginePage::comboBoxPopupPositionAfterChildMove()
 {
+#if defined(Q_OS_MACOS) && (defined(__arm64__) || defined(__aarch64__))
+    QSKIP("This test crashes for Apple M1");
+#endif
     QWidget mainWidget;
     mainWidget.setLayout(new QHBoxLayout);
 
@@ -1444,7 +1459,7 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterChildMove()
     const auto oldTlws = QGuiApplication::topLevelWindows();
 
     QFETCH(bool, withTouch);
-    QWindow *window = view.window()->windowHandle();
+    QPointer<QWindow> window = view.window()->windowHandle();
     makeClick(window, withTouch, view.mapTo(view.window(), elementCenter(view.page(), "foo")));
 
     QWindow *popup = nullptr;
@@ -2073,14 +2088,14 @@ void tst_QWebEnginePage::symmetricUrl()
 
     QVERIFY(view.url().isEmpty());
 
-    QCOMPARE(view.history()->count(), 1);
+    QCOMPARE(view.history()->count(), 0);
 
     QUrl dataUrl("data:text/html,<h1>Test");
 
     view.setUrl(dataUrl);
     view.show();
     QCOMPARE(view.url(), dataUrl);
-    QCOMPARE(view.history()->count(), 1);
+    QCOMPARE(view.history()->count(), 0);
 
     // loading is _not_ immediate, so the text isn't set just yet.
     QVERIFY(toPlainTextSync(view.page()).isEmpty());
@@ -2393,7 +2408,7 @@ void tst_QWebEnginePage::setHtmlWithBaseURL()
     QCOMPARE(evaluateJavaScriptSync(&page, "document.images[0].height").toInt(), 128);
 
     // no history item has to be added.
-    QCOMPARE(m_view->page()->history()->count(), 1);
+    QCOMPARE(m_view->page()->history()->count(), 0);
 }
 
 class MyPage : public QWebEnginePage
@@ -2824,7 +2839,7 @@ void tst_QWebEnginePage::setUrlHistory()
     int expectedLoadFinishedCount = 0;
     QSignalSpy spy(m_page, SIGNAL(loadFinished(bool)));
 
-    QCOMPARE(m_page->history()->count(), 1);
+    QCOMPARE(m_page->history()->count(), 0);
 
     m_page->setUrl(QUrl());
     expectedLoadFinishedCount++;
@@ -2898,7 +2913,7 @@ void tst_QWebEnginePage::setUrlUsingStateObject()
     QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool)));
     int expectedUrlChangeCount = 0;
 
-    QCOMPARE(m_page->history()->count(), 1);
+    QCOMPARE(m_page->history()->count(), 0);
 
     url = QUrl("qrc:/resources/test1.html");
     m_page->setUrl(url);
@@ -3077,7 +3092,7 @@ void tst_QWebEnginePage::loadInSignalHandlers()
     URLSetter setter(m_page, signal, type, urlForSetter);
     QSignalSpy spy(&setter, &URLSetter::finished);
     m_page->load(url);
-    QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 1, 20000);
+    QTRY_VERIFY_WITH_TIMEOUT(spy.size() >= 1, 20000);
     QCOMPARE(m_page->url(), urlForSetter);
 }
 
@@ -3708,7 +3723,7 @@ void tst_QWebEnginePage::openLinkInNewPage()
             QCOMPARE(page1.history()->count(), 1);
         else
             QCOMPARE(page1.history()->count(), 2);
-        QCOMPARE(page2.history()->count(), 1);
+        QCOMPARE(page2.history()->count(), 0);
         break;
     case Effect::LoadInOther:
         QTRY_COMPARE(page2.spy.size(), 1);
@@ -5315,6 +5330,53 @@ void tst_QWebEnginePage::openLinkInNewPageWithWebWindowType()
     QCOMPARE(page.windowType, webWindowType);
 }
 
+class DoNothingInterceptor : public QWebEngineUrlRequestInterceptor
+{
+public:
+    DoNothingInterceptor() { }
+
+    void interceptRequest(QWebEngineUrlRequestInfo &) override
+    {
+        ran = true;
+    }
+    bool ran = false;
+};
+
+void tst_QWebEnginePage::keepInterceptorAfterNewWindowRequested()
+{
+    DoNothingInterceptor interceptor;
+    QWebEnginePage page;
+    page.setUrlRequestInterceptor(&interceptor);
+    connect(&page, &QWebEnginePage::newWindowRequested, [&](QWebEngineNewWindowRequest &request) {
+        request.openIn(&page);
+    });
+    QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+
+    QWebEngineView view;
+    view.resize(500, 500);
+    view.setPage(&page);
+    view.show();
+    QVERIFY(QTest::qWaitForWindowExposed(&view));
+
+    page.setHtml("<html><body>"
+                  "<a id='link' href='hello' target='_blank'>link</a>"
+                  "</body></html>");
+    QTRY_COMPARE(loadFinishedSpy.size(), 1);
+    QVERIFY(loadFinishedSpy.takeFirst().value(0).toBool());
+    QVERIFY(interceptor.ran);
+    interceptor.ran = false;
+
+    QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, elementCenter(&page, "link"));
+    QTRY_COMPARE(loadFinishedSpy.size(), 1);
+    QVERIFY(loadFinishedSpy.takeFirst().value(0).toBool());
+    QVERIFY(!interceptor.ran);
+
+    page.setHtml("<html><body></body></html>");
+    QTRY_COMPARE(loadFinishedSpy.size(), 1);
+    QVERIFY(loadFinishedSpy.takeFirst().value(0).toBool());
+    QVERIFY(interceptor.ran);
+}
+
 static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")};
 W_QTEST_MAIN(tst_QWebEnginePage, params)
 
diff --git a/tests/auto/widgets/qwebenginescript/resources/test_window_open.html b/tests/auto/widgets/qwebenginescript/resources/test_window_open.html
index 3f72d176de1..3ceafc49dc3 100644
--- a/tests/auto/widgets/qwebenginescript/resources/test_window_open.html
+++ b/tests/auto/widgets/qwebenginescript/resources/test_window_open.html
@@ -3,7 +3,7 @@
     <head>
         <title>window.open</title>
         <script>
-            window.open("qrc:/resource/test_iframe_main.html", "iframe_main");
+            window.open("qrc:/resources/test_iframe_main.html", "iframe_main");
         </script>
     </head>
     <body></body>
diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST
index 356f9c9b0c2..26f2da4bbe8 100644
--- a/tests/auto/widgets/qwebengineview/BLACKLIST
+++ b/tests/auto/widgets/qwebengineview/BLACKLIST
@@ -8,6 +8,5 @@ windows
 windows
 
 [horizontalScrollbarTest]
-b2qt # different scrollbar
 macos
 rhel # flaky
diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
index 15e22613943..4331a5e3684 100644
--- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
+++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp
@@ -183,6 +183,7 @@ private Q_SLOTS:
     void navigateOnDrop_data();
     void navigateOnDrop();
     void datalist();
+    void longKeyEventText();
 };
 
 // This will be called before the first test function is executed.
@@ -683,6 +684,12 @@ void tst_QWebEngineView::unhandledKeyEventPropagation()
 
 void tst_QWebEngineView::horizontalScrollbarTest()
 {
+#if QT_CONFIG(webengine_embedded_build)
+    // Embedded builds enable the OverlayScrollbar and Viewport features (see 'useEmbeddedSwitches' in web_engine_context.cpp).
+    // These features make the scrollbar simpler assuming we are on a device with small (usually touch) display.
+    // These scrollbars behave differently on mouse events.
+    QSKIP("Embedded builds have different scrollbar, skipping test.");
+#endif
     QString html("<html><body>"
                  "<div style='width: 1000px; height: 1000px; background-color: green' />"
                  "</body></html>");
@@ -1353,18 +1360,19 @@ void tst_QWebEngineView::inputMethodsTextFormat_data()
 
 void tst_QWebEngineView::inputMethodsTextFormat()
 {
-    QWebEngineView view;
-    view.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
-    QSignalSpy loadFinishedSpy(&view, SIGNAL(loadFinished(bool)));
+    QWebEnginePage page;
+    QWebEngineView view(&page);
+    page.settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true);
+    QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
 
-    view.setHtml("<html><body>"
+    page.setHtml("<html><body>"
                  " <input type='text' id='input1' style='font-family: serif' value='' maxlength='20'/>"
                  "</body></html>");
     QTRY_COMPARE(loadFinishedSpy.size(), 1);
 
-    evaluateJavaScriptSync(view.page(), "document.getElementById('input1').focus()");
     view.show();
     QVERIFY(QTest::qWaitForWindowExposed(&view));
+    evaluateJavaScriptSync(&page, "document.getElementById('input1').focus()");
 
     QFETCH(QString, string);
     QFETCH(int, start);
@@ -1388,8 +1396,8 @@ void tst_QWebEngineView::inputMethodsTextFormat()
     attrs.append(QInputMethodEvent::Attribute(QInputMethodEvent::TextFormat, start, length, format));
 
     QInputMethodEvent im(string, attrs);
-    QVERIFY(QApplication::sendEvent(view.focusProxy(), &im));
-    QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), string);
+    QApplication::sendEvent(view.focusProxy(), &im);
+    QTRY_COMPARE_WITH_TIMEOUT(evaluateJavaScriptSync(&page, "document.getElementById('input1').value").toString(), string, 20000);
 }
 
 void tst_QWebEngineView::keyboardEvents()
@@ -2054,8 +2062,8 @@ void tst_QWebEngineView::inputContextQueryInput()
         QApplication::sendEvent(view.focusProxy(), &event);
     }
     QTRY_COMPARE(testContext.infos.size(), 1);
-    QCOMPARE(testContext.infos[0].cursorPosition, 3);
-    QCOMPARE(testContext.infos[0].anchorPosition, 3);
+    QCOMPARE(testContext.infos[0].cursorPosition, 0);
+    QCOMPARE(testContext.infos[0].anchorPosition, 0);
     QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!"));
     QCOMPARE(testContext.infos[0].selectedText, QStringLiteral(""));
     QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!"));
@@ -2309,22 +2317,19 @@ void tst_QWebEngineView::textSelectionOutOfInputField()
 
     // Select text by ctrl+a
     QTest::keyClick(view.windowHandle(), Qt::Key_A, Qt::ControlModifier);
-    QVERIFY(selectionChangedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 1);
+    QTRY_COMPARE(selectionChangedSpy.size(), 1);
     QVERIFY(view.hasSelection());
     QCOMPARE(view.page()->selectedText(), QString("This is a text"));
 
     // Deselect text by mouse click
     QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, view.geometry().center());
-    QVERIFY(selectionChangedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 2);
+    QTRY_COMPARE(selectionChangedSpy.size(), 2);
     QVERIFY(!view.hasSelection());
     QVERIFY(view.page()->selectedText().isEmpty());
 
     // Select text by ctrl+a
     QTest::keyClick(view.windowHandle(), Qt::Key_A, Qt::ControlModifier);
-    QVERIFY(selectionChangedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 3);
+    QTRY_COMPARE(selectionChangedSpy.size(), 3);
     QVERIFY(view.hasSelection());
     QCOMPARE(view.page()->selectedText(), QString("This is a text"));
 
@@ -2332,8 +2337,7 @@ void tst_QWebEngineView::textSelectionOutOfInputField()
     view.hide();
     view.page()->setLifecycleState(QWebEnginePage::LifecycleState::Discarded);
     view.show();
-    QVERIFY(loadFinishedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 4);
+    QTRY_COMPARE(selectionChangedSpy.size(), 4);
     QVERIFY(!view.hasSelection());
     QVERIFY(view.page()->selectedText().isEmpty());
 
@@ -2356,31 +2360,27 @@ void tst_QWebEngineView::textSelectionOutOfInputField()
 
     // Select the whole page by ctrl+a
     QTest::keyClick(view.windowHandle(), Qt::Key_A, Qt::ControlModifier);
-    QVERIFY(selectionChangedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 1);
+    QTRY_COMPARE(selectionChangedSpy.size(), 1);
     QVERIFY(view.hasSelection());
     QVERIFY(view.page()->selectedText().startsWith(QString("This is a text")));
 
     // Remove selection by clicking into an input field
     QPoint textInputCenter = elementCenter(view.page(), "input1");
     QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, textInputCenter);
-    QVERIFY(selectionChangedSpy.wait());
+    QTRY_COMPARE(selectionChangedSpy.size(), 2);
     QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1"));
-    QCOMPARE(selectionChangedSpy.size(), 2);
     QVERIFY(!view.hasSelection());
     QVERIFY(view.page()->selectedText().isEmpty());
 
     // Select the content of the input field by ctrl+a
     QTest::keyClick(view.windowHandle(), Qt::Key_A, Qt::ControlModifier);
-    QVERIFY(selectionChangedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 3);
+    QTRY_COMPARE(selectionChangedSpy.size(), 3);
     QVERIFY(view.hasSelection());
     QCOMPARE(view.page()->selectedText(), QString("QtWebEngine"));
 
     // Deselect input field's text by mouse click
     QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, view.geometry().center());
-    QVERIFY(selectionChangedSpy.wait());
-    QCOMPARE(selectionChangedSpy.size(), 4);
+    QTRY_COMPARE(selectionChangedSpy.size(), 4);
     QVERIFY(!view.hasSelection());
     QVERIFY(view.page()->selectedText().isEmpty());
 }
@@ -2659,8 +2659,8 @@ void tst_QWebEngineView::imeComposition()
         QApplication::sendEvent(view.focusProxy(), &event);
     }
     QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString(""));
-    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11);
-    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 11);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0);
+    QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0);
     QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString(""));
     QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QString("QtWebEngine"));
 
@@ -2959,6 +2959,7 @@ void tst_QWebEngineView::imeCompositionQueryEvent()
     }
 
     QInputMethodQueryEvent srrndTextQuery(Qt::ImSurroundingText);
+    QInputMethodQueryEvent absolutePosQuery(Qt::ImAbsolutePosition);
     QInputMethodQueryEvent cursorPosQuery(Qt::ImCursorPosition);
     QInputMethodQueryEvent anchorPosQuery(Qt::ImAnchorPosition);
 
@@ -2970,16 +2971,18 @@ void tst_QWebEngineView::imeCompositionQueryEvent()
         qApp->processEvents();
     }
     QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QString("composition"));
-    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11);
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0);
 
     QApplication::sendEvent(input, &srrndTextQuery);
+    QApplication::sendEvent(input, &absolutePosQuery);
     QApplication::sendEvent(input, &cursorPosQuery);
     QApplication::sendEvent(input, &anchorPosQuery);
     qApp->processEvents();
 
     QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString(""));
-    QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 11);
-    QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11);
+    QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 0);
+    QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 0);
+    QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 0);
 
     // Send commit
     {
@@ -2993,13 +2996,64 @@ void tst_QWebEngineView::imeCompositionQueryEvent()
     QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("composition"));
 
     QApplication::sendEvent(input, &srrndTextQuery);
+    QApplication::sendEvent(input, &absolutePosQuery);
+    QApplication::sendEvent(input, &cursorPosQuery);
+    QApplication::sendEvent(input, &anchorPosQuery);
+    qApp->processEvents();
+
+    QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString("composition"));
+    QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 11);
+    QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 11);
+    QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11);
+
+    // Test another composition to ensure that the cursor position is set correctly.
+    // In this case cursor will be at position 11 during input composition.
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("123", attributes);
+        QApplication::sendEvent(input, &event);
+        qApp->processEvents();
+    }
+    QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value")
+                         .toString(),
+                 QString("composition123"));
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11);
+
+    QApplication::sendEvent(input, &srrndTextQuery);
+    QApplication::sendEvent(input, &absolutePosQuery);
     QApplication::sendEvent(input, &cursorPosQuery);
     QApplication::sendEvent(input, &anchorPosQuery);
     qApp->processEvents();
 
     QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString("composition"));
+    QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 11);
     QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 11);
     QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11);
+
+    // Send commit
+    {
+        QList<QInputMethodEvent::Attribute> attributes;
+        QInputMethodEvent event("", attributes);
+        event.setCommitString("123");
+        QApplication::sendEvent(input, &event);
+        qApp->processEvents();
+    }
+
+    QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value")
+                         .toString(),
+                 QString("composition123"));
+    QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 14);
+
+    QApplication::sendEvent(input, &srrndTextQuery);
+    QApplication::sendEvent(input, &absolutePosQuery);
+    QApplication::sendEvent(input, &cursorPosQuery);
+    QApplication::sendEvent(input, &anchorPosQuery);
+    qApp->processEvents();
+
+    QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString("composition123"));
+    QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 14);
+    QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 14);
+    QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 14);
 }
 
 #if QT_CONFIG(clipboard)
@@ -3785,5 +3839,49 @@ void tst_QWebEngineView::datalist()
             QStringLiteral("fil"));
 }
 
+class ConsolePage : public QWebEnginePage
+{
+    Q_OBJECT
+public:
+    ConsolePage(QObject *parent = nullptr) : QWebEnginePage(parent) { }
+    void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message,
+                                  int lineNumber, const QString &sourceID) override
+    {
+        Q_UNUSED(level)
+        Q_UNUSED(lineNumber)
+        Q_UNUSED(sourceID)
+        if (message.contains("TEST_KEY:Shift"))
+            emit done();
+    }
+signals:
+    void done();
+};
+
+//qtbug_113704
+void tst_QWebEngineView::longKeyEventText()
+{
+    const QString html(QStringLiteral("<html><body><p>TEST</p>"
+                                      "<script>"
+                                      "document.addEventListener('keydown', (event)=> {"
+                                      "console.log('TEST_KEY:' + event.key);"
+                                      "});"
+                                      "</script>"
+                                      "</body></html>"));
+
+    QWebEngineView view;
+    ConsolePage page;
+    view.setPage(&page);
+    QSignalSpy loadFinishedSpy(view.page(), &QWebEnginePage::loadFinished);
+    view.resize(200, 400);
+    view.show();
+    view.setHtml(html);
+    QTRY_VERIFY(loadFinishedSpy.size());
+    QSignalSpy consoleMessageSpy(&page, &ConsolePage::done);
+    Qt::Key key(Qt::Key_Shift);
+    QKeyEvent event(QKeyEvent::KeyPress, key, Qt::NoModifier, QKeySequence(key).toString());
+    QApplication::sendEvent(view.focusProxy(), &event);
+    QTRY_VERIFY(consoleMessageSpy.size());
+}
+
 QTEST_MAIN(tst_QWebEngineView)
 #include "tst_qwebengineview.moc"
diff --git a/tests/auto/widgets/spellchecking/CMakeLists.txt b/tests/auto/widgets/spellchecking/CMakeLists.txt
index 8c538377d60..d0c7656c1e9 100644
--- a/tests/auto/widgets/spellchecking/CMakeLists.txt
+++ b/tests/auto/widgets/spellchecking/CMakeLists.txt
@@ -2,6 +2,7 @@
 # SPDX-License-Identifier: BSD-3-Clause
 
 include(../../util/util.cmake)
+include(../../../../src/core/api/Qt6WebEngineCoreMacros.cmake)
 
 qt_internal_add_test(tst_spellchecking
     SOURCES
diff --git a/tests/auto/widgets/touchinput/tst_touchinput.cpp b/tests/auto/widgets/touchinput/tst_touchinput.cpp
index 562ccfcef0e..de3712370a0 100644
--- a/tests/auto/widgets/touchinput/tst_touchinput.cpp
+++ b/tests/auto/widgets/touchinput/tst_touchinput.cpp
@@ -130,7 +130,7 @@ void TouchInputTest::initTestCase()
     view.setHtml("<html><head><style>.rect { min-width: 240px; min-height: 120px; }</style></head><body>"
                  "<p id='text' style='width: 150px;'>The Qt Company</p>"
                  "<div id='notext' style='width: 150px; height: 100px; background-color: #f00;'></div>"
-                 "<form><input id='input' width='150px' type='text' value='The Qt Company2' /></form>"
+                 "<form><input id='input' style='width: 150px;' type='text' value='The Qt Company2' /></form>"
                  "<button id='btn' type='button' onclick='alert(\"button clicked!\")'>Click Me!</button>"
                  "<select id='select' onchange='alert(\"option changed to: \" + this.value)'>"
                  "<option value='O1'>O1</option><option value='O2'>O2</option><option value='O3'>O3</option></select>"
diff --git a/tests/manual/examples/quick/minimal/main.qml b/tests/manual/examples/quick/minimal/main.qml
index a8733a8c82f..6890b501b9c 100644
--- a/tests/manual/examples/quick/minimal/main.qml
+++ b/tests/manual/examples/quick/minimal/main.qml
@@ -11,6 +11,6 @@ Window {
     visible: true
     WebEngineView {
         anchors.fill: parent
-        url: "https://www.qt.io"
+        url: "chrome://qt"
     }
 }
diff --git a/tests/manual/examples/widgets/minimal/main.cpp b/tests/manual/examples/widgets/minimal/main.cpp
index 86c04e7214f..425973116dd 100644
--- a/tests/manual/examples/widgets/minimal/main.cpp
+++ b/tests/manual/examples/widgets/minimal/main.cpp
@@ -11,7 +11,7 @@ QUrl commandLineUrlArgument()
         if (!arg.startsWith(QLatin1Char('-')))
             return QUrl::fromUserInput(arg);
     }
-    return QUrl(QStringLiteral("https://www.qt.io"));
+    return QUrl(QStringLiteral("chrome://qt"));
 }
 
 int main(int argc, char *argv[])
diff --git a/tests/manual/quick/CMakeLists.txt b/tests/manual/quick/CMakeLists.txt
index 0562237b4d0..d6c4b88a984 100644
--- a/tests/manual/quick/CMakeLists.txt
+++ b/tests/manual/quick/CMakeLists.txt
@@ -1 +1,2 @@
 add_subdirectory(touchbrowser)
+add_subdirectory(geopermission)
diff --git a/tests/manual/quick/geopermission/CMakeLists.txt b/tests/manual/quick/geopermission/CMakeLists.txt
new file mode 100644
index 00000000000..088f248e1ac
--- /dev/null
+++ b/tests/manual/quick/geopermission/CMakeLists.txt
@@ -0,0 +1,63 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+    cmake_minimum_required(VERSION 3.16)
+    project(tst_geopermission LANGUAGES CXX)
+    find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_manual_test(tst_geopermission
+    SOURCES
+        main.cpp
+    LIBRARIES
+        Qt::Core
+        Qt::Gui
+        Qt::Qml
+        Qt::Quick
+        Qt::WebEngineQuick
+)
+
+if(WIN32)
+    set_property(
+        TARGET tst_geopermission
+        APPEND PROPERTY
+            SOURCES tst_geopermission.exe.manifest)
+endif()
+
+set_target_properties(tst_geopermission PROPERTIES
+    WIN32_EXECUTABLE TRUE
+    MACOSX_BUNDLE TRUE
+    MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.dev.webenginequick.tst_geopermission"
+)
+
+# Resources:
+set(resources_resource_files
+    "tst_geopermission.qml"
+    "geolocation.html"
+)
+
+qt_add_resources(tst_geopermission "resources"
+    PREFIX
+        "/"
+    FILES
+        ${resources_resource_files}
+)
+
+foreach(permission_plugin IN LISTS QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_permissions)
+    set(permission_plugin "${QT_CMAKE_EXPORT_NAMESPACE}::${permission_plugin}")
+        qt6_import_plugins(tst_geopermission INCLUDE ${permission_plugin})
+endforeach()
+
+if (APPLE)
+    set_target_properties(tst_geopermission PROPERTIES
+        MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
+    )
+
+    if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+        # Need to sign application for location permissions to work
+        add_custom_command(TARGET tst_geopermission
+            POST_BUILD COMMAND codesign -s - tst_geopermission.app)
+    endif()
+endif()
+
diff --git a/tests/manual/quick/geopermission/Info.plist b/tests/manual/quick/geopermission/Info.plist
new file mode 100644
index 00000000000..9853e190081
--- /dev/null
+++ b/tests/manual/quick/geopermission/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleName</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+    <key>CFBundleIdentifier</key>
+    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+    <key>CFBundleExecutable</key>
+    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+    <key>CFBundleVersion</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+    <key>CFBundleShortVersionString</key>
+    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
+    <key>NSHumanReadableCopyright</key>
+    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+    <key>CFBundleIconFile</key>
+    <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>NSSupportsAutomaticGraphicsSwitching</key>
+    <true/>
+    <key>NSLocationUsageDescription</key>
+    <string>Geolocation test would like to give web sites access to your location for demo purposes.</string>
+</dict>
+</plist>
diff --git a/tests/manual/quick/geopermission/geolocation.html b/tests/manual/quick/geopermission/geolocation.html
new file mode 100644
index 00000000000..e8c54bc5847
--- /dev/null
+++ b/tests/manual/quick/geopermission/geolocation.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<title>Geolocation Permission API Test</title>
+<script>
+
+var errorMessage;
+var handled = false;
+
+function successHandler(location) {
+    var message = document.getElementById("message");
+    message.innerHTML = "Latitude: " + location.coords.latitude +
+    "<br>Longitude: " + location.coords.longitude;
+
+    errorMessage = "";
+    handled = true;
+}
+
+function errorHandler(error) {
+    errorMessage = error.message;
+    handled = true;
+}
+
+<!-- One shot example -->
+navigator.geolocation.getCurrentPosition(successHandler, errorHandler);
+
+</script>
+</head>
+<body>
+<div id="message">Location unknown</div>
+</body>
+</html>
+
diff --git a/tests/manual/quick/geopermission/main.cpp b/tests/manual/quick/geopermission/main.cpp
new file mode 100644
index 00000000000..e0ff6f3e7f3
--- /dev/null
+++ b/tests/manual/quick/geopermission/main.cpp
@@ -0,0 +1,39 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+
+#include <QtWebEngineQuick/qtwebenginequickglobal.h>
+
+#include <QtQml/QQmlApplicationEngine>
+#include <QtQml/QQmlContext>
+#include <QQuickView>
+
+#include <QtGui/QGuiApplication>
+
+#include <QtCore/QCommandLineParser>
+#include <QtCore/QCommandLineOption>
+#include <QtCore/QLoggingCategory>
+
+int main(int argc, char **argv)
+{
+    QCoreApplication::setApplicationName("Geopermission test");
+    QCoreApplication::setOrganizationName("QtProject");
+
+    QtWebEngineQuick::initialize();
+
+    QGuiApplication app(argc, argv);
+
+    QQuickView view;
+
+    view.setTitle("Touch Browser");
+    view.setFlags(Qt::Window | Qt::WindowTitleHint);
+    view.setResizeMode(QQuickView::SizeRootObjectToView);
+    view.setSource(QUrl("qrc:/tst_geopermission.qml"));
+
+    QObject::connect(view.engine(), SIGNAL(quit()), &app, SLOT(quit()));
+
+    view.show();
+    if (view.size().isEmpty())
+        view.setGeometry(0, 0, 800, 600);
+
+    return app.exec();
+}
diff --git a/tests/manual/quick/geopermission/tst_geopermission.qml b/tests/manual/quick/geopermission/tst_geopermission.qml
new file mode 100644
index 00000000000..36317c176ae
--- /dev/null
+++ b/tests/manual/quick/geopermission/tst_geopermission.qml
@@ -0,0 +1,28 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+import QtQuick
+import QtTest
+import QtWebEngine
+
+WebEngineView {
+    id: webEngineView
+    width: 200
+    height: 200
+    url: Qt.resolvedUrl("qrc:/geolocation.html")
+    property bool deniedGeolocation: false
+    property bool geoPermissionRequested: false
+
+    onFeaturePermissionRequested: function(securityOrigin, feature) {
+        if (feature === WebEngineView.Geolocation) {
+            geoPermissionRequested = true
+            if (deniedGeolocation) {
+                webEngineView.grantFeaturePermission(securityOrigin, feature, false)
+            }
+            else {
+                webEngineView.grantFeaturePermission(securityOrigin, feature, true)
+            }
+        }
+    }
+
+}
diff --git a/tests/manual/quick/touchbrowser/touchmockingapplication.cpp b/tests/manual/quick/touchbrowser/touchmockingapplication.cpp
deleted file mode 100644
index e958d21cd12..00000000000
--- a/tests/manual/quick/touchbrowser/touchmockingapplication.cpp
+++ /dev/null
@@ -1,261 +0,0 @@
-// Copyright (C) 2022 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 "touchmockingapplication.h"
-
-#include <qpa/qwindowsysteminterface.h>
-#include <QtQuick/QQuickItem>
-#include <QtQuick/QQuickView>
-#include <QInputDevice>
-
-static inline bool isTouchEvent(const QEvent* event)
-{
-    switch (event->type()) {
-    case QEvent::TouchBegin:
-    case QEvent::TouchUpdate:
-    case QEvent::TouchEnd:
-        return true;
-    default:
-        return false;
-    }
-}
-
-static inline bool isMouseEvent(const QEvent* event)
-{
-    switch (event->type()) {
-    case QEvent::MouseButtonPress:
-    case QEvent::MouseMove:
-    case QEvent::MouseButtonRelease:
-    case QEvent::MouseButtonDblClick:
-        return true;
-    default:
-        return false;
-    }
-}
-
-TouchMockingApplication::TouchMockingApplication(int& argc, char** argv)
-    : QGuiApplication(argc, argv)
-    , m_realTouchEventReceived(false)
-    , m_pendingFakeTouchEventCount(0)
-    , m_holdingControl(false)
-{
-}
-
-bool TouchMockingApplication::notify(QObject* target, QEvent* event)
-{
-    // We try to be smart, if we received real touch event, we are probably on a device
-    // with touch screen, and we should not have touch mocking.
-
-    if (!event->spontaneous() || m_realTouchEventReceived)
-        return QGuiApplication::notify(target, event);
-
-    if (isTouchEvent(event)) {
-        if (m_pendingFakeTouchEventCount)
-            --m_pendingFakeTouchEventCount;
-        else
-            m_realTouchEventReceived = true;
-        return QGuiApplication::notify(target, event);
-    }
-
-    QQuickView* window = qobject_cast<QQuickView*>(target);
-    if (!window)
-        return QGuiApplication::notify(target, event);
-
-    m_holdingControl = QGuiApplication::keyboardModifiers().testFlag(Qt::ControlModifier);
-
-    if (event->type() == QEvent::KeyRelease && static_cast<QKeyEvent*>(event)->key() == Qt::Key_Control) {
-        foreach (int id, m_heldTouchPoints)
-            if (m_touchPoints.contains(id) && !QGuiApplication::mouseButtons().testFlag(Qt::MouseButton(id))) {
-                QMutableEventPoint::setState(m_touchPoints[id], QEventPoint::Released);
-                m_heldTouchPoints.remove(id);
-            } else
-                QMutableEventPoint::setState(m_touchPoints[id], QEventPoint::Stationary);
-
-        sendTouchEvent(window, m_heldTouchPoints.isEmpty() ? QEvent::TouchEnd : QEvent::TouchUpdate, static_cast<QKeyEvent*>(event)->timestamp());
-    }
-
-    if (isMouseEvent(event)) {
-        const QMouseEvent* const mouseEvent = static_cast<QMouseEvent*>(event);
-
-        QEventPoint touchPoint;
-        QMutableEventPoint::setPressure(touchPoint, 1);
-
-        QEvent::Type touchType = QEvent::None;
-
-        switch (mouseEvent->type()) {
-        case QEvent::MouseButtonPress:
-            QMutableEventPoint::setId(touchPoint, mouseEvent->button());
-            if (m_touchPoints.contains(touchPoint.id())) {
-                QMutableEventPoint::setState(touchPoint, QEventPoint::Updated);
-                touchType = QEvent::TouchUpdate;
-            } else {
-                QMutableEventPoint::setState(touchPoint, QEventPoint::Pressed);
-                // Check if more buttons are held down than just the event triggering one.
-                if (mouseEvent->buttons() > mouseEvent->button())
-                    touchType = QEvent::TouchUpdate;
-                else
-                    touchType = QEvent::TouchBegin;
-            }
-            break;
-        case QEvent::MouseMove:
-            if (!mouseEvent->buttons()) {
-                // We have to swallow the event instead of propagating it,
-                // since we avoid sending the mouse release events and if the
-                // Flickable is the mouse grabber it would receive the event
-                // and would move the content.
-                event->accept();
-                return true;
-            }
-            touchType = QEvent::TouchUpdate;
-            QMutableEventPoint::setId(touchPoint, mouseEvent->buttons());
-            QMutableEventPoint::setState(touchPoint, QEventPoint::Updated);
-            break;
-        case QEvent::MouseButtonRelease:
-            // Check if any buttons are still held down after this event.
-            if (mouseEvent->buttons())
-                touchType = QEvent::TouchUpdate;
-            else
-                touchType = QEvent::TouchEnd;
-            QMutableEventPoint::setId(touchPoint, mouseEvent->button());
-            QMutableEventPoint::setState(touchPoint, QEventPoint::Released);
-            break;
-        case QEvent::MouseButtonDblClick:
-            // Eat double-clicks, their accompanying press event is all we need.
-            event->accept();
-            return true;
-        default:
-            Q_ASSERT_X(false, "multi-touch mocking", "unhandled event type");
-        }
-
-        // A move can have resulted in multiple buttons, so we need check them individually.
-        if (touchPoint.id() & Qt::LeftButton)
-            updateTouchPoint(mouseEvent, touchPoint, Qt::LeftButton);
-        if (touchPoint.id() & Qt::MiddleButton)
-            updateTouchPoint(mouseEvent, touchPoint, Qt::MiddleButton);
-        if (touchPoint.id() & Qt::RightButton)
-            updateTouchPoint(mouseEvent, touchPoint, Qt::RightButton);
-
-        if (m_holdingControl && touchPoint.state() == QEventPoint::Released) {
-            // We avoid sending the release event because the Flickable is
-            // listening to mouse events and would start a bounce-back
-            // animation if it received a mouse release.
-            event->accept();
-            return true;
-        }
-
-        // Update states for all other touch-points
-        for (QHash<int, QEventPoint>::iterator it = m_touchPoints.begin(), end = m_touchPoints.end(); it != end; ++it) {
-            if (!(it.value().id() & touchPoint.id()))
-                QMutableEventPoint::setState(it.value(), QEventPoint::Stationary);
-        }
-
-        Q_ASSERT(touchType != QEvent::None);
-
-        if (!sendTouchEvent(window, touchType, mouseEvent->timestamp()))
-            return QGuiApplication::notify(target, event);
-
-        event->accept();
-        return true;
-    }
-
-    return QGuiApplication::notify(target, event);
-}
-
-void TouchMockingApplication::updateTouchPoint(const QMouseEvent* mouseEvent, QEventPoint touchPoint, Qt::MouseButton mouseButton)
-{
-    // Ignore inserting additional touch points if Ctrl isn't held because it produces
-    // inconsistent touch events and results in assers in the gesture recognizers.
-    if (!m_holdingControl && m_touchPoints.size() && !m_touchPoints.contains(mouseButton))
-        return;
-
-    if (m_holdingControl && touchPoint.state() == QEventPoint::Released) {
-        m_heldTouchPoints.insert(mouseButton);
-        return;
-    }
-
-    // Gesture recognition uses the screen position for the initial threshold
-    // but since the canvas translates touch events we actually need to pass
-    // the screen position as the scene position to deliver the appropriate
-    // coordinates to the target.
-    QMutableEventPoint::setPosition(touchPoint, mouseEvent->position());
-    QMutableEventPoint::setScenePosition(touchPoint, mouseEvent->globalPosition());
-
-    if (touchPoint.state() == QEventPoint::Pressed)
-        QMutableEventPoint::setScenePosition(touchPoint, mouseEvent->scenePosition());
-    else {
-        const QEventPoint& oldTouchPoint = m_touchPoints[mouseButton];
-        QMutableEventPoint::setGlobalLastPosition(touchPoint, oldTouchPoint.globalPosition());
-    }
-
-    // Update current touch-point.
-    QMutableEventPoint::setId(touchPoint, mouseButton);
-    m_touchPoints.insert(mouseButton, touchPoint);
-}
-
-bool TouchMockingApplication::sendTouchEvent(QQuickView* window, QEvent::Type type, ulong timestamp)
-{
-    static QPointingDevice* device = 0;
-    if (!device) {
-        device = new QPointingDevice(QStringLiteral("MockTouchDevice"), 1,
-                                     QPointingDevice::DeviceType::TouchScreen,
-                                     QPointingDevice::PointerType::AllPointerTypes,
-                                     QInputDevice::Capability::All, 3, 3,
-                                     QString(), QPointingDeviceUniqueId(), window->rootObject());
-
-        QWindowSystemInterface::registerInputDevice(device);
-    }
-
-    m_pendingFakeTouchEventCount++;
-
-    const QList<QEventPoint>& currentTouchPoints = m_touchPoints.values();
-    QEventPoint::States touchPointStates = QEventPoint::States();
-    foreach (const QEventPoint& touchPoint, currentTouchPoints)
-        touchPointStates |= touchPoint.state();
-
-    QTouchEvent event(type, device, Qt::NoModifier, currentTouchPoints);
-    event.setTimestamp(timestamp);
-    event.setAccepted(false);
-
-    QGuiApplication::notify(window, &event);
-
-    updateVisualMockTouchPoints(window, m_holdingControl ? currentTouchPoints : QList<QEventPoint>());
-
-    // Get rid of touch-points that are no longer valid
-    foreach (const QEventPoint& touchPoint, currentTouchPoints) {
-        if (touchPoint.state() == QEventPoint::Released)
-            m_touchPoints.remove(touchPoint.id());
-    }
-
-    return event.isAccepted();
-}
-
-void TouchMockingApplication::updateVisualMockTouchPoints(QQuickView* window,const QList<QEventPoint>& touchPoints)
-{
-    if (touchPoints.isEmpty()) {
-        // Hide all touch indicator items.
-        foreach (QQuickItem* item, m_activeMockComponents.values())
-            item->setProperty("pressed", false);
-
-        return;
-    }
-
-    foreach (const QEventPoint& touchPoint, touchPoints) {
-        QQuickItem* mockTouchPointItem = m_activeMockComponents.value(touchPoint.id());
-
-        if (!mockTouchPointItem) {
-            QQmlComponent touchMockPointComponent(window->engine(), QUrl("qrc:///MockTouchPoint.qml"));
-            mockTouchPointItem = qobject_cast<QQuickItem*>(touchMockPointComponent.create());
-            Q_ASSERT(mockTouchPointItem);
-            m_activeMockComponents.insert(touchPoint.id(), mockTouchPointItem);
-            mockTouchPointItem->setProperty("pointId", QVariant(touchPoint.id()));
-            mockTouchPointItem->setParent(window->rootObject());
-            mockTouchPointItem->setParentItem(window->rootObject());
-        }
-
-        mockTouchPointItem->setX(touchPoint.position().x());
-        mockTouchPointItem->setY(touchPoint.position().y());
-        mockTouchPointItem->setWidth(touchPoint.ellipseDiameters().width());
-        mockTouchPointItem->setHeight(touchPoint.ellipseDiameters().height());
-        mockTouchPointItem->setProperty("pressed", QVariant(touchPoint.state() != QEventPoint::Released));
-    }
-}
diff --git a/tests/manual/widgets/CMakeLists.txt b/tests/manual/widgets/CMakeLists.txt
index 1153e7763ea..297a9b20653 100644
--- a/tests/manual/widgets/CMakeLists.txt
+++ b/tests/manual/widgets/CMakeLists.txt
@@ -1,3 +1,4 @@
 add_subdirectory(inputmethods)
+add_subdirectory(geolocation)
 add_subdirectory(touchbrowser)
 add_subdirectory(webgl)
diff --git a/tests/manual/widgets/geolocation/CMakeLists.txt b/tests/manual/widgets/geolocation/CMakeLists.txt
new file mode 100644
index 00000000000..2ca8c2f524b
--- /dev/null
+++ b/tests/manual/widgets/geolocation/CMakeLists.txt
@@ -0,0 +1,55 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+if (NOT QT_BUILD_STANDALONE_TESTS AND NOT QT_BUILDING_QT)
+    cmake_minimum_required(VERSION 3.16)
+    project(geolocation LANGUAGES CXX)
+    find_package(Qt6BuildInternals COMPONENTS STANDALONE_TEST)
+endif()
+
+qt_internal_add_manual_test(geolocation
+    GUI
+    SOURCES
+        main.cpp
+    LIBRARIES
+        Qt::Core
+        Qt::Gui
+        Qt::Test
+        Qt::WebEngineWidgets
+    ENABLE_AUTOGEN_TOOLS
+        moc
+)
+
+set_target_properties(geolocation PROPERTIES
+    WIN32_EXECUTABLE TRUE
+    MACOSX_BUNDLE TRUE
+    MACOSX_BUNDLE_GUI_IDENTIFIER "io.qt.dev.webenginewidgets.geolocation"
+)
+
+set(geolocation_resource_files
+    "geolocation.html"
+)
+
+qt_add_resources(geolocation "geolocation"
+    PREFIX
+    "/"
+    FILES
+    ${geolocation_resource_files}
+)
+
+    foreach(permission_plugin IN LISTS QT_ALL_PLUGINS_FOUND_BY_FIND_PACKAGE_permissions)
+        set(permission_plugin "${QT_CMAKE_EXPORT_NAMESPACE}::${permission_plugin}")
+        qt6_import_plugins(geolocation INCLUDE ${permission_plugin})
+    endforeach()
+
+if (APPLE)
+    set_target_properties(geolocation PROPERTIES
+        MACOSX_BUNDLE_INFO_PLIST "${CMAKE_CURRENT_SOURCE_DIR}/Info.plist"
+    )
+
+    if (NOT CMAKE_GENERATOR STREQUAL "Xcode")
+        # Need to sign application for location permissions to work
+        add_custom_command(TARGET geolocation
+            POST_BUILD COMMAND codesign -s - geolocation.app)
+    endif()
+endif()
diff --git a/tests/manual/widgets/geolocation/Info.plist b/tests/manual/widgets/geolocation/Info.plist
new file mode 100644
index 00000000000..9853e190081
--- /dev/null
+++ b/tests/manual/widgets/geolocation/Info.plist
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleName</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_NAME}</string>
+    <key>CFBundleIdentifier</key>
+    <string>${MACOSX_BUNDLE_GUI_IDENTIFIER}</string>
+    <key>CFBundleExecutable</key>
+    <string>${MACOSX_BUNDLE_EXECUTABLE_NAME}</string>
+    <key>CFBundleVersion</key>
+    <string>${MACOSX_BUNDLE_BUNDLE_VERSION}</string>
+    <key>CFBundleShortVersionString</key>
+    <string>${MACOSX_BUNDLE_SHORT_VERSION_STRING}</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>${CMAKE_OSX_DEPLOYMENT_TARGET}</string>
+    <key>NSHumanReadableCopyright</key>
+    <string>${MACOSX_BUNDLE_COPYRIGHT}</string>
+    <key>CFBundleIconFile</key>
+    <string>${MACOSX_BUNDLE_ICON_FILE}</string>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>NSSupportsAutomaticGraphicsSwitching</key>
+    <true/>
+    <key>NSLocationUsageDescription</key>
+    <string>Geolocation test would like to give web sites access to your location for demo purposes.</string>
+</dict>
+</plist>
diff --git a/tests/manual/widgets/geolocation/geolocation.html b/tests/manual/widgets/geolocation/geolocation.html
new file mode 100644
index 00000000000..e8c54bc5847
--- /dev/null
+++ b/tests/manual/widgets/geolocation/geolocation.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+<title>Geolocation Permission API Test</title>
+<script>
+
+var errorMessage;
+var handled = false;
+
+function successHandler(location) {
+    var message = document.getElementById("message");
+    message.innerHTML = "Latitude: " + location.coords.latitude +
+    "<br>Longitude: " + location.coords.longitude;
+
+    errorMessage = "";
+    handled = true;
+}
+
+function errorHandler(error) {
+    errorMessage = error.message;
+    handled = true;
+}
+
+<!-- One shot example -->
+navigator.geolocation.getCurrentPosition(successHandler, errorHandler);
+
+</script>
+</head>
+<body>
+<div id="message">Location unknown</div>
+</body>
+</html>
+
diff --git a/tests/manual/widgets/geolocation/main.cpp b/tests/manual/widgets/geolocation/main.cpp
new file mode 100644
index 00000000000..f33cf5798b7
--- /dev/null
+++ b/tests/manual/widgets/geolocation/main.cpp
@@ -0,0 +1,51 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QApplication>
+#include <QFormLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QLabel>
+#include <QMainWindow>
+#include <QMessageBox>
+#include <QVBoxLayout>
+#include <QWebEnginePage>
+#include <QWebEngineView>
+
+class GeoPermissionWebView : public QWebEngineView {
+  Q_OBJECT
+
+public slots:
+    void handleFeaturePermissionRequested(const QUrl &securityOrigin,
+                                               QWebEnginePage::Feature feature)
+    {
+        qWarning("Feature Permission");
+        QString title = tr("Permission Request");
+        QString question = QLatin1String("Allow access to geolocation?");
+        if (!question.isEmpty() && QMessageBox::question(window(), title, question) == QMessageBox::Yes)
+            page()->setFeaturePermission(securityOrigin, feature,
+                                         QWebEnginePage::PermissionGrantedByUser);
+        else
+            page()->setFeaturePermission(securityOrigin, feature,
+                                         QWebEnginePage::PermissionDeniedByUser);
+    }
+
+};
+
+int main(int argc, char *argv[])
+{
+    QApplication a(argc, argv);
+    QMainWindow w;
+    GeoPermissionWebView webview;
+    QWebEnginePage page;
+    QObject::connect(&page, &QWebEnginePage::featurePermissionRequested, &webview,
+            &GeoPermissionWebView::handleFeaturePermissionRequested);
+    webview.setPage(&page);
+    page.load(QUrl("qrc:/geolocation.html"));
+    w.setCentralWidget(&webview);
+    w.show();
+
+    return a.exec();
+}
+
+#include "main.moc"
diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py
index 41cd46b3c1c..735660e2aae 100755
--- a/tools/scripts/take_snapshot.py
+++ b/tools/scripts/take_snapshot.py
@@ -41,7 +41,6 @@ def isInChromiumBlacklist(file_path):
     if (file_path.startswith('android_webview')
         or file_path.startswith('apps/')
         or file_path.startswith('ash/')
-        or file_path.startswith('base/android')
         or file_path.startswith('buildtools/clang_format/script')
         or file_path.startswith('buildtools/third_party/libc++')
         or file_path.startswith('buildtools/third_party/libc++abi')
@@ -118,7 +117,10 @@ def isInChromiumBlacklist(file_path):
         or (file_path.startswith('net/data/')
           and '_unittest/' in file_path)
         or file_path.startswith('net/data/fuzzer_data/')
-        or file_path.startswith('remoting')
+        or (file_path.startswith('remoting')
+            and not file_path.endswith('VERSION')
+            and not file_path.endswith('branding_Chromium')
+            and not file_path.endswith('remove_spaces.py'))
         or file_path.startswith('rlz')
         or file_path.startswith('testing/android')
         or file_path.startswith('testing/buildbot')
@@ -155,6 +157,7 @@ def isInChromiumBlacklist(file_path):
             or file_path.startswith('third_party/chromite')
             or file_path.startswith('third_party/colorama')
             or file_path.startswith('third_party/depot_tools')
+            or file_path.startswith('third_party/devtools-frontend/src/third_party/image_diff')
             or (file_path.startswith('third_party/node/node_modules/')
               and not file_path.startswith('third_party/node/node_modules/@babel/')
               and not file_path.startswith('third_party/node/node_modules/@types/d3')
@@ -180,6 +183,7 @@ def isInChromiumBlacklist(file_path):
               and not file_path.startswith('third_party/node/node_modules/indent/')
               and not file_path.startswith('third_party/node/node_modules/is-core-module/')
               and not file_path.startswith('third_party/node/node_modules/is-windows/')
+              and not file_path.startswith('third_party/node/node_modules/@jridgewell/')
               and not file_path.startswith('third_party/node/node_modules/js-tokens/')
               and not file_path.startswith('third_party/node/node_modules/jsesc/')
               and not file_path.startswith('third_party/node/node_modules/jsonschema/')
diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py
index 9dd60b4776b..b5e6f67b822 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 = '108.0.5359.220'
-chromium_branch = '5359'
+chromium_version = '112.0.5615.213'
+chromium_branch = '5615'
 ninja_version = 'v1.8.2'
 
 json_url = 'http://omahaproxy.appspot.com/all.json'
