diff --git a/.cmake.conf b/.cmake.conf index f5b3715d7bc..504f5f93c3a 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,4 +1,4 @@ -set(QT_REPO_MODULE_VERSION "6.9.0") +set(QT_REPO_MODULE_VERSION "6.9.2") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEBENGINE "3.19") set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") diff --git a/.gitreview b/.gitreview new file mode 100644 index 00000000000..a17ec896fca --- /dev/null +++ b/.gitreview @@ -0,0 +1,4 @@ +[gerrit] +host=codereview.qt-project.org +project=qt/qtwebengine +defaultbranch=dev diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index 7f98334efb0..6ffbd94987f 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ -Based on Chromium version: 122.0.6261.171 -Patched with security patches up to Chromium version: 129.0.6668.58 +Based on Chromium version: 130.0.6723.192 +Patched with security patches up to Chromium version: 136.0.7103.114 diff --git a/CMakeLists.txt b/CMakeLists.txt index c600f450154..90b90053c56 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -12,6 +12,8 @@ include(cmake/Functions.cmake) include(cmake/QtGnTargetHelpers.cmake) include(cmake/QtGnConfigHelpers.cmake) include(cmake/QtConfigureHelpers.cmake) +include(cmake/QtWebEngineSbomHelpers.cmake) +include(cmake/QtToolchainHelpers.cmake) project(QtWebEngineDummy) find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core) @@ -35,7 +37,7 @@ find_package(Qt6 ${PROJECT_VERSION} CONFIG QUIET OPTIONAL_COMPONENTS WebChannel WebChannelQuick Positioning QuickControls2 Test QuickWidgets QuickTest WebSockets Designer JpegPrivate PngPrivate HarfbuzzPrivate FreetypePrivate ZlibPrivate - HttpServer + HttpServer Svg ) if(MATRIX_BUILD AND NOT MATRIX_SUBBUILD AND NOT QT_SUPERBUILD) @@ -48,4 +50,14 @@ if(MATRIX_BUILD AND NOT MATRIX_SUBBUILD AND NOT QT_SUPERBUILD) return() endif() +# Don't auto create the SBOM projects, they will be manually created +# for each sub-project. +set(QT_SKIP_SBOM_AUTO_PROJECT TRUE) qt_build_repo() + +# Coin sanity check after qt_build_repo report is printed + +qt_webengine_configure_check_coin(coin.nodes + "${QT_CONFIGURE_CHECK_qtwebengine_build}" + "${QT_CONFIGURE_CHECK_qtpdf_build}" +) diff --git a/REUSE.toml b/REUSE.toml index 9474f351661..faaa2093da1 100644 --- a/REUSE.toml +++ b/REUSE.toml @@ -11,7 +11,8 @@ path = ["src/core/doc/QtWebEngineDoc", "src/process/QtWebEngineProcess.exe.manifest", "src/webenginequick/ui/information.png", "src/webenginequick/ui/question.png", - "src/webenginewidgets/plugins/qwebengineview/images/qwebengineview.png"] + "src/webenginewidgets/plugins/qwebengineview/images/qwebengineview.png", + "src/pdf/plugins/imageformats/pdf/pdf.json"] precedence = "closest" comment = "module and plugin" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." @@ -70,29 +71,30 @@ SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GPL-3.0-only" [[annotations]] -path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml", "**.json", - "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in"] +path = ["**.pro", "**.qrc", "**CMakeLists.txt", ".cmake.conf", "**.yaml", + "**.cfg", "**BLACKLIST", "**.plist", "**.plist.in", "**BUILD**.in", "coin.nodes", + "coin/qt-installer-package-config.json", ".tag"] precedence = "closest" comment = "build system" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "BSD-3-Clause" [[annotations]] -path = [".tag", "**/.gitattributes", "**.gitignore"] +path = ["**/.gitattributes", "**.gitignore", ".gitmodules", "**.gitreview"] precedence = "closest" -comment = "version control system. Licensed as build system" +comment = "version control system. Infrastructure" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." -SPDX-License-Identifier = "BSD-3-Clause" +SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] -path = ["**/doc/images/**", "examples/**", "tests/manual/examples/**", "**/doc/snippets/**"] +path = ["examples/**", "tests/manual/examples/**", "**/doc/snippets/**"] comment = "this must be after the build system table because example and snippets take precedence over build system" precedence = "closest" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] -path = ["**.qdocconf", "config_help.txt", ".gitmodules"] +path = ["**/doc/images/**", "**.qdocconf", "config_help.txt"] comment = "documentation" precedence = "closest" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." @@ -100,10 +102,10 @@ SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-on [[annotations]] path = ["**.toml", "licenseRule.json"] -comment = "documentation" +comment = "infrastructure" precedence = "override" SPDX-FileCopyrightText = "Copyright (C) 2024 The Qt Company Ltd." -SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only" +SPDX-License-Identifier = "LicenseRef-Qt-Commercial OR BSD-3-Clause" [[annotations]] path = ["**/qt_attribution.json"] diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index ca4ce729286..b5d5e812be1 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -40,39 +40,6 @@ function(get_forward_declaration_macro result) endif() endfunction() -function(get_darwin_sdk_version result) - if(APPLE) - if(IOS) - set(sdk_name "iphoneos") - elseif(TVOS) - set(sdk_name "appletvos") - elseif(WATCHOS) - set(sdk_name "watchos") - else() - # Default to macOS - set(sdk_name "macosx") - endif() - set(xcrun_version_arg "--show-sdk-version") - execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg} - OUTPUT_VARIABLE sdk_version - ERROR_VARIABLE xcrun_error) - if(NOT sdk_version) - message(FATAL_ERROR - "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}") - endif() - string(STRIP "${sdk_version}" sdk_version) - set(${result} "${sdk_version}" PARENT_SCOPE) - endif() -endfunction() - -function(get_ios_target_triple_and_sysroot result arch) - get_ios_sysroot(sysroot ${arch}) - set(${result} - -target ${arch}-apple-ios${CMAKE_OSX_DEPLOYMENT_TARGET} - -isysroot ${sysroot} PARENT_SCOPE - ) -endfunction() - function(add_ninja_target) cmake_parse_arguments(PARSE_ARGV 0 arg "" "TARGET;CMAKE_TARGET;NINJA_TARGET;BUILDDIR;NINJA_STAMP;NINJA_DATA_STAMP;CONFIG;ARCH" "" @@ -335,517 +302,9 @@ function(qt_internal_add_external_project_dependency_to_root_project name) cmake_policy(POP) endfunction() -# Function maps TEST_architecture_arch or CMAKE_SYSTEM_PROCESSOR into gn architecture -function(get_gn_arch result arch) - set(armList arm armv7-a) - set(arm64List arm64 ARM64 aarch64) - set(mips64List mips64 mipsel64) - set(x86List i386 i686) - set(x64List x86_64 AMD64 x86_64h) - if(arch IN_LIST x86List) - set(${result} "x86" PARENT_SCOPE) - elseif(arch IN_LIST x64List) - set(${result} "x64" PARENT_SCOPE) - elseif(arch IN_LIST armList) - set(${result} "arm" PARENT_SCOPE) - elseif(arch IN_LIST arm64List) - set(${result} "arm64" PARENT_SCOPE) - elseif(arch STREQUAL "mipsel") - set(${result} "mipsel" PARENT_SCOPE) - elseif(arch IN_LIST mipsList) - set(${result} "mips64el" PARENT_SCOPE) - elseif(arch STREQUAL "riscv64") - set(${result} "riscv64" PARENT_SCOPE) - else() - message(FATAL_ERROR "Unknown architecture: ${arch}") - endif() -endfunction() - -# Function maps gn architecture for v8 -function(get_v8_arch result targetArch hostArch) - set(list32 x86 arm mipsel riscv32) - if(hostArch STREQUAL targetArch) - set(${result} "${targetArch}" PARENT_SCOPE) - elseif(targetArch IN_LIST list32) - # 32bit target which needs a 32bit compatible host - if(hostArch STREQUAL "x64") - set(${result} "x86" PARENT_SCOPE) - elseif(hostArch STREQUAL "arm64") - set(${result} "arm" PARENT_SCOPE) - elseif(hostArch STREQUAL "mips64el") - set(${result} "mipsel" PARENT_SCOPE) - elseif(hostArch STREQUAL "riscv64") - set(${result} "riscv32" PARENT_SCOPE) - elseif(hostArch IN_LIST list32) - set(${result} "${hostArch}" PARENT_SCOPE) - else() - message(FATAL_ERROR "Unknown architecture: ${hostArch}") - endif() - else() - # assume 64bit target which matches 64bit host - set(${result} "${hostArch}" PARENT_SCOPE) - endif() -endfunction() - -function(get_gn_os result) - if(WIN32) - set(${result} "win" PARENT_SCOPE) - elseif(LINUX) - set(${result} "linux" PARENT_SCOPE) - elseif(MACOS) - set(${result} "mac" PARENT_SCOPE) - elseif(IOS) - set(${result} "ios" PARENT_SCOPE) - else() - message(DEBUG "Unrecognized OS") - endif() -endfunction() - -function(get_gn_is_clang result) - if(CLANG) - set(${result} "true" PARENT_SCOPE) - else() - set(${result} "false" PARENT_SCOPE) - endif() -endfunction() - - -function(get_gn_is_mingw result) - if(MINGW) - set(${result} "true" PARENT_SCOPE) - else() - set(${result} "false" PARENT_SCOPE) - endif() -endfunction() - -function(get_ios_sysroot result arch) - if(NOT CMAKE_APPLE_ARCH_SYSROOTS) - message(FATAL_ERROR "CMAKE_APPLE_ARCH_SYSROOTS not set.") - endif() - get_architectures(archs) - list(FIND archs ${arch} known_arch) - if (known_arch EQUAL "-1") - message(FATAL_ERROR "Unknown iOS architecture ${arch}.") - endif() - list(GET CMAKE_APPLE_ARCH_SYSROOTS ${known_arch} sysroot) - set(${result} ${sysroot} PARENT_SCOPE) -endfunction() - -function(configure_gn_toolchain name cpu v8Cpu toolchainIn toolchainOut) - set(GN_TOOLCHAIN ${name}) - get_gn_os(GN_OS) - get_gn_is_clang(GN_IS_CLANG) - get_gn_is_mingw(GN_IS_MINGW) - set(GN_CPU ${cpu}) - set(GN_V8_CPU ${v8Cpu}) - configure_file(${toolchainIn} ${toolchainOut}/BUILD.gn @ONLY) -endfunction() - -function(create_pkg_config_wrapper wrapperName wrapperCmd) - file(WRITE ${wrapperName} - "#!/bin/sh\n" - "unset PKG_CONFIG_LIBDIR\n" - "unset PKG_CONFIG_PATH\n" - "unset PKG_CONFIG_SYSROOT_DIR\n" - "exec ${wrapperCmd} \"$@\"" - ) - file(CHMOD ${wrapperName} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) -endfunction() - -function(extract_cflag result cflag) - set(i 1) - while(NOT "x${CMAKE_CXX_COMPILER_ARG${i}}" STREQUAL "x") - list(APPEND cflags ${CMAKE_CXX_COMPILER_ARG${i}}) - math(EXPR i "${i} + 1") - endwhile() - list(APPEND cflags ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}) - string(REPLACE ";" " " cflags "${cflags}") - message(DEBUG "Found cflags: ${cflags}") - if(cflags MATCHES "-${cflag}=([^ ]+)") - set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE) - return() - endif() - if(cflags MATCHES "-${cflag}") - set(${result} ON PARENT_SCOPE) - else() - set(${result} OFF PARENT_SCOPE) - endif() -endfunction() - -function(extend_gn_list_cflag outList) - cmake_parse_arguments(PARSE_ARGV 1 GN "" "" "ARG;CFLAG") - _qt_internal_validate_all_args_are_parsed(GN) - - extract_cflag(cflag "${GN_CFLAG}") - if(cflag) - set(${outList} "${${outList}}" "${GN_ARG}=\"${cflag}\"" PARENT_SCOPE) - endif() -endfunction() - -function(get_arm_version result cflag) - if(cflag MATCHES "^armv([0-9])") - set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE) - endif() -endfunction() - -function(check_thumb result) - extract_cflag(thumb "mthumb") - if(thumb) - set(${result} TRUE PARENT_SCOPE) - return() - else() - extract_cflag(marm "marm") - if(marm) - set(${result} FALSE PARENT_SCOPE) - return() - else() - extract_cflag(march "march") - get_arm_version(arm_version ${march}) - if(arm_version GREATER_EQUAL 7) - set(${result} TRUE PARENT_SCOPE) - return() - endif() - endif() - endif() - set(${result} FALSE PARENT_SCOPE) -endfunction() - -macro(create_pkg_config_host_wrapper buildDir) - find_package(PkgConfigHost) - if(CMAKE_CROSSCOMPILING) - create_pkg_config_wrapper("${buildDir}/pkg-config-host_wrapper.sh" "${PKG_CONFIG_HOST_EXECUTABLE}") - set(PKG_CONFIG_HOST_EXECUTABLE "${buildDir}/pkg-config-host_wrapper.sh") - endif() -endmacro() - -macro(setup_toolchains) - get_gn_arch(gn_arch ${TEST_architecture_arch}) - if(NOT CMAKE_CROSSCOMPILING) # delivered by hostBuild project - configure_gn_toolchain(host ${gn_arch} ${gn_arch} - ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in - ${buildDir}/host_toolchain) - configure_gn_toolchain(v8 ${gn_arch} ${gn_arch} - ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in - ${buildDir}/v8_toolchain) - endif() - configure_gn_toolchain(target ${gn_arch} ${gn_arch} - ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in - ${buildDir}/target_toolchain) - unset(gn_arch) -endmacro() - -macro(append_build_type_setup) - list(APPEND gnArgArg - is_qtwebengine=true - init_stack_vars=false - is_component_build=false - is_shared=true - use_sysroot=false - forbid_non_component_debug_builds=false - treat_warnings_as_errors=false - use_allocator_shim=false - use_partition_alloc=true - use_partition_alloc_as_malloc=false - use_custom_libcxx=false - enable_rust=false # We do not yet support rust - enable_chromium_prelude=false - build_tflite_with_xnnpack=false - assert_cpp20=false - ) - if(${config} STREQUAL "Debug") - list(APPEND gnArgArg is_debug=true symbol_level=2) - if(WIN32) - list(APPEND gnArgArg enable_iterator_debugging=true) - endif() - elseif(${config} STREQUAL "Release") - list(APPEND gnArgArg is_debug=false symbol_level=0) - elseif(${config} STREQUAL "RelWithDebInfo") - list(APPEND gnArgArg is_debug=false) - if(WIN32 AND NOT CLANG) - list(APPEND gnArgArg symbol_level=2) - else() - list(APPEND gnArgArg symbol_level=1) - endif() - elseif(${config} STREQUAL "MinSizeRel") - list(APPEND gnArgArg is_debug=false symbol_level=0 optimize_for_size=true) - endif() - if(FEATURE_developer_build OR (${config} STREQUAL "Debug") OR QT_FEATURE_webengine_sanitizer) - list(APPEND gnArgArg - is_official_build=false - use_viz_debugger=false - ) - else() - list(APPEND gnArgArg is_official_build=true) - if(NOT CLANG OR NOT QT_FEATURE_use_lld_linker) - list(APPEND gnArgArg - use_thin_lto=false - ) - endif() - endif() - extend_gn_list(gnArgArg - ARGS is_unsafe_developer_build - CONDITION FEATURE_developer_build - ) - - #TODO: refactor to not check for IOS here - if(NOT QT_FEATURE_webengine_full_debug_info AND NOT IOS) - list(APPEND gnArgArg blink_symbol_level=0 v8_symbol_level=0) - endif() - - extend_gn_list(gnArgArg ARGS use_jumbo_build CONDITION QT_FEATURE_webengine_jumbo_build) - if(QT_FEATURE_webengine_jumbo_build) - list(APPEND gnArgArg jumbo_file_merge_limit=${QT_FEATURE_webengine_jumbo_file_merge_limit}) - if(QT_FEATURE_webengine_jumbo_file_merge_limit LESS_EQUAL 8) - list(APPEND gnArgArg "jumbo_build_excluded=[\"browser\"]") - endif() - endif() - - extend_gn_list(gnArgArg - ARGS enable_precompiled_headers - CONDITION BUILD_WITH_PCH AND NOT LINUX - ) - extend_gn_list(gnArgArg - ARGS dcheck_always_on - CONDITION QT_FEATURE_force_asserts - ) -endmacro() - -macro(append_compiler_linker_sdk_setup) - if(CMAKE_CXX_COMPILER_LAUNCHER) - list(APPEND gnArgArg cc_wrapper="${CMAKE_CXX_COMPILER_LAUNCHER}") - endif() - - extend_gn_list(gnArgArg ARGS is_clang CONDITION CLANG) - extend_gn_list(gnArgArg ARGS is_mingw CONDITION MINGW) - extend_gn_list(gnArgArg ARGS is_msvc CONDITION MSVC) - extend_gn_list(gnArgArg ARGS is_gcc CONDITION LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - - if(CLANG) - if(MACOS) - get_darwin_sdk_version(macSdkVersion) - # macOS needs to use the objcxx compiler as the cxx compiler is just a link - get_filename_component(clangBasePath ${CMAKE_OBJCXX_COMPILER} DIRECTORY) - get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) - else() - get_filename_component(clangBasePath ${CMAKE_CXX_COMPILER} DIRECTORY) - get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) - endif() - - string(REGEX MATCH "[0-9]+" clangVersion ${CMAKE_CXX_COMPILER_VERSION}) - list(APPEND gnArgArg - clang_base_path="${clangBasePath}" - clang_use_chrome_plugins=false - clang_version=${clangVersion} - fatal_linker_warnings=false - ) - - if(MACOS) - list(APPEND gnArgArg - use_system_xcode=true - mac_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}" - mac_sdk_min="${macSdkVersion}" - use_libcxx=true - ) - _qt_internal_get_apple_sdk_version(apple_sdk_version) - if (apple_sdk_version LESS 13.2) - list(APPEND gnArgArg - use_sck=false - ) - endif() - endif() - if(IOS) - list(APPEND gnArgArg - use_system_xcode=true - enable_ios_bitcode=true - ios_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}" - ios_enable_code_signing=false - use_libcxx=true - ) - endif() - if(DEFINED QT_FEATURE_stdlib_libcpp AND LINUX) - extend_gn_list(gnArgArg ARGS use_libcxx - CONDITION QT_FEATURE_stdlib_libcpp - ) - endif() - if(ANDROID) - list(APPEND gnArgArg - android_ndk_root="${CMAKE_ANDROID_NDK}" - android_ndk_version="${CMAKE_ANDROID_NDK_VERSION}" - clang_use_default_sample_profile=false - #android_ndk_major_version=22 - ) - endif() - else() - if(QT_FEATURE_use_lld_linker) - get_filename_component(clangBasePath ${CMAKE_LINKER} DIRECTORY) - get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) - list(APPEND gnArgArg - clang_base_path="${clangBasePath}" - fatal_linker_warnings=false - ) - endif() - endif() - - if(MSVC) - get_filename_component(windows_sdk_path $ENV{WINDOWSSDKDIR} ABSOLUTE) - get_filename_component(visual_studio_path $ENV{VSINSTALLDIR} ABSOLUTE) - qt_webengine_get_windows_sdk_version(windows_sdk_version sdk_minor) - list(APPEND gnArgArg - win_linker_timing=true - use_incremental_linking=false - visual_studio_version=2022 - visual_studio_path=\"${visual_studio_path}\" - windows_sdk_version=\"${windows_sdk_version}\" - windows_sdk_path=\"${windows_sdk_path}\" - ) - endif() - get_gn_arch(cpu ${TEST_architecture_arch}) - if(LINUX AND CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm") - - extend_gn_list_cflag(gnArgArg - ARG arm_tune - CFLAG mtune - ) - extend_gn_list_cflag(gnArgArg - ARG arm_float_abi - CFLAG mfloat-abi - ) - extend_gn_list_cflag(gnArgArg - ARG arm_arch - CFLAG march - ) - extend_gn_list_cflag(gnArgArg - ARG arm_cpu - CFLAG mcpu - ) - extract_cflag(cflag "mfpu") - get_arm_version(arm_version "${cflag}") - extend_gn_list(gnArgArg - ARGS arm_use_neon - CONDITION (arm_version GREATER_EQUAL 8) OR ("${cflag}" MATCHES ".*neon.*") - ) - if(arm_version EQUAL 7 AND NOT "${cflag}" MATCHES ".*neon.*") - # If the toolchain does not explicitly specify to use NEON instructions - # we use arm_neon_optional for ARMv7 - list(APPEND gnArgArg arm_optionally_use_neon=true) - endif() - extract_cflag(march "march") - get_arm_version(arm_version ${march}) - if(arm_version EQUAL 7) - list(APPEND gnArgArg use_arm_crc32=false) - endif() - check_thumb(armThumb) - extend_gn_list(gnArgArg - ARGS arm_use_thumb - CONDITION armThumb - ) - endif() - extend_gn_list(gnArgArg - ARGS use_gold - CONDITION QT_FEATURE_use_gold_linker - ) - extend_gn_list(gnArgArg - ARGS use_lld - CONDITION QT_FEATURE_use_lld_linker - ) - unset(cpu) -endmacro() - -macro(append_sanitizer_setup) - if(QT_FEATURE_webengine_sanitizer) - extend_gn_list(gnArgArg - ARGS is_asan - CONDITION address IN_LIST ECM_ENABLE_SANITIZERS - ) - extend_gn_list(gnArgArg - ARGS is_tsan - CONDITION thread IN_LIST ECM_ENABLE_SANITIZERS - ) - extend_gn_list(gnArgArg - ARGS is_msan - CONDITION memory IN_LIST ECM_ENABLE_SANITIZERS - ) - extend_gn_list(gnArgArg - ARGS is_ubsan is_ubsan_vptr - CONDITION undefined IN_LIST ECM_ENABLE_SANITIZERS - ) - if(APPLE) - list(APPEND gnArgArg - clang_version=\"${QT_COMPILER_VERSION_MAJOR}.${QT_COMPILER_VERSION_MINOR}.${QT_COMPILER_VERSION_PATCH}\" - ) - endif() - endif() -endmacro() - -macro(append_toolchain_setup) - if(WIN32) - get_gn_arch(cpu ${arch}) - list(APPEND gnArgArg target_cpu="${cpu}") - if(MINGW) - get_gn_arch(cpu ${TEST_architecture_arch}) - list(APPEND gnArgArg - # note '/' prefix - custom_toolchain="/${buildDir}/target_toolchain:target" - host_toolchain="/${buildDir}/host_toolchain:host" - host_cpu="${cpu}" - ) - endif() - elseif(LINUX) - get_gn_arch(cpu ${TEST_architecture_arch}) - list(APPEND gnArgArg - custom_toolchain="${buildDir}/target_toolchain:target" - host_toolchain="${buildDir}/host_toolchain:host" - ) - if(CMAKE_CROSSCOMPILING) - list(APPEND gnArgArg - v8_snapshot_toolchain="${buildDir}/v8_toolchain:v8" - target_cpu="${cpu}" - ) - else() - list(APPEND gnArgArg host_cpu="${cpu}") - endif() - if(CMAKE_SYSROOT) - list(APPEND gnArgArg target_sysroot="${CMAKE_SYSROOT}") - endif() - elseif(MACOS) - get_gn_arch(cpu ${arch}) - list(APPEND gnArgArg target_cpu="${cpu}") - elseif(IOS) - get_gn_arch(cpu ${arch}) - get_ios_sysroot(sysroot ${arch}) - list(APPEND gnArgArg target_cpu="${cpu}" target_sysroot="${sysroot}" target_os="ios") - elseif(ANDROID) - get_gn_arch(cpu ${TEST_architecture_arch}) - list(APPEND gnArgArg target_os="android" target_cpu="${cpu}") - if(CMAKE_HOST_WIN32) - list(APPEND gnArgArg - host_toolchain="/${buildDir}/host_toolchain:host" - host_cpu="x64" - v8_snapshot_toolchain="/${buildDir}/v8_toolchain:v8" - ) - endif() - endif() - unset(cpu) -endmacro() - - -macro(append_pkg_config_setup) - if(PkgConfig_FOUND) - list(APPEND gnArgArg - pkg_config="${PKG_CONFIG_EXECUTABLE}" - host_pkg_config="${PKG_CONFIG_HOST_EXECUTABLE}" - ) - if(NOT "$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") - list(APPEND gnArgArg - system_libdir="$ENV{PKG_CONFIG_LIBDIR}" - ) - endif() - endif() -endmacro() - function(add_ninja_command) cmake_parse_arguments(PARSE_ARGV 0 arg - "" "TARGET;BUILDDIR;MODULE" "OUTPUT;BYPRODUCTS" + "" "TARGET;BUILDDIR;MODULE" "OUTPUT;BYPRODUCTS;DEPENDS" ) _qt_internal_validate_all_args_are_parsed(arg) @@ -865,37 +324,13 @@ function(add_ninja_command) USES_TERMINAL VERBATIM COMMAND_EXPAND_LISTS - DEPENDS run_${arg_MODULE}_NinjaReady + DEPENDS run_${arg_MODULE}_NinjaReady ${arg_DEPENDS} ) endfunction() -function(get_configs result) - if(QT_GENERATOR_IS_MULTI_CONFIG) - set(${result} ${CMAKE_CONFIGURATION_TYPES}) - else() - set(${result} ${CMAKE_BUILD_TYPE}) - endif() - if(NOT ${result}) - message(FATAL_ERROR "No valid configurations found !") - endif() - set(${result} ${${result}} PARENT_SCOPE) -endfunction() - -function(get_architectures result) - if(CMAKE_OSX_ARCHITECTURES) - set(${result} ${CMAKE_OSX_ARCHITECTURES}) - else() - set(${result} ${CMAKE_SYSTEM_PROCESSOR}) - endif() - if(NOT ${result}) - message(FATAL_ERROR "No valid architectures found. In case of cross-compiling make sure you have CMAKE_SYSTEM_PROCESSOR in your toolchain file.") - endif() - set(${result} ${${result}} PARENT_SCOPE) -endfunction() - function(add_gn_build_artifacts_to_target) cmake_parse_arguments(PARSE_ARGV 0 arg - "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP" "" + "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP;DEPENDS" "" ) _qt_internal_validate_all_args_are_parsed(arg) @@ -908,12 +343,16 @@ function(add_gn_build_artifacts_to_target) foreach(arch ${archs}) set(target ${arg_NINJA_TARGET}_${config}_${arch}) set(stamps ${arg_NINJA_STAMP} ${arg_NINJA_DATA_STAMP}) + set(data_stamp_option "") + if(arg_NINJA_DATA_STAMP) + set(data_stamp_option NINJA_DATA_STAMP ${arg_NINJA_DATA_STAMP}) + endif() add_ninja_target( TARGET ${target} NINJA_TARGET ${arg_NINJA_TARGET} CMAKE_TARGET ${arg_CMAKE_TARGET} NINJA_STAMP ${arg_NINJA_STAMP} - NINJA_DATA_STAMP ${arg_NINJA_DATA_STAMP} + ${data_stamp_option} CONFIG ${config} ARCH ${arch} BUILDDIR ${arg_BUILDDIR} @@ -923,7 +362,10 @@ function(add_gn_build_artifacts_to_target) OUTPUT ${stamps} BUILDDIR ${arg_BUILDDIR}/${config}/${arch} MODULE ${arg_MODULE} + DEPENDS ${arg_DEPENDS} ) + qt_webengine_add_gn_target_to_sbom(${arg_NINJA_TARGET} ${arg_BUILDDIR}/${config}/${arch}) + qt_webengine_add_gn_artifact_relationship_to_sbom(${arg_NINJA_TARGET} ${arg_CMAKE_TARGET}) add_dependencies(run_${arg_MODULE}_NinjaDone ${target}) set_target_properties(${arg_CMAKE_TARGET} PROPERTIES LINK_DEPENDS ${arg_BUILDDIR}/${config}/${arch}/${arg_NINJA_STAMP} @@ -1002,6 +444,7 @@ function(add_gn_command) run_${arg_MODULE}_GnReady "${WEBENGINE_ROOT_SOURCE_DIR}/src/${arg_MODULE}/configure/BUILD.root.gn.in" "${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtGnGen.cmake" + "${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtBuildGnHelpers.cmake" ) add_custom_target(runGn_${arg_GN_TARGET} DEPENDS #TODO this is fixed in cmake 3.20 so we could simply use GN_TARGET and not create new one @@ -1033,7 +476,6 @@ function(addCopyCommand target src dst) COMMAND ${CMAKE_COMMAND} -E make_directory ${dst} COMMAND ${CMAKE_COMMAND} -E copy ${src} ${dst} TARGET ${target} - DEPENDS ${src} USES_TERMINAL ) endfunction() @@ -1102,6 +544,7 @@ macro(qt_webengine_externalproject_add) -DCMAKE_OSX_ARCHITECTURES=${OSX_ARCH_STR} -DWEBENGINE_ROOT_BUILD_DIR=${PROJECT_BINARY_DIR} -DQT_ALLOW_SYMLINK_IN_PATHS=${QT_ALLOW_SYMLINK_IN_PATHS} + -DPython3_EXECUTABLE=${Python3_EXECUTABLE} ) unset(OSX_ARCH_STR) endmacro() diff --git a/cmake/QtBuildGnHelpers.cmake b/cmake/QtBuildGnHelpers.cmake index d838b8662c7..135219fcff5 100644 --- a/cmake/QtBuildGnHelpers.cmake +++ b/cmake/QtBuildGnHelpers.cmake @@ -41,6 +41,25 @@ function(recover_framework_build includeDirs compilerFlags) set(${compilerFlags} ${${compilerFlags}} ${frameworkDirs} PARENT_SCOPE) endfunction() +# CMake uses a "SHELL:" prefix to group options and avoid unwanted option de-duplication; we +# need to strip these after manually de-duplicating, but before passing to GN. +# See https://cmake.org/cmake/help/latest/command/target_compile_options.html#option-de-duplication +function(transform_cmake_compile_options_for_gn out_var compile_options_var) + get_property(flags_var DIRECTORY PROPERTY ${compile_options_var}) + + list(REMOVE_DUPLICATES flags_var) + set(out_flags "") + foreach(elem IN LISTS flags_var) + if(elem MATCHES "^SHELL:(.*)") + # Split on spaces and enclose each argument with quotes. + string(REPLACE " " "\";\"" elem "${CMAKE_MATCH_1}") + endif() + list(APPEND out_flags "\"${elem}\"") + endforeach() + + set(${out_var} ${out_flags} PARENT_SCOPE) +endfunction() + function(configure_gn_target source_dir in_file_path out_file_path path_mode) # GN_SOURCES GN_HEADERS @@ -76,18 +95,10 @@ function(configure_gn_target source_dir in_file_path out_file_path path_mode) set(GN_ARGS_MOC_BIN \"${moc_file_path}\") # GN_CFLAGS_CC - get_property(gn_cxx_compile_options DIRECTORY PROPERTY GN_CXX_COMPILE_OPTIONS) - foreach(gn_cxx_compile_option ${gn_cxx_compile_options}) - list(APPEND GN_CFLAGS_CC \"${gn_cxx_compile_option}\") - endforeach() - list(REMOVE_DUPLICATES GN_CFLAGS_CC) + transform_cmake_compile_options_for_gn(GN_CFLAGS_CC GN_CXX_COMPILE_OPTIONS) # GN_CFLAGS_C - get_property(gn_c_compile_options DIRECTORY PROPERTY GN_C_COMPILE_OPTIONS) - foreach(gn_c_compile_option ${gn_c_compile_options}) - list(APPEND GN_CFLAGS_C \"${gn_c_compile_option}\") - endforeach() - list(REMOVE_DUPLICATES GN_CFLAGS_C) + transform_cmake_compile_options_for_gn(GN_CFLAGS_C GN_C_COMPILE_OPTIONS) # GN_SOURCE_ROOT get_filename_component(GN_SOURCE_ROOT "${source_dir}" ${path_mode}) diff --git a/cmake/QtConfigureHelpers.cmake b/cmake/QtConfigureHelpers.cmake index e7c555a8caf..e469fc67a0b 100644 --- a/cmake/QtConfigureHelpers.cmake +++ b/cmake/QtConfigureHelpers.cmake @@ -36,8 +36,8 @@ endmacro() macro(qt_webengine_check_support) foreach(module_checked ${configure_checks}) - set(error_message "\n -- The following configure errors were found:") - set(warning_message "\n -- The following configure warnings were found:") + set(error_message "The following configure errors were found:") + set(warning_message "The following configure warnings were found:") string(TOLOWER ${module_checked} module) set(QT_CONFIGURE_CHECK_${module}_build ON CACHE BOOL "Build ${module_checked} Modules" FORCE) if(${configure_checks_${module}_error} OR ${configure_checks_${module}_warning}) @@ -257,8 +257,52 @@ endfunction() function(qt_webengine_get_windows_sdk_version result_sdk_full result_sdk_minor) set(windows_sdk_version $ENV{WindowsSDKVersion}) - String(REGEX REPLACE "([0-9.]+).*" "\\1" windows_sdk_version "${windows_sdk_version}") + string(REGEX REPLACE "([0-9.]+).*" "\\1" windows_sdk_version "${windows_sdk_version}") string(REGEX REPLACE "^[0-9]+\\.[0-9]+\\.([0-9]+)\\.[0-9]+" "\\1" sdk_minor "${windows_sdk_version}") set(${result_sdk_full} "${windows_sdk_version}" PARENT_SCOPE) set(${result_sdk_minor} "${sdk_minor}" PARENT_SCOPE) endfunction() + +function(qt_webengine_configure_check_coin white_list_file webengine_check pdf_check) + if("${webengine_check}" STREQUAL "" OR "${pdf_check}" STREQUAL "") + return() + endif() + set(coin_id $ENV{COIN_PLATFORM_ID}) + if(coin_id) + set(res OFF) + file(READ ${white_list_file} white_list) + string(REPLACE "\n" ";" white_list "${white_list}") + foreach(line IN LISTS white_list) + string(REPLACE " " ";" line "${line}") + list(REMOVE_ITEM line "") + if(NOT line) + continue() + endif() + list(POP_FRONT line id) + if(id MATCHES "^#") # skip comments + continue() + endif() + if(id) + set(${id} ${line}) + endif() + endforeach() + if(DEFINED ${coin_id}) + list(POP_FRONT ${coin_id} webengine_build) + list(POP_FRONT ${coin_id} pdf_build) + set(res ON) + if(webengine_build AND NOT webengine_check) + set(res OFF) + endif() + if(pdf_build AND NOT pdf_check) + set(res OFF) + endif() + else() + message(WARNING "Undefined coin sanity check for ${coin_id} platform") + return() + endif() + if(NOT res) + message(FATAL_ERROR "!!! Coin sanity check failed for ${coin_id} platform with: + (qtwebegine=${QT_CONFIGURE_CHECK_qtwebengine_build} qtpdf=${QT_CONFIGURE_CHECK_qtpdf_build}), but expected: (qtwebengine=${webengine_build} qtpdf=${pdf_build})") + endif() + endif() +endfunction() diff --git a/cmake/QtGnConfigHelpers.cmake b/cmake/QtGnConfigHelpers.cmake index bee08a96745..62469c09828 100644 --- a/cmake/QtGnConfigHelpers.cmake +++ b/cmake/QtGnConfigHelpers.cmake @@ -62,7 +62,7 @@ endfunction() function(create_c_config cmake_target arch config_file_name) file(GENERATE OUTPUT $/${arch}/${config_file_name} - CONTENT "set(GN_C_COMPILE_OPTIONS $)" + CONTENT "set(GN_C_COMPILE_OPTIONS \"$\")" CONDITION $ TARGET ${cmake_target}) endfunction() diff --git a/cmake/QtGnCredits.cmake b/cmake/QtGnCredits.cmake index 87cdd7d24e3..499698cb906 100644 --- a/cmake/QtGnCredits.cmake +++ b/cmake/QtGnCredits.cmake @@ -18,7 +18,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT) if(NOT Python3_EXECUTABLE) - find_package(Python3 3.6 REQUIRED) + message(FATAL_ERROR "\nPython3_EXECUTABLE not set.\n") endif() set(extra_third_party_dirs "") diff --git a/cmake/QtGnGen.cmake b/cmake/QtGnGen.cmake index 3ad41ef8cfe..a961330744f 100644 --- a/cmake/QtGnGen.cmake +++ b/cmake/QtGnGen.cmake @@ -29,7 +29,7 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT) if(NOT Python3_EXECUTABLE) - find_package(Python3 3.6 REQUIRED) + message(FATAL_ERROR "\nPython3_EXECUTABLE not set.\n") endif() set(gn_command ${Gn_EXECUTABLE}) diff --git a/cmake/QtGnSbom.cmake b/cmake/QtGnSbom.cmake new file mode 100644 index 00000000000..905efed1370 --- /dev/null +++ b/cmake/QtGnSbom.cmake @@ -0,0 +1,53 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# This is a wrapper around sbom.py which creates an SBOM document for a GN-based target. + +if(NOT CMAKE_SCRIPT_MODE_FILE) + message(FATAL_ERROR "This file should run only in script mode") + return() +endif() + +foreach(variable + Python3_EXECUTABLE SCRIPT_PATH GN_TARGET_LIST BUILD_DIR_LIST + PACKAGE_ID DOC_NAMESPACE OUTPUT) + if(NOT DEFINED ${variable} OR "${${variable}}" STREQUAL "") + message(FATAL_ERROR "\n${variable} not set (${${variable}})\n") + endif() +endforeach() + +set(path_mode REALPATH) +if(APPLE AND QT_ALLOW_SYMLINK_IN_PATHS) + set(path_mode ABSOLUTE) +endif() + +get_filename_component(WEBENGINE_ROOT_SOURCE_DIR "${CMAKE_CURRENT_LIST_DIR}/.." ${path_mode}) +get_filename_component(WEBENGINE_ROOT_BUILD_DIR "${CMAKE_CURRENT_BINARY_DIR}" ${path_mode}) + +include(${WEBENGINE_ROOT_SOURCE_DIR}/.cmake.conf) +include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtBuildGnHelpers.cmake) + +set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_LIST_DIR}) + +find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT MODULE REQUIRED) + +execute_process( + COMMAND "${Python3_EXECUTABLE}" "${SCRIPT_PATH}" + --gn-binary "${Gn_EXECUTABLE}" + --gn-target-list "${GN_TARGET_LIST}" + --build-dir-list "${BUILD_DIR_LIST}" + --gn-version ${Gn_VERSION} + --package-id ${PACKAGE_ID} + --namespace "${DOC_NAMESPACE}" + "${OUTPUT}" + RESULT_VARIABLE gn_result + OUTPUT_VARIABLE gn_output + ERROR_VARIABLE gn_error + TIMEOUT 600 +) + +if(NOT gn_result EQUAL 0) + string(REGEX REPLACE "\n$" "" gn_output "${gn_output}") + string(REGEX REPLACE "\n$" "" gn_error "${gn_error}") + message(FATAL_ERROR "\n-- SBOM generation FAILED\n${gn_output}\n${gn_error}\n-- Exit code: ${gn_result}\n") +endif() diff --git a/cmake/QtToolchainHelpers.cmake b/cmake/QtToolchainHelpers.cmake new file mode 100644 index 00000000000..eaa3a433908 --- /dev/null +++ b/cmake/QtToolchainHelpers.cmake @@ -0,0 +1,625 @@ +# Copyright (C) 2025 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +function(get_darwin_sdk_version result) + if(APPLE) + if(IOS) + set(sdk_name "iphoneos") + elseif(TVOS) + set(sdk_name "appletvos") + elseif(WATCHOS) + set(sdk_name "watchos") + else() + # Default to macOS + set(sdk_name "macosx") + endif() + set(xcrun_version_arg "--show-sdk-version") + execute_process(COMMAND /usr/bin/xcrun --sdk ${sdk_name} ${xcrun_version_arg} + OUTPUT_VARIABLE sdk_version + ERROR_VARIABLE xcrun_error) + if(NOT sdk_version) + message(FATAL_ERROR + "Can't determine darwin ${sdk_name} SDK version. Error: ${xcrun_error}") + endif() + string(STRIP "${sdk_version}" sdk_version) + set(${result} "${sdk_version}" PARENT_SCOPE) + endif() +endfunction() + +function(get_ios_target_triple_and_sysroot result arch) + get_ios_sysroot(sysroot ${arch}) + set(${result} + -target ${arch}-apple-ios${CMAKE_OSX_DEPLOYMENT_TARGET} + -isysroot ${sysroot} PARENT_SCOPE + ) +endfunction() + +# Function maps TEST_architecture_arch or CMAKE_SYSTEM_PROCESSOR into gn architecture +function(get_gn_arch result arch) + set(armList arm armv7-a) + set(arm64List arm64 ARM64 aarch64) + set(mips64List mips64 mipsel64) + set(x86List i386 i686) + set(x64List x86_64 AMD64 x86_64h) + if(arch IN_LIST x86List) + set(${result} "x86" PARENT_SCOPE) + elseif(arch IN_LIST x64List) + set(${result} "x64" PARENT_SCOPE) + elseif(arch IN_LIST armList) + set(${result} "arm" PARENT_SCOPE) + elseif(arch IN_LIST arm64List) + set(${result} "arm64" PARENT_SCOPE) + elseif(arch STREQUAL "mipsel") + set(${result} "mipsel" PARENT_SCOPE) + elseif(arch IN_LIST mipsList) + set(${result} "mips64el" PARENT_SCOPE) + elseif(arch STREQUAL "riscv64") + set(${result} "riscv64" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown architecture: ${arch}") + endif() +endfunction() + +# Function maps gn architecture for v8 +function(get_v8_arch result targetArch hostArch) + set(list32 x86 arm mipsel riscv32) + if(hostArch STREQUAL targetArch) + set(${result} "${targetArch}" PARENT_SCOPE) + elseif(targetArch IN_LIST list32) + # 32bit target which needs a 32bit compatible host + if(hostArch STREQUAL "x64") + set(${result} "x86" PARENT_SCOPE) + elseif(hostArch STREQUAL "arm64") + set(${result} "arm" PARENT_SCOPE) + elseif(hostArch STREQUAL "mips64el") + set(${result} "mipsel" PARENT_SCOPE) + elseif(hostArch STREQUAL "riscv64") + set(${result} "riscv32" PARENT_SCOPE) + elseif(hostArch IN_LIST list32) + set(${result} "${hostArch}" PARENT_SCOPE) + else() + message(FATAL_ERROR "Unknown architecture: ${hostArch}") + endif() + else() + # assume 64bit target which matches 64bit host + set(${result} "${hostArch}" PARENT_SCOPE) + endif() +endfunction() + +function(get_gn_os result) + if(WIN32) + set(${result} "win" PARENT_SCOPE) + elseif(LINUX) + set(${result} "linux" PARENT_SCOPE) + elseif(MACOS) + set(${result} "mac" PARENT_SCOPE) + elseif(IOS) + set(${result} "ios" PARENT_SCOPE) + else() + message(DEBUG "Unrecognized OS") + endif() +endfunction() + +function(get_gn_is_clang result) + if(CLANG) + set(${result} "true" PARENT_SCOPE) + else() + set(${result} "false" PARENT_SCOPE) + endif() +endfunction() + +function(get_gn_is_mingw result) + if(MINGW) + set(${result} "true" PARENT_SCOPE) + else() + set(${result} "false" PARENT_SCOPE) + endif() +endfunction() + +function(get_ios_sysroot result arch) + if(NOT CMAKE_APPLE_ARCH_SYSROOTS) + message(FATAL_ERROR "CMAKE_APPLE_ARCH_SYSROOTS not set.") + endif() + get_architectures(archs) + list(FIND archs ${arch} known_arch) + if (known_arch EQUAL "-1") + message(FATAL_ERROR "Unknown iOS architecture ${arch}.") + endif() + list(GET CMAKE_APPLE_ARCH_SYSROOTS ${known_arch} sysroot) + set(${result} ${sysroot} PARENT_SCOPE) +endfunction() + +function(configure_gn_toolchain name cpu v8Cpu toolchainIn toolchainOut) + set(GN_TOOLCHAIN ${name}) + get_gn_os(GN_OS) + get_gn_is_clang(GN_IS_CLANG) + get_gn_is_mingw(GN_IS_MINGW) + set(GN_CPU ${cpu}) + set(GN_V8_CPU ${v8Cpu}) + configure_file(${toolchainIn} ${toolchainOut}/BUILD.gn @ONLY) +endfunction() + +function(create_pkg_config_wrapper wrapperName wrapperCmd) + file(WRITE ${wrapperName} + "#!/bin/sh\n" + "unset PKG_CONFIG_LIBDIR\n" + "unset PKG_CONFIG_PATH\n" + "unset PKG_CONFIG_SYSROOT_DIR\n" + "exec ${wrapperCmd} \"$@\"" + ) + file(CHMOD ${wrapperName} PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE) +endfunction() + +function(extract_cflag result cflag) + set(i 1) + while(NOT "x${CMAKE_CXX_COMPILER_ARG${i}}" STREQUAL "x") + list(APPEND cflags ${CMAKE_CXX_COMPILER_ARG${i}}) + math(EXPR i "${i} + 1") + endwhile() + list(APPEND cflags ${CMAKE_C_FLAGS} ${CMAKE_CXX_FLAGS}) + string(REPLACE ";" " " cflags "${cflags}") + message(DEBUG "Found cflags: ${cflags}") + if(cflags MATCHES "-${cflag}=([^ ]+)") + set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE) + return() + endif() + if(cflags MATCHES "-${cflag}") + set(${result} ON PARENT_SCOPE) + else() + set(${result} OFF PARENT_SCOPE) + endif() +endfunction() + +function(extend_gn_list_cflag outList) + cmake_parse_arguments(PARSE_ARGV 1 GN "" "" "ARG;CFLAG") + _qt_internal_validate_all_args_are_parsed(GN) + + extract_cflag(cflag "${GN_CFLAG}") + if(cflag) + set(${outList} "${${outList}}" "${GN_ARG}=\"${cflag}\"" PARENT_SCOPE) + endif() +endfunction() + +function(get_arm_version result cflag) + if(cflag MATCHES "^armv([0-9])") + set(${result} ${CMAKE_MATCH_1} PARENT_SCOPE) + endif() +endfunction() + +function(check_thumb result) + extract_cflag(thumb "mthumb") + if(thumb) + set(${result} TRUE PARENT_SCOPE) + return() + else() + extract_cflag(marm "marm") + if(marm) + set(${result} FALSE PARENT_SCOPE) + return() + else() + extract_cflag(march "march") + get_arm_version(arm_version ${march}) + if(arm_version GREATER_EQUAL 7) + set(${result} TRUE PARENT_SCOPE) + return() + endif() + endif() + endif() + set(${result} FALSE PARENT_SCOPE) +endfunction() + +macro(create_pkg_config_host_wrapper buildDir) + find_package(PkgConfigHost) + if(CMAKE_CROSSCOMPILING) + create_pkg_config_wrapper("${buildDir}/pkg-config-host_wrapper.sh" "${PKG_CONFIG_HOST_EXECUTABLE}") + set(PKG_CONFIG_HOST_EXECUTABLE "${buildDir}/pkg-config-host_wrapper.sh") + endif() +endmacro() + +macro(setup_toolchains) + if(MSVC) + if(CLANG) + set(toolchain_in_file "BUILD.clang-cl.toolchain.gn.in") + else() + set(toolchain_in_file "BUILD.msvc.toolchain.gn.in") + endif() + else() + set(toolchain_in_file "BUILD.toolchain.gn.in") + endif() + get_gn_arch(gn_arch ${TEST_architecture_arch}) + if(NOT CMAKE_CROSSCOMPILING) # delivered by hostBuild project + configure_gn_toolchain(host ${gn_arch} ${gn_arch} + ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/${toolchain_in_file} + ${buildDir}/host_toolchain) + configure_gn_toolchain(v8 ${gn_arch} ${gn_arch} + ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/${toolchain_in_file} + ${buildDir}/v8_toolchain) + endif() + configure_gn_toolchain(target ${gn_arch} ${gn_arch} + ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/${toolchain_in_file} + ${buildDir}/target_toolchain) + unset(gn_arch) + unset(toolchain_in_file) +endmacro() + +macro(append_build_type_setup) + list(APPEND gnArgArg + use_ml=false + init_stack_vars=false + is_component_build=false + is_shared=true + use_sysroot=false + forbid_non_component_debug_builds=false + treat_warnings_as_errors=false + use_allocator_shim=false + use_freelist_dispatcher=false + use_partition_alloc=true + use_partition_alloc_as_malloc=false + use_custom_libcxx=false + enable_rust=false # We do not yet support rust + enable_chromium_prelude=false + assert_cpp20=false + ) + if(${config} STREQUAL "Debug") + list(APPEND gnArgArg is_debug=true symbol_level=2) + if(WIN32) + list(APPEND gnArgArg enable_iterator_debugging=true) + endif() + elseif(${config} STREQUAL "Release") + list(APPEND gnArgArg is_debug=false symbol_level=0) + elseif(${config} STREQUAL "RelWithDebInfo") + list(APPEND gnArgArg is_debug=false) + if(WIN32 AND NOT CLANG) + list(APPEND gnArgArg symbol_level=2) + else() + list(APPEND gnArgArg symbol_level=1) + endif() + elseif(${config} STREQUAL "MinSizeRel") + list(APPEND gnArgArg is_debug=false symbol_level=0 optimize_for_size=true) + endif() + if(FEATURE_developer_build OR (${config} STREQUAL "Debug") OR QT_FEATURE_webengine_sanitizer) + list(APPEND gnArgArg + is_official_build=false + use_viz_debugger=false + ) + else() + list(APPEND gnArgArg is_official_build=true) + if(NOT CLANG OR NOT QT_FEATURE_use_lld_linker) + list(APPEND gnArgArg + use_thin_lto=false + ) + endif() + endif() + extend_gn_list(gnArgArg + ARGS is_unsafe_developer_build + CONDITION FEATURE_developer_build + ) + + #TODO: refactor to not check for IOS here + if(NOT QT_FEATURE_webengine_full_debug_info AND NOT IOS) + list(APPEND gnArgArg blink_symbol_level=0 v8_symbol_level=0) + endif() + + extend_gn_list(gnArgArg ARGS use_jumbo_build CONDITION QT_FEATURE_webengine_jumbo_build) + if(QT_FEATURE_webengine_jumbo_build) + list(APPEND gnArgArg jumbo_file_merge_limit=${QT_FEATURE_webengine_jumbo_file_merge_limit}) + if(QT_FEATURE_webengine_jumbo_file_merge_limit LESS_EQUAL 8) + list(APPEND gnArgArg "jumbo_build_excluded=[\"browser\"]") + endif() + endif() + + extend_gn_list(gnArgArg + ARGS enable_precompiled_headers + CONDITION BUILD_WITH_PCH AND NOT LINUX + ) + extend_gn_list(gnArgArg + ARGS dcheck_always_on + CONDITION QT_FEATURE_force_asserts + ) +endmacro() + +function(get_clang_version_from_runtime_path result) +if(CLANG AND CMAKE_CXX_COMPILER) + if(NOT DEFINED CLANG_RUNTIME_PATH) + set(CLANG_PRINT_RUNTIME_DIR_COMMAND -print-runtime-dir) + if (MSVC) + # clang-cl does not accept the argument unless it's piped via /clang: + set(CLANG_PRINT_RUNTIME_DIR_COMMAND /clang:-print-runtime-dir) + endif() + execute_process( + COMMAND ${CMAKE_CXX_COMPILER} ${CLANG_PRINT_RUNTIME_DIR_COMMAND} + OUTPUT_VARIABLE clang_output + ERROR_QUIET + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + cmake_path(CONVERT "${clang_output}" TO_CMAKE_PATH_LIST clang_output NORMALIZE) + set(CLANG_RUNTIME_PATH "${clang_output}" CACHE INTERNAL "internal") + mark_as_advanced(CLANG_RUNTIME_PATH) + endif() + string(REGEX MATCH "\\/([0-9.]+)\\/" clang_run_time_path_version "${CLANG_RUNTIME_PATH}") + if(clang_run_time_path_version) + string(REPLACE "/" "" clang_run_time_path_version ${clang_run_time_path_version}) + else() + string(REGEX MATCH "[0-9]+" clang_run_time_path_version ${CMAKE_CXX_COMPILER_VERSION}) + endif() + set(${result} ${clang_run_time_path_version} PARENT_SCOPE) +endif() +endfunction() + +macro(append_compiler_linker_sdk_setup) + if(CMAKE_CXX_COMPILER_LAUNCHER) + list(APPEND gnArgArg cc_wrapper="${CMAKE_CXX_COMPILER_LAUNCHER}") + endif() + + extend_gn_list(gnArgArg ARGS is_clang CONDITION CLANG) + extend_gn_list(gnArgArg ARGS is_mingw CONDITION MINGW) + extend_gn_list(gnArgArg ARGS is_msvc CONDITION MSVC) + extend_gn_list(gnArgArg ARGS is_gcc CONDITION LINUX AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + + if(CLANG) + if(MACOS) + get_darwin_sdk_version(macSdkVersion) + # macOS needs to use the objcxx compiler as the cxx compiler is just a link + get_filename_component(clangBasePath ${CMAKE_OBJCXX_COMPILER} DIRECTORY) + get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) + else() + get_filename_component(clangBasePath ${CMAKE_CXX_COMPILER} DIRECTORY) + get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) + endif() + get_clang_version_from_runtime_path(clang_version) + if (NOT DEFINED clang_version) + message(FATAL_ERROR "Clang version for runtime is missing." + "Please open bug report.Found clang runtime path: ${CLANG_RUNTIME_PATH}" + ) + endif() + list(APPEND gnArgArg + clang_base_path="${clangBasePath}" + clang_version="${clang_version}" + clang_use_chrome_plugins=false + fatal_linker_warnings=false + ) + + if(MACOS) + list(APPEND gnArgArg + use_system_xcode=true + mac_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}" + mac_sdk_min="${macSdkVersion}" + use_libcxx=true + ) + _qt_internal_get_apple_sdk_version(apple_sdk_version) + if (apple_sdk_version LESS 13.2) + list(APPEND gnArgArg + use_sck=false + ) + endif() + endif() + if(IOS) + list(APPEND gnArgArg + use_system_xcode=true + enable_ios_bitcode=true + ios_deployment_target="${CMAKE_OSX_DEPLOYMENT_TARGET}" + ios_enable_code_signing=false + use_libcxx=true + ) + endif() + if(DEFINED QT_FEATURE_stdlib_libcpp AND LINUX) + extend_gn_list(gnArgArg ARGS use_libcxx + CONDITION QT_FEATURE_stdlib_libcpp + ) + endif() + if(ANDROID) + list(APPEND gnArgArg + android_ndk_root="${CMAKE_ANDROID_NDK}" + android_ndk_version="${CMAKE_ANDROID_NDK_VERSION}" + clang_use_default_sample_profile=false + #android_ndk_major_version=22 + ) + endif() + else() + if(QT_FEATURE_use_lld_linker) + get_filename_component(clangBasePath ${CMAKE_LINKER} DIRECTORY) + get_filename_component(clangBasePath ${clangBasePath} DIRECTORY) + list(APPEND gnArgArg + clang_base_path="${clangBasePath}" + fatal_linker_warnings=false + ) + endif() + endif() + + if(MSVC) + get_filename_component(windows_sdk_path $ENV{WINDOWSSDKDIR} ABSOLUTE) + get_filename_component(visual_studio_path $ENV{VSINSTALLDIR} ABSOLUTE) + get_filename_component(wdk_path $ENV{WINDOWSSDKDIR} ABSOLUTE) + qt_webengine_get_windows_sdk_version(windows_sdk_version sdk_minor) + list(APPEND gnArgArg + win_linker_timing=true + use_incremental_linking=false + visual_studio_version=2022 + visual_studio_path=\"${visual_studio_path}\" + windows_sdk_version=\"${windows_sdk_version}\" + windows_sdk_path=\"${windows_sdk_path}\" + wdk_path=\"${windows_sdk_path}\" + setup_toolchain_script=\"//build/toolchain/win/qwe_setup_toolchain.py\" + ) + endif() + get_gn_arch(cpu ${TEST_architecture_arch}) + if(LINUX AND CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm") + + extend_gn_list_cflag(gnArgArg + ARG arm_tune + CFLAG mtune + ) + extend_gn_list_cflag(gnArgArg + ARG arm_float_abi + CFLAG mfloat-abi + ) + extend_gn_list_cflag(gnArgArg + ARG arm_arch + CFLAG march + ) + extend_gn_list_cflag(gnArgArg + ARG arm_cpu + CFLAG mcpu + ) + extract_cflag(cflag "mfpu") + get_arm_version(arm_version "${cflag}") + extend_gn_list(gnArgArg + ARGS arm_use_neon + CONDITION (arm_version GREATER_EQUAL 8) OR ("${cflag}" MATCHES ".*neon.*") + ) + if(arm_version EQUAL 7 AND NOT "${cflag}" MATCHES ".*neon.*") + # If the toolchain does not explicitly specify to use NEON instructions + # we use arm_neon_optional for ARMv7 + list(APPEND gnArgArg arm_optionally_use_neon=true) + endif() + extract_cflag(march "march") + get_arm_version(arm_version ${march}) + if(arm_version EQUAL 7) + list(APPEND gnArgArg use_arm_crc32=false) + endif() + check_thumb(armThumb) + extend_gn_list(gnArgArg + ARGS arm_use_thumb + CONDITION armThumb + ) + endif() + extend_gn_list(gnArgArg + ARGS use_gold + CONDITION QT_FEATURE_use_gold_linker + ) + extend_gn_list(gnArgArg + ARGS use_lld + CONDITION QT_FEATURE_use_lld_linker OR (MSVC AND CLANG) + ) + unset(cpu) +endmacro() + +macro(append_sanitizer_setup) + if(QT_FEATURE_webengine_sanitizer) + extend_gn_list(gnArgArg + ARGS is_asan + CONDITION address IN_LIST ECM_ENABLE_SANITIZERS + ) + extend_gn_list(gnArgArg + ARGS is_tsan + CONDITION thread IN_LIST ECM_ENABLE_SANITIZERS + ) + extend_gn_list(gnArgArg + ARGS is_msan + CONDITION memory IN_LIST ECM_ENABLE_SANITIZERS + ) + extend_gn_list(gnArgArg + ARGS is_ubsan is_ubsan_vptr + CONDITION undefined IN_LIST ECM_ENABLE_SANITIZERS + ) + if(APPLE) + list(APPEND gnArgArg + clang_version=\"${QT_COMPILER_VERSION_MAJOR}.${QT_COMPILER_VERSION_MINOR}.${QT_COMPILER_VERSION_PATCH}\" + ) + endif() + endif() +endmacro() + +macro(append_toolchain_setup) + if(WIN32) + if(CMAKE_CROSSCOMPILING) + #TODO: fetch this from HOST QT or gn + set(host_cpu "x64") + get_gn_arch(target_cpu ${TEST_architecture_arch}) + else() + get_gn_arch(host_cpu ${TEST_architecture_arch}) + set(target_cpu ${host_cpu}) + endif() + list(APPEND gnArgArg target_cpu="${target_cpu}") + if(MINGW) + list(APPEND gnArgArg + # note '/' prefix + custom_toolchain="/${buildDir}/target_toolchain:target" + host_toolchain="/${buildDir}/host_toolchain:host" + host_cpu="${host_cpu}" + ) + else() + #TODO: no point genrete this in buildDir, it is a fixed set of toolchain afterall + list(APPEND gnArgArg + # note '/' prefix + custom_toolchain="/${buildDir}/target_toolchain:${target_cpu}" + host_toolchain="/${buildDir}/target_toolchain:${host_cpu}" + ) + endif() + unset(host_cpu) + unset(target_cpu) + elseif(LINUX) + get_gn_arch(cpu ${TEST_architecture_arch}) + list(APPEND gnArgArg + custom_toolchain="${buildDir}/target_toolchain:target" + host_toolchain="${buildDir}/host_toolchain:host" + ) + if(CMAKE_CROSSCOMPILING) + list(APPEND gnArgArg + v8_snapshot_toolchain="${buildDir}/v8_toolchain:v8" + target_cpu="${cpu}" + ) + else() + list(APPEND gnArgArg host_cpu="${cpu}") + endif() + if(CMAKE_SYSROOT) + list(APPEND gnArgArg target_sysroot="${CMAKE_SYSROOT}") + endif() + elseif(MACOS) + get_gn_arch(cpu ${arch}) + list(APPEND gnArgArg target_cpu="${cpu}") + elseif(IOS) + get_gn_arch(cpu ${arch}) + get_ios_sysroot(sysroot ${arch}) + list(APPEND gnArgArg target_cpu="${cpu}" target_sysroot="${sysroot}" target_os="ios") + elseif(ANDROID) + get_gn_arch(cpu ${TEST_architecture_arch}) + list(APPEND gnArgArg target_os="android" target_cpu="${cpu}") + if(CMAKE_HOST_WIN32) + list(APPEND gnArgArg + host_toolchain="/${buildDir}/host_toolchain:host" + host_cpu="x64" + v8_snapshot_toolchain="/${buildDir}/v8_toolchain:v8" + ) + endif() + endif() + unset(cpu) +endmacro() + +macro(append_pkg_config_setup) + if(PkgConfig_FOUND) + list(APPEND gnArgArg + pkg_config="${PKG_CONFIG_EXECUTABLE}" + host_pkg_config="${PKG_CONFIG_HOST_EXECUTABLE}" + ) + if(NOT "$ENV{PKG_CONFIG_LIBDIR}" STREQUAL "") + list(APPEND gnArgArg + system_libdir="$ENV{PKG_CONFIG_LIBDIR}" + ) + endif() + endif() +endmacro() + +function(get_configs result) + if(QT_GENERATOR_IS_MULTI_CONFIG) + set(${result} ${CMAKE_CONFIGURATION_TYPES}) + else() + set(${result} ${CMAKE_BUILD_TYPE}) + endif() + if(NOT ${result}) + message(FATAL_ERROR "No valid configurations found !") + endif() + set(${result} ${${result}} PARENT_SCOPE) +endfunction() + +function(get_architectures result) + if(CMAKE_OSX_ARCHITECTURES) + set(${result} ${CMAKE_OSX_ARCHITECTURES}) + else() + set(${result} ${CMAKE_SYSTEM_PROCESSOR}) + endif() + if(NOT ${result}) + message(FATAL_ERROR "No valid architectures found. In case of cross-compiling make sure you have CMAKE_SYSTEM_PROCESSOR in your toolchain file.") + endif() + set(${result} ${${result}} PARENT_SCOPE) +endfunction() diff --git a/cmake/QtWebEngineSbomHelpers.cmake b/cmake/QtWebEngineSbomHelpers.cmake new file mode 100644 index 00000000000..c16b5af39a7 --- /dev/null +++ b/cmake/QtWebEngineSbomHelpers.cmake @@ -0,0 +1,145 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + +# Helper functions for SBOM generation. We defer setting up targets until the end of build setup +# because we only want to generate e.g. one SBOM document for WebEngine. This in turn requires +# us to only call sbom.py once for WebEngine. + +# Setup data structures used in other calls +function(qt_webengine_sbom_project_begin project_name cmake_target_name) + if(NOT QT_GENERATE_SBOM) + return() + endif() + + set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_PROJECT_NAME ${project_name}) + set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_CMAKE_TARGET_NAME ${cmake_target_name}) + set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_GN_TARGETS "") + set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_BUILD_DIRS "") + set_property(GLOBAL PROPERTY QTWEBENGINE_SBOM_CMAKE_TO_GN_DEPENDENCY_PAIRS "") +endfunction() + +# Add a GN target to the list of components contained in an SBOM document +function(qt_webengine_add_gn_target_to_sbom gn_target build_dir) + if(NOT QT_GENERATE_SBOM) + return() + endif() + + get_property(project_name GLOBAL PROPERTY QTWEBENGINE_SBOM_PROJECT_NAME) + if(NOT DEFINED project_name) + message(FATAL_ERROR "Call qt_webengine_sbom_project_begin first") + return() + endif() + + set_property(GLOBAL APPEND PROPERTY QTWEBENGINE_SBOM_GN_TARGETS ":${gn_target}") + set_property(GLOBAL APPEND PROPERTY QTWEBENGINE_SBOM_BUILD_DIRS "${build_dir}") +endfunction() + +function(qt_webengine_add_gn_artifact_relationship_to_sbom ninja_target cmake_target) + if(NOT QT_GENERATE_SBOM) + return() + endif() + + set_property(GLOBAL APPEND PROPERTY QTWEBENGINE_SBOM_CMAKE_TO_GN_DEPENDENCY_PAIRS + "${cmake_target};${ninja_target}") +endfunction() + +# Join all the targets into (at most) two documents for Pdf / WebEngine +function(qt_webengine_sbom_project_end) + if(NOT QT_GENERATE_SBOM) + return() + endif() + + # We have the situation that qtbase by default does not generate JSON files if the required + # python dependency spdx-tools is not found. + # But QtWebEngine requires the spdx-tools package to be available, otherwise we can't generate + # a tag/value document from the Chromium-generated json file, and then link the Chromium + # SBOM document to the qtwebengine one. + # Skip the Chromium SBOM generation if the dependency is not found. + # A warning or skip message should have already been shown at general configure check time. + qt_internal_sbom_verify_deps_for_generate_tag_value_spdx_document( + OUT_VAR_DEPS_FOUND sbom_deps_found + ) + if(NOT sbom_deps_found) + return() + endif() + + get_property(project_name GLOBAL PROPERTY QTWEBENGINE_SBOM_PROJECT_NAME) + get_property(gn_target_list GLOBAL PROPERTY QTWEBENGINE_SBOM_GN_TARGETS) + get_property(build_dir_list GLOBAL PROPERTY QTWEBENGINE_SBOM_BUILD_DIRS) + get_property(cmake_target_name GLOBAL PROPERTY QTWEBENGINE_SBOM_CMAKE_TARGET_NAME) + get_property(cmake_to_gn_dep_pairs GLOBAL PROPERTY + QTWEBENGINE_SBOM_CMAKE_TO_GN_DEPENDENCY_PAIRS) + + string(TOLOWER ${project_name} project_name_lower) + set(chromium_project_name QtWebEngine-Chromium-${project_name}) + string(TOLOWER ${chromium_project_name} chromium_project_name_lower) + qt_internal_sbom_get_project_supplier_url(http://github.com/supplier_url) + qt_internal_sbom_compute_project_namespace(doc_namespace SUPPLIER_URL ${supplier_url} + PROJECT_NAME ${chromium_project_name_lower}) + qt_internal_sbom_compute_project_file_name(output_file_name EXTENSION_JSON + PROJECT_NAME ${chromium_project_name_lower}) + set(output_file_path ${WEBENGINE_ROOT_BUILD_DIR}/qt_sbom/${output_file_name}) + + set(generate_sbom_script_path + "${CMAKE_CURRENT_BINARY_DIR}/gen_qtwebengine_chromium_sbom_${project_name}-$.cmake") + set(chromium_sbom_script + "${WEBENGINE_ROOT_SOURCE_DIR}/src/3rdparty/chromium/tools/licenses/sbom.py") + set(generate_sbom_script_contents " +message(STATUS \"Generating Chromium SBOM for ${project_name}...\") +execute_process( + COMMAND \"${CMAKE_COMMAND}\" + \"-DSCRIPT_PATH=${chromium_sbom_script}\" + \"-DGN_TARGET_LIST=${gn_target_list}\" + \"-DBUILD_DIR_LIST=${build_dir_list}\" + \"-DQT_HOST_PATH=${QT_HOST_PATH}\" + \"-DQT6_HOST_INFO_LIBEXECDIR=${QT6_HOST_INFO_LIBEXECDIR}\" + \"-DQT6_HOST_INFO_BINDIR=${QT6_HOST_INFO_BINDIR}\" + -DPACKAGE_ID=${project_name} + -DDOC_NAMESPACE=${doc_namespace} + \"-DOUTPUT=${output_file_path}\" + \"-DPython3_EXECUTABLE=${Python3_EXECUTABLE}\" + -P \"${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtGnSbom.cmake\" + WORKING_DIRECTORY \"${WEBENGINE_ROOT_BUILD_DIR}\" + COMMAND_ERROR_IS_FATAL ANY +) +file(INSTALL \"${output_file_path}\" DESTINATION \"${QT6_INSTALL_PREFIX}/${INSTALL_SBOMDIR}\") +message(STATUS \"Done generating Chromium SBOM for ${project_name}.\") +") + file(GENERATE OUTPUT "${generate_sbom_script_path}" CONTENT "${generate_sbom_script_contents}") + qt_internal_sbom_add_cmake_include_step(STEP BEGIN INCLUDE_PATH "${generate_sbom_script_path}") + qt_internal_sbom_generate_tag_value_spdx_document( + OPERATION_ID ${chromium_project_name_lower} + INPUT_JSON_FILE_PATH "${output_file_path}" + OUT_VAR_OUTPUT_FILE_NAME external_output_file_name + ) + # Reference to external document. + qt_internal_sbom_get_external_document_ref_spdx_id(${chromium_project_name_lower} document_ref_spdx_id) + set(external_package_spdx_id "SPDXRef-${chromium_project_name}-Internal-Components") + qt_internal_sbom_add_external_reference( + EXTERNAL_DOCUMENT_FILE_PATH "sbom/${external_output_file_name}" + EXTERNAL_DOCUMENT_SPDX_ID "${document_ref_spdx_id}" + EXTERNAL_PACKAGE_SPDX_ID "${external_package_spdx_id}" + ) + + while(NOT "${cmake_to_gn_dep_pairs}" STREQUAL "") + list(POP_FRONT cmake_to_gn_dep_pairs cmake_target gn_target) + qt_internal_sbom_get_target_spdx_id("${cmake_target}" cmake_spdx_id) + qt_internal_sbom_get_sanitized_spdx_id(gn_spdx_id + "SPDXRef-${chromium_project_name}-${gn_target}") + set(relationship "${cmake_spdx_id} CONTAINS ${document_ref_spdx_id}:${gn_spdx_id}") + qt_internal_extend_target(${cmake_target} + SBOM_RELATIONSHIPS + "${relationship}" + ) + endwhile() +endfunction() + +# Shims for SBOM commands that may be missing < 6.9 +if(NOT COMMAND qt_internal_sbom_begin_qt_repo_project) + function(qt_internal_sbom_begin_qt_repo_project) + endfunction() + function(qt_internal_sbom_end_qt_repo_project) + endfunction() + function(qt_internal_sbom_add_files) + endfunction() +endif() diff --git a/coin.nodes b/coin.nodes new file mode 100644 index 00000000000..0b00f30363d --- /dev/null +++ b/coin.nodes @@ -0,0 +1,49 @@ +# coin-platofrm-id # builds-webengine # builds-pdf # +android-arm64-on-macos OFF ON +android-armv7-on-windows OFF ON +android-9-x86-on-linux OFF ON +android-15-x86_64-on-linux OFF ON +android-14-x86_64-on-linux OFF ON +ios-universal OFF ON +macos-14-arm64-developer-build ON ON +macos-14-x86_64-developer-build ON ON +macos-universal-on-arm64 ON ON +macos-universal-on-x86_64 ON ON +qemu-arm64-developer-build ON ON +qemu-armv7-developer-build ON ON +qemu-mips64-developer-build OFF OFF +qnx-710-arm64-on-linux OFF OFF +qnx-710-armv7-on-linux OFF OFF +qnx-710-x86_64-developer-build-on-linux OFF OFF +qnx-710-arm64-on-windows OFF OFF +qnx-800-arm64-on-linux OFF OFF +qnx-800-x86_64-developer-build-on-linux OFF OFF +rhel-8.10 ON ON +rhel-9.4 ON ON +sles-15_sp5-static OFF ON +sles-15_sp6-static OFF ON +ubuntu-22.04 ON ON +ubuntu-22.04-developer-build ON ON +ubuntu-24.04-arm64 ON ON +ubuntu-24.04-arm64-developer-build ON ON +ubuntu-24.04-x64-developer-build ON ON +ubuntu-24.04-x64 ON ON +webassembly-windows OFF OFF +webassembly-linux-thread OFF OFF +webassembly-linux-shared OFF OFF +webassembly-linux-thread-asyncify OFF OFF +windows-10_22h2-msvc2022 ON ON +windows-10_22h2-mingw13 OFF ON +windows-11_22h2-arm64-msvc2022 OFF ON +windows-11_23H2-llvm OFF ON +windows-11_23H2-msvc2022-arm64 OFF ON +windows-11_23H2-msvc2022 ON ON +windows-11_23H2-msvc2022-developer-build ON ON +windows-11_23H2-mingw13-developer-build OFF ON +opensuse-15.6-host-asan OFF OFF +opensuse-15.6-developer-build OFF OFF +jammy-arm64-debian-pkg-packaging ON ON +jammy-amd64-debian-pkg-packaging ON ON +documentation-warnings ON ON +offline-documentation ON ON +visionos-developer-build OFF OFF diff --git a/coin/module_config.yaml b/coin/module_config.yaml index 9c6e1d003e5..240c1eabb71 100644 --- a/coin/module_config.yaml +++ b/coin/module_config.yaml @@ -13,6 +13,16 @@ machine_type: instructions: Build: + - type: AppendToEnvironmentVariable + variableName: COMMON_NON_QTBASE_CMAKE_ARGS + variableValue: " -DFEATURE_webengine_system_libxml=OFF" + enable_if: + condition: property + property: features + contains_value: Packaging + - type: EnvironmentVariable + variableName: VERIFY_SOURCE_SBOM + variableValue: "ON" - type: EnvironmentVariable variableName: CMAKE_BUILD_TIMEOUT variableValue: "36000" diff --git a/coin/qt-installer-package-config.json b/coin/qt-installer-package-config.json index aec45688b39..433ddfd824a 100644 --- a/coin/qt-installer-package-config.json +++ b/coin/qt-installer-package-config.json @@ -3,6 +3,7 @@ "module-split": { "qtpdf": [ "**/bin/*Pdf*", + "**/sbom/qtpdf*", "**/include/*QtPdf*/**/*", "**/lib/cmake/Qt*Gui/*Pdf*", "**/lib/cmake/Qt*Pdf*/*", diff --git a/configure.cmake b/configure.cmake index c4acca20c99..86c120248e3 100644 --- a/configure.cmake +++ b/configure.cmake @@ -24,6 +24,7 @@ qt_webengine_set_version(vpx 1.10.0) qt_webengine_set_version(libavutil 58.29.100) qt_webengine_set_version(libavcodec 60.31.102) qt_webengine_set_version(libavformat 60.16.100) +qt_webengine_set_version(windows_sdk 26100) # we only care about minor number "10.0.26100.0" if(QT_CONFIGURE_RUNNING) function(qt_webengine_configure_check) @@ -35,10 +36,9 @@ if(QT_CONFIGURE_RUNNING) else() find_package(Ninja ${QT_CONFIGURE_CHECK_ninja_version}) find_package(Gn ${QT_REPO_MODULE_VERSION} EXACT) - find_program(Python3_EXECUTABLE NAMES python3 python HINTS $ENV{PYTHON3_PATH}) - if(NOT Python3_EXECUTABLE) - find_package(Python3 ${QT_CONFIGURE_CHECK_python3_version}) - endif() + set(Python3_ROOT_DIR $ENV{PYTHON3_PATH}) + find_package(Python3 ${QT_CONFIGURE_CHECK_python3_version}) + unset(Python3_ROOT_DIR) find_package(GPerf) find_package(BISON) find_package(FLEX) @@ -46,6 +46,10 @@ else() find_package(PkgConfig) find_package(Snappy) find_package(Nodejs ${QT_CONFIGURE_CHECK_nodejs_version}) + _qt_internal_sbom_verify_deps_for_generate_tag_value_spdx_document( + OUT_VAR_DEPS_FOUND sbom_deps_found + OUT_VAR_REASON_FAILURE_MESSAGE sbom_missing_deps_message + ) endif() if(PkgConfig_FOUND) @@ -87,6 +91,7 @@ if(PkgConfig_FOUND) pkg_check_modules(XKBCOMMON xkbcommon) pkg_check_modules(XKBFILE xkbfile) pkg_check_modules(XCBDRI3 xcb-dri3) + pkg_check_modules(LIBUDEV libudev) endif() if(Python3_EXECUTABLE) @@ -156,31 +161,20 @@ int main() { }" ) -qt_config_compile_test(snappy +qt_config_compile_test(webengine_system_snappy LABEL "snappy" LIBRARIES Snappy::Snappy CODE " #include \"snappy.h\" +#include int main() { snappy::Source *src = 0; snappy::Sink *sink = 0; - return 0; -}" -) - -qt_config_compile_test(libxml2 - LABEL "compatible libxml2 and libxslt" - LIBRARIES - PkgConfig::LIBXML2 - CODE -" -#include \"libxml/xmlversion.h\" -#if !defined(LIBXML_ICU_ENABLED) -#error libxml icu not enabled -#endif -int main() { + const char *str = \"string\"; + std::string compressed; + snappy::Compress(str, 7, &compressed); return 0; }" ) @@ -302,12 +296,12 @@ endif() qt_webengine_configure_check("supported-platform" MODULES QtWebEngine - CONDITION LINUX OR (WIN32 AND NOT WIN_ARM_64) OR MACOS + CONDITION LINUX OR (WIN32 AND NOT (WIN_ARM_64 AND DEFINED ENV{COIN_PLATFORM_ID})) OR MACOS MESSAGE "Build can be done only on Linux, Windows or macOS." ) qt_webengine_configure_check("supported-platform" MODULES QtPdf - CONDITION LINUX OR (WIN32 AND NOT WIN_ARM_64) OR MACOS OR IOS OR ANDROID + CONDITION LINUX OR WIN32 OR MACOS OR IOS OR ANDROID MESSAGE "Build can be done only on Linux, Windows, macO, iOS and Android." ) @@ -328,7 +322,7 @@ qt_webengine_configure_check("static-build" ) qt_webengine_configure_check("nodejs" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION TARGET Nodejs::Nodejs AND NOT (Nodejs_ARCH STREQUAL "ia32") AND NOT (Nodejs_ARCH STREQUAL "x86") AND @@ -338,29 +332,37 @@ qt_webengine_configure_check("nodejs" ) qt_webengine_configure_check("python3" MODULES QtWebEngine QtPdf - CONDITION Python3_EXECUTABLE - MESSAGE "Python ${QT_CONFIGURE_CHECK_python3_version} or later is required." + CONDITION Python3_FOUND + MESSAGE "Python ${QT_CONFIGURE_CHECK_python3_version} or later is required. Please use -DPython3_EXECUTABLE for custom path to interpreter." DOCUMENTATION "Python ${QT_CONFIGURE_CHECK_python3_version} version or later." ) +if(QT_GENERATE_SBOM AND QT_SBOM_GENERATE_JSON AND QT_SBOM_REQUIRE_GENERATE_JSON) + qt_webengine_configure_check("sbom-generate-json" + MODULES QtWebEngine QtPdf + CONDITION sbom_deps_found + MESSAGE + "SBOM JSON file generation requirements missing, but JSON files were explicitly required. ${sbom_missing_deps_message}" + ) +endif() qt_webengine_configure_check("python3-html5lib" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION Python3_EXECUTABLE AND NOT html5lib_NOT_FOUND - MESSAGE "Python3 html5lib is missing." + MESSAGE "Python3 html5lib is missing (${Python3_EXECUTABLE})." DOCUMENTATION "Python3 html5lib module.") qt_webengine_configure_check("gperf" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION GPerf_FOUND MESSAGE "Tool gperf is required." DOCUMENTATION "GNU gperf binary." ) qt_webengine_configure_check("bison" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION BISON_FOUND MESSAGE "Tool bison is required." DOCUMENTATION "GNU bison binary." ) qt_webengine_configure_check("flex" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION FLEX_FOUND MESSAGE "Tool flex is required." DOCUMENTATION "GNU flex binary." @@ -373,14 +375,14 @@ qt_webengine_configure_check("pkg-config" TAGS LINUX_PLATFORM ) qt_webengine_configure_check("glibc" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION NOT LINUX OR TEST_glibc MESSAGE "A suitable version >= ${QT_CONFIGURE_CHECK_glibc_version} of glibc is required." DOCUMENTATION "glibc library at least ${QT_CONFIGURE_CHECK_glibc_version} version or later." TAGS LINUX_PLATFORM ) qt_webengine_configure_check("glib" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION NOT UNIX OR GLIB_FOUND MESSAGE "No glib library at least ${QT_CONFIGURE_CHECK_glib_version} version or later. Using build-in one" DOCUMENTATION "glib library at least ${QT_CONFIGURE_CHECK_glib_version} version or later." @@ -396,7 +398,7 @@ qt_webengine_configure_check("harfbuzz" OPTIONAL ) qt_webengine_configure_check("mesa-headers" - MODULES QtWebEngine QtPdf + MODULES QtWebEngine CONDITION NOT LINUX OR TEST_khr MESSAGE "Build requires Khronos development headers for build - see mesa/libegl1-mesa-dev" DOCUMENTATION "Mesa development headers." @@ -423,6 +425,14 @@ qt_webengine_configure_check("dbus" DOCUMENTATION "Dbus" TAGS LINUX_PKG_CONFIG ) +qt_webengine_configure_check("libudev" + MODULES QtWebEngine + CONDITION NOT UNIX OR LIBUDEV_FOUND + MESSAGE "No libudev found." + DOCUMENTATION "libudev library." + TAGS PLATFROM_MACOS PLATFORM_LINUX + OPTIONAL +) # Only check for the 'xcb' feature if the Gui targets exists, aka Qt was not configured with # -no-gui. @@ -505,9 +515,9 @@ endif() qt_webengine_configure_check("windows-sdk" MODULES QtWebEngine - CONDITION NOT WIN32 OR sdk_minor GREATER_EQUAL 22621 - MESSAGE "Build requires Windows 11 SDK at least version 10.0.22621.0" - DOCUMENTATION "Windows 11 SDK at least version 10.0.22621.0" + CONDITION NOT WIN32 OR sdk_minor GREATER_EQUAL ${QT_CONFIGURE_CHECK_windows_sdk_version} + MESSAGE "Build requires Windows 11 SDK at least version 10.0.${QT_CONFIGURE_CHECK_windows_sdk_version}.0" + DOCUMENTATION "Windows 11 SDK at least version 10.0.${QT_CONFIGURE_CHECK_windows_sdk_version}.0" TAGS WINDOWS_PLATFORM ) unset(sdk_minor) @@ -619,7 +629,7 @@ qt_feature("webengine-system-libvpx" PRIVATE ) qt_feature("webengine-system-snappy" PRIVATE LABEL "snappy" - CONDITION UNIX AND TEST_snappy + CONDITION UNIX AND TEST_webengine_system_snappy ) qt_feature("webengine-system-glib" PRIVATE LABEL "glib" @@ -645,7 +655,7 @@ qt_feature("webengine-system-libevent" PRIVATE ) qt_feature("webengine-system-libxml" PRIVATE LABEL "libxml2 and libxslt" - CONDITION UNIX AND TEST_libxml2 + CONDITION UNIX AND LIBXML2_FOUND ) qt_feature("webengine-system-lcms2" PRIVATE LABEL "lcms2" @@ -704,6 +714,11 @@ qt_feature("webengine-system-libpci" PRIVATE CONDITION UNIX AND LIBPCI_FOUND ) +qt_feature("webengine-system-libudev" PRIVATE + LABEL "libudev" + CONDITION UNIX AND LIBUDEV_FOUND +) + qt_feature("webengine-ozone-x11" PRIVATE LABEL "Support X11 on qpa-xcb" CONDITION LINUX @@ -752,6 +767,7 @@ if(UNIX) qt_configure_add_summary_entry(ARGS "webengine-system-harfbuzz") qt_configure_add_summary_entry(ARGS "webengine-system-freetype") qt_configure_add_summary_entry(ARGS "webengine-system-libpci") + qt_configure_add_summary_entry(ARGS "webengine-system-libudev") qt_configure_end_summary_section() endif() @@ -811,4 +827,12 @@ if(NOT QT_SUPERBUILD) CONDITION QT_SHOW_EXTRA_IDE_SOURCES OR (NOT DEFINED QT_SHOW_EXTRA_IDE_SOURCES AND CMAKE_VERSION VERSION_GREATER_EQUAL 3.20) ) endif() - +# Only show the warning if JSON generation is not required. For the case when it is required, +# there's an extra configure check. +if(QT_GENERATE_SBOM AND NOT QT_SBOM_REQUIRE_GENERATE_JSON) + qt_configure_add_report_entry( + TYPE WARNING + MESSAGE "Qt WebEngine And Qt Pdf SBOM generation will be skipped due to missing dependencies. ${sbom_missing_deps_message}" + CONDITION NOT sbom_deps_found + ) +endif() diff --git a/dependencies.yaml b/dependencies.yaml index 6283dc1146f..d247e74650a 100644 --- a/dependencies.yaml +++ b/dependencies.yaml @@ -1,13 +1,13 @@ dependencies: ../qtdeclarative: - ref: f5673f1e0e139fab33a456275b015fe4e5ca3986 + ref: 2572db088ba6301f6b0bd27bde09582d9557b859 required: true ../qtpositioning: - ref: 7db6885dce399ad7ef47493c612127b71d3b229d + ref: b8b7a1d0e4b50ce1299e3ca3718edf1c09aa3da2 required: false ../qttools: - ref: 3557f0897aa2624b633a0bb83f1970245de37e1f + ref: 2069e86c36779791ce2b63e0828429d7e9adf968 required: false ../qtwebchannel: - ref: a13deb0fbd2f0af0c23311b83c3783ab27140a56 + ref: 3f5c1142bc65b924f5f2a123b8bca4866fca976d required: false diff --git a/examples/pdf/CMakeLists.txt b/examples/pdf/CMakeLists.txt index bdc1d0f0524..7255752b814 100644 --- a/examples/pdf/CMakeLists.txt +++ b/examples/pdf/CMakeLists.txt @@ -3,6 +3,3 @@ qt_internal_add_example(singlepage) qt_internal_add_example(multipage) -if(NOT TARGET Qt::Svg) - message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") -endif() diff --git a/examples/pdf/multipage/CMakeLists.txt b/examples/pdf/multipage/CMakeLists.txt index 8f8111c826d..fb4e449fd7a 100644 --- a/examples/pdf/multipage/CMakeLists.txt +++ b/examples/pdf/multipage/CMakeLists.txt @@ -12,7 +12,10 @@ endif() set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/multipage") -find_package(Qt6 REQUIRED COMPONENTS Gui Qml) +find_package(Qt6 REQUIRED COMPONENTS Gui Qml OPTIONAL_COMPONENTS Svg) +if(NOT TARGET Qt::Svg) + message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") +endif() qt_add_executable(multipage main.cpp diff --git a/examples/pdf/multipage/viewer.qrc b/examples/pdf/multipage/viewer.qrc index e786ae4ce6c..b8ec1c8c68e 100644 --- a/examples/pdf/multipage/viewer.qrc +++ b/examples/pdf/multipage/viewer.qrc @@ -1,5 +1,5 @@ - + viewer.qml resources/document-open.svg resources/edit-clear.svg diff --git a/examples/pdf/singlepage/CMakeLists.txt b/examples/pdf/singlepage/CMakeLists.txt index fac95f54a98..647a30f8d4d 100644 --- a/examples/pdf/singlepage/CMakeLists.txt +++ b/examples/pdf/singlepage/CMakeLists.txt @@ -12,7 +12,10 @@ endif() set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/pdf/singlepage") -find_package(Qt6 REQUIRED COMPONENTS Gui Qml) +find_package(Qt6 REQUIRED COMPONENTS Gui Qml OPTIONAL_COMPONENTS Svg) +if(NOT TARGET Qt::Svg) + message(WARNING "QtSvg is required as runtime dependency for qtpdfquick examples.") +endif() qt_add_executable(pdfviewerquick main.cpp diff --git a/examples/webenginewidgets/clientcertificate/CMakeLists.txt b/examples/webenginewidgets/clientcertificate/CMakeLists.txt index 97c9393ffce..ef1f9a6d415 100644 --- a/examples/webenginewidgets/clientcertificate/CMakeLists.txt +++ b/examples/webenginewidgets/clientcertificate/CMakeLists.txt @@ -14,20 +14,20 @@ set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/webenginewidgets/clientcertificat find_package(Qt6 REQUIRED COMPONENTS Core Gui WebEngineWidgets) -qt_add_executable(server +qt_add_executable(example_cert_server server.cpp ) -qt_add_executable(client +qt_add_executable(example_cert_client client.cpp ) -set_target_properties(client PROPERTIES +set_target_properties(example_cert_client PROPERTIES WIN32_EXECUTABLE TRUE MACOSX_BUNDLE TRUE ) -qt_add_resources(client "client" +qt_add_resources(example_cert_client "client" PREFIX "/" FILES @@ -35,7 +35,7 @@ qt_add_resources(client "client" "resources/client.key" ) -qt_add_resources(server "server" +qt_add_resources(example_cert_server "server" PREFIX "/" FILES @@ -44,16 +44,16 @@ qt_add_resources(server "server" "resources/ca.pem" ) -target_link_libraries(client PUBLIC +target_link_libraries(example_cert_client PUBLIC Qt::WebEngineWidgets ) -target_link_libraries(server PUBLIC +target_link_libraries(example_cert_server PUBLIC Qt::Core Qt::Network ) -install(TARGETS server client +install(TARGETS example_cert_server example_cert_client RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}" BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}" LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}" diff --git a/examples/webenginewidgets/clientcertificate/client.cpp b/examples/webenginewidgets/clientcertificate/client.cpp index 1227fa28e8a..c10cff24769 100644 --- a/examples/webenginewidgets/clientcertificate/client.cpp +++ b/examples/webenginewidgets/clientcertificate/client.cpp @@ -21,11 +21,17 @@ int main(int argc, char *argv[]) QApplication app(argc, argv); QFile certFile(":/resources/client.pem"); - certFile.open(QIODevice::ReadOnly); + if (!certFile.open(QIODevice::ReadOnly)) { + qFatal("Failed to read cert file %s: %s", qPrintable(certFile.fileName()), + qPrintable(certFile.errorString())); + } const QSslCertificate cert(certFile.readAll(), QSsl::Pem); QFile keyFile(":/resources/client.key"); - keyFile.open(QIODevice::ReadOnly); + if (!keyFile.open(QIODevice::ReadOnly)) { + qFatal("Failed to read key file %s: %s", qPrintable(keyFile.fileName()), + qPrintable(keyFile.errorString())); + } const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); QWebEngineProfile::defaultProfile()->clientCertificateStore()->add(cert, sslKey); @@ -36,7 +42,7 @@ int main(int argc, char *argv[]) QObject::connect( &page, &QWebEnginePage::selectClientCertificate, &page, - [&cert](QWebEngineClientCertificateSelection selection) { + [](QWebEngineClientCertificateSelection selection) { QDialog dialog; QVBoxLayout *layout = new QVBoxLayout; QLabel *label = new QLabel(QLatin1String("Select certificate")); diff --git a/examples/webenginewidgets/clientcertificate/server.cpp b/examples/webenginewidgets/clientcertificate/server.cpp index ee83dab8a59..0d1bf771030 100644 --- a/examples/webenginewidgets/clientcertificate/server.cpp +++ b/examples/webenginewidgets/clientcertificate/server.cpp @@ -38,7 +38,10 @@ int main(int argc, char *argv[]) configuration.setPeerVerifyMode(QSslSocket::VerifyPeer); QFile keyFile(":/resources/server.key"); - keyFile.open(QIODevice::ReadOnly); + if (!keyFile.open(QIODevice::ReadOnly)) { + qFatal("Failed to read key file %s: %s", qPrintable(keyFile.fileName()), + qPrintable(keyFile.errorString())); + } QSslKey key(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey); configuration.setPrivateKey(key); diff --git a/examples/webenginewidgets/contentmanipulation/mainwindow.cpp b/examples/webenginewidgets/contentmanipulation/mainwindow.cpp index 3990be2b8a7..4e661f4d825 100644 --- a/examples/webenginewidgets/contentmanipulation/mainwindow.cpp +++ b/examples/webenginewidgets/contentmanipulation/mainwindow.cpp @@ -12,7 +12,10 @@ MainWindow::MainWindow(const QUrl& url) QFile file; file.setFileName(":/jquery.min.js"); - file.open(QIODevice::ReadOnly); + if (!file.open(QIODevice::ReadOnly)) { + qFatal("Failed to read jQuery file %s: %s", qPrintable(file.fileName()), + qPrintable(file.errorString())); + } jQuery = file.readAll(); jQuery.append("\nvar qt = { 'jQuery': jQuery.noConflict(true) };"); file.close(); diff --git a/examples/webenginewidgets/maps/mainwindow.cpp b/examples/webenginewidgets/maps/mainwindow.cpp index 07b8d8ab3da..31cc0bbf0cb 100644 --- a/examples/webenginewidgets/maps/mainwindow.cpp +++ b/examples/webenginewidgets/maps/mainwindow.cpp @@ -13,8 +13,7 @@ MainWindow::MainWindow(QWidget *parent) QWebEnginePage *page = m_view->page(); - connect(page, &QWebEnginePage::permissionRequested, - [this, page](QWebEnginePermission permission) { + connect(page, &QWebEnginePage::permissionRequested, [this](QWebEnginePermission permission) { if (permission.permissionType() != QWebEnginePermission::PermissionType::Geolocation) return; diff --git a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt index c4d8f9cd43e..c7d241d8f67 100644 --- a/examples/webenginewidgets/permissionbrowser/CMakeLists.txt +++ b/examples/webenginewidgets/permissionbrowser/CMakeLists.txt @@ -1,7 +1,7 @@ # Copyright (C) 2024 The Qt Company Ltd. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause -cmake_minimum_required(VERSION 3.5) +cmake_minimum_required(VERSION 3.16) project(permissionbrowser LANGUAGES CXX) set(CMAKE_AUTOMOC ON) diff --git a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc index fd01cf42da6..6a71d5da8cc 100644 --- a/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc +++ b/examples/webenginewidgets/permissionbrowser/doc/src/permissionbrowser.qdoc @@ -193,7 +193,7 @@ \list \li \l QWebEngineProfile::StoreOnDisk is the default, and it ensures that any permissions that have been granted in the current application run will be - loaded back up at next startup. A permission onlycneeds to be granted once, and + loaded back up at next startup. A permission only needs to be granted once, and subsequent uses of the API that triggered the request will automatically be granted, until the application calls QWebEnginePermission::reset(). \li \l QWebEngineProfile::StoreInMemory Has the same behavior as above, diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp index 8fd811e8383..1cc9b74efd6 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.cpp +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.cpp @@ -9,30 +9,23 @@ #include PermissionDialog::PermissionDialog(const QWebEngineProfile *profile, QWidget *parent) - : QDialog(parent) - , m_profile(profile) - , m_permission(nullptr) + : QDialog(parent), m_profile(profile) { setupUi(this); auto metaEnum = QMetaEnum::fromType(); - Q_ASSERT(metaEnum.value((quint8)QWebEnginePermission::PermissionType::Unsupported) == 0); - for (int i = 1; i < metaEnum.keyCount(); ++i) { - QWebEnginePermission::PermissionType permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i)); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + auto permissionType = QWebEnginePermission::PermissionType(metaEnum.value(i)); if (QWebEnginePermission::isPersistent(permissionType)) - m_permissionTypeComboBox->addItem(metaEnum.valueToKey((quint8)permissionType), QVariant::fromValue(permissionType)); + m_permissionTypeComboBox->addItem(metaEnum.key(i), QVariant::fromValue(permissionType)); } } -PermissionDialog::~PermissionDialog() +QWebEnginePermission PermissionDialog::permission() const { - delete m_permission; -} - -QWebEnginePermission PermissionDialog::permission() -{ - return m_profile->queryPermission(QUrl(m_originLineEdit->text()), - QWebEnginePermission::PermissionType(m_permissionTypeComboBox->itemData(m_permissionTypeComboBox->currentIndex()).toInt())); + return m_profile->queryPermission( + QUrl(m_originLineEdit->text()), + m_permissionTypeComboBox->currentData().value()); } PermissionWidget::PermissionWidget(const QWebEnginePermission &permission, QWidget *parent) @@ -92,6 +85,13 @@ MainWindow::MainWindow(const QUrl &url) , m_pendingWidget(nullptr) { setupUi(this); + + auto metaEnum = QMetaEnum::fromType(); + for (int i = 0; i < metaEnum.keyCount(); ++i) { + auto policy = QWebEngineProfile::PersistentPermissionsPolicy(metaEnum.value(i)); + m_policyComboBox->addItem(metaEnum.key(i), QVariant::fromValue(policy)); + } + m_urlLineEdit->setText(url.toString()); m_layout->addItem(new QSpacerItem(0,0, QSizePolicy::Minimum, QSizePolicy::Expanding)); @@ -204,21 +204,10 @@ void MainWindow::handleForwardClicked() m_webview->triggerPageAction(QWebEnginePage::Forward); } -void MainWindow::handlePolicyComboBoxIndexChanged(int index) +void MainWindow::handlePolicyComboBoxIndexChanged(int) { - QWebEngineProfile::PersistentPermissionsPolicy policy; - switch (index) { - case 0: - policy = QWebEngineProfile::PersistentPermissionsPolicy::AskEveryTime; - break; - case 1: - policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreInMemory; - break; - case 2: - policy = QWebEngineProfile::PersistentPermissionsPolicy::StoreOnDisk; - break; - } - + auto policy = + m_policyComboBox->currentData().value(); if (policy == m_profile->persistentPermissionsPolicy()) return; diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.h b/examples/webenginewidgets/permissionbrowser/mainwindow.h index 8f7a0945035..ce239be8250 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.h +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.h @@ -20,12 +20,10 @@ class PermissionDialog : public QDialog, public Ui_PermissionDialog Q_OBJECT public: PermissionDialog(const QWebEngineProfile *profile, QWidget *parent = nullptr); - ~PermissionDialog(); - QWebEnginePermission permission(); + QWebEnginePermission permission() const; private: const QWebEngineProfile *m_profile; - QWebEnginePermission *m_permission; }; class PermissionWidget : public QWidget, public Ui_PermissionWidget @@ -60,7 +58,7 @@ private slots: void handleRefreshClicked(); void handleBackClicked(); void handleForwardClicked(); - void handlePolicyComboBoxIndexChanged(int index); + void handlePolicyComboBoxIndexChanged(int); private: bool containsPermission(const QWebEnginePermission &permission); diff --git a/examples/webenginewidgets/permissionbrowser/mainwindow.ui b/examples/webenginewidgets/permissionbrowser/mainwindow.ui index 4496b8c0782..2cef35130ab 100644 --- a/examples/webenginewidgets/permissionbrowser/mainwindow.ui +++ b/examples/webenginewidgets/permissionbrowser/mainwindow.ui @@ -215,21 +215,6 @@ QComboBox::AdjustToContents - - - Persist on disk - - - - - Persist in memory - - - - - Do not persist - - diff --git a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc index a312da3ad1e..8523ed6896f 100644 --- a/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc +++ b/examples/webenginewidgets/simplebrowser/doc/src/simplebrowser.qdoc @@ -180,7 +180,7 @@ We add a menu item to the context menu, so that users can right-click to have an inspector opened in a new window. We override QWebEngineView::contextMenuEvent and use - QWebEnginePage::createStandardContextMenu to create a default QMenu with a + QWebEngineView::createStandardContextMenu to create a default QMenu with a default list of QWebEnginePage::WebAction actions. The default name for QWebEnginePage::InspectElement action is diff --git a/licenseRule.json b/licenseRule.json index 5f78a7dc8c1..4ae4a4e8453 100644 --- a/licenseRule.json +++ b/licenseRule.json @@ -1,6 +1,6 @@ [ { - "comment" : ["file_pattern_ending: strings matched against the end of a file name.", + "comment": ["file_pattern_ending: strings matched against the end of a file name.", "location keys: regular expression matched against the beginning of", "the file path (relative to the git submodule root).", "spdx: list of SPDX-License-Expression's allowed in the matching files.", @@ -9,95 +9,152 @@ "unless they are examples", "Files with other endings can also be build system files" ], - "file_pattern_ending" : ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", - "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", ".clang-format"], - "location" : { - "" : { - "comment" : "Default", - "file type" : "build system", - "spdx" : ["BSD-3-Clause"] - }, - "(.*)(examples/|snippets/)" : { - "comment" : "Example takes precedence", - "file type" : "examples and snippets", - "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + "file_pattern_ending": ["CMakeLists.txt", ".cmake", ".pro", ".pri", ".prf", + "configure", "configure.bat", "cmake.in", "plist.in", "CMakeLists.txt.in", + ".clang-format", ".plist", ".qrc", "BLACKLIST", + ".tag", ".cmake.conf", ".yaml", "coin/qt-installer-package-config.json", + "BUILD.root.gn.in", "BUILD.toolchain.gn.in", "BUILD.msvc.toolchain.gn.in", + "BUILD.clang-cl.toolchain.gn.in", ".cfg", "coin.nodes"], + "location": { + "": { + "comment": "Default", + "file type": "build system", + "spdx": ["BSD-3-Clause"] + }, + "(.*)(examples/|snippets/)": { + "comment": "Example takes precedence", + "file type": "examples and snippets", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + } + } + }, + { + "comments": ["Files with the following endings are infrastructure licensed"], + "file_pattern_ending": [".gitattributes", ".gitignore", ".gitmodules", ".gitreview", + "clang-format", "licenseRule.json", "REUSE.toml"], + "location":{ + "": { + "comment": "Default", + "file type": "infrastructure", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] } } }, { - "comments" : ["Files with the following endings are Tool licensed,", + "comments": ["Files with the following endings are Tool licensed,", "unless they are examples.", "Files with other endings can also be tool files."], - "file_pattern_ending" : [".sh", ".py", ".pl", ".bat", ".ps1"], - "location" :{ - "" : { - "comment" : "Default", - "file type" : "tools and utils", - "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] - }, - "(.*)(examples/|snippets/)" : { - "comment" : "Example takes precedence", - "file type" : "examples and snippets", - "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + "file_pattern_ending": [".sh", ".py", ".pl", ".bat", ".ps1"], + "location":{ + "": { + "comment": "Default", + "file type": "tools and utils", + "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0"] + }, + "(.*)(examples/|snippets/)": { + "comment": "Example takes precedence", + "file type": "examples and snippets", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] } } }, { - "comment" : "Files with the following endings are Documentation licensed.", - "file_pattern_ending" : [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", ".txt", "README", "qt_attribution.json"], - "location" :{ - "" : { - "comment" : "", - "file type" : "documentation", - "spdx" : ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + "comment": "Files with the following endings are Documentation licensed.", + "file_pattern_ending": [".qdoc", ".qdoc.in", ".qdocinc" , ".qdocconf", "README", "qt_attribution.json", + "config_help.txt"], + "location":{ + "": { + "comment": "", + "file type": "documentation", + "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] } } }, { - "comment" : ["All other files", + "comment": ["All other files", "The licensing is defined only by the file location in the Qt module repository.", "NO key for this case!", "This needs to be the last entry of the file."], - "location" : { - "" : { - "comment" : "Default", - "file type" : "module and plugin", - "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] - }, - "src/" : { - "comment" : "Default", - "file type" : "module and plugin", - "spdx" : ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] - }, - "tests/" : { - "comment" : "Default", - "file type" : "test", - "spdx" : ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] - }, - "(.*)(examples/|snippets/)" : { - "comment" : "Default", - "file type" : "examples and snippets", - "spdx" : ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] - }, - "src/host/config\\.tests/" : { - "comment" : "Default", - "file type" : "build system", - "spdx" : ["BSD-3-Clause"] - }, - "src/core/clipboard_util_win.cpp" : { - "comment" : "Partially from Chromium", - "file type" : "module and plugin", - "spdx" : ["BSD-3-Clause"] - }, - "src/core/common/qt_messages.*" : { - "comment" : "Partially from Chromium", - "file type" : "module and plugin", - "spdx" : ["BSD-3-Clause"] - }, - "src/core/tools/qwebengine_convert_dict/main.cpp" : { - "comment" : "Partially from Chromium", - "file type" : "module and plugin", - "spdx" : ["BSD-3-Clause"] + "location": { + "": { + "comment": "Default", + "file type": "module and plugin", + "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "dist/": { + "comment": "Default", + "file type": "documentation", + "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + }, + "src/": { + "comment": "Default", + "file type": "module and plugin", + "spdx": ["LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only"] + }, + "tests/": { + "comment": "Default", + "file type": "test", + "spdx": ["LicenseRef-Qt-Commercial OR GPL-3.0-only"] + }, + "(.*)(examples/|snippets/)": { + "comment": "Default", + "file type": "examples and snippets", + "spdx": ["LicenseRef-Qt-Commercial OR BSD-3-Clause"] + }, + "(.*|examples).*doc/images/": { + "comment": "Default", + "file type": "documentation", + "spdx": ["LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only"] + }, + "src/host/config\\.tests/": { + "comment": "Default", + "file type": "build system", + "spdx": ["BSD-3-Clause"] + }, + "src/core/clipboard_util_win.cpp": { + "comment": "Partially from Chromium", + "file type": "module and plugin", + "spdx": ["BSD-3-Clause"] + }, + "src/core/common/qt_messages.*": { + "comment": "Partially from Chromium", + "file type": "module and plugin", + "spdx": ["BSD-3-Clause"] + }, + "src/core/tools/qwebengine_convert_dict/main.cpp": { + "comment": "Partially from Chromium", + "file type": "module and plugin", + "spdx": ["BSD-3-Clause"] + }, + "tests/auto/widgets/qwebengine(view|script|page|history)/tst_qwebengine.*.cpp": { + "comment": "exception", + "file type": "test", + "spdx": ["LGPL-2.0-or-later"] + }, + "tests/auto/widgets/accessibility/tst_accessibility.cpp": { + "comment": "exception", + "file type": "test", + "spdx": ["LGPL-2.0-or-later"] + }, + "tests/auto/core/qwebengine(settings|frame)/tst_qwebengine.*.cpp": { + "comment": "exception", + "file type": "test", + "spdx": ["LGPL-2.0-or-later"] + }, + "examples/webenginewidgets/contentmanipulation/jquery.min.js": { + "comment": "", + "file type": "3rd party", + "spdx": ["MIT"] + }, + "src/core/ozone/(ozone_extra.gni|BUILD.gn)": { + "comment": "Chrominum", + "file type": "3rd party", + "spdx": ["BSD-3-Clause"] + }, + "CHROMIUM_VERSION": { + "comment": "Chrominum", + "file type": "3rd party", + "spdx": ["CC0-1.0"] } } } diff --git a/src/3rdparty b/src/3rdparty index b7c46a2abb5..2001f9c8990 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit b7c46a2abb5b3cdc37250f9c3006aa6228acdc9e +Subproject commit 2001f9c899030483ffacf33603a1428abb1f83a9 diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index cfe2721c995..453b2c1b602 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -22,6 +22,11 @@ endif() # MODULES ## +if(QT_FEATURE_qtwebengine_build) + # Use implicit PROJECT_NAME. + qt_internal_sbom_begin_qt_repo_project() + qt_webengine_sbom_project_begin(WebEngine WebEngineCore) +endif() if(QT_FEATURE_qtwebengine_core_build) add_subdirectory(core) add_subdirectory(process) @@ -36,8 +41,14 @@ endif() if(QT_FEATURE_qtwebengine_quick_build) add_subdirectory(webenginequick) endif() +if(QT_FEATURE_qtwebengine_build) + qt_webengine_sbom_project_end() + qt_internal_sbom_end_qt_repo_project() +endif() if(QT_FEATURE_qtpdf_build) + qt_internal_sbom_begin_qt_repo_project(SBOM_PROJECT_NAME QtPdf) + qt_webengine_sbom_project_begin(Pdf Pdf) add_subdirectory(pdf) endif() if(QT_FEATURE_qtpdf_widgets_build) @@ -61,6 +72,14 @@ if(QT_FEATURE_qtpdf_build) endif() endif() +# No SBOM information will be generated for any targets created past this point in the file +# or any add_subdirectory calls. For the external project GN, we'll have to come up with some +# additional API. +if(QT_FEATURE_qtpdf_build) + qt_webengine_sbom_project_end() + qt_internal_sbom_end_qt_repo_project() +endif() + set(installDir ${PROJECT_BINARY_DIR}/install) ## @@ -95,7 +114,7 @@ endif() # HOST PROJECT ## -if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS) +if(CMAKE_CROSSCOMPILING AND NOT IOS AND NOT MACOS AND NOT WIN32) if(NOT Gn_FOUND) message(FATAL_ERROR "\nHost gn not found - cross compilation not possible") diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d24513fae14..d5e9b715ecc 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -21,7 +21,7 @@ add_subdirectory(tools/qwebengine_convert_dict) # TOOLCHAIN SETUP ## -if(LINUX) +if(LINUX OR WIN32) setup_toolchains() endif() @@ -213,7 +213,7 @@ foreach(arch ${archs}) ozone/gl_helper.cpp ozone/gl_helper.h ) - extend_gn_target(${buildGn} CONDITION LINUX AND QT_FEATURE_opengl AND QT_FEATURE_webengine_ozone_x11 + extend_gn_target(${buildGn} CONDITION LINUX AND QT_FEATURE_opengl AND QT_FEATURE_webengine_ozone_x11 AND QT_FEATURE_xcb_glx_plugin SOURCES ozone/glx_helper.cpp ozone/glx_helper.h ) @@ -322,11 +322,17 @@ foreach(arch ${archs}) qtwebengine_target="${buildDir}/${config}/${arch}:QtWebEngineCore" build_dawn_tests=false build_with_tflite_lib=false + is_qtwebengine=true + is_qtpdf=false + chrome_pgo_phase=0 + disable_fieldtrial_testing_config=true enable_background_contents=false enable_background_mode=false + enable_bluetooth_emulation=false enable_ipc_fuzzer=false enable_ipc_logging=false enable_java_templates=false + enable_library_cdms=true enable_media_remoting=false enable_message_center=false enable_nacl=false @@ -339,29 +345,29 @@ foreach(arch ${archs}) enable_supervised_users=false enable_swiftshader=false enable_swiftshader_vulkan=false + enable_nocompile_tests=false angle_enable_swiftshader=false dawn_use_swiftshader=false + pdf_enable_fontations=false enable_vr=false enable_web_speech=false enable_widevine=true - enable_library_cdms=true + enable_bound_session_credentials=false fatal_linker_warnings=false has_native_accessibility=false - safe_browsing_mode=0 - toolkit_views=false - chrome_pgo_phase=0 optimize_webui=false + safe_browsing_mode=0 strip_absolute_paths_from_debug_symbols=false + toolkit_views=false pdf_use_skia=true use_cups=false use_dawn=false skia_use_dawn=false + use_static_angle=true devtools_fast_bundle=false devtools_skip_typecheck=false - use_static_angle=true content_enable_legacy_ipc=true - enable_bound_session_credentials=false - webnn_use_tflite=false + headless_use_policy=false ) extend_gn_list(gnArgArg ARGS use_v8_context_snapshot v8_use_external_startup_data @@ -413,7 +419,7 @@ foreach(arch ${archs}) CONDITION QT_FEATURE_webengine_kerberos ) extend_gn_list(gnArgArg - ARGS proprietary_codecs + ARGS proprietary_codecs rtc_use_h264 CONDITION QT_FEATURE_webengine_proprietary_codecs ) if(QT_FEATURE_webengine_proprietary_codecs) @@ -441,7 +447,6 @@ foreach(arch ${archs}) use_bundled_fontconfig=false use_glib=false use_bluez=false - use_udev=true is_cfi=false use_ozone=true ozone_auto_platforms=false @@ -517,6 +522,10 @@ foreach(arch ${archs}) ARGS rtc_use_x11 CONDITION QT_FEATURE_webengine_ozone_x11 AND QT_FEATURE_webengine_webrtc ) + extend_gn_list(gnArgArg + ARGS use_udev + CONDITION QT_FEATURE_webengine_system_libudev + ) if(QT_FEATURE_webengine_kerberos) list(APPEND gnArgArg @@ -524,11 +533,24 @@ foreach(arch ${archs}) ) endif() get_gn_arch(cpu ${TEST_architecture_arch}) - if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm") + + if(cpu STREQUAL "arm" AND + CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND + CMAKE_CXX_COMPILER_VERSION VERSION_LESS "11.0.0") + list(APPEND gnArgArg libyuv_use_neon=false) + #TODO check if libyuv really uses udot in case of arm32 + endif() + if(cpu STREQUAL "arm64" AND NOT QT_FEATURE_webengine_arm64_udot_support) + list(APPEND gnArgArg libyuv_use_neon=false) + endif() + if(cpu STREQUAL "arm") check_thumb(armThumb) if(NOT armThumb AND NOT QT_FEATURE_webengine_system_ffmpeg) list(APPEND gnArgArg media_use_ffmpeg=false use_webaudio_ffmpeg=false) endif() + # sme and sve depend on armv9 + list(APPEND gnArgArg libyuv_use_sme=false + libyuv_use_sve=false) endif() if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm64") @@ -540,6 +562,14 @@ foreach(arch ${archs}) ) endif() endif() + if(cpu STREQUAL "arm64") + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "14.0.0") + list(APPEND gnArgArg libyuv_use_sme=false) + endif() + if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS "12.0.0") + list(APPEND gnArgArg libyuv_use_sve=false) + endif() + endif() unset(cpu) endif() @@ -552,7 +582,6 @@ foreach(arch ${archs}) if(WIN32) list(APPEND gnArgArg - ninja_use_custom_environment_files=false com_init_check_hook_disabled=true heterogeneous_executables=true ) @@ -585,18 +614,20 @@ target_include_directories(WebEngineCore PRIVATE ) set(stamps QtWebEngineCore.stamp) +set(dataStampOption "") if(QT_FEATURE_webengine_v8_context_snapshot) - set(dataStamp obj/tools/v8_context_snapshot/v8_context_snapshot.stamp) + set(dataStampOption NINJA_DATA_STAMP obj/tools/v8_context_snapshot/v8_context_snapshot.stamp) endif() add_gn_build_artifacts_to_target( CMAKE_TARGET WebEngineCore NINJA_TARGET QtWebEngineCore MODULE core + DEPENDS WebEngineCore_sync_headers BUILDDIR ${buildDir} COMPLETE_STATIC FALSE NINJA_STAMP QtWebEngineCore.stamp - NINJA_DATA_STAMP ${dataStamp} + ${dataStampOption} ) add_dependencies(WebEngineCore run_core_NinjaDone) if(COIN_BUG_699) @@ -617,6 +648,7 @@ if(WIN32) BUILDDIR ${buildDir}/${config}/${arch} MODULE core ) + qt_webengine_add_gn_target_to_sbom(QtWebEngineCoreSandbox ${buildDir}/${config}/${arch}) set(sandboxLibraryPath ${buildDir}/${config}/${arch}/QtWebEngineCoreSandbox.lib) set_property(TARGET WebEngineCoreSandbox PROPERTY IMPORTED_LOCATION_${cfg} ${sandboxLibraryPath} @@ -664,6 +696,7 @@ if(QT_FEATURE_webenginedriver) BUILDDIR ${buildDir}/$/${arch} MODULE core ) + qt_webengine_add_gn_target_to_sbom(webenginedriver_group ${buildDir}/$/${arch}) add_custom_target(webenginedriver DEPENDS ${buildDir}/$/${arch}/${WEBENGINEDRIVER_EXECUTABLE}) diff --git a/src/core/accessibility_activation_observer.cpp b/src/core/accessibility_activation_observer.cpp index 4f25a35ffed..4e90b9b3b38 100644 --- a/src/core/accessibility_activation_observer.cpp +++ b/src/core/accessibility_activation_observer.cpp @@ -5,6 +5,8 @@ #include "content/browser/accessibility/browser_accessibility_state_impl.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { namespace { @@ -14,9 +16,8 @@ bool isAccessibilityEnabled() { // QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to 0. For details, // see QTBUG-59922. #ifdef Q_OS_LINUX - static bool accessibility_enabled - = qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", QLatin1String("1")) - == QLatin1String("1"); + static bool accessibility_enabled = + qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", u"1"_s) == "1"_L1; #else const bool accessibility_enabled = true; #endif diff --git a/src/core/accessibility_tree_formatter_qt.cpp b/src/core/accessibility_tree_formatter_qt.cpp index a86727a4415..481c188c93a 100644 --- a/src/core/accessibility_tree_formatter_qt.cpp +++ b/src/core/accessibility_tree_formatter_qt.cpp @@ -1,9 +1,9 @@ // Copyright (C) 2018 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only -#include "content/browser/accessibility/browser_accessibility_manager.h" #include "content/browser/accessibility/accessibility_tree_formatter_blink.h" #include "content/public/browser/ax_inspect_factory.h" +#include "ui/accessibility/platform/browser_accessibility_manager.h" #include "ui/accessibility/platform/inspect/ax_event_recorder.h" #include @@ -17,7 +17,7 @@ #include "base/strings/stringprintf.h" #include "base/values.h" -#include "content/browser/accessibility/browser_accessibility.h" +#include "ui/accessibility/platform/browser_accessibility.h" #include "ui/accessibility/platform/inspect/ax_tree_formatter_base.h" #include @@ -26,7 +26,8 @@ namespace content { #if QT_CONFIG(accessibility) -class AccessibilityTreeFormatterQt : public ui::AXTreeFormatterBase { +class AccessibilityTreeFormatterQt : public ui::AXTreeFormatterBase +{ public: explicit AccessibilityTreeFormatterQt(); ~AccessibilityTreeFormatterQt() override; @@ -38,8 +39,9 @@ class AccessibilityTreeFormatterQt : public ui::AXTreeFormatterBase { } private: - void RecursiveBuildAccessibilityTree(const BrowserAccessibility &node, base::Value::Dict *dict) const; - void AddProperties(const BrowserAccessibility &node, base::Value::Dict *dict) const; + void RecursiveBuildAccessibilityTree(const ui::BrowserAccessibility &node, + base::Value::Dict *dict) const; + void AddProperties(const ui::BrowserAccessibility &node, base::Value::Dict *dict) const; std::string ProcessTreeForOutput(const base::Value::Dict &node) const override; }; @@ -53,14 +55,15 @@ AccessibilityTreeFormatterQt::~AccessibilityTreeFormatterQt() base::Value::Dict AccessibilityTreeFormatterQt::BuildTree(ui::AXPlatformNodeDelegate *start) const { - BrowserAccessibility *root_internal = - BrowserAccessibility::FromAXPlatformNodeDelegate(start); + ui::BrowserAccessibility *root_internal = + ui::BrowserAccessibility::FromAXPlatformNodeDelegate(start); base::Value::Dict dict; RecursiveBuildAccessibilityTree(*root_internal, &dict); return dict; } -void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const BrowserAccessibility &node, base::Value::Dict *dict) const +void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree( + const ui::BrowserAccessibility &node, base::Value::Dict *dict) const { AddProperties(node, dict); @@ -68,7 +71,7 @@ void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const Browser for (size_t i = 0; i < node.PlatformChildCount(); ++i) { base::Value::Dict child_dict; - content::BrowserAccessibility *child_node = node.PlatformGetChild(i); + ui::BrowserAccessibility *child_node = node.PlatformGetChild(i); RecursiveBuildAccessibilityTree(*child_node, &child_dict); children.Append(std::move(child_dict)); @@ -76,10 +79,11 @@ void AccessibilityTreeFormatterQt::RecursiveBuildAccessibilityTree(const Browser dict->Set(kChildrenDictAttr, std::move(children)); } -void AccessibilityTreeFormatterQt::AddProperties(const BrowserAccessibility &node, base::Value::Dict *dict) const +void AccessibilityTreeFormatterQt::AddProperties(const ui::BrowserAccessibility &node, + base::Value::Dict *dict) const { dict->Set("id", node.GetId()); - const QAccessibleInterface *iface = toQAccessibleInterface(&node); + const QAccessibleInterface *iface = ui::toQAccessibleInterface(&node); dict->Set("role", qAccessibleRoleString(iface->role())); @@ -196,7 +200,7 @@ std::unique_ptr AXInspectFactory::CreateFormatter(ui::AXApi // Developer mode: crash immediately on any accessibility fatal error. // This only runs during integration tests, or if a developer is // using an inspection tool, e.g. chrome://accessibility. - BrowserAccessibilityManager::AlwaysFailFast(); + ui::BrowserAccessibilityManager::AlwaysFailFast(); switch (type) { case ui::AXApiType::kBlink: diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index f148afee14b..e2456a4f6f7 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -46,6 +46,7 @@ qt_internal_add_module(WebEngineCore qwebengineprofilebuilder.cpp qwebengineprofilebuilder.h qwebengineprofilebuilder_p.h DEFINES BUILDING_CHROMIUM + TOOLKIT_QT INCLUDE_DIRECTORIES ../ ../../3rdparty/chromium @@ -214,14 +215,28 @@ if(QT_FEATURE_framework) ) else() + set(locale_install_path "${INSTALL_TRANSLATIONSDIR}/qtwebengine_locales") install(FILES ${localeFiles} - DESTINATION ${INSTALL_TRANSLATIONSDIR}/qtwebengine_locales + DESTINATION ${locale_install_path} CONFIGURATIONS ${config} ) + qt_internal_sbom_add_files(WebEngineCore + FILES "${localeFiles}" + FILE_TYPE "TRANSLATIONS" + INSTALL_PATH "${locale_install_path}" + ) + + qt_path_join(resource_install_path "${INSTALL_DATADIR}" "resources") install(FILES ${resourceFiles} - DESTINATION ${INSTALL_DATADIR}/resources + DESTINATION ${resource_install_path} CONFIGURATIONS ${config} ) + qt_internal_sbom_add_files(WebEngineCore + FILES "${resourceFiles}" + FILE_TYPE "RESOURCES" + INSTALL_PATH "${resource_install_path}" + ) + if(QT_SUPERBUILD OR NOT QT_WILL_INSTALL) addCopyCommand(WebEngineCore "${localeFiles}" ${QT_BUILD_DIR}/${INSTALL_TRANSLATIONSDIR}/qtwebengine_locales diff --git a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake index e67eb212b3d..b6f8b146380 100644 --- a/src/core/api/Qt6WebEngineCoreDeploySupport.cmake +++ b/src/core/api/Qt6WebEngineCoreDeploySupport.cmake @@ -74,24 +74,44 @@ function(_qt_internal_deploy_webenginecore_binary) endif() endforeach() - set(install_destination "${QT_DEPLOY_PREFIX}/") + # CMAKE_INSTALL_PREFIX does not contain $ENV{DESTDIR}, whereas QT_DEPLOY_PREFIX does. + # The install_ variant should be used in file(INSTALL) to avoid double DESTDIR in paths. + # Other code should reference the destdir_ variant instead. + set(install_destination "${CMAKE_INSTALL_PREFIX}/") + set(destdir_destination "${QT_DEPLOY_PREFIX}/") + if(__QT_DEPLOY_SYSTEM_NAME STREQUAL "Windows") string(APPEND install_destination "${QT_DEPLOY_BIN_DIR}") + string(APPEND destdir_destination "${QT_DEPLOY_BIN_DIR}") else() string(APPEND install_destination "${QT_DEPLOY_LIBEXEC_DIR}") + string(APPEND destdir_destination "${QT_DEPLOY_LIBEXEC_DIR}") endif() file(INSTALL "${process_path}" DESTINATION "${install_destination}") get_filename_component(process_file_name "${process_path}" NAME) if(CMAKE_VERSION GREATER_EQUAL "3.19") - file(CHMOD "${install_destination}/${process_file_name}" + file(CHMOD "${destdir_destination}/${process_file_name}" PERMISSIONS OWNER_EXECUTE OWNER_READ OWNER_WRITE GROUP_EXECUTE GROUP_READ WORLD_EXECUTE WORLD_READ ) else() execute_process( - COMMAND chmod 0755 "${install_destination}/${process_file_name}" + COMMAND chmod 0755 "${destdir_destination}/${process_file_name}" + ) + endif() + + # Checking for __QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH is a bit strange because this is not a + # plugin, but it gives a single common way to detect when the rpath adjustment must be done, + # because the lib dir is different than the original Qt configured one. + if(__QT_DEPLOY_MUST_ADJUST_PLUGINS_RPATH) + _qt_internal_get_rpath_origin(rpath_origin) + file(RELATIVE_PATH rel_lib_dir "${destdir_destination}" + "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_LIB_DIR}") + _qt_internal_set_rpath( + FILE "${destdir_destination}/${process_file_name}" + NEW_RPATH "${rpath_origin}/${rel_lib_dir}" ) endif() endfunction() @@ -117,8 +137,9 @@ function(_qt_internal_deploy_webenginecore_data) list(APPEND data_files "${snapshot_file}") endif() + # See comment above why we use CMAKE_INSTALL_PREFIX instead of QT_DEPLOY_PREFIX. get_filename_component(install_destination "${QT_DEPLOY_WEBENGINECORE_RESOURCES_DIR}" ABSOLUTE - BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_DATA_DIR}" + BASE_DIR "${CMAKE_INSTALL_PREFIX}/${QT_DEPLOY_DATA_DIR}" ) foreach(data_file IN LISTS data_files) file(INSTALL "${resources_dir}/${data_file}" DESTINATION "${install_destination}") @@ -163,8 +184,9 @@ function(_qt_internal_deploy_webenginecore_translations) get_filename_component(locales_dir "qtwebengine_locales" ABSOLUTE BASE_DIR "${__QT_DEPLOY_QT_INSTALL_PREFIX}/${__QT_DEPLOY_QT_INSTALL_TRANSLATIONS}" ) + # See comment above why we use CMAKE_INSTALL_PREFIX instead of QT_DEPLOY_PREFIX. get_filename_component(install_destination "qtwebengine_locales" ABSOLUTE - BASE_DIR "${QT_DEPLOY_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}" + BASE_DIR "${CMAKE_INSTALL_PREFIX}/${QT_DEPLOY_TRANSLATIONS_DIR}" ) file(GLOB locale_files "${locales_dir}/*.pak") foreach(locale_file IN LISTS locale_files) diff --git a/src/core/api/configure.cmake b/src/core/api/configure.cmake index 44dd38d5594..4a556656efb 100644 --- a/src/core/api/configure.cmake +++ b/src/core/api/configure.cmake @@ -36,6 +36,20 @@ qt_config_compile_test(alsa int main(){}; ") +qt_config_compile_test(udot + LABEL "udot on arm64" + CODE +" +static_assert(__aarch64__); +static void test_dot_prod(){ +asm volatile ( +\"udot v0.4s, v4.16b, v16.16b\" +: +: +: \"v0\",\"v4\",\"v16\"); +} +") + #### Features qt_feature("webengine-embedded-build" PRIVATE @@ -168,6 +182,10 @@ qt_feature("webenginedriver" PUBLIC AND NOT (CMAKE_OSX_ARCHITECTURES AND osx_arch_count GREATER 1) DISABLE CMAKE_BUILD_TYPE STREQUAL Debug ) +qt_feature("webengine-arm64-udot-support" PRIVATE + LABEL "Use libyuv on neon64" + CONDITION UNIX AND TEST_udot +) qt_configure_add_summary_section(NAME "Qt WebEngineCore") qt_configure_add_summary_entry(ARGS "webengine-embedded-build") qt_configure_add_summary_entry(ARGS "webengine-full-debug-info") diff --git a/src/core/api/qwebenginecertificateerror.cpp b/src/core/api/qwebenginecertificateerror.cpp index 85c5d512752..60ec3c95b19 100644 --- a/src/core/api/qwebenginecertificateerror.cpp +++ b/src/core/api/qwebenginecertificateerror.cpp @@ -42,6 +42,7 @@ QWebEngineCertificateError::~QWebEngineCertificateError() = default; QSslError::SslError values are not used directly, because the Qt error categories cannot be mapped to the Chromium error categories. + \value Ok There was no actual certificate error. \value SslPinnedKeyNotInCertificateChain The certificate did not match the built-in public keys pinned for the host name. \value CertificateCommonNameInvalid The certificate's common name did not match the host name. @@ -74,7 +75,9 @@ QWebEngineCertificateError::~QWebEngineCertificateError() = default; */ bool QWebEngineCertificateError::isOverridable() const { - return d->overridable(); + if (Q_LIKELY(d)) + return d->overridable(); + return false; } /*! @@ -84,7 +87,9 @@ bool QWebEngineCertificateError::isOverridable() const */ QUrl QWebEngineCertificateError::url() const { - return d->url(); + if (Q_LIKELY(d)) + return d->url(); + return QUrl(); } /*! @@ -97,7 +102,9 @@ QUrl QWebEngineCertificateError::url() const */ bool QWebEngineCertificateError::isMainFrame() const { - return d->isMainFrame(); + if (Q_LIKELY(d)) + return d->isMainFrame(); + return false; } /*! @@ -107,7 +114,9 @@ bool QWebEngineCertificateError::isMainFrame() const */ QWebEngineCertificateError::Type QWebEngineCertificateError::type() const { - return d->error(); + if (Q_LIKELY(d)) + return d->error(); + return Ok; } /*! @@ -117,7 +126,9 @@ QWebEngineCertificateError::Type QWebEngineCertificateError::type() const */ QString QWebEngineCertificateError::description() const { - return d->errorString(); + if (Q_LIKELY(d)) + return d->errorString(); + return QString(); } /*! @@ -135,7 +146,8 @@ QString QWebEngineCertificateError::description() const */ void QWebEngineCertificateError::defer() { - d->defer(); + if (Q_LIKELY(d)) + d->defer(); } /*! @@ -145,7 +157,8 @@ void QWebEngineCertificateError::defer() */ void QWebEngineCertificateError::acceptCertificate() { - d->ignoreCertificateError(); + if (Q_LIKELY(d)) + d->ignoreCertificateError(); } /*! @@ -155,7 +168,8 @@ void QWebEngineCertificateError::acceptCertificate() */ void QWebEngineCertificateError::rejectCertificate() { - d->rejectCertificate(); + if (Q_LIKELY(d)) + d->rejectCertificate(); } /*! @@ -167,7 +181,9 @@ void QWebEngineCertificateError::rejectCertificate() */ QList QWebEngineCertificateError::certificateChain() const { - return d->certificateChain(); + if (Q_LIKELY(d)) + return d->certificateChain(); + return QList(); } QT_END_NAMESPACE diff --git a/src/core/api/qwebenginecertificateerror.h b/src/core/api/qwebenginecertificateerror.h index 3eef3dcca58..73a3ac09099 100644 --- a/src/core/api/qwebenginecertificateerror.h +++ b/src/core/api/qwebenginecertificateerror.h @@ -27,12 +27,15 @@ class Q_WEBENGINECORE_EXPORT QWebEngineCertificateError Q_PROPERTY(bool isMainFrame READ isMainFrame CONSTANT FINAL REVISION(6, 8)) public: + QWebEngineCertificateError() = default; QWebEngineCertificateError(const QWebEngineCertificateError &other); QWebEngineCertificateError &operator=(const QWebEngineCertificateError &other); ~QWebEngineCertificateError(); // Keep this identical to NET_ERROR in net_error_list.h, or add mapping layer. enum Type { + Ok = 0, // No actual error. See net_errors.h for that one + SslPinnedKeyNotInCertificateChain = -150, CertificateCommonNameInvalid = -200, CertificateDateInvalid = -201, diff --git a/src/core/api/qwebenginedownloadrequest.cpp b/src/core/api/qwebenginedownloadrequest.cpp index 107549f7efe..536d193b7f8 100644 --- a/src/core/api/qwebenginedownloadrequest.cpp +++ b/src/core/api/qwebenginedownloadrequest.cpp @@ -56,8 +56,7 @@ static inline QWebEngineDownloadRequest::DownloadState toDownloadState(int state case ProfileAdapterClient::DownloadInterrupted: return QWebEngineDownloadRequest::DownloadInterrupted; default: - Q_UNREACHABLE(); - return QWebEngineDownloadRequest::DownloadCancelled; + Q_UNREACHABLE_RETURN(QWebEngineDownloadRequest::DownloadCancelled); } } @@ -146,17 +145,13 @@ void QWebEngineDownloadRequestPrivate::update(const ProfileAdapterClient::Downlo downloadState = toDownloadState(info.state); Q_EMIT q->stateChanged(downloadState); } - - if (info.receivedBytes != receivedBytes || info.totalBytes != totalBytes) { - - if (info.receivedBytes != receivedBytes) { - receivedBytes = info.receivedBytes; - Q_EMIT q->receivedBytesChanged(); - } - if (info.totalBytes != totalBytes) { - totalBytes = info.totalBytes; - Q_EMIT q->totalBytesChanged(); - } + if (info.receivedBytes != receivedBytes) { + receivedBytes = info.receivedBytes; + Q_EMIT q->receivedBytesChanged(); + } + if (info.totalBytes != totalBytes) { + totalBytes = info.totalBytes; + Q_EMIT q->totalBytesChanged(); } if (info.done) @@ -183,7 +178,7 @@ void QWebEngineDownloadRequestPrivate::answer() return; if (profileAdapter) { - QString path = QDir(downloadDirectory).filePath(downloadFileName); + const QString path = QDir(downloadDirectory).filePath(downloadFileName); bool accepted = downloadState != QWebEngineDownloadRequest::DownloadCancelled && downloadState != QWebEngineDownloadRequest::DownloadRequested; profileAdapter->acceptDownload(downloadId, accepted, useDownloadTargetCallback, path, savePageFormat); @@ -480,7 +475,7 @@ void QWebEngineDownloadRequest::setDownloadDirectory(const QString &directory) d->suggestedFileName, d->startTime)).fileName(); if (d->downloadFileName != newFileName) { - d->downloadFileName = newFileName; + d->downloadFileName = std::move(newFileName); Q_EMIT downloadFileNameChanged(); } } diff --git a/src/core/api/qwebenginefilesystemaccessrequest.cpp b/src/core/api/qwebenginefilesystemaccessrequest.cpp index 3f901b671cf..0834468f659 100644 --- a/src/core/api/qwebenginefilesystemaccessrequest.cpp +++ b/src/core/api/qwebenginefilesystemaccessrequest.cpp @@ -72,7 +72,8 @@ QWebEngineFileSystemAccessRequest::QWebEngineFileSystemAccessRequest( */ void QWebEngineFileSystemAccessRequest::reject() { - d_ptr->reject(); + if (Q_LIKELY(d_ptr)) + d_ptr->reject(); } /*! @@ -80,7 +81,8 @@ void QWebEngineFileSystemAccessRequest::reject() */ void QWebEngineFileSystemAccessRequest::accept() { - d_ptr->accept(); + if (Q_LIKELY(d_ptr)) + d_ptr->accept(); } /*! @@ -90,7 +92,9 @@ void QWebEngineFileSystemAccessRequest::accept() QUrl QWebEngineFileSystemAccessRequest::origin() const { - return d_ptr->origin(); + if (Q_LIKELY(d_ptr)) + return d_ptr->origin(); + return QUrl(); } /*! @@ -100,7 +104,9 @@ QUrl QWebEngineFileSystemAccessRequest::origin() const QUrl QWebEngineFileSystemAccessRequest::filePath() const { - return d_ptr->filePath(); + if (Q_LIKELY(d_ptr)) + return d_ptr->filePath(); + return QUrl(); } /*! @@ -109,7 +115,9 @@ QUrl QWebEngineFileSystemAccessRequest::filePath() const */ HandleType QWebEngineFileSystemAccessRequest::handleType() const { - return d_ptr->handleType(); + if (Q_LIKELY(d_ptr)) + return d_ptr->handleType(); + return File; } /*! @@ -118,7 +126,9 @@ HandleType QWebEngineFileSystemAccessRequest::handleType() const */ AccessFlags QWebEngineFileSystemAccessRequest::accessFlags() const { - return d_ptr->accessFlags(); + if (Q_LIKELY(d_ptr)) + return d_ptr->accessFlags(); + return {}; } QT_END_NAMESPACE diff --git a/src/core/api/qwebenginefilesystemaccessrequest.h b/src/core/api/qwebenginefilesystemaccessrequest.h index 37b1e186111..7707c607c8c 100644 --- a/src/core/api/qwebenginefilesystemaccessrequest.h +++ b/src/core/api/qwebenginefilesystemaccessrequest.h @@ -24,6 +24,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFileSystemAccessRequest Q_PROPERTY(AccessFlags accessFlags READ accessFlags CONSTANT FINAL) public: + QWebEngineFileSystemAccessRequest() = default; QWebEngineFileSystemAccessRequest(const QWebEngineFileSystemAccessRequest &other); QWebEngineFileSystemAccessRequest &operator=(const QWebEngineFileSystemAccessRequest &other); QWebEngineFileSystemAccessRequest(QWebEngineFileSystemAccessRequest &&other) noexcept = default; diff --git a/src/core/api/qwebenginefullscreenrequest.h b/src/core/api/qwebenginefullscreenrequest.h index 8e25286b64f..b07d158fd35 100644 --- a/src/core/api/qwebenginefullscreenrequest.h +++ b/src/core/api/qwebenginefullscreenrequest.h @@ -23,6 +23,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineFullScreenRequest Q_PROPERTY(QUrl origin READ origin CONSTANT) public: + QWebEngineFullScreenRequest() : QWebEngineFullScreenRequest(QUrl(), false, [](bool){}) {} QWebEngineFullScreenRequest(const QWebEngineFullScreenRequest &other); QWebEngineFullScreenRequest &operator=(const QWebEngineFullScreenRequest &other); QWebEngineFullScreenRequest(QWebEngineFullScreenRequest &&other); diff --git a/src/core/api/qwebenginehttprequest.cpp b/src/core/api/qwebenginehttprequest.cpp index 050213d1e2d..0039533d687 100644 --- a/src/core/api/qwebenginehttprequest.cpp +++ b/src/core/api/qwebenginehttprequest.cpp @@ -148,8 +148,8 @@ QWebEngineHttpRequest QWebEngineHttpRequest::postRequest(const QUrl &url, QByteArray buffer; for (QMap::const_iterator it = postData.begin(); it != postData.end(); it++) { - QByteArray key = QUrl::toPercentEncoding(it.key()); - QByteArray value = QUrl::toPercentEncoding(it.value()); + const QByteArray key = QUrl::toPercentEncoding(it.key()); + const QByteArray value = QUrl::toPercentEncoding(it.value()); if (buffer.size() > 0) buffer += '&'; diff --git a/src/core/api/qwebengineloadinginfo.h b/src/core/api/qwebengineloadinginfo.h index a268f888ff6..16da45a2adb 100644 --- a/src/core/api/qwebengineloadinginfo.h +++ b/src/core/api/qwebengineloadinginfo.h @@ -28,7 +28,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo Q_PROPERTY(ErrorDomain errorDomain READ errorDomain CONSTANT FINAL) Q_PROPERTY(int errorCode READ errorCode CONSTANT FINAL) Q_PROPERTY(QMultiMap responseHeaders READ responseHeaders CONSTANT REVISION(6,6) FINAL) - Q_PROPERTY(bool isDownload READ isDownload CONSTANT REVISION(6,9) FINAL) + Q_PROPERTY(bool isDownload READ isDownload CONSTANT REVISION(6,9)) public: enum LoadStatus { @@ -51,6 +51,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineLoadingInfo }; Q_ENUM(ErrorDomain) + QWebEngineLoadingInfo() : QWebEngineLoadingInfo(QUrl(), LoadStartedStatus) {} QWebEngineLoadingInfo(const QWebEngineLoadingInfo &other); QWebEngineLoadingInfo &operator=(const QWebEngineLoadingInfo &other); QWebEngineLoadingInfo(QWebEngineLoadingInfo &&other); diff --git a/src/core/api/qwebenginemessagepumpscheduler.cpp b/src/core/api/qwebenginemessagepumpscheduler.cpp index a435e2c0c5a..860696c3740 100644 --- a/src/core/api/qwebenginemessagepumpscheduler.cpp +++ b/src/core/api/qwebenginemessagepumpscheduler.cpp @@ -16,11 +16,6 @@ void QWebEngineMessagePumpScheduler::scheduleImmediateWork() QCoreApplication::postEvent(this, new QTimerEvent(0), Qt::NormalEventPriority); } -void QWebEngineMessagePumpScheduler::scheduleIdleWork() -{ - QCoreApplication::postEvent(this, new QTimerEvent(0), Qt::LowEventPriority); -} - void QWebEngineMessagePumpScheduler::scheduleDelayedWork(int delay) { if (delay < 0) { diff --git a/src/core/api/qwebenginemessagepumpscheduler_p.h b/src/core/api/qwebenginemessagepumpscheduler_p.h index 37f7dd9a6fc..b2c51415a93 100644 --- a/src/core/api/qwebenginemessagepumpscheduler_p.h +++ b/src/core/api/qwebenginemessagepumpscheduler_p.h @@ -29,7 +29,6 @@ class Q_WEBENGINECORE_EXPORT QWebEngineMessagePumpScheduler : public QObject public: QWebEngineMessagePumpScheduler(std::function callback); void scheduleImmediateWork(); - void scheduleIdleWork(); void scheduleDelayedWork(int delay); protected: diff --git a/src/core/api/qwebenginenewwindowrequest.cpp b/src/core/api/qwebenginenewwindowrequest.cpp index 1f0be9aa03c..500f3ac2bf2 100644 --- a/src/core/api/qwebenginenewwindowrequest.cpp +++ b/src/core/api/qwebenginenewwindowrequest.cpp @@ -98,7 +98,7 @@ QWebEngineNewWindowRequest::DestinationType QWebEngineNewWindowRequest::destinat \brief The URL that is requested for the new page. */ /*! - \qmlproperty QUrl WebEngineNewWindowRequest::requestedUrl + \qmlproperty url WebEngineNewWindowRequest::requestedUrl \brief The URL that is requested for the new page. \since QtWebEngine 1.5 */ @@ -112,7 +112,7 @@ QUrl QWebEngineNewWindowRequest::requestedUrl() const \brief The size that is requested for the new page. */ /*! - \qmlproperty QRect WebEngineNewWindowRequest::requestedGeometry + \qmlproperty rect WebEngineNewWindowRequest::requestedGeometry \brief The size that is requested for the new page. \since QtWebEngine 2.0 */ diff --git a/src/core/api/qwebenginepage.cpp b/src/core/api/qwebenginepage.cpp index 311fb100a2c..6ff454a0720 100644 --- a/src/core/api/qwebenginepage.cpp +++ b/src/core/api/qwebenginepage.cpp @@ -57,6 +57,7 @@ QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; using namespace QtWebEngineCore; static QWebEnginePage::WebWindowType toWindowType(WebContentsAdapterClient::WindowOpenDisposition disposition) @@ -661,8 +662,7 @@ static QWebEnginePage::Feature toDeprecatedFeature(QWebEnginePermission::Permiss break; } - Q_UNREACHABLE(); - return QWebEnginePage::Feature(-1); + Q_UNREACHABLE_RETURN(QWebEnginePage::Feature(-1)); } QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) @@ -1336,16 +1336,16 @@ void QWebEnginePage::triggerAction(WebAction action, bool) break; case CopyLinkToClipboard: if (d->view && d->view->lastContextMenuRequest() && !d->view->lastContextMenuRequest()->linkUrl().isEmpty()) { - QString urlString = d->view->lastContextMenuRequest()->linkUrl().toString( - QUrl::FullyEncoded); - QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped(); + const QString urlString = + d->view->lastContextMenuRequest()->linkUrl().toString(QUrl::FullyEncoded); + const QString linkText = d->view->lastContextMenuRequest()->linkText().toHtmlEscaped(); QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) - title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - QString html = QStringLiteral("") - + linkText + QStringLiteral(""); + const QString html = + "' + linkText + ""_L1; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->linkUrl()); QGuiApplication::clipboard()->setMimeData(data); @@ -1372,17 +1372,17 @@ void QWebEnginePage::triggerAction(WebAction action, bool) if (d->view && d->view->lastContextMenuRequest() && d->view->lastContextMenuRequest()->mediaUrl().isValid() && d->view->lastContextMenuRequest()->mediaType() == QWebEngineContextMenuRequest::MediaTypeImage) { - QString urlString = + const QString urlString = d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded); QString alt = d->view->lastContextMenuRequest()->altText(); if (!alt.isEmpty()) - alt = QStringLiteral(" alt=\"%1\"").arg(alt.toHtmlEscaped()); + alt = " alt=\""_L1 + alt.toHtmlEscaped() + u'"'; QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) - title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - QString html = QStringLiteral(""); + const QString html = ""_L1; data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->mediaUrl()); QGuiApplication::clipboard()->setMimeData(data); @@ -1402,20 +1402,19 @@ void QWebEnginePage::triggerAction(WebAction action, bool) == QWebEngineContextMenuRequest::MediaTypeAudio || d->view->lastContextMenuRequest()->mediaType() == QWebEngineContextMenuRequest::MediaTypeVideo)) { - QString urlString = + const QString urlString = d->view->lastContextMenuRequest()->mediaUrl().toString(QUrl::FullyEncoded); QString title = d->view->lastContextMenuRequest()->titleText(); if (!title.isEmpty()) - title = QStringLiteral(" title=\"%1\"").arg(title.toHtmlEscaped()); + title = " title=\""_L1 + title.toHtmlEscaped() + u'"'; QMimeData *data = new QMimeData(); data->setText(urlString); - if (d->view->lastContextMenuRequest()->mediaType() - == QWebEngineContextMenuRequest::MediaTypeAudio) - data->setHtml(QStringLiteral("")); - else - data->setHtml(QStringLiteral("")); + const bool isAudio = d->view->lastContextMenuRequest()->mediaType() + == QWebEngineContextMenuRequest::MediaTypeAudio; + const auto avTagName = isAudio ? "audio"_L1 : "video"_L1; + const QString html = u'<' + avTagName + "src=\""_L1 + urlString + u'"' + title + + ">'; + data->setHtml(html); data->setUrls(QList() << d->view->lastContextMenuRequest()->mediaUrl()); QGuiApplication::clipboard()->setMimeData(data); } @@ -1491,40 +1490,47 @@ void QWebEnginePage::triggerAction(WebAction action, bool) QTimer::singleShot(0, this, [d](){ d->adapter->viewSource(); }); break; case ToggleBold: - runJavaScript(QStringLiteral("document.execCommand('bold');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('bold');"_s, QWebEngineScript::ApplicationWorld); break; case ToggleItalic: - runJavaScript(QStringLiteral("document.execCommand('italic');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('italic');"_s, QWebEngineScript::ApplicationWorld); break; case ToggleUnderline: - runJavaScript(QStringLiteral("document.execCommand('underline');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('underline');"_s, QWebEngineScript::ApplicationWorld); break; case ToggleStrikethrough: - runJavaScript(QStringLiteral("document.execCommand('strikethrough');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('strikethrough');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignLeft: - runJavaScript(QStringLiteral("document.execCommand('justifyLeft');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyLeft');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignCenter: - runJavaScript(QStringLiteral("document.execCommand('justifyCenter');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyCenter');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignRight: - runJavaScript(QStringLiteral("document.execCommand('justifyRight');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyRight');"_s, + QWebEngineScript::ApplicationWorld); break; case AlignJustified: - runJavaScript(QStringLiteral("document.execCommand('justifyFull');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('justifyFull');"_s, + QWebEngineScript::ApplicationWorld); break; case Indent: - runJavaScript(QStringLiteral("document.execCommand('indent');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('indent');"_s, QWebEngineScript::ApplicationWorld); break; case Outdent: - runJavaScript(QStringLiteral("document.execCommand('outdent');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('outdent');"_s, QWebEngineScript::ApplicationWorld); break; case InsertOrderedList: - runJavaScript(QStringLiteral("document.execCommand('insertOrderedList');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('insertOrderedList');"_s, + QWebEngineScript::ApplicationWorld); break; case InsertUnorderedList: - runJavaScript(QStringLiteral("document.execCommand('insertUnorderedList');"), QWebEngineScript::ApplicationWorld); + runJavaScript(u"document.execCommand('insertUnorderedList');"_s, + QWebEngineScript::ApplicationWorld); break; case ChangeTextDirectionLTR: d->adapter->changeTextDirection(true /*left to right*/); @@ -1748,7 +1754,7 @@ void QWebEnginePagePrivate::setToolTip(const QString &toolTipText) \since 5.12 This signal is emitted when the JavaScript \c{window.print()} method is called on the main - frame, or the user pressed the print button of PDF viewer plugin. + frame, or the user pressed the print button of the PDF viewer plugin. Typically, the signal handler can simply call printToPdf(). Since 6.8, this signal is only emitted for the main frame, instead of being emitted for any @@ -2015,7 +2021,7 @@ void QWebEnginePage::toPlainText(const std::function &res void QWebEnginePage::setHtml(const QString &html, const QUrl &baseUrl) { - setContent(html.toUtf8(), QStringLiteral("text/html;charset=UTF-8"), baseUrl); + setContent(html.toUtf8(), u"text/html;charset=UTF-8"_s, baseUrl); } void QWebEnginePage::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl) @@ -2073,7 +2079,7 @@ QUrl QWebEnginePage::iconUrl() const By default, this property contains a null icon. If touch icons are disabled (see \c QWebEngineSettings::TouchIconsEnabled), the favicon is provided in two sizes - (16x16 and 32x32 pixels) encapsulated in \c{QIcon}. Otherwise, single icon is provided + (16x16 and 32x32 pixels) encapsulated in \c{QIcon}. Otherwise, a single icon is provided with the largest available size. \sa iconChanged(), iconUrl(), iconUrlChanged(), QWebEngineSettings::TouchIconsEnabled @@ -2235,7 +2241,7 @@ void QWebEnginePage::setDevToolsPage(QWebEnginePage *devToolsPage) If remote debugging is enabled (see \l{Qt WebEngine Developer Tools}), the id can be used to build the URL to connect to the developer tool websocket: - \c{ws://localhost:/devtools/page/)}. The websocket can be used to to interact + \c{ws://localhost:/devtools/page/)}. The websocket can be used to to interact with the page using the \l{https://chromedevtools.github.io/devtools-protocol/}{DevTools Protocol}. */ @@ -2284,7 +2290,7 @@ bool QWebEnginePage::javaScriptPrompt(const QUrl &securityOrigin, const QString void QWebEnginePage::javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString &message, int lineNumber, const QString &sourceID) { static QLoggingCategory loggingCategory("js", QtWarningMsg); - static QByteArray file = sourceID.toUtf8(); + const QByteArray file = sourceID.toUtf8(); QMessageLogger logger(file.constData(), lineNumber, nullptr, loggingCategory.categoryName()); switch (level) { @@ -2526,7 +2532,7 @@ QWebEnginePage::LifecycleState QWebEnginePage::recommendedState() const user. If the page is connected to a \e {view} then this property will be managed - automatically by the view according to it's own visibility. + automatically by the view according to its own visibility. \sa lifecycleState */ diff --git a/src/core/api/qwebengineprofile.cpp b/src/core/api/qwebengineprofile.cpp index 1c5807a9386..45b5a349d26 100644 --- a/src/core/api/qwebengineprofile.cpp +++ b/src/core/api/qwebengineprofile.cpp @@ -216,7 +216,7 @@ void QWebEngineProfilePrivate::cleanDownloads() m_ongoingDownloads.clear(); } -void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +void QWebEngineProfilePrivate::downloadRequested(const DownloadItemInfo &info) { Q_Q(QWebEngineProfile); diff --git a/src/core/api/qwebengineprofile_p.h b/src/core/api/qwebengineprofile_p.h index 0ccc2703756..d4b3513cd5d 100644 --- a/src/core/api/qwebengineprofile_p.h +++ b/src/core/api/qwebengineprofile_p.h @@ -51,7 +51,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineProfilePrivate : public QtWebEngineCore:: void cleanDownloads(); - void downloadRequested(DownloadItemInfo &info) override; + void downloadRequested(const DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; void showNotification(QSharedPointer &) override; diff --git a/src/core/api/qwebengineprofilebuilder.cpp b/src/core/api/qwebengineprofilebuilder.cpp index a30a390c368..91a604ba194 100644 --- a/src/core/api/qwebengineprofilebuilder.cpp +++ b/src/core/api/qwebengineprofilebuilder.cpp @@ -10,6 +10,8 @@ #include #include +using namespace Qt::StringLiterals; + /*! \class QWebEngineProfileBuilder \brief The QWebEngineProfileBuilder class provides a way to construct \l{QWebEngineProfile}. @@ -53,15 +55,15 @@ QWebEngineProfile *QWebEngineProfileBuilder::createOffTheRecordProfile(QObject * \sa QWebEngineProfile::storageName() */ QWebEngineProfile *QWebEngineProfileBuilder::createProfile(const QString &storageName, - QObject *parent) + QObject *parent) const { - d_ptr->m_storageName = storageName; auto buildLocationFromStandardPath = [](const QString &standardPath, const QString &name) { - QString location = standardPath; + QString location; + location += standardPath; if (location.isEmpty()) - location = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); + location += QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); - location.append(QLatin1String("/QtWebEngine/") % name); + location += "/QtWebEngine/"_L1 % name; return location; }; @@ -80,7 +82,7 @@ QWebEngineProfile *QWebEngineProfileBuilder::createProfile(const QString &storag return new QWebEngineProfile( new QWebEngineProfilePrivate(new QtWebEngineCore::ProfileAdapter( - d_ptr->m_storageName, d_ptr->m_dataPath, d_ptr->m_cachePath, + storageName, d_ptr->m_dataPath, d_ptr->m_cachePath, QtWebEngineCore::ProfileAdapter::HttpCacheType(d_ptr->m_httpCacheType), QtWebEngineCore::ProfileAdapter::PersistentCookiesPolicy( d_ptr->m_persistentCookiesPolicy), diff --git a/src/core/api/qwebengineprofilebuilder.h b/src/core/api/qwebengineprofilebuilder.h index fe8c713a82f..d81a6bd471f 100644 --- a/src/core/api/qwebengineprofilebuilder.h +++ b/src/core/api/qwebengineprofilebuilder.h @@ -4,31 +4,32 @@ #ifndef QWEBENGINEPROFILEBUILDER_H #define QWEBENGINEPROFILEBUILDER_H -#include #include #include +#include + QT_BEGIN_NAMESPACE struct QWebEngineProfileBuilderPrivate; -class Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder +class QWebEngineProfileBuilder { public: - QWebEngineProfileBuilder(); - ~QWebEngineProfileBuilder(); - QWebEngineProfile *createProfile(const QString &storageName, QObject *parent = nullptr); - static QWebEngineProfile *createOffTheRecordProfile(QObject *parent = nullptr); - QWebEngineProfileBuilder &setPersistentStoragePath(const QString &path); - QWebEngineProfileBuilder &setCachePath(const QString &path); - QWebEngineProfileBuilder &setHttpCacheType(QWebEngineProfile::HttpCacheType httpCacheType); - QWebEngineProfileBuilder &setPersistentCookiesPolicy( - QWebEngineProfile::PersistentCookiesPolicy persistentCookiesPolicy); - QWebEngineProfileBuilder &setHttpCacheMaximumSize(int maxSizeInBytes); - QWebEngineProfileBuilder &setPersistentPermissionsPolicy( + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder(); + Q_WEBENGINECORE_EXPORT ~QWebEngineProfileBuilder(); + Q_WEBENGINECORE_EXPORT QWebEngineProfile *createProfile(const QString &storageName, QObject *parent = nullptr) const; + Q_WEBENGINECORE_EXPORT static QWebEngineProfile *createOffTheRecordProfile(QObject *parent = nullptr); + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setPersistentStoragePath(const QString &path); + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setCachePath(const QString &path); + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setHttpCacheType(QWebEngineProfile::HttpCacheType httpCacheType); + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setPersistentCookiesPolicy( + QWebEngineProfile::PersistentCookiesPolicy persistentCookiesPolicy); + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setHttpCacheMaximumSize(int maxSizeInBytes); + Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilder &setPersistentPermissionsPolicy( QWebEngineProfile::PersistentPermissionsPolicy persistentPermissionPolicy); private: - Q_DISABLE_COPY(QWebEngineProfileBuilder) + Q_DISABLE_COPY_MOVE(QWebEngineProfileBuilder) std::unique_ptr d_ptr; }; diff --git a/src/core/api/qwebengineprofilebuilder_p.h b/src/core/api/qwebengineprofilebuilder_p.h index 32fcc730ea7..4146b55085d 100644 --- a/src/core/api/qwebengineprofilebuilder_p.h +++ b/src/core/api/qwebengineprofilebuilder_p.h @@ -20,9 +20,8 @@ #include "qwebengineprofile.h" QT_BEGIN_NAMESPACE -struct Q_WEBENGINECORE_EXPORT QWebEngineProfileBuilderPrivate +struct QWebEngineProfileBuilderPrivate { - QString m_storageName; QString m_dataPath; QString m_cachePath; QWebEngineProfile::HttpCacheType m_httpCacheType = QWebEngineProfile::DiskHttpCache; diff --git a/src/core/api/qwebenginescript.cpp b/src/core/api/qwebenginescript.cpp index 846b011967c..ab91576bd89 100644 --- a/src/core/api/qwebenginescript.cpp +++ b/src/core/api/qwebenginescript.cpp @@ -7,6 +7,7 @@ #include #include +using namespace Qt::StringLiterals; using QtWebEngineCore::UserScript; QT_BEGIN_NAMESPACE @@ -161,17 +162,17 @@ void QWebEngineScript::setSourceUrl(const QUrl &url) QFile file; if (url.isLocalFile()) { file.setFileName(url.toLocalFile()); - } else if (url.scheme().compare(QLatin1String("qrc"), Qt::CaseInsensitive) == 0) { + } else if (url.scheme().compare("qrc"_L1, Qt::CaseInsensitive) == 0) { if (url.authority().isEmpty()) file.setFileName(QLatin1Char(':') + url.path()); } if (!file.open(QIODevice::ReadOnly)) { - qWarning() << "Can't open user script " << url; + qWarning("Can't open user script %ls", qUtf16Printable(url.toString())); return; } - QString source = QString::fromUtf8(file.readAll()); + const QString source = QString::fromUtf8(file.readAll()); setSourceCode(source); } diff --git a/src/core/api/qwebenginesettings.h b/src/core/api/qwebenginesettings.h index e5dc2d678d1..3813dfecb04 100644 --- a/src/core/api/qwebenginesettings.h +++ b/src/core/api/qwebenginesettings.h @@ -64,7 +64,7 @@ class Q_WEBENGINECORE_EXPORT QWebEngineSettings ForceDarkMode, PrintHeaderAndFooter, PreferCSSMarginsForPrinting, - JSTouchEventsEnabled, + TouchEventsApiEnabled, }; enum FontSize { diff --git a/src/core/api/qwebengineurlscheme.cpp b/src/core/api/qwebengineurlscheme.cpp index be56a304801..d2ca56f62d8 100644 --- a/src/core/api/qwebengineurlscheme.cpp +++ b/src/core/api/qwebengineurlscheme.cpp @@ -335,29 +335,33 @@ void QWebEngineUrlScheme::setFlags(Flags newValue) void QWebEngineUrlScheme::registerScheme(const QWebEngineUrlScheme &scheme) { if (scheme.d->name.empty()) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme name cannot be empty"); return; } bool needsPort = scheme.d->has_port_component(); bool hasPort = scheme.d->default_port != url::PORT_UNSPECIFIED; if (needsPort && !hasPort) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "needs a default port"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s needs a default port", + scheme.d->name.data()); return; } if (url::CustomScheme::FindScheme(scheme.d->name)) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "already registered"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s already registered", + scheme.d->name.data()); return; } if (url::IsStandard(scheme.d->name.data(), url::Component(0, static_cast(scheme.d->name.size())))) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Scheme" << scheme.name() << "is a standard scheme"; + qWarning("QWebEngineUrlScheme::registerScheme: Scheme %s is a standard scheme", + scheme.d->name.data()); return; } if (g_schemesLocked) { - qWarning() << "QWebEngineUrlScheme::registerScheme: Too late to register scheme" << scheme.name(); + qWarning("QWebEngineUrlScheme::registerScheme: Too late to register scheme %s", + scheme.d->name.data()); return; } diff --git a/src/core/api/qwebenginewebauthuxrequest.cpp b/src/core/api/qwebenginewebauthuxrequest.cpp index 18ebbb70ea9..8e64948214e 100644 --- a/src/core/api/qwebenginewebauthuxrequest.cpp +++ b/src/core/api/qwebenginewebauthuxrequest.cpp @@ -12,7 +12,7 @@ \since QtWebEngine 6.7 \brief Encapsulates the data of a WebAuth UX request. - Web engine's WebAuth UX requests are passed to the user in the + WebEngine's WebAuth UX requests are passed to the user in the \l WebEngineView::webAuthUxRequested() signal. For more information about how to handle web engine authenticator requests, see the @@ -109,8 +109,9 @@ \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. \li The minimum PIN length that the authenticator will accept for the PIN. \endlist - Use this structure to update the WebAuth UX dialog when the WebAuth UX state is \l - WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin. + Use this structure to update the WebAuth UX dialog when the WebAuth UX + \l {WebEngineWebAuthUxRequest::}{state} is + \c {WebEngineWebAuthUxRequest.WebAuthUxState.CollectPin}. */ /*! @@ -137,7 +138,7 @@ /*! \qmlproperty int QtWebEngine::webEngineWebAuthPinRequest::remainingAttempts \brief The number of attempts remaining before a hard lock. Should be ignored unless - \l{WebEngineWebAuthPinRequest::reason} is + \l{webEngineWebAuthPinRequest::reason} is \c{WebEngineWebAuthUxRequest.PinEntryReason.Challenge}. */ @@ -208,7 +209,7 @@ \value StorageFull The resident credential could not be created because the authenticator has insufficient storage. \value UserConsentDenied User consent denied. - \value WinUserCancelled The user clicked \uicontrol Cancel in the native windows UI. + \value WinUserCancelled The user clicked \uicontrol Cancel in the native Windows UI. */ /*! diff --git a/src/core/authenticator_request_client_delegate_qt.cpp b/src/core/authenticator_request_client_delegate_qt.cpp index 5f9fd9ca37d..5d01df536e1 100644 --- a/src/core/authenticator_request_client_delegate_qt.cpp +++ b/src/core/authenticator_request_client_delegate_qt.cpp @@ -103,11 +103,16 @@ bool AuthenticatorRequestClientDelegateQt::DoesBlockRequestOnFailure( } return true; } + void AuthenticatorRequestClientDelegateQt::RegisterActionCallbacks( - base::OnceClosure cancel_callback, base::RepeatingClosure start_over_callback, + base::OnceClosure cancel_callback, + base::RepeatingClosure start_over_callback, AccountPreselectedCallback account_preselected_callback, device::FidoRequestHandlerBase::RequestCallback request_callback, - base::RepeatingClosure bluetooth_adapter_power_on_callback) + base::RepeatingClosure bluetooth_adapter_power_on_callback, + base::RepeatingCallback< + void(device::FidoRequestHandlerBase::BlePermissionCallback)> + request_ble_permission_callback) { m_cancelCallback = std::move(cancel_callback); m_startOverCallback = std::move(start_over_callback); @@ -116,13 +121,6 @@ void AuthenticatorRequestClientDelegateQt::RegisterActionCallbacks( m_bluetoothAdapterPowerOnCallback = std::move(bluetooth_adapter_power_on_callback); } -void AuthenticatorRequestClientDelegateQt::ShouldReturnAttestation( - const std::string &relying_party_id, const device::FidoAuthenticator *authenticator, - bool is_enterprise_attestation, base::OnceCallback callback) -{ - std::move(callback).Run(!is_enterprise_attestation); -} - void AuthenticatorRequestClientDelegateQt::SelectAccount( std::vector responses, base::OnceCallback callback) @@ -150,7 +148,7 @@ void AuthenticatorRequestClientDelegateQt::SelectAccount( if (has_user_identifying_info) { QString userName = toQt(*response.user_entity->name); m_userMap[userName] = nIndex; - userList.append(userName); + userList.append(std::move(userName)); } } m_dialogController->selectAccount(userList); diff --git a/src/core/authenticator_request_client_delegate_qt.h b/src/core/authenticator_request_client_delegate_qt.h index 05c6136bd16..8c8089f04d3 100644 --- a/src/core/authenticator_request_client_delegate_qt.h +++ b/src/core/authenticator_request_client_delegate_qt.h @@ -34,15 +34,15 @@ class AuthenticatorRequestClientDelegateQt : public content::AuthenticatorReques // content::AuthenticatorRequestClientDelegate ovverrides void SetRelyingPartyId(const std::string &rp_id) override; bool DoesBlockRequestOnFailure(InterestingFailureReason reason) override; - void RegisterActionCallbacks(base::OnceClosure cancel_callback, - base::RepeatingClosure start_over_callback, - AccountPreselectedCallback account_preselected_callback, - device::FidoRequestHandlerBase::RequestCallback request_callback, - base::RepeatingClosure bluetooth_adapter_power_on_callback) override; - void ShouldReturnAttestation(const std::string &relying_party_id, - const device::FidoAuthenticator *authenticator, - bool is_enterprise_attestation, - base::OnceCallback callback) override; + void RegisterActionCallbacks( + base::OnceClosure cancel_callback, + base::RepeatingClosure start_over_callback, + AccountPreselectedCallback account_preselected_callback, + device::FidoRequestHandlerBase::RequestCallback request_callback, + base::RepeatingClosure bluetooth_adapter_power_on_callback, + base::RepeatingCallback< + void(device::FidoRequestHandlerBase::BlePermissionCallback)> + request_ble_permission_callback) override; void SelectAccount( std::vector responses, base::OnceCallback callback) override; diff --git a/src/core/autofill_client_qt.cpp b/src/core/autofill_client_qt.cpp index b9a84943e04..b0e846844ef 100644 --- a/src/core/autofill_client_qt.cpp +++ b/src/core/autofill_client_qt.cpp @@ -61,8 +61,9 @@ const PrefService *AutofillClientQt::GetPrefs() const return profile->GetPrefs(); } -void AutofillClientQt::ShowAutofillSuggestions(const autofill::AutofillClient::PopupOpenArgs &open_args, - base::WeakPtr delegate) +autofill::AutofillClient::SuggestionUiSessionId AutofillClientQt::ShowAutofillSuggestions( + const autofill::AutofillClient::PopupOpenArgs &open_args, + base::WeakPtr delegate) { m_popupController->d->delegate = delegate; m_popupController->d->suggestions = open_args.suggestions; @@ -74,6 +75,7 @@ void AutofillClientQt::ShowAutofillSuggestions(const autofill::AutofillClient::P adapterClient()->showAutofillPopup(m_popupController.data(), QRect(toQt(gfx::ToEnclosingRect(open_args.element_bounds))), autoSelectFirstSuggestion); + return {}; } void AutofillClientQt::UpdateAutofillDataListValues( diff --git a/src/core/autofill_client_qt.h b/src/core/autofill_client_qt.h index 9e7bbd300a1..2f97e005ba5 100644 --- a/src/core/autofill_client_qt.h +++ b/src/core/autofill_client_qt.h @@ -45,16 +45,13 @@ class AutofillClientQt : public autofill::ContentAutofillClient, PrefService *GetPrefs() override; const PrefService *GetPrefs() const override; - void ShowAutofillSuggestions( - const PopupOpenArgs &open_args, - base::WeakPtr delegate) override; + SuggestionUiSessionId + ShowAutofillSuggestions(const PopupOpenArgs &open_args, + base::WeakPtr delegate) override; void UpdateAutofillDataListValues( base::span datalist) override; void PinAutofillSuggestions() override; base::span GetAutofillSuggestions() const override; - void UpdatePopup(const std::vector &suggestions, - autofill::FillingProduct main_filling_product, - autofill::AutofillSuggestionTriggerSource trigger_source) override{}; void HideAutofillSuggestions(autofill::SuggestionHidingReason reason) override; bool IsAutocompleteEnabled() const override; bool IsPasswordManagerEnabled() override; diff --git a/src/core/autofill_popup_controller.cpp b/src/core/autofill_popup_controller.cpp index a60392051ab..99eb09f379c 100644 --- a/src/core/autofill_popup_controller.cpp +++ b/src/core/autofill_popup_controller.cpp @@ -9,7 +9,7 @@ namespace QtWebEngineCore { -using SuggestionPosition = autofill::AutofillSuggestionDelegate::SuggestionPosition; +using SuggestionPosition = autofill::AutofillSuggestionDelegate::SuggestionMetadata; AutofillPopupController::AutofillPopupController(AutofillPopupControllerPrivate *dd) { @@ -86,7 +86,7 @@ void AutofillPopupController::acceptSuggestion() void AutofillPopupController::notifyPopupShown() { - d->delegate->OnSuggestionsShown(); + d->delegate->OnSuggestionsShown({}); } void AutofillPopupController::notifyPopupHidden() diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp index bc78b815aee..a36076ffef1 100644 --- a/src/core/browser_accessibility_manager_qt.cpp +++ b/src/core/browser_accessibility_manager_qt.cpp @@ -3,7 +3,7 @@ #include "qtwebenginecoreglobal.h" -#include "content/browser/accessibility/browser_accessibility_manager.h" +#include "ui/accessibility/platform/browser_accessibility_manager.h" #include @@ -12,18 +12,19 @@ #include "browser_accessibility_manager_qt.h" #include "render_widget_host_view_qt.h" // WebContentsAccessibilityQt -#include "content/browser/accessibility/browser_accessibility.h" #include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/platform/browser_accessibility.h" #include #endif // QT_CONFIG(accessibility) -namespace content { +namespace ui { // static -BrowserAccessibilityManager *BrowserAccessibilityManager::Create( - const ui::AXTreeUpdate &initialTree, - ui::AXPlatformTreeManagerDelegate *delegate) +BrowserAccessibilityManager * +BrowserAccessibilityManager::Create(const ui::AXTreeUpdate &initialTree, + ui::AXNodeIdDelegate &nodeDelegate, + ui::AXPlatformTreeManagerDelegate *delegate) { #if QT_CONFIG(accessibility) Q_ASSERT(delegate); @@ -35,7 +36,7 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create( return nullptr; } - return new BrowserAccessibilityManagerQt(access, initialTree, delegate); + return new BrowserAccessibilityManagerQt(access, initialTree, nodeDelegate, delegate); #else Q_UNUSED(initialTree); Q_UNUSED(delegate); @@ -44,12 +45,15 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create( } // static -BrowserAccessibilityManager *BrowserAccessibilityManager::Create( - ui::AXPlatformTreeManagerDelegate *delegate) +BrowserAccessibilityManager * +BrowserAccessibilityManager::Create(ui::AXNodeIdDelegate &nodeDelegate, + ui::AXPlatformTreeManagerDelegate *delegate) { #if QT_CONFIG(accessibility) - return BrowserAccessibilityManager::Create(BrowserAccessibilityManagerQt::GetEmptyDocument(), delegate); + return BrowserAccessibilityManager::Create(BrowserAccessibilityManagerQt::GetEmptyDocument(), + nodeDelegate, delegate); #else + Q_UNUSED(nodeDelegate); Q_UNUSED(delegate); return nullptr; #endif @@ -57,11 +61,11 @@ BrowserAccessibilityManager *BrowserAccessibilityManager::Create( #if QT_CONFIG(accessibility) BrowserAccessibilityManagerQt::BrowserAccessibilityManagerQt( - QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility, - const ui::AXTreeUpdate &initialTree, - ui::AXPlatformTreeManagerDelegate *delegate) - : BrowserAccessibilityManager(delegate) - , m_webContentsAccessibility(webContentsAccessibility) + QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility, + const ui::AXTreeUpdate &initialTree, ui::AXNodeIdDelegate &nodeDelegate, + ui::AXPlatformTreeManagerDelegate *delegate) + : BrowserAccessibilityManager(nodeDelegate, delegate) + , m_webContentsAccessibility(webContentsAccessibility) { Initialize(initialTree); m_valid = true; // BrowserAccessibilityQt can start using the AXTree @@ -74,7 +78,7 @@ BrowserAccessibilityManagerQt::~BrowserAccessibilityManagerQt() QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible() { - content::BrowserAccessibility *parent_node = GetParentNodeFromParentTreeAsBrowserAccessibility(); + ui::BrowserAccessibility *parent_node = GetParentNodeFromParentTreeAsBrowserAccessibility(); if (!parent_node) { Q_ASSERT(m_webContentsAccessibility); return QAccessible::queryAccessibleInterface(m_webContentsAccessibility->accessibilityParentObject()); diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h index 5006f22111d..3b8f1833794 100644 --- a/src/core/browser_accessibility_manager_qt.h +++ b/src/core/browser_accessibility_manager_qt.h @@ -4,7 +4,7 @@ #ifndef BROWSER_ACCESSIBILITY_MANAGER_QT_H #define BROWSER_ACCESSIBILITY_MANAGER_QT_H -#include "content/browser/accessibility/browser_accessibility_manager.h" +#include "ui/accessibility/platform/browser_accessibility_manager.h" #include #include @@ -15,14 +15,15 @@ namespace QtWebEngineCore { class WebContentsAccessibilityQt; } -namespace content { +namespace ui { class BrowserAccessibilityManagerQt : public BrowserAccessibilityManager { public: - BrowserAccessibilityManagerQt(QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility, - const ui::AXTreeUpdate &initialTree, - ui::AXPlatformTreeManagerDelegate *delegate); + BrowserAccessibilityManagerQt( + QtWebEngineCore::WebContentsAccessibilityQt *webContentsAccessibility, + const ui::AXTreeUpdate &initialTree, ui::AXNodeIdDelegate &nodeDelegate, + ui::AXPlatformTreeManagerDelegate *delegate); ~BrowserAccessibilityManagerQt() override; void FireBlinkEvent(ax::mojom::Event event_type, BrowserAccessibility *node, diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 1d2f39c2f9e..54a15650da0 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -11,19 +11,18 @@ #include "type_conversion.h" #if QT_CONFIG(accessibility) -#include "content/browser/accessibility/browser_accessibility.h" #include "ui/accessibility/ax_enums.mojom.h" +#include "ui/accessibility/platform/browser_accessibility.h" #include namespace QtWebEngineCore { class BrowserAccessibilityInterface; -class BrowserAccessibilityQt - : public content::BrowserAccessibility +class BrowserAccessibilityQt : public ui::BrowserAccessibility { public: - BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager, ui::AXNode *node); + BrowserAccessibilityQt(ui::BrowserAccessibilityManager *manager, ui::AXNode *node); ~BrowserAccessibilityQt(); bool isReady() const; @@ -127,17 +126,16 @@ class BrowserAccessibilityInterface void modelChange(QAccessibleTableModelChangeEvent *event) override; private: - content::BrowserAccessibility *findTable() const; + ui::BrowserAccessibility *findTable() const; QObject *m_object = nullptr; QAccessible::Id m_id = 0; BrowserAccessibilityQt *q; }; -BrowserAccessibilityQt::BrowserAccessibilityQt(content::BrowserAccessibilityManager *manager, +BrowserAccessibilityQt::BrowserAccessibilityQt(ui::BrowserAccessibilityManager *manager, ui::AXNode *node) - : content::BrowserAccessibility(manager, node) - , interface(new BrowserAccessibilityInterface(this)) + : ui::BrowserAccessibility(manager, node), interface(new BrowserAccessibilityInterface(this)) { } @@ -159,8 +157,8 @@ BrowserAccessibilityInterface::BrowserAccessibilityInterface(BrowserAccessibilit { if (parent() && parent()->object()) { m_object = new QObject(parent()->object()); - QString name = toQt(q->GetAuthorUniqueId()); - if (!name.isEmpty()) + const std::u16string name = q->GetAuthorUniqueId(); + if (!name.empty()) m_object->setObjectName(name); } @@ -182,7 +180,7 @@ bool BrowserAccessibilityInterface::isValid() const if (!q->isReady()) return false; - auto managerQt = static_cast(q->manager()); + auto managerQt = static_cast(q->manager()); return managerQt && managerQt->isValid(); } @@ -246,15 +244,15 @@ void *BrowserAccessibilityInterface::interface_cast(QAccessible::InterfaceType t QAccessibleInterface *BrowserAccessibilityInterface::parent() const { - content::BrowserAccessibility *chromiumParent = q->PlatformGetParent(); + ui::BrowserAccessibility *chromiumParent = q->PlatformGetParent(); if (chromiumParent) return toQAccessibleInterface(chromiumParent); - return static_cast(q->manager())->rootParentAccessible(); + return static_cast(q->manager())->rootParentAccessible(); } QAccessibleInterface *BrowserAccessibilityInterface::child(int index) const { - content::BrowserAccessibility *chromiumChild = q->PlatformGetChild(index); + ui::BrowserAccessibility *chromiumChild = q->PlatformGetChild(index); return chromiumChild ? toQAccessibleInterface(chromiumChild) : nullptr; } @@ -358,7 +356,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const case ax::mojom::Role::kCaption: return QAccessible::Heading; case ax::mojom::Role::kCaret: - return QAccessible::NoRole; // FIXME: https://codereview.chromium.org/2781613003 + return QAccessible::Caret; case ax::mojom::Role::kCell: return QAccessible::Cell; case ax::mojom::Role::kCheckBox: @@ -375,7 +373,6 @@ QAccessible::Role BrowserAccessibilityInterface::role() const return QAccessible::ColumnHeader; case ax::mojom::Role::kComboBoxGrouping: case ax::mojom::Role::kComboBoxMenuButton: - case ax::mojom::Role::kTextFieldWithComboBox: return QAccessible::ComboBox; case ax::mojom::Role::kComboBoxSelect: return QAccessible::PopupMenu; @@ -478,8 +475,6 @@ QAccessible::Role BrowserAccessibilityInterface::role() const case ax::mojom::Role::kFooter: // CORE-AAM recommends LANDMARK instead of FOOTER. return QAccessible::Section; - case ax::mojom::Role::kFooterAsNonLandmark: - return QAccessible::Section; case ax::mojom::Role::kForm: return QAccessible::Form; case ax::mojom::Role::kGraphicsDocument: @@ -490,10 +485,11 @@ QAccessible::Role BrowserAccessibilityInterface::role() const return QAccessible::Graphic; case ax::mojom::Role::kGrid: return QAccessible::Table; + case ax::mojom::Role::kGridCell: + return QAccessible::Cell; case ax::mojom::Role::kGroup: return QAccessible::Grouping; case ax::mojom::Role::kHeader: - case ax::mojom::Role::kHeaderAsNonLandmark: return QAccessible::Section; case ax::mojom::Role::kHeading: return QAccessible::Heading; @@ -616,7 +612,7 @@ QAccessible::Role BrowserAccessibilityInterface::role() const return QAccessible::Grouping; case ax::mojom::Role::kPopUpButton: return QAccessible::ComboBox; - case ax::mojom::Role::kPortal: + case ax::mojom::Role::kPortalDeprecated: return QAccessible::Button; case ax::mojom::Role::kPreDeprecated: return QAccessible::Section; @@ -647,6 +643,8 @@ QAccessible::Role BrowserAccessibilityInterface::role() const case ax::mojom::Role::kSearchBox: return QAccessible::EditableText; case ax::mojom::Role::kSection: + case ax::mojom::Role::kSectionFooter: + case ax::mojom::Role::kSectionHeader: case ax::mojom::Role::kSectionWithoutName: return QAccessible::Section; case ax::mojom::Role::kSlider: @@ -685,6 +683,8 @@ QAccessible::Role BrowserAccessibilityInterface::role() const return QAccessible::StaticText; case ax::mojom::Role::kTextField: return QAccessible::EditableText; + case ax::mojom::Role::kTextFieldWithComboBox: + return QAccessible::ComboBox; case ax::mojom::Role::kTime: case ax::mojom::Role::kTimer: return QAccessible::Clock; @@ -838,7 +838,8 @@ BrowserAccessibilityInterface::keyBindingsForAction(const QString & /*actionName void BrowserAccessibilityInterface::addSelection(int startOffset, int endOffset) { - q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset), q->CreatePositionAt(endOffset))); + q->manager()->SetSelection(ui::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset), + q->CreatePositionAt(endOffset))); } QString BrowserAccessibilityInterface::attributes(int offset, int *startOffset, int *endOffset) const @@ -896,19 +897,22 @@ QString BrowserAccessibilityInterface::text(int startOffset, int endOffset) cons void BrowserAccessibilityInterface::removeSelection(int selectionIndex) { - q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(0), q->CreatePositionAt(0))); + q->manager()->SetSelection( + ui::BrowserAccessibility::AXRange(q->CreatePositionAt(0), q->CreatePositionAt(0))); } void BrowserAccessibilityInterface::setCursorPosition(int position) { - q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(position), q->CreatePositionAt(position))); + q->manager()->SetSelection(ui::BrowserAccessibility::AXRange(q->CreatePositionAt(position), + q->CreatePositionAt(position))); } void BrowserAccessibilityInterface::setSelection(int selectionIndex, int startOffset, int endOffset) { if (selectionIndex != 0) return; - q->manager()->SetSelection(content::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset), q->CreatePositionAt(endOffset))); + q->manager()->SetSelection(ui::BrowserAccessibility::AXRange(q->CreatePositionAt(startOffset), + q->CreatePositionAt(endOffset))); } int BrowserAccessibilityInterface::characterCount() const @@ -988,9 +992,9 @@ QAccessibleInterface *BrowserAccessibilityInterface::cellAt(int row, int column) return nullptr; std::optional cell_id = q->GetCellId(row, column); - content::BrowserAccessibility *cell = cell_id ? q->manager()->GetFromID(*cell_id) : nullptr; + ui::BrowserAccessibility *cell = cell_id ? q->manager()->GetFromID(*cell_id) : nullptr; if (cell) - return content::toQAccessibleInterface(cell); + return ui::toQAccessibleInterface(cell); return nullptr; } @@ -1132,9 +1136,9 @@ bool BrowserAccessibilityInterface::isSelected() const return false; } -content::BrowserAccessibility *BrowserAccessibilityInterface::findTable() const +ui::BrowserAccessibility *BrowserAccessibilityInterface::findTable() const { - content::BrowserAccessibility *parent = q->PlatformGetParent(); + ui::BrowserAccessibility *parent = q->PlatformGetParent(); while (parent && parent->GetRole() != ax::mojom::Role::kTable) parent = parent->PlatformGetParent(); @@ -1143,9 +1147,9 @@ content::BrowserAccessibility *BrowserAccessibilityInterface::findTable() const QAccessibleInterface *BrowserAccessibilityInterface::table() const { - content::BrowserAccessibility *table = findTable(); + ui::BrowserAccessibility *table = findTable(); Q_ASSERT(table); - return content::toQAccessibleInterface(table); + return ui::toQAccessibleInterface(table); } void BrowserAccessibilityInterface::modelChange(QAccessibleTableModelChangeEvent *) @@ -1155,7 +1159,7 @@ void BrowserAccessibilityInterface::modelChange(QAccessibleTableModelChangeEvent } // namespace QtWebEngineCore #endif // QT_CONFIG(accessibility) -namespace content { +namespace ui { // static std::unique_ptr BrowserAccessibility::Create(BrowserAccessibilityManager *man, ui::AXNode *node) @@ -1181,4 +1185,4 @@ const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *o } #endif // #if QT_CONFIG(accessibility) -} // namespace content +} // namespace ui diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index 598aa3ef52d..85196e19c0a 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -9,13 +9,13 @@ #if QT_CONFIG(accessibility) QT_FORWARD_DECLARE_CLASS(QAccessibleInterface) -namespace content { +namespace ui { class BrowserAccessibility; QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj); const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *obj); -} // namespace content +} // namespace ui #endif // QT_CONFIG(accessibility) #endif // BROWSER_ACCESSIBILITY_QT_H diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp index 2104a91ccb9..35407a62b0d 100644 --- a/src/core/browser_main_parts_qt.cpp +++ b/src/core/browser_main_parts_qt.cpp @@ -153,8 +153,7 @@ class MessagePumpForUIQt : public base::MessagePump if (more_work_info.is_immediate()) return m_scheduler.scheduleImmediateWork(); - if (m_delegate->DoIdleWork()) - return m_scheduler.scheduleIdleWork(); + m_delegate->DoIdleWork(); ScheduleDelayedWork(more_work_info.delayed_run_time); } diff --git a/src/core/client_cert_select_controller.cpp b/src/core/client_cert_select_controller.cpp index d6af984c187..e898da618ae 100644 --- a/src/core/client_cert_select_controller.cpp +++ b/src/core/client_cert_select_controller.cpp @@ -75,7 +75,7 @@ void ClientCertSelectController::select(const QSslCertificate &certificate) LOG(WARNING) << "ClientCertSelectController::select() certificate already selected"; return; } - QByteArray derCertificate = certificate.toDer(); + const QByteArray derCertificate = certificate.toDer(); scoped_refptr selectedCert = net::X509Certificate::CreateFromBytes(base::make_span((const unsigned char *)derCertificate.constData(), (long unsigned)derCertificate.length())); diff --git a/src/core/clipboard_qt.cpp b/src/core/clipboard_qt.cpp index 463d858503f..1560d581594 100644 --- a/src/core/clipboard_qt.cpp +++ b/src/core/clipboard_qt.cpp @@ -32,6 +32,8 @@ #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static void registerMetaTypes() @@ -125,21 +127,22 @@ void ClipboardQt::WritePortableAndPlatformRepresentations(ui::ClipboardBuffer ty m_dataSrc[type] = std::move(data_src); } -void ClipboardQt::WriteText(base::StringPiece text) +void ClipboardQt::WriteText(std::string_view text) { getUncommittedData()->setText(toQString(text)); } -void ClipboardQt::WriteHTML(base::StringPiece markup, std::optional source_url) +void ClipboardQt::WriteHTML(std::string_view markup, std::optional source_url) { - QString markup_string = toQString(markup); + QString markup_string; #if defined (Q_OS_MACOS) // We need to prepend the charset on macOS to prevent garbled Unicode characters // when pasting to certain applications (e.g. Notes, TextEdit) // Mirrors the behavior in ui/base/clipboard/clipboard_mac.mm in Chromium. - markup_string.prepend(QLatin1String("")); + markup_string += ""_L1; #endif + markup_string += toQString(markup); #if !defined(Q_OS_WIN) getUncommittedData()->setHtml(markup_string); @@ -162,7 +165,7 @@ void ClipboardQt::WriteHTML(base::StringPiece markup, std::optionalsetData(QString::fromLatin1(ui::kMimeTypeRTF), toQByteArray(rtf)); } @@ -177,12 +180,12 @@ void ClipboardQt::WriteBitmap(const SkBitmap &bitmap) getUncommittedData()->setImageData(toQImage(bitmap).copy()); } -void ClipboardQt::WriteBookmark(base::StringPiece title_in, base::StringPiece url_in) +void ClipboardQt::WriteBookmark(std::string_view title_in, std::string_view url_in) { // FIXME: Untested, seems to be used only for drag-n-drop. // Write as a mozilla url (UTF16: URL, newline, title). - QString url = toQString(url_in); - QString title = toQString(title_in); + const QString url = toQString(url_in); + const QString title = toQString(title_in); QByteArray data; data.append(reinterpret_cast(url.utf16()), url.size() * 2); @@ -235,8 +238,10 @@ void ClipboardQt::ReadAvailableTypes(ui::ClipboardBuffer type, for (const auto& mime_type : GetStandardFormats(type, data_dst)) types->push_back(mime_type); - if (mimeData->hasFormat(QString::fromLatin1(ui::kMimeTypeWebCustomData))) { - const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData)); + const QString serializedDataTransferCustomType = + QString::fromStdString(ui::ClipboardFormatType::DataTransferCustomType().Serialize()); + if (mimeData->hasFormat(serializedDataTransferCustomType)) { + const QByteArray customData = mimeData->data(serializedDataTransferCustomType); const base::span custom_data(customData.constData(), (unsigned long)customData.size()); ui::ReadCustomDataTypes(base::as_bytes(custom_data), types); } @@ -337,15 +342,17 @@ void ClipboardQt::ReadPng(ui::ClipboardBuffer type, const ui::DataTransferEndpoi return std::move(callback).Run(std::move(pngData)); } -void ClipboardQt::ReadCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type, - const ui::DataTransferEndpoint *data_dst, - std::u16string *result) const +void ClipboardQt::ReadDataTransferCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type, + const ui::DataTransferEndpoint *data_dst, + std::u16string *result) const { const QMimeData *mimeData = QGuiApplication::clipboard()->mimeData( clipboard_type == ui::ClipboardBuffer::kCopyPaste ? QClipboard::Clipboard : QClipboard::Selection); if (!mimeData) return; - const QByteArray customData = mimeData->data(QString::fromLatin1(ui::kMimeTypeWebCustomData)); + const QString serializedDataTransferCustomType = + QString::fromStdString(ui::ClipboardFormatType::DataTransferCustomType().Serialize()); + const QByteArray customData = mimeData->data(serializedDataTransferCustomType); const base::span custom_data(customData.constData(), (unsigned long)customData.size()); if (auto maybe_result = ui::ReadCustomDataForType(base::as_bytes(custom_data), type)) *result = *std::move(maybe_result); @@ -369,7 +376,7 @@ void ClipboardQt::ReadSvg(ui::ClipboardBuffer clipboard_type, *result = toString16(QString::fromUtf8(svgData)); } -void ClipboardQt::WriteSvg(base::StringPiece markup) +void ClipboardQt::WriteSvg(std::string_view markup) { getUncommittedData()->setData(QString::fromLatin1(ui::kMimeTypeSvg), toQByteArray(markup)); diff --git a/src/core/clipboard_qt.h b/src/core/clipboard_qt.h index af75ff0e68e..077251fc7d1 100644 --- a/src/core/clipboard_qt.h +++ b/src/core/clipboard_qt.h @@ -24,7 +24,8 @@ class ClipboardQt : public ui::Clipboard void ReadHTML(ui::ClipboardBuffer type, const ui::DataTransferEndpoint *data_dst, std::u16string *markup, std::string *src_url, uint32_t *fragment_start, uint32_t *fragment_end) const override; void ReadRTF(ui::ClipboardBuffer type, const ui::DataTransferEndpoint *data_dst, std::string *result) const override; - void ReadCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type, const ui::DataTransferEndpoint *data_dst, std::u16string *result) const override; + void ReadDataTransferCustomData(ui::ClipboardBuffer clipboard_type, const std::u16string &type, const ui::DataTransferEndpoint *data_dst, std::u16string *result) const override; + void ReadBookmark(const ui::DataTransferEndpoint *data_dst, std::u16string *title, std::string *url) const override; void ReadData(const ui::ClipboardFormatType &format, const ui::DataTransferEndpoint *data_dst, std::string *result) const override; #if BUILDFLAG(IS_OZONE) @@ -48,14 +49,14 @@ class ClipboardQt : public ui::Clipboard std::vector platform_representations, std::unique_ptr data_src, uint32_t) override; - void WriteText(base::StringPiece text) override; - void WriteHTML(base::StringPiece markup, std::optional source_url) override; - void WriteRTF(base::StringPiece rtf) override; - void WriteBookmark(base::StringPiece title, base::StringPiece url) override; + void WriteText(std::string_view text) override; + void WriteHTML(std::string_view markup, std::optional source_url) override; + void WriteRTF(std::string_view rtf) override; + void WriteBookmark(std::string_view title, std::string_view url) override; void WriteWebSmartPaste() override; void WriteBitmap(const SkBitmap &bitmap) override; void WriteData(const ui::ClipboardFormatType &format, base::span data) override; - void WriteSvg(base::StringPiece markup) override; + void WriteSvg(std::string_view markup) override; void WriteFilenames(std::vector filenames) override; void WriteClipboardHistory() override; diff --git a/src/core/clipboard_util_win.cpp b/src/core/clipboard_util_win.cpp index 2dbd173d3c8..f3ae7e730b8 100644 --- a/src/core/clipboard_util_win.cpp +++ b/src/core/clipboard_util_win.cpp @@ -45,7 +45,7 @@ std::string HtmlToCFHtml(const std::string &html, const std::string &base_url) size_t end_fragment_offset = start_fragment_offset + html.length(); size_t end_html_offset = end_fragment_offset + strlen(end_markup); - std::string result = base::StringPrintf(header, start_html_offset, end_html_offset, + std::string result = base::StringPrintfNonConstexpr(header, start_html_offset, end_html_offset, start_fragment_offset, end_fragment_offset); if (!base_url.empty()) { result += source_url_prefix; diff --git a/src/core/compositor/compositor.cpp b/src/core/compositor/compositor.cpp index 35b30234f14..2cbe0846ab2 100644 --- a/src/core/compositor/compositor.cpp +++ b/src/core/compositor/compositor.cpp @@ -6,12 +6,15 @@ #include "base/memory/ref_counted.h" #include "components/viz/common/surfaces/frame_sink_id.h" +#include #include -#include +#include #include namespace QtWebEngineCore { +Q_LOGGING_CATEGORY(lcWebEngineCompositor, "qt.webengine.compositor"); + // Compositor::Id Compositor::Id::Id(viz::FrameSinkId fid) : client_id(fid.client_id()), sink_id(fid.sink_id()) { } @@ -44,7 +47,8 @@ struct Compositor::Binding class Compositor::BindingMap { public: - void lock() { m_mutex.lock(); } + void lock() { m_mutex.lockForRead(); } + void lockForWrite() { m_mutex.lockForWrite(); } void unlock() { m_mutex.unlock(); } @@ -59,7 +63,7 @@ class Compositor::BindingMap void remove(Id id) { m_map.remove(id); } private: - QMutex m_mutex; + QReadWriteLock m_mutex; QHash m_map; } static g_bindings; @@ -73,7 +77,7 @@ Compositor::Binding::~Binding() void Compositor::Observer::bind(Id id) { DCHECK(!m_binding); - g_bindings.lock(); + g_bindings.lockForWrite(); m_binding = g_bindings.findOrCreate(id); DCHECK(!m_binding->observer); m_binding->observer = this; @@ -82,7 +86,7 @@ void Compositor::Observer::bind(Id id) void Compositor::Observer::unbind() { - g_bindings.lock(); + g_bindings.lockForWrite(); if (m_binding) { m_binding->observer = nullptr; if (m_binding->compositor == nullptr) @@ -111,7 +115,7 @@ Compositor::Observer::~Observer() void Compositor::bind(Id id) { DCHECK(!m_binding); - g_bindings.lock(); + g_bindings.lockForWrite(); m_binding = g_bindings.findOrCreate(id); DCHECK(!m_binding->compositor); m_binding->compositor = this; @@ -120,7 +124,7 @@ void Compositor::bind(Id id) void Compositor::unbind() { - g_bindings.lock(); + g_bindings.lockForWrite(); if (m_binding) { m_binding->compositor = nullptr; if (m_binding->observer == nullptr) @@ -130,13 +134,12 @@ void Compositor::unbind() g_bindings.unlock(); } -Compositor::Handle Compositor::observer() +void Compositor::readyToSwap() { g_bindings.lock(); if (m_binding && m_binding->observer) - return m_binding->observer; // delay unlock + m_binding->observer->readyToSwap(); g_bindings.unlock(); - return nullptr; } void Compositor::waitForTexture() @@ -149,18 +152,24 @@ void Compositor::releaseTexture() QSGTexture *Compositor::texture(QQuickWindow *, uint32_t textureOptions) { - Q_UNREACHABLE(); - return nullptr; + Q_UNREACHABLE_RETURN(nullptr); } bool Compositor::textureIsFlipped() { - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); } void Compositor::releaseResources() { } +Compositor::Compositor(Type type) : m_type(type) +{ + qCDebug(lcWebEngineCompositor, "Compositor Type: %s", + m_type == Type::Software ? "Software" : "Native"); + qCDebug(lcWebEngineCompositor, "QPA Platform Plugin: %ls", + qUtf16Printable(QGuiApplication::platformName())); +} + Compositor::~Compositor() { DCHECK(!m_binding); // check that unbind() was called by derived final class diff --git a/src/core/compositor/compositor.h b/src/core/compositor/compositor.h index ee45b400be7..aaa1a74c8c0 100644 --- a/src/core/compositor/compositor.h +++ b/src/core/compositor/compositor.h @@ -18,6 +18,8 @@ class FrameSinkId; namespace QtWebEngineCore { +Q_DECLARE_LOGGING_CATEGORY(lcWebEngineCompositor); + // Produces composited frames for display. // // Used by quick/widgets libraries for accessing the frames and @@ -99,8 +101,8 @@ class Q_WEBENGINECORE_EXPORT Compositor void bind(Id id); void unbind(); - // Observer if bound. - Handle observer(); + // Tell observer ready to swap + void readyToSwap(); // Update to next frame if possible. virtual void swapFrame() = 0; @@ -132,7 +134,7 @@ class Q_WEBENGINECORE_EXPORT Compositor virtual void releaseResources(); protected: - Compositor(Type type) : m_type(type) { } + Compositor(Type type); virtual ~Compositor(); private: diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp index 62f23edb50a..2ad608f26fb 100644 --- a/src/core/compositor/display_software_output_surface.cpp +++ b/src/core/compositor/display_software_output_surface.cpp @@ -73,8 +73,7 @@ void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(SwapBuffersCallback swa m_swapCompletionCallback = std::move(swap_ack_callback); } - if (auto obs = observer()) - obs->readyToSwap(); + readyToSwap(); } inline QImage::Format imageFormat(SkColorType colorType) @@ -85,8 +84,7 @@ inline QImage::Format imageFormat(SkColorType colorType) case kRGBA_8888_SkColorType: return QImage::Format_RGBA8888_Premultiplied; default: - Q_UNREACHABLE(); - return QImage::Format_ARGB32_Premultiplied; + Q_UNREACHABLE_RETURN(QImage::Format_ARGB32_Premultiplied); } } diff --git a/src/core/compositor/native_skia_output_device.cpp b/src/core/compositor/native_skia_output_device.cpp index 756803a3e4d..f42b2b93341 100644 --- a/src/core/compositor/native_skia_output_device.cpp +++ b/src/core/compositor/native_skia_output_device.cpp @@ -50,16 +50,19 @@ NativeSkiaOutputDevice::NativeSkiaOutputDevice( , m_representationFactory(shared_image_representation_factory) , m_deps(dependency) { + qCDebug(lcWebEngineCompositor, "Skia Graphics Context Type: %s", + gpu::GrContextTypeToString(contextState->gr_context_type()).c_str()); + capabilities_.uses_default_gl_framebuffer = false; capabilities_.supports_surfaceless = true; capabilities_.output_surface_origin = gfx::SurfaceOrigin::kTopLeft; - capabilities_.preserve_buffer_content = true; - capabilities_.only_invalidates_damage_rect = false; #if BUILDFLAG(IS_OZONE) m_isNativeBufferSupported = ui::OzonePlatform::GetInstance() ->GetPlatformRuntimeProperties() .supports_native_pixmaps; + qCDebug(lcWebEngineCompositor, "Native Buffer Supported: %s", + m_isNativeBufferSupported ? "yes" : "no"); #endif } @@ -73,14 +76,10 @@ void NativeSkiaOutputDevice::SetFrameSinkId(const viz::FrameSinkId &id) bind(id); } -bool NativeSkiaOutputDevice::Reshape(const SkImageInfo &image_info, - const gfx::ColorSpace &colorSpace, - int sample_count, - float device_scale_factor, - gfx::OverlayTransform transform) +bool NativeSkiaOutputDevice::Reshape(const ReshapeParams ¶ms) { - m_shape = Shape{image_info, device_scale_factor, colorSpace, sample_count}; - DCHECK_EQ(transform, gfx::OVERLAY_TRANSFORM_NONE); + m_shape = Shape{ params.image_info, params.device_scale_factor, params.color_space, params.sample_count }; + DCHECK_EQ(params.transform, gfx::OVERLAY_TRANSFORM_NONE); return true; } @@ -99,9 +98,7 @@ void NativeSkiaOutputDevice::Present(const std::optional &update_rect std::swap(m_middleBuffer, m_backBuffer); m_readyToUpdate = true; } - - if (auto obs = observer()) - obs->readyToSwap(); + readyToSwap(); } void NativeSkiaOutputDevice::EnsureBackbuffer() @@ -213,6 +210,8 @@ NativeSkiaOutputDevice::Buffer::Buffer(NativeSkiaOutputDevice *parent) NativeSkiaOutputDevice::Buffer::~Buffer() { + DCHECK(!textureCleanupCallback); + if (m_scopedSkiaWriteAccess) endWriteSkia(false); @@ -226,21 +225,33 @@ NativeSkiaOutputDevice::Buffer::~Buffer() // found in the LICENSE file. bool NativeSkiaOutputDevice::Buffer::initialize() { - uint32_t kDefaultSharedImageUsage = gpu::SHARED_IMAGE_USAGE_DISPLAY_READ - | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE; + qCDebug(lcWebEngineCompositor, "Initializing buffer %p with SharedImage:", this); + + gpu::SharedImageUsageSet sharedImageUsage = + gpu::SHARED_IMAGE_USAGE_DISPLAY_READ + | gpu::SHARED_IMAGE_USAGE_DISPLAY_WRITE; if (m_parent->m_contextState->gr_context_type() == gpu::GrContextType::kGL) - kDefaultSharedImageUsage |= gpu::SHARED_IMAGE_USAGE_GLES2_READ; + sharedImageUsage |= gpu::SHARED_IMAGE_USAGE_GLES2_READ; if (m_parent->m_isNativeBufferSupported) - kDefaultSharedImageUsage |= gpu::SHARED_IMAGE_USAGE_SCANOUT; + sharedImageUsage |= gpu::SHARED_IMAGE_USAGE_SCANOUT; + + qCDebug(lcWebEngineCompositor, " Usage: %s", + gpu::CreateLabelForSharedImageUsage(sharedImageUsage).c_str()); + qCDebug(lcWebEngineCompositor, " Pixels size: %dx%d", m_shape.imageInfo.width(), + m_shape.imageInfo.height()); + + auto mailbox = gpu::Mailbox::Generate(); - auto mailbox = gpu::Mailbox::GenerateForSharedImage(); + const SkColorType skColorType = m_shape.imageInfo.colorType(); + const viz::SharedImageFormat sharedImageFormat = + viz::SkColorTypeToSinglePlaneSharedImageFormat(skColorType); + qCDebug(lcWebEngineCompositor, " Format: %s", sharedImageFormat.ToString().c_str()); - SkColorType skColorType = m_shape.imageInfo.colorType(); if (!m_parent->m_factory->CreateSharedImage( - mailbox, viz::SkColorTypeToSinglePlaneSharedImageFormat(skColorType), + mailbox, sharedImageFormat, { m_shape.imageInfo.width(), m_shape.imageInfo.height() }, m_shape.colorSpace, kTopLeft_GrSurfaceOrigin, kPremul_SkAlphaType, m_parent->m_deps->GetSurfaceHandle(), - kDefaultSharedImageUsage, "QWE_SharedImageBuffer")) { + sharedImageUsage, "QWE_SharedImageBuffer")) { LOG(ERROR) << "CreateSharedImage failed."; return false; } @@ -252,6 +263,7 @@ bool NativeSkiaOutputDevice::Buffer::initialize() LOG(ERROR) << "ProduceSkia() failed."; return false; } + qCDebug(lcWebEngineCompositor, " Backing: %s", m_skiaRepresentation->backing_name()); if (m_parent->m_isNativeBufferSupported) { m_overlayRepresentation = m_parent->m_representationFactory->ProduceOverlay(m_mailbox); diff --git a/src/core/compositor/native_skia_output_device.h b/src/core/compositor/native_skia_output_device.h index 294d678e434..7dabca07dfc 100644 --- a/src/core/compositor/native_skia_output_device.h +++ b/src/core/compositor/native_skia_output_device.h @@ -60,11 +60,7 @@ class NativeSkiaOutputDevice : public viz::SkiaOutputDevice, public Compositor // Overridden from SkiaOutputDevice. void SetFrameSinkId(const viz::FrameSinkId &frame_sink_id) override; - bool Reshape(const SkImageInfo &image_info, - const gfx::ColorSpace &color_space, - int sample_count, - float device_scale_factor, - gfx::OverlayTransform transform) override; + bool Reshape(const ReshapeParams ¶ms) override; void Present(const std::optional& update_rect, BufferPresentedCallback feedback, viz::OutputSurfaceFrame frame) override; diff --git a/src/core/compositor/native_skia_output_device_direct3d11.cpp b/src/core/compositor/native_skia_output_device_direct3d11.cpp index 495af7a408f..12ddecdbe7e 100644 --- a/src/core/compositor/native_skia_output_device_direct3d11.cpp +++ b/src/core/compositor/native_skia_output_device_direct3d11.cpp @@ -21,11 +21,13 @@ NativeSkiaOutputDeviceDirect3D11::NativeSkiaOutputDeviceDirect3D11( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Direct3D11"); + SkColorType skColorType = kRGBA_8888_SkColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRX_8888)] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType; } NativeSkiaOutputDeviceDirect3D11::~NativeSkiaOutputDeviceDirect3D11() { } @@ -41,6 +43,8 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_ return nullptr; } + qCDebug(lcWebEngineCompositor, "D3D: Importing DXGI Resource into D3D11 Texture."); + Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); Microsoft::WRL::ComPtr chromeTexture = overlayImage->nv12_texture(); if (!chromeTexture) { @@ -77,9 +81,9 @@ QSGTexture *NativeSkiaOutputDeviceDirect3D11::texture(QQuickWindow *win, uint32_ ID3D11Texture2D *qtTexture = nullptr; hr = device1->OpenSharedResource1(sharedHandle, IID_PPV_ARGS(&qtTexture)); if (FAILED(hr)) { - qWarning("D3D: Failed to share D3D11 texture (%s). This will result in failed rendering. " + qWarning("D3D: Failed to share D3D11 texture (%ls). This will result in failed rendering. " "Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu", - qPrintable(QSystemError::windowsComString(hr))); + qUtf16Printable(QSystemError::windowsComString(hr))); ::CloseHandle(sharedHandle); return nullptr; } diff --git a/src/core/compositor/native_skia_output_device_metal.cpp b/src/core/compositor/native_skia_output_device_metal.cpp index a9d6e4fd53b..77f869de75e 100644 --- a/src/core/compositor/native_skia_output_device_metal.cpp +++ b/src/core/compositor/native_skia_output_device_metal.cpp @@ -18,11 +18,13 @@ NativeSkiaOutputDeviceMetal::NativeSkiaOutputDeviceMetal( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Metal"); + SkColorType skColorType = kRGBA_8888_SkColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRX_8888)] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType; } NativeSkiaOutputDeviceMetal::~NativeSkiaOutputDeviceMetal() { } @@ -42,6 +44,8 @@ QSGTexture *NativeSkiaOutputDeviceMetal::texture(QQuickWindow *win, uint32_t tex return nullptr; } + qCDebug(lcWebEngineCompositor, "METAL: Importing IOSurface into Metal Texture."); + // This is a workaround to not to release metal texture too early. // In RHI, QMetalTexture wraps MTLTexture. QMetalTexture seems to be only destructed after the // next MTLTexture is imported. The "old" MTLTexture can be still pontentially used by RHI diff --git a/src/core/compositor/native_skia_output_device_opengl.cpp b/src/core/compositor/native_skia_output_device_opengl.cpp index 558821bb54a..7cfc390d8a2 100644 --- a/src/core/compositor/native_skia_output_device_opengl.cpp +++ b/src/core/compositor/native_skia_output_device_opengl.cpp @@ -19,13 +19,9 @@ #include "ui/gfx/linux/drm_util_linux.h" #include "ui/gfx/linux/native_pixmap_dmabuf.h" -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) #include "ozone/glx_helper.h" - -#if !defined(GL_RGBA8_OES) -#define GL_RGBA8_OES 0x8058 #endif -#endif // BUILDFLAG(IS_OZONE_X11) #if QT_CONFIG(egl) #include "ozone/egl_helper.h" @@ -63,16 +59,18 @@ NativeSkiaOutputDeviceOpenGL::NativeSkiaOutputDeviceOpenGL( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: OpenGL"); + SkColorType skColorType = kRGBA_8888_SkColorType; -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) if (OzoneUtilQt::usingGLX() && m_contextState->gr_context_type() == gpu::GrContextType::kGL) skColorType = kBGRA_8888_SkColorType; #endif - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRX_8888)] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType; } NativeSkiaOutputDeviceOpenGL::~NativeSkiaOutputDeviceOpenGL() { } @@ -150,14 +148,27 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te #if BUILDFLAG(IS_OZONE) QOpenGLContext *glContext = QOpenGLContext::currentContext(); + Q_ASSERT(glContext); auto glFun = glContext->functions(); GLuint glTexture = 0; +#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) + // Log and clear error flags for assert at end of function + while (true) { + auto glError = glFun->glGetError(); + if (glError == GL_NO_ERROR || glError == GL_CONTEXT_LOST) + break; + qWarning("GL error flag set on entry: %s", getGLErrorString(glError)); + } +#endif // !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) + if (nativePixmap) { Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL); -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) if (OzoneUtilQt::usingGLX()) { + qCDebug(lcWebEngineCompositor, "GLX: Importing NativePixmap into GL Texture."); + GLXHelper *glxHelper = GLXHelper::instance(); auto *glxFun = glxHelper->functions(); @@ -202,17 +213,20 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te glxFun->glXBindTexImageEXT(display, glxPixmap, GLX_FRONT_LEFT_EXT, nullptr); glFun->glBindTexture(GL_TEXTURE_2D, 0); - m_frontBuffer->textureCleanupCallback = [glFun, glxFun, display, glxPixmap, - glTexture]() { + m_frontBuffer->textureCleanupCallback = [glFun, glxFun, display, glxPixmap, glTexture, + glxHelper, pixmapId]() { glxFun->glXReleaseTexImageEXT(display, glxPixmap, GLX_FRONT_LEFT_EXT); glFun->glDeleteTextures(1, &glTexture); glXDestroyGLXPixmap(display, glxPixmap); + glxHelper->freePixmap(pixmapId); }; } -#endif // BUILDFLAG(IS_OZONE_X11) +#endif // BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) #if QT_CONFIG(egl) if (OzoneUtilQt::usingEGL()) { + qCDebug(lcWebEngineCompositor, "EGL: Importing NativePixmap into GL Texture."); + EGLHelper *eglHelper = EGLHelper::instance(); auto *eglFun = eglHelper->functions(); auto *glExtFun = GLHelper::instance()->functions(); @@ -260,6 +274,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te #endif // QT_CONFIG(egl) } else { #if BUILDFLAG(ENABLE_VULKAN) + qCDebug(lcWebEngineCompositor, "VULKAN: Importing VkImage into GL Texture."); Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kVulkan); gpu::VulkanFunctionPointers *vfp = gpu::GetVulkanFunctionPointers(); @@ -283,14 +298,26 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te auto *glExtFun = GLHelper::instance()->functions(); + // Import memory object GLuint glMemoryObject; - glFun->glGenTextures(1, &glTexture); - glFun->glBindTexture(GL_TEXTURE_2D, glTexture); glExtFun->glCreateMemoryObjectsEXT(1, &glMemoryObject); + GLint dedicated = GL_TRUE; + glExtFun->glMemoryObjectParameterivEXT(glMemoryObject, GL_DEDICATED_MEMORY_OBJECT_EXT, + &dedicated); glExtFun->glImportMemoryFdEXT(glMemoryObject, importedImageSize, GL_HANDLE_TYPE_OPAQUE_FD_EXT, fd); - glExtFun->glTextureStorageMem2DEXT(glTexture, 1, GL_RGBA8_OES, size().width(), - size().height(), glMemoryObject, 0); + if (!glExtFun->glIsMemoryObjectEXT(glMemoryObject)) + qFatal("VULKAN: Failed to import memory object."); + + // Bind memory object to texture + glFun->glGenTextures(1, &glTexture); + glFun->glBindTexture(GL_TEXTURE_2D, glTexture); + glFun->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_TILING_EXT, + vkImageInfo.fImageTiling == VK_IMAGE_TILING_OPTIMAL + ? GL_OPTIMAL_TILING_EXT + : GL_LINEAR_TILING_EXT); + glExtFun->glTexStorageMem2DEXT(GL_TEXTURE_2D, 1, GL_RGBA8, size().width(), size().height(), + glMemoryObject, 0); glFun->glBindTexture(GL_TEXTURE_2D, 0); m_frontBuffer->textureCleanupCallback = [glFun, glExtFun, glTexture, glMemoryObject]() { @@ -307,6 +334,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); Q_ASSERT(glFun->glGetError() == GL_NO_ERROR); #elif defined(Q_OS_WIN) + qCDebug(lcWebEngineCompositor, "WGL: Importing DXGI Resource into GL Texture."); Q_ASSERT(m_contextState->gr_context_type() == gpu::GrContextType::kGL); Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); @@ -344,6 +372,7 @@ QSGTexture *NativeSkiaOutputDeviceOpenGL::texture(QQuickWindow *win, uint32_t te delete d3dSharedTexture; }; #elif defined(Q_OS_MACOS) + qCDebug(lcWebEngineCompositor, "CGL: Importing IOSurface into GL Texture."); uint32_t glTexture = makeCGLTexture(win, ioSurface.get(), size()); texture = QNativeInterface::QSGOpenGLTexture::fromNative(glTexture, win, size(), texOpts); diff --git a/src/core/compositor/native_skia_output_device_vulkan.cpp b/src/core/compositor/native_skia_output_device_vulkan.cpp index c292a3269e4..5f410621bf5 100644 --- a/src/core/compositor/native_skia_output_device_vulkan.cpp +++ b/src/core/compositor/native_skia_output_device_vulkan.cpp @@ -37,11 +37,13 @@ NativeSkiaOutputDeviceVulkan::NativeSkiaOutputDeviceVulkan( shared_image_factory, shared_image_representation_factory, didSwapBufferCompleteCallback) { + qCDebug(lcWebEngineCompositor, "Native Skia Output Device: Vulkan"); + SkColorType skColorType = kRGBA_8888_SkColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::RGBX_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRA_8888)] = skColorType; - capabilities_.sk_color_types[static_cast(gfx::BufferFormat::BGRX_8888)] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kRGBX_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRA_8888] = skColorType; + capabilities_.sk_color_type_map[viz::SinglePlaneFormat::kBGRX_8888] = skColorType; } NativeSkiaOutputDeviceVulkan::~NativeSkiaOutputDeviceVulkan() { } @@ -110,16 +112,6 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te QVulkanFunctions *f = win->vulkanInstance()->functions(); QVulkanDeviceFunctions *df = win->vulkanInstance()->deviceFunctions(qtVulkanDevice); - VkImageLayout imageLayout = VK_IMAGE_LAYOUT_UNDEFINED; - VkPhysicalDeviceProperties deviceProperties; - f->vkGetPhysicalDeviceProperties(qtPhysicalDevice, &deviceProperties); - if (deviceProperties.vendorID == 0x10DE) { - // FIXME: This is a workaround for Nvidia driver. - // The imported image is empty if the initialLayout is not - // VK_IMAGE_LAYOUT_PREINITIALIZED. - imageLayout = VK_IMAGE_LAYOUT_PREINITIALIZED; - } - VkExternalMemoryImageCreateInfoKHR externalMemoryImageCreateInfo = { .sType = VK_STRUCTURE_TYPE_EXTERNAL_MEMORY_IMAGE_CREATE_INFO_KHR, .pNext = nullptr, @@ -144,20 +136,28 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te .pPlaneLayouts = &planeLayout, }; + bool usingDrmModifier = false; if (nativePixmap) { + qCDebug(lcWebEngineCompositor, "VULKAN: Importing NativePixmap into VkImage."); gfx::NativePixmapHandle nativePixmapHandle = nativePixmap->ExportHandle(); - if (nativePixmapHandle.planes.size() != 1) - qFatal("VULKAN: Multiple planes are not supported."); + qCDebug(lcWebEngineCompositor, " DRM Format Modifier: 0x%lx", nativePixmapHandle.modifier); + + if (nativePixmapHandle.modifier != gfx::NativePixmapHandle::kNoModifier) { + usingDrmModifier = true; + if (nativePixmapHandle.planes.size() != 1) + qFatal("VULKAN: Multiple planes are not supported."); - planeLayout.offset = nativePixmapHandle.planes[0].offset; - planeLayout.rowPitch = nativePixmapHandle.planes[0].stride; - modifierInfo.drmFormatModifier = nativePixmapHandle.modifier; + planeLayout.offset = nativePixmapHandle.planes[0].offset; + planeLayout.rowPitch = nativePixmapHandle.planes[0].stride; + modifierInfo.drmFormatModifier = nativePixmapHandle.modifier; - externalMemoryImageCreateInfo.pNext = &modifierInfo; + externalMemoryImageCreateInfo.pNext = &modifierInfo; + } externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT; scopedFd = std::move(nativePixmapHandle.planes[0].fd); } else { + qCDebug(lcWebEngineCompositor, "VULKAN: Importing VkImage into VkImage."); externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT_KHR; @@ -183,6 +183,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te if (!scopedFd.is_valid()) qFatal("VULKAN: Unable to extract file descriptor."); #elif defined(Q_OS_WIN) + qCDebug(lcWebEngineCompositor, "VULKAN: Importing DXGI Resource into VkImage."); externalMemoryImageCreateInfo.handleTypes = VK_EXTERNAL_MEMORY_HANDLE_TYPE_D3D11_TEXTURE_BIT; Q_ASSERT(overlayImage->type() == gl::DCLayerOverlayType::kNV12Texture); @@ -205,10 +206,6 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te Q_ASSERT(sharedHandle != INVALID_HANDLE_VALUE); #endif - constexpr VkImageUsageFlags kUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT - | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT - | VK_IMAGE_USAGE_TRANSFER_SRC_BIT; - VkImageCreateInfo importedImageCreateInfo = { .sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, .pNext = &externalMemoryImageCreateInfo, @@ -224,17 +221,19 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te .arrayLayers = 1, .samples = VK_SAMPLE_COUNT_1_BIT, .tiling = VK_IMAGE_TILING_OPTIMAL, - .usage = kUsage, + // The image is fed into a combined image sampler + .usage = VK_IMAGE_USAGE_SAMPLED_BIT, .sharingMode = VK_SHARING_MODE_EXCLUSIVE, .queueFamilyIndexCount = 0, .pQueueFamilyIndices = nullptr, - .initialLayout = imageLayout, + // VkExternalMemoryImageCreateInfo only allows UNDEFINED + .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED, }; #if BUILDFLAG(IS_OZONE) - if (nativePixmap) + if (usingDrmModifier) importedImageCreateInfo.tiling = VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT; - else + else if (vkImageInfo.fAlloc.fMemory != VK_NULL_HANDLE) importedImageCreateInfo.tiling = vkImageInfo.fImageTiling; #endif @@ -243,7 +242,7 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te result = df->vkCreateImage(qtVulkanDevice, &importedImageCreateInfo, nullptr /* pAllocator */, &importedImage); if (result != VK_SUCCESS) - qFatal() << "VULKAN: vkCreateImage failed result:" << result; + qFatal("VULKAN: vkCreateImage failed result: %d", static_cast(result)); #if BUILDFLAG(IS_OZONE) VkImportMemoryFdInfoKHR importMemoryHandleInfo = { @@ -304,13 +303,13 @@ QSGTexture *NativeSkiaOutputDeviceVulkan::texture(QQuickWindow *win, uint32_t te result = df->vkAllocateMemory(qtVulkanDevice, &memoryAllocateInfo, nullptr /* pAllocator */, &importedImageMemory); if (result != VK_SUCCESS) - qFatal() << "VULKAN: vkAllocateMemory failed result:" << result; + qFatal("VULKAN: vkAllocateMemory failed result: %d", static_cast(result)); df->vkBindImageMemory(qtVulkanDevice, importedImage, importedImageMemory, 0); QQuickWindow::CreateTextureOptions texOpts(textureOptions); - QSGTexture *texture = QNativeInterface::QSGVulkanTexture::fromNative(importedImage, imageLayout, - win, size(), texOpts); + QSGTexture *texture = QNativeInterface::QSGVulkanTexture::fromNative( + importedImage, importedImageCreateInfo.initialLayout, win, size(), texOpts); m_frontBuffer->textureCleanupCallback = [=]() { df->vkDestroyImage(qtVulkanDevice, importedImage, nullptr); diff --git a/src/core/compositor/wgl_helper.cpp b/src/core/compositor/wgl_helper.cpp index d6c8401373d..11526f4f95a 100644 --- a/src/core/compositor/wgl_helper.cpp +++ b/src/core/compositor/wgl_helper.cpp @@ -46,14 +46,14 @@ WGLHelper::WGLHelper() : m_functions(new WGLHelper::WGLFunctions()) hr = CreateDXGIFactory(IID_PPV_ARGS(&m_factory)); if (FAILED(hr)) { - qFatal() << "WGL: Failed to create DXGI Factory:" - << qPrintable(QSystemError::windowsComString(hr)); + qFatal("WGL: Failed to create DXGI Factory: %ls", + qUtf16Printable(QSystemError::windowsComString(hr))); } hr = m_factory->EnumAdapters(0, &m_adapter); if (FAILED(hr)) { - qFatal() << "WGL: Failed to enumerate adapters:" - << qPrintable(QSystemError::windowsComString(hr)); + qFatal("WGL: Failed to enumerate adapters: %ls", + qUtf16Printable(QSystemError::windowsComString(hr))); } uint devFlags = 0; @@ -66,13 +66,15 @@ WGLHelper::WGLHelper() : m_functions(new WGLHelper::WGLFunctions()) featureLevels, std::size(featureLevels), D3D11_SDK_VERSION, &m_device, /*pFeatureLevel=*/nullptr, &m_immediateContext); if (FAILED(hr)) { - qFatal() << "WGL: Failed to create D3D11 device:" - << qPrintable(QSystemError::windowsComString(hr)); + qFatal("WGL: Failed to create D3D11 device: %ls", + qUtf16Printable(QSystemError::windowsComString(hr))); } m_interopDevice = m_functions->wglDXOpenDeviceNV(m_device.Get()); - if (m_interopDevice == INVALID_HANDLE_VALUE) - qWarning() << "WGL: Failed to open interop device:" << ::GetLastError(); + if (m_interopDevice == INVALID_HANDLE_VALUE) { + qWarning("WGL: Failed to open interop device: %ls", + qUtf16Printable(QSystemError::windowsString())); + } } WGLHelper::~WGLHelper() @@ -95,9 +97,9 @@ D3DSharedTexture::D3DSharedTexture(WGLHelper::WGLFunctions *wglFun, ID3D11Device Microsoft::WRL::ComPtr srcTexture; hr = device1->OpenSharedResource1(dxgiSharedHandle, IID_PPV_ARGS(&srcTexture)); if (FAILED(hr)) { - qWarning("WGL: Failed to share D3D11 texture (%s). This will result in failed rendering. " + qWarning("WGL: Failed to share D3D11 texture (%ls). This will result in failed rendering. " "Report the bug, and try restarting with QTWEBENGINE_CHROMIUM_FLAGS=--disble-gpu", - qPrintable(QSystemError::windowsComString(hr))); + qUtf16Printable(QSystemError::windowsComString(hr))); return; } Q_ASSERT(srcTexture); @@ -161,7 +163,8 @@ void D3DSharedTexture::lockObject() bool status = m_wglFun->wglDXLockObjectsNV(m_interopDevice, 1, &m_glTextureHandle); if (!status) { - qWarning() << "WGL: Failed to lock shared texture:" << ::GetLastError(); + qWarning("WGL: Failed to lock shared texture: %ls", + qUtf16Printable(QSystemError::windowsString())); return; } @@ -177,7 +180,8 @@ void D3DSharedTexture::unlockObject() bool status = m_wglFun->wglDXUnlockObjectsNV(m_interopDevice, 1, &m_glTextureHandle); if (!status) { - qWarning() << "WGL: Failed to unlock shared texture:" << ::GetLastError(); + qWarning("WGL: Failed to unlock shared texture: %ls", + qUtf16Printable(QSystemError::windowsString())); return; } diff --git a/src/core/configure/BUILD.root.gn.in b/src/core/configure/BUILD.root.gn.in index 5a1fc1d63e8..214ef6e7156 100644 --- a/src/core/configure/BUILD.root.gn.in +++ b/src/core/configure/BUILD.root.gn.in @@ -182,6 +182,7 @@ shared_library("QtWebEngineCore") { } if (is_win) { + configs -= [ "//build/config/compiler:no_rtti" ] configs += [ "//build/config/compiler:rtti" ] data_deps += [ ":QtWebEngineCoreSandbox" ] } @@ -288,6 +289,7 @@ source_set("qtwebengine_sources") { "//chrome/browser/resources/net_internals:resources", "//chrome/browser/signin:identity_manager_provider", "//chrome/common:buildflags", + "//chrome/common:channel_info", "//chrome/common:version_header", "//components/custom_handlers", "//components/embedder_support:embedder_support", @@ -403,11 +405,14 @@ source_set("qtwebengine_sources") { deps += [ "//ui/base/x:gl", "//ui/gfx/linux:gpu_memory_buffer_support_x11", + "//ui/gfx/x", ] sources += [ "//ui/ozone/platform/x11/gl_egl_utility_x11.cc", "//ui/ozone/platform/x11/gl_egl_utility_x11.h", + "//ui/ozone/platform/x11/native_pixmap_egl_x11_binding.cc", + "//ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h", ] } } diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index c3d613c9881..51396f6fb38 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -32,6 +32,7 @@ #include "content/public/common/content_switches.h" #include "content/public/common/url_constants.h" #include "content/public/common/user_agent.h" +#include "base/version_info/version_info.h" #include "ipc/ipc_channel_proxy.h" #include "extensions/buildflags/buildflags.h" #include "mojo/public/cpp/bindings/self_owned_associated_receiver.h" @@ -162,7 +163,7 @@ // Implement IsHandledProtocol as declared in //url/url_util_qt.h. namespace url { -bool IsHandledProtocol(base::StringPiece scheme) +bool IsHandledProtocol(std::string_view scheme) { static const char *const kProtocolList[] = { url::kHttpScheme, @@ -288,6 +289,7 @@ void ContentBrowserClientQt::AllowCertificateError(content::WebContents *webCont base::OnceClosure ContentBrowserClientQt::SelectClientCertificate(content::BrowserContext *browser_context, + int process_id, content::WebContents *webContents, net::SSLCertRequestInfo *certRequestInfo, net::ClientCertIdentityList clientCerts, @@ -703,17 +705,12 @@ static void LaunchURL(const GURL& url, contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } - -bool ContentBrowserClientQt::HandleExternalProtocol(const GURL &url, - base::RepeatingCallback web_contents_getter, - int frame_tree_node_id, - content::NavigationUIData *navigation_data, - bool is_primary_main_frame, - bool is_in_fenced_frame_tree, - network::mojom::WebSandboxFlags sandbox_flags, - ui::PageTransition page_transition, - bool has_user_gesture, - const std::optional &initiating_origin, +bool ContentBrowserClientQt::HandleExternalProtocol( + const GURL &url, base::RepeatingCallback web_contents_getter, + content::FrameTreeNodeId frame_tree_node_id, content::NavigationUIData *navigation_data, + bool is_primary_main_frame, bool is_in_fenced_frame_tree, + network::mojom::WebSandboxFlags sandbox_flags, ui::PageTransition page_transition, + bool has_user_gesture, const std::optional &initiating_origin, content::RenderFrameHost *initiator_document, mojo::PendingRemote *out_factory) { @@ -779,8 +776,8 @@ std::vector> ContentBrowserClientQt::CreateURLLoaderThrottles( const network::ResourceRequest &request, content::BrowserContext *browser_context, const base::RepeatingCallback & /*wc_getter*/, - content::NavigationUIData * /*navigation_ui_data*/, int frame_tree_node_id, - std::optional navigation_id) + content::NavigationUIData * /*navigation_ui_data*/, + content::FrameTreeNodeId frame_tree_node_id, std::optional navigation_id) { std::vector> result; result.push_back(std::make_unique( @@ -936,17 +933,18 @@ bool ContentBrowserClientQt::DoesSiteRequireDedicatedProcess(content::BrowserCon return ContentBrowserClient::DoesSiteRequireDedicatedProcess(browser_context, effective_site_url); } -bool ContentBrowserClientQt::ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, - const GURL &site_url) +std::optional +ContentBrowserClientQt::ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, + const GURL &site_url) { #if BUILDFLAG(ENABLE_EXTENSIONS) if (site_url.SchemeIs(extensions::kExtensionScheme)) - return false; + return SpareProcessRefusedByEmbedderReason::ExtensionProcess; #endif return ContentBrowserClient::ShouldUseSpareRenderProcessHost(browser_context, site_url); } -bool ContentBrowserClientQt::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme, bool is_embedded_origin_secure) +bool ContentBrowserClientQt::ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(std::string_view scheme, bool is_embedded_origin_secure) { if (is_embedded_origin_secure && scheme == content::kChromeUIScheme) return true; @@ -982,8 +980,8 @@ std::string ContentBrowserClientQt::getUserAgent() { // Mention the Chromium version we're based on to get passed stupid UA-string-based feature detection (several WebRTC demos need this) return content::BuildUserAgentFromProduct("QtWebEngine/" + std::string(qWebEngineVersion()) - + " Chrome/" - + std::string(qWebEngineChromiumVersion())); + + " Chrome/" + version_info::GetMajorVersionNumber() + + ".0.0.0"); } blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata() @@ -995,7 +993,7 @@ blink::UserAgentMetadata ContentBrowserClientQt::GetUserAgentMetadata() std::string ContentBrowserClientQt::GetProduct() { - QString productName(qApp->applicationName() % '/' % qApp->applicationVersion()); + QString productName(qApp->applicationName() % u'/' % qApp->applicationVersion()); return productName.toStdString(); } @@ -1044,8 +1042,9 @@ std::vector ContentBrowserClientQt::GetNetworkContextsParentDire toFilePath(QStandardPaths::writableLocation(QStandardPaths::CacheLocation)) }; } -mojo::PendingRemote ContentBrowserClientQt::CreateNonNetworkNavigationURLLoaderFactory( - const std::string &scheme, int frame_tree_node_id) +mojo::PendingRemote +ContentBrowserClientQt::CreateNonNetworkNavigationURLLoaderFactory( + const std::string &scheme, content::FrameTreeNodeId frame_tree_node_id) { content::WebContents *web_contents = content::WebContents::FromFrameTreeNodeId(frame_tree_node_id); Profile *profile = Profile::FromBrowserContext(web_contents->GetBrowserContext()); @@ -1245,15 +1244,15 @@ void ContentBrowserClientQt::WillCreateURLLoaderFactory( // Will manage its own lifetime // FIXME: use navigation_response_task_runner? new ProxyingURLLoaderFactoryQt( - adapter, - frame ? frame->GetFrameTreeNodeId() : content::RenderFrameHost::kNoFrameTreeNodeId, + adapter, frame ? frame->GetFrameTreeNodeId() : content::FrameTreeNodeId{}, std::move(proxied_receiver), std::move(pending_url_loader_factory), type); } std::vector> -ContentBrowserClientQt::WillCreateURLLoaderRequestInterceptors(content::NavigationUIData *navigation_ui_data, - int frame_tree_node_id, int64_t navigation_id, - scoped_refptr navigation_response_task_runner) +ContentBrowserClientQt::WillCreateURLLoaderRequestInterceptors( + content::NavigationUIData *navigation_ui_data, content::FrameTreeNodeId frame_tree_node_id, + int64_t navigation_id, bool force_no_https_upgrade, + scoped_refptr navigation_response_task_runner) { Q_UNUSED(navigation_ui_data); Q_UNUSED(navigation_id); diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index 285e13a4050..4e24012e46b 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -39,6 +39,7 @@ class ContentBrowserClientQt : public content::ContentBrowserClient bool strict_enforcement, base::OnceCallback callback) override; base::OnceClosure SelectClientCertificate(content::BrowserContext* browser_context, + int process_id, content::WebContents* web_contents, net::SSLCertRequestInfo* cert_request_info, net::ClientCertIdentityList client_certs, @@ -127,8 +128,9 @@ class ContentBrowserClientQt : public content::ContentBrowserClient bool ShouldUseProcessPerSite(content::BrowserContext *browser_context, const GURL &effective_url) override; bool DoesSiteRequireDedicatedProcess(content::BrowserContext *browser_context, const GURL &effective_site_url) override; - bool ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, const GURL& site_url) override; - bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(base::StringPiece scheme, + std::optional + ShouldUseSpareRenderProcessHost(content::BrowserContext *browser_context, const GURL& site_url) override; + bool ShouldTreatURLSchemeAsFirstPartyWhenTopLevel(std::string_view scheme, bool is_embedded_origin_secure) override; bool DoesSchemeAllowCrossOriginSharedWorker(const std::string &scheme) override; void OverrideURLLoaderFactoryParams(content::BrowserContext *browser_context, @@ -148,16 +150,11 @@ class ContentBrowserClientQt : public content::ContentBrowserClient LoginAuthRequiredCallback auth_required_callback) override; bool HandleExternalProtocol( - const GURL &url, - base::RepeatingCallback web_contents_getter, - int frame_tree_node_id, - content::NavigationUIData *navigation_data, - bool is_primary_main_frame, - bool is_in_fenced_frame_tree, - network::mojom::WebSandboxFlags sandbox_flags, - ui::PageTransition page_transition, - bool has_user_gesture, - const std::optional &initiating_origin, + const GURL &url, base::RepeatingCallback web_contents_getter, + content::FrameTreeNodeId frame_tree_node_id, content::NavigationUIData *navigation_data, + bool is_primary_main_frame, bool is_in_fenced_frame_tree, + network::mojom::WebSandboxFlags sandbox_flags, ui::PageTransition page_transition, + bool has_user_gesture, const std::optional &initiating_origin, content::RenderFrameHost *initiator_document, mojo::PendingRemote *out_factory) override; @@ -165,7 +162,8 @@ class ContentBrowserClientQt : public content::ContentBrowserClient CreateURLLoaderThrottles(const network::ResourceRequest &request, content::BrowserContext *browser_context, const base::RepeatingCallback &wc_getter, - content::NavigationUIData *navigation_ui_data, int frame_tree_node_id, + content::NavigationUIData *navigation_ui_data, + content::FrameTreeNodeId frame_tree_node_id, std::optional navigation_id) override; std::vector> CreateThrottlesForNavigation( @@ -176,10 +174,11 @@ class ContentBrowserClientQt : public content::ContentBrowserClient bool HasCustomSchemeHandler(content::BrowserContext *browser_context, const std::string &scheme) override; std::vector> - WillCreateURLLoaderRequestInterceptors(content::NavigationUIData *navigation_ui_data, - int frame_tree_node_id, - int64_t navigation_id, - scoped_refptr navigation_response_task_runner) override; + WillCreateURLLoaderRequestInterceptors( + content::NavigationUIData *navigation_ui_data, + content::FrameTreeNodeId frame_tree_node_id, int64_t navigation_id, + bool force_no_https_upgrade, + scoped_refptr navigation_response_task_runner) override; void WillCreateURLLoaderFactory(content::BrowserContext *browser_context, content::RenderFrameHost *frame, int render_process_id, @@ -204,8 +203,9 @@ class ContentBrowserClientQt : public content::ContentBrowserClient cert_verifier::mojom::CertVerifierCreationParams *cert_verifier_creation_params) override; std::vector GetNetworkContextsParentDirectory() override; - mojo::PendingRemote CreateNonNetworkNavigationURLLoaderFactory(const std::string &scheme, - int frame_tree_node_id) override; + mojo::PendingRemote + CreateNonNetworkNavigationURLLoaderFactory( + const std::string &scheme, content::FrameTreeNodeId frame_tree_node_id) override; void RegisterNonNetworkSubresourceURLLoaderFactories(int render_process_id, int render_frame_id, const std::optional& request_initiator_origin, NonNetworkURLLoaderFactoryMap *factories) override; diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp index b8534cc9806..492dc51838b 100644 --- a/src/core/content_client_qt.cpp +++ b/src/core/content_client_qt.cpp @@ -3,10 +3,11 @@ #include "content_client_qt.h" +#include "compositor/compositor.h" + #include "base/command_line.h" #include "base/files/file_util.h" #include "base/json/json_string_value_serializer.h" -#include "base/strings/string_piece.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/values.h" @@ -29,7 +30,8 @@ #include #include #include - +#include +#include #if BUILDFLAG(ENABLE_LIBRARY_CDMS) #include "media/cdm/cdm_paths.h" // nogncheck @@ -57,13 +59,15 @@ const char kWidevineCdmFileName[] = const char kPdfPluginPath[] = "internal-pdf-viewer"; #endif // QT_CONFIG(webengine_printing_and_pdf) +using namespace Qt::StringLiterals; using Robustness = content::CdmInfo::Robustness; static QString webenginePluginsPath() { // Look for plugins in /plugins/webengine or application dir. static bool initialized = false; - static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/webengine"); + static QString potentialPluginsPath = + QLibraryInfo::path(QLibraryInfo::PluginsPath) % "/webengine"_L1; if (!initialized) { initialized = true; if (!QFileInfo::exists(potentialPluginsPath)) @@ -77,18 +81,33 @@ static QString webenginePluginsPath() static QString getLocalAppDataDir() { QString result; - wchar_t path[MAX_PATH]; - if (SHGetSpecialFolderPath(0, path, CSIDL_LOCAL_APPDATA, FALSE)) + PWSTR path; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &path); + if (SUCCEEDED(hr)) result = QDir::fromNativeSeparators(QString::fromWCharArray(path)); + CoTaskMemFree(path); return result; } static QString getProgramFilesDir(bool x86Dir = false) { QString result; - wchar_t path[MAX_PATH]; - if (SHGetSpecialFolderPath(0, path, x86Dir ? CSIDL_PROGRAM_FILESX86 : CSIDL_PROGRAM_FILES, FALSE)) + PWSTR path; + HRESULT hr = SHGetKnownFolderPath(x86Dir ? FOLDERID_ProgramFilesX86 : FOLDERID_ProgramFilesX64, 0, NULL, &path); + if (SUCCEEDED(hr)) + result = QDir::fromNativeSeparators(QString::fromWCharArray(path)); + CoTaskMemFree(path); + return result; +} + +static QString getSystem32Dir() +{ + QString result; + PWSTR path; + HRESULT hr = SHGetKnownFolderPath(FOLDERID_System, 0, NULL, &path); + if (SUCCEEDED(hr)) result = QDir::fromNativeSeparators(QString::fromWCharArray(path)); + CoTaskMemFree(path); return result; } #endif @@ -107,7 +126,8 @@ static QString ppapiPluginsPath() { // Look for plugins in /plugins/ppapi or application dir. static bool initialized = false; - static QString potentialPluginsPath = QLibraryInfo::path(QLibraryInfo::PluginsPath) % QLatin1String("/ppapi"); + static QString potentialPluginsPath = + QLibraryInfo::path(QLibraryInfo::PluginsPath) % "/ppapi"_L1; if (!initialized) { initialized = true; if (!QFileInfo::exists(potentialPluginsPath)) @@ -151,7 +171,7 @@ namespace QtWebEngineCore { static const QDir widevineCdmDirHint(const QDir &widevineDir) { const QString hintFilePath = widevineDir.absolutePath() % QDir::separator() - % QLatin1String("latest-component-updated-widevine-cdm"); + % "latest-component-updated-widevine-cdm"_L1; if (!QFileInfo::exists(hintFilePath)) { // CDM hint file does not exist. return widevineDir; @@ -189,63 +209,93 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, if (!widevine_argument.empty()) pluginPaths << QtWebEngineCore::toQt(widevine_argument); else { - pluginPaths << webenginePluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); + pluginPaths << webenginePluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName); #if QT_CONFIG(webengine_pepper_plugins) - pluginPaths << ppapiPluginsPath() + QStringLiteral("/") + QString::fromLatin1(kWidevineCdmFileName); + pluginPaths << ppapiPluginsPath() + u'/' + QLatin1StringView(kWidevineCdmFileName); #endif #if defined(Q_OS_OSX) - QDir potentialWidevineDir("/Applications/Google Chrome.app/Contents/Frameworks"); + QDir potentialWidevineDir(u"/Applications/Google Chrome.app/Contents/Frameworks"_s); + const auto archDir = QSysInfo::currentCpuArchitecture() == "x86_64"_L1 + ? "mac_x64/"_L1 + : "mac_arm64/"_L1; if (potentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); - const QString library = QLatin1String("/Versions/Current/Libraries/" - "WidevineCdm/_platform_specific/mac_x64/libwidevinecdm.dylib"); + const auto libraryBase = "/Versions/Current/Libraries/WidevineCdm/_platform_specific/"_L1; + const auto libraryFilename = "libwidevinecdm.dylib"_L1; for (const QFileInfo &info : widevineVersionDirs) - pluginPaths << info.absoluteFilePath() + library; + pluginPaths << info.absoluteFilePath() + libraryBase + archDir + libraryFilename; } - QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"); + QDir oldPotentialWidevineDir(QDir::homePath() + "/Library/Application Support/Google/Chrome/WidevineCDM"_L1); if (oldPotentialWidevineDir.exists()) { QFileInfoList widevineVersionDirs = oldPotentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { - QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/mac_x64/" + QString::fromLatin1(kWidevineCdmFileName); - pluginPaths << potentialWidevinePluginPath; + const QString versionDirPath = widevineVersionDirs.at(i).absoluteFilePath(); + QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/"_L1 + archDir + + QLatin1StringView(kWidevineCdmFileName); + pluginPaths.append(std::move(potentialWidevinePluginPath)); } } #elif defined(Q_OS_WIN) - const QString googleChromeDir = QLatin1String("/Google/Chrome/Application"); - const QStringList programFileDirs{getProgramFilesDir() + googleChromeDir, - getProgramFilesDir(true) + googleChromeDir}; + const auto arch = QSysInfo::currentCpuArchitecture(); + auto appendArchitectureAndFilename = [&arch](QString &inString) { + if (arch == "x86_64"_L1) { + inString += "/win_x64/"_L1; + } else if (arch == "i386"_L1) { + inString += "/win_x86/"_L1; + } else if (arch == "arm64"_L1) { + inString += "/win_arm64/"_L1; + } else { + Q_UNREACHABLE(); + } + + inString += QLatin1StringView(kWidevineCdmFileName); + }; + + // Look inside Program Files; first for Microsoft Edge, then for Google Chrome + const auto microsoftEdgeDir = "/Microsoft/Edge/Application"_L1; + const auto googleChromeDir = "/Google/Chrome/Application"_L1; + const QStringList programFileDirs { + getProgramFilesDir() + microsoftEdgeDir, + getProgramFilesDir(true) + microsoftEdgeDir, + getProgramFilesDir() + googleChromeDir, + getProgramFilesDir(true) + googleChromeDir + }; + for (const QString &dir : programFileDirs) { QDir d(dir); if (d.exists()) { QFileInfoList widevineVersionDirs = d.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { - QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); -#ifdef WIN64 - QString potentialWidevinePluginPath = versionDirPath + - "/WidevineCdm/_platform_specific/win_x64/" + - QString::fromLatin1(kWidevineCdmFileName); -#else - QString potentialWidevinePluginPath = versionDirPath + - "/WidevineCdm/_platform_specific/win_x86/" + - QString::fromLatin1(kWidevineCdmFileName); -#endif + QString potentialWidevinePluginPath + = widevineVersionDirs.at(i).absoluteFilePath() + + "/WidevineCdm/_platform_specific"_L1; + + appendArchitectureAndFilename(potentialWidevinePluginPath); pluginPaths << potentialWidevinePluginPath; } } } - QDir potentialWidevineDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"); - if (potentialWidevineDir.exists()) { - QFileInfoList widevineVersionDirs = potentialWidevineDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); + + // Look inside WebView data that lives in system32 + QDir potentialEdgeWebViewDir(getSystem32Dir() + "/Microsoft-Edge-WebView"_L1); + if (potentialEdgeWebViewDir.exists()) { + QString potentialWidevinePluginPath = potentialEdgeWebViewDir.absolutePath() + "/WidevineCdm/_platform_specific"_L1; + appendArchitectureAndFilename(potentialWidevinePluginPath); + pluginPaths << potentialWidevinePluginPath; + } + + // As a last resort, look for Google Chrome data inside %APPDATA%. This may be obsolete + QDir potentialChromeUserDataDir(getLocalAppDataDir() + "/Google/Chrome/User Data/WidevineCDM"_L1); + if (potentialChromeUserDataDir.exists()) { + QFileInfoList widevineVersionDirs = potentialChromeUserDataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (int i = 0; i < widevineVersionDirs.size(); ++i) { - QString versionDirPath(widevineVersionDirs.at(i).absoluteFilePath()); -#ifdef WIN64 - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x64/" + QString::fromLatin1(kWidevineCdmFileName); -#else - QString potentialWidevinePluginPath = versionDirPath + "/_platform_specific/win_x86/" + QString::fromLatin1(kWidevineCdmFileName); -#endif + QString potentialWidevinePluginPath + = widevineVersionDirs.at(i).absoluteFilePath() + + "/_platform_specific"_L1; + + appendArchitectureAndFilename(potentialWidevinePluginPath); pluginPaths << potentialWidevinePluginPath; } } @@ -253,23 +303,23 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, QList potentialWidevineVersionDirs; // Google Chrome widevine modules - QDir chromeWidevineDir(QDir::homePath() + "/.config/google-chrome/WidevineCdm"); + QDir chromeWidevineDir(QDir::homePath() + "/.config/google-chrome/WidevineCdm"_L1); if (chromeWidevineDir.exists()) potentialWidevineVersionDirs << widevineCdmDirHint(chromeWidevineDir); // Firefox widevine modules - QDir firefoxPotentialProfilesDir(QDir::homePath() + "/.mozilla/firefox"); + QDir firefoxPotentialProfilesDir(QDir::homePath() + "/.mozilla/firefox"_L1); if (firefoxPotentialProfilesDir.exists()) { QFileInfoList firefoxProfileDirs = firefoxPotentialProfilesDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot, QDir::Name | QDir::Reversed); for (const QFileInfo &info : firefoxProfileDirs) { - QDir widevinePluginsDir(info.absoluteFilePath() + "/gmp-widevinecdm"); + QDir widevinePluginsDir(info.absoluteFilePath() + "/gmp-widevinecdm"_L1); if (widevinePluginsDir.exists()) potentialWidevineVersionDirs << widevinePluginsDir; } } // Chromium widevine modules (might not work with proprietary codecs) - QDir chromiumWidevineDir(QDir::homePath() + "/.config/chromium/WidevineCdm"); + QDir chromiumWidevineDir(QDir::homePath() + "/.config/chromium/WidevineCdm"_L1); if (chromiumWidevineDir.exists()) potentialWidevineVersionDirs << widevineCdmDirHint(chromiumWidevineDir); @@ -279,28 +329,29 @@ static bool IsWidevineAvailable(base::FilePath *cdm_path, widevineVersionDirs.prepend(QFileInfo(dir.absolutePath())); // ### alternatively look up in the manifest.json and take the path from there. #if Q_PROCESSOR_WORDSIZE == 8 - const QString library = QLatin1String("/_platform_specific/linux_x64/libwidevinecdm.so"); + const auto library = "/_platform_specific/linux_x64/libwidevinecdm.so"_L1; #else - const QString library = QLatin1String("/_platform_specific/linux_x86/libwidevinecdm.so"); + const auto library = "/_platform_specific/linux_x86/libwidevinecdm.so"_L1; #endif for (const QFileInfo &info : widevineVersionDirs) { - pluginPaths << info.absoluteFilePath() + "/libwidevinecdm.so"; + pluginPaths << info.absoluteFilePath() + "/libwidevinecdm.so"_L1; pluginPaths << info.absoluteFilePath() + library; } } // Fixed paths: - pluginPaths << QStringLiteral("/usr/lib/chromium/libwidevinecdm.so") // Arch - << QStringLiteral("/usr/lib/chromium-browser/libwidevinecdm.so") // Ubuntu/neon - << QStringLiteral("/usr/lib64/chromium/libwidevinecdm.so") // OpenSUSE style + pluginPaths + << u"/usr/lib/chromium/libwidevinecdm.so"_s // Arch + << u"/usr/lib/chromium-browser/libwidevinecdm.so"_s // Ubuntu/neon + << u"/usr/lib64/chromium/libwidevinecdm.so"_s // OpenSUSE style #if Q_PROCESSOR_WORDSIZE == 8 - << QStringLiteral("/usr/lib64/chromium-browser/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") // Gentoo - << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so") // Old Google Chrome + << u"/usr/lib64/chromium-browser/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"_s // Gentoo + << u"/opt/google/chrome/WidevineCdm/_platform_specific/linux_x64/libwidevinecdm.so"_s // Old Google Chrome #else - << QStringLiteral("/usr/lib/chromium-browser/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") // Gentoo - << QStringLiteral("/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so") // Old Google Chrome + << u"/usr/lib/chromium-browser/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so"_s // Gentoo + << u"/opt/google/chrome/WidevineCdm/_platform_specific/linux_x86/libwidevinecdm.so"_s // Old Google Chrome #endif - << QStringLiteral("/opt/google/chrome/libwidevinecdm.so"); // Older Google Chrome + << u"/opt/google/chrome/libwidevinecdm.so"_s; // Older Google Chrome #endif } @@ -400,7 +451,8 @@ void ContentClientQt::AddAdditionalSchemes(Schemes* schemes) #endif } -base::StringPiece ContentClientQt::GetDataResource(int resource_id, ui::ResourceScaleFactor scale_factor) +std::string_view ContentClientQt::GetDataResource(int resource_id, + ui::ResourceScaleFactor scale_factor) { return ui::ResourceBundle::GetSharedInstance().GetRawDataResourceForScale(resource_id, scale_factor); } @@ -435,4 +487,104 @@ blink::OriginTrialPolicy *ContentClientQt::GetOriginTrialPolicy() return origin_trial_policy_.get(); } +void ContentClientQt::SetGpuInfo(const gpu::GPUInfo &gpu_info) +{ + if (Q_LIKELY(!lcWebEngineCompositor().isDebugEnabled())) + return; + + base::CommandLine *commandLine = base::CommandLine::ForCurrentProcess(); + const bool isBrowserProcess = !commandLine->HasSwitch(switches::kProcessType); + const bool isMainThread = QThread::currentThread() == qApp->thread(); + + // Limit this to the main thread of the browser process for now. + if (!isBrowserProcess || !isMainThread) + return; + + if (!gpu_info.IsInitialized()) { + // This is probably not an issue but suspicious. + qCDebug(lcWebEngineCompositor, "Failed to initialize GPUInfo."); + return; + } + + const gpu::GPUInfo::GPUDevice &primary = gpu_info.gpu; + + // Do not print the info again if the device hasn't been changed. + // Change of the device is unexpected: we don't support or implement fallback yet. + // It is suspicious if the info is logged twice. + if (m_gpuInfo && m_gpuInfo->gpu.device_string == primary.device_string) + return; + m_gpuInfo = gpu_info; + + auto deviceToString = [](const gpu::GPUInfo::GPUDevice &device) -> QString { + if (device.vendor_id == 0x0) + return "Disabled"_L1; + + QString log; + + // TODO: Factor vendor translation out from QtWebEngineCore::GPUInfo. + // Only name the most commmon desktop GPU hardware vendors for now. + switch (device.vendor_id) { + case 0x1002: + log += "AMD"_L1; + break; + case 0x10DE: + log += "Nvidia"_L1; + break; + case 0x8086: + log += "Intel"_L1; + break; + default: + log += "vendor id: 0x"_L1 + QString::number(device.vendor_id, 16); + } + + log += ", device id: 0x"_L1 + QString::number(device.device_id, 16); + + if (!device.driver_vendor.empty()) { + log += ", driver: "_L1 + QLatin1StringView(device.driver_vendor) + u' ' + + QLatin1StringView(device.driver_version); + } + log += ", system device id: 0x"_L1 + QString::number(device.system_device_id, 16); + + log += ", preference: "_L1; + switch (device.gpu_preference) { + case gl::GpuPreference::kNone: + log += "None"_L1; + break; + case gl::GpuPreference::kDefault: + log += "Default"_L1; + break; + case gl::GpuPreference::kLowPower: + log += "LowPower"_L1; + break; + case gl::GpuPreference::kHighPerformance: + log += "HighPerformance"_L1; + break; + } + + log += ", active: "_L1 + (device.active ? "yes"_L1 : "no"_L1); + return log; + }; + + QString log; + if (gpu_info.gl_vendor.empty() || gpu_info.gl_vendor == "Disabled") { + log += "ANGLE is disabled:\n"_L1; + log += " GL Renderer: "_L1 + QLatin1StringView(gpu_info.gl_renderer) + u'\n'; + log += " Software Renderer: "_L1 + (primary.IsSoftwareRenderer() ? "yes"_L1 : "no"_L1) + + u'\n'; + log += " Primary GPU: "_L1 + deviceToString(primary) + u'\n'; + } else { + log += QLatin1StringView(gpu_info.display_type) + " display is initialized:\n"_L1; + log += " GL Renderer: "_L1 + QLatin1StringView(gpu_info.gl_renderer) + u'\n'; + log += " "_L1 + QString::number(gpu_info.GpuCount()) + " GPU(s) detected:\n"_L1; + log += " "_L1 + deviceToString(primary) + u'\n'; + for (auto &secondary : gpu_info.secondary_gpus) + log += " "_L1 + deviceToString(secondary) + u'\n'; + + log += " NVIDIA Optimus: "_L1 + (gpu_info.optimus ? "enabled"_L1 : "disabled"_L1) + u'\n'; + log += " AMD Switchable: "_L1 + (gpu_info.amd_switchable ? "enabled"_L1 : "disabled"_L1); + } + + qCDebug(lcWebEngineCompositor, "%ls", qUtf16Printable(log)); +} + } // namespace QtWebEngineCore diff --git a/src/core/content_client_qt.h b/src/core/content_client_qt.h index f58e17f9649..854233ae0b0 100644 --- a/src/core/content_client_qt.h +++ b/src/core/content_client_qt.h @@ -6,13 +6,14 @@ #include "qtwebenginecoreglobal_p.h" -#include "base/strings/string_piece.h" #include "base/synchronization/lock.h" #include "components/embedder_support/origin_trials/origin_trial_policy_impl.h" #include "content/public/common/content_client.h" +#include "gpu/config/gpu_info.h" #include "ui/base/layout.h" #include +#include namespace QtWebEngineCore { @@ -25,16 +26,18 @@ class ContentClientQt : public content::ContentClient { std::vector *cdm_host_file_paths) override; void AddAdditionalSchemes(Schemes* schemes) override; - base::StringPiece GetDataResource(int, ui::ResourceScaleFactor) override; + std::string_view GetDataResource(int, ui::ResourceScaleFactor) override; base::RefCountedMemory* GetDataResourceBytes(int resource_id) override; gfx::Image &GetNativeImageNamed(int resource_id) override; std::u16string GetLocalizedString(int message_id) override; blink::OriginTrialPolicy *GetOriginTrialPolicy() override; + void SetGpuInfo(const gpu::GPUInfo &gpu_info) override; private: // Used to lock when |origin_trial_policy_| is initialized. base::Lock origin_trial_policy_lock_; std::unique_ptr origin_trial_policy_; + std::optional m_gpuInfo; }; } // namespace QtWebEngineCore diff --git a/src/core/content_main_delegate_qt.cpp b/src/core/content_main_delegate_qt.cpp index 604657e3181..c96328b3efa 100644 --- a/src/core/content_main_delegate_qt.cpp +++ b/src/core/content_main_delegate_qt.cpp @@ -46,7 +46,6 @@ #if BUILDFLAG(IS_MAC) #include "base/trace_event/trace_event.h" #include "content/public/common/content_features.h" -#include "media/gpu/mac/vt_video_decode_accelerator_mac.h" #endif #include @@ -171,13 +170,6 @@ void ContentMainDelegateQt::PreSandboxStartup() #if BUILDFLAG(IS_WIN) media::PreSandboxMediaFoundationInitialization(); #endif - -#if BUILDFLAG(IS_MAC) - { - TRACE_EVENT0("gpu", "Initialize VideoToolbox"); - media::InitializeVideoToolbox(); - } -#endif } if (parsedCommandLine->HasSwitch(switches::kApplicationName)) { diff --git a/src/core/desktop_media_controller.cpp b/src/core/desktop_media_controller.cpp index 09c1aea1914..abf62645089 100644 --- a/src/core/desktop_media_controller.cpp +++ b/src/core/desktop_media_controller.cpp @@ -42,7 +42,7 @@ std::unique_ptr createMediaList(DesktopMediaType type) std::unique_ptr screenCapturer = webrtc::DesktopCapturer::CreateScreenCapturer(options); if (!screenCapturer) { - qWarning() << "Screen capturing is not available. Media list will be empty."; + qWarning("Screen capturing is not available. Media list will be empty."); return nullptr; } auto capturer = std::make_unique(std::move(screenCapturer)); @@ -52,13 +52,13 @@ std::unique_ptr createMediaList(DesktopMediaType type) std::unique_ptr windowCapturer = webrtc::DesktopCapturer::CreateWindowCapturer(options); if (!windowCapturer) { - qWarning() << "Window capturing is not available. Media list will be empty."; + qWarning("Window capturing is not available. Media list will be empty."); return nullptr; } auto capturer = std::make_unique(std::move(windowCapturer)); return std::make_unique( listType, std::move(capturer), - !content::desktop_capture::ShouldEnumerateCurrentProcessWindows()); + !content::desktop_capture::ShouldEnumerateCurrentProcessWindows(), /*auto_show_delegated_source_list:*/ false); } default: { Q_UNREACHABLE(); diff --git a/src/core/devtools_frontend_qt.cpp b/src/core/devtools_frontend_qt.cpp index 97a1ef68d60..e36b5a37819 100644 --- a/src/core/devtools_frontend_qt.cpp +++ b/src/core/devtools_frontend_qt.cpp @@ -26,7 +26,7 @@ using namespace QtWebEngineCore; namespace { -static const char kScreencastEnabled[] = "screencastEnabled"; +static const char kScreencastEnabled[] = "screencast-enabled"; static std::string GetFrontendURL() { diff --git a/src/core/devtools_manager_delegate_qt.cpp b/src/core/devtools_manager_delegate_qt.cpp index 6654ead0ec6..b584ecb0de7 100644 --- a/src/core/devtools_manager_delegate_qt.cpp +++ b/src/core/devtools_manager_delegate_qt.cpp @@ -20,6 +20,7 @@ #include "net/socket/tcp_server_socket.h" #include "ui/base/resource/resource_bundle.h" +using namespace Qt::StringLiterals; using content::DevToolsAgentHost; namespace { @@ -52,7 +53,7 @@ class TCPServerSocketFactory : public content::DevToolsSocketFactory { namespace QtWebEngineCore { DevToolsServerQt::DevToolsServerQt() - : m_bindAddress(QLatin1String("127.0.0.1")) + : m_bindAddress(u"127.0.0.1"_s) , m_port(0) , m_valid(false) , m_isStarted(false) @@ -72,7 +73,7 @@ void DevToolsServerQt::parseAddressAndPort() if (commandLine.HasSwitch(switches::kRemoteDebuggingPort)) { portStr = QString::fromStdString(commandLine.GetSwitchValueASCII(switches::kRemoteDebuggingPort)); } else if (!inspectorEnv.isEmpty()) { - int portColonPos = inspectorEnv.lastIndexOf(':'); + int portColonPos = inspectorEnv.lastIndexOf(u':'); if (portColonPos != -1) { portStr = inspectorEnv.mid(portColonPos + 1); m_bindAddress = inspectorEnv.mid(0, portColonPos); @@ -83,8 +84,12 @@ void DevToolsServerQt::parseAddressAndPort() m_port = portStr.toInt(&m_valid); m_valid = m_valid && (m_port > 0 && m_port < 65535); - if (!m_valid) - qWarning("Invalid port given for the inspector server \"%s\". Examples of valid input: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's network interface).", qPrintable(portStr)); + if (!m_valid) { + qWarning("Invalid port given for the inspector server \"%ls\". " + "Examples of valid input: \"12345\" or \"192.168.2.14:12345\" " + "(with the address of one of this host's network interface).", + qUtf16Printable(portStr)); + } } std::unique_ptr DevToolsServerQt::CreateSocketFactory() @@ -123,8 +128,9 @@ void DevToolsServerQt::stop() void DevToolsManagerDelegateQt::Initialized(const net::IPEndPoint *ip_address) { if (ip_address && ip_address->address().size()) { - QString addressAndPort = QString::fromStdString(ip_address->ToString()); - qWarning("Remote debugging server started successfully. Try pointing a Chromium-based browser to http://%s", qPrintable(addressAndPort)); + qWarning("Remote debugging server started successfully. " + "Try pointing a Chromium-based browser to http://%s", + ip_address->ToString().c_str()); } else qWarning("Couldn't start the inspector server on bind address. In case of invalid input, try something like: \"12345\" or \"192.168.2.14:12345\" (with the address of one of this host's interface)."); diff --git a/src/core/doc/qtwebengine.qdocconf b/src/core/doc/qtwebengine.qdocconf index 3f836244dd8..eb1e8173e18 100644 --- a/src/core/doc/qtwebengine.qdocconf +++ b/src/core/doc/qtwebengine.qdocconf @@ -74,6 +74,7 @@ headerdirs += ../../core/api \ sourcedirs += ../../core/api \ ../../core/doc \ + ../../core/tools/webenginedriver \ ../../webenginequick/api \ ../../webenginequick/doc \ ../../webenginewidgets/api \ @@ -104,5 +105,9 @@ navigation.toctitles.inclusive = false # \QWE macro expands to 'Qt WebEngine' without auto-linking anywhere. macro.QWE = "Qt \\WebEngine" +# QTBUG-134416: Ignore overwrite warnings, attribution +# documentation generates many of these +spurious += "Output file already exists, overwriting .*" + # Enforce zero documentation warnings warninglimit = 2 diff --git a/src/core/doc/src/qtwebengine-features.qdoc b/src/core/doc/src/qtwebengine-features.qdoc index 246ca7b6ad9..b62eff3e5dc 100644 --- a/src/core/doc/src/qtwebengine-features.qdoc +++ b/src/core/doc/src/qtwebengine-features.qdoc @@ -457,7 +457,7 @@ WebEngineView::javaScriptDialogRequested(), WebEngineView::colorDialogRequested(), WebEngineView::fileDialogRequested(), and - WebEngineView::formValidationMessageRequested() signals. For an example, + WebEngineView::formValidationMessageRequested() signals. \section1 PDF File Viewing @@ -643,6 +643,11 @@ When the \QWE spellchecker initializes, it will try to load the \c bdict dictionaries and to check them for consistency. + For CMake, you can use the \l qt_add_webengine_dictionary command to convert + Hunspell \c .dic files into the \c .bdic binary format. The command creates + a \c qtwebengine_dictionaries target, which your project can use a + dependency. + If \c QTWEBENGINE_DICTIONARIES_PATH is set, the spellchecker uses the dictionaries in the specified directory without looking anywere else. Otherwise, it uses the \e qtwebengine_dictionaries directory relative to the @@ -711,7 +716,7 @@ Some websites use this API to decide whether they run on a mobile device or on desktop and base their design on it. This can cause unwanted results on touchscreen laptops or other setups that emulate a fake touch device. - Applications can set this feature explicitly with \l {QWebEngineSettings::JSTouchEventsEnabled}. + Applications can set this feature explicitly with \l {QWebEngineSettings::TouchEventsApiEnabled}. Note that touch events will still be delivered to web pages even if the API is disabled. Dispatching touch events to web pages can be prohibited by installing an event filter object diff --git a/src/core/doc/src/qwebenginesettings_lgpl.qdoc b/src/core/doc/src/qwebenginesettings_lgpl.qdoc index 0b784508ca6..1cd797ab52d 100644 --- a/src/core/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/core/doc/src/qwebenginesettings_lgpl.qdoc @@ -193,7 +193,7 @@ \value PreferCSSMarginsForPrinting Turns on preferring CSS margins over the margins of the specified QPageLayout. Disabled by default. (Added in Qt 6.9) - \value JSTouchEventsEnabled Enables support for JavaScript touch events API, + \value TouchEventsApiEnabled Enables support for JavaScript touch events API, meaning \c ontouchstart, \c ontouchend and \c ontouchmove handlers will be present in the \c document.window object. Enabled by default if a touch device detected by the system and disabled otherwise. (Added in Qt 6.9) Note that some websites use this API to decide whether they run on a mobile device or on desktop and base their design on it. diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index 88c8b0039ea..1278558539d 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include "profile_adapter_client.h" #include "profile_adapter.h" @@ -22,8 +23,24 @@ #include "type_conversion.h" #include "web_contents_delegate_qt.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { +void provideDownloadTarget(download::DownloadItem *item, download::DownloadTargetCallback *callback, + const base::FilePath &target) +{ + download::DownloadTargetInfo target_info; + target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE; + target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; + target_info.insecure_download_status = download::DownloadItem::VALIDATED; + target_info.mime_type = item->GetMimeType(); + target_info.display_name = item->GetFileNameToReportUser(); + target_info.target_path = target; + target_info.intermediate_path = target.AddExtensionASCII("download"); + std::move(*callback).Run(std::move(target_info)); +} + DownloadManagerDelegateQt::DownloadManagerDelegateQt(ProfileAdapter *profileAdapter) : m_profileAdapter(profileAdapter) , m_currentId(0) @@ -90,6 +107,14 @@ void DownloadManagerDelegateQt::removeDownload(quint32 downloadId) bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem *item, download::DownloadTargetCallback *callback) { + // The item came back for another round of target determination; this happens for example when + // network error occurs. We already gave it a target path, let it use that, then it can report + // the reason of its failure in OnDownloadUpdated(). + if (m_currentId >= item->GetId() && !item->GetTargetFilePath().empty()) { + provideDownloadTarget(item, callback, item->GetTargetFilePath()); + return true; + } + m_currentId = item->GetId(); // Keep the forced file path if set, also as the temporary file, so the check for existence @@ -153,10 +178,10 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * } if (suggestedFilename.isEmpty()) { - suggestedFilename = QStringLiteral("qwe_download"); + suggestedFilename += "qwe_download"_L1; QMimeType mimeType = QMimeDatabase().mimeTypeForName(mimeTypeString); if (mimeType.isValid() && !mimeType.preferredSuffix().isEmpty()) - suggestedFilename += QStringLiteral(".") + mimeType.preferredSuffix(); + suggestedFilename += u'.' + mimeType.preferredSuffix(); } QDir defaultDownloadDirectory(m_profileAdapter->downloadPath()); @@ -167,16 +192,14 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * item->AddObserver(this); QList clients = m_profileAdapter->clients(); if (!clients.isEmpty()) { - Q_ASSERT(m_currentId == item->GetId()); - ProfileAdapterClient::DownloadItemInfo info = {}; info.id = item->GetId(); info.url = toQt(item->GetURL()); info.state = item->GetState(); info.totalBytes = item->GetTotalBytes(); info.receivedBytes = item->GetReceivedBytes(); - info.mimeType = mimeTypeString; - info.path = suggestedFilePath; + info.mimeType = std::move(mimeTypeString); + info.path = std::move(suggestedFilePath); info.savePageFormat = ProfileAdapterClient::UnknownSavePageFormat; info.accepted = acceptedByDefault; info.paused = false; @@ -185,11 +208,12 @@ bool DownloadManagerDelegateQt::DetermineDownloadTarget(download::DownloadItem * info.useDownloadTargetCallback = true; info.downloadInterruptReason = item->GetLastReason(); info.page = adapterClient; - info.suggestedFileName = suggestedFilename; + info.suggestedFileName = std::move(suggestedFilename); info.startTime = item->GetStartTime().ToTimeT(); m_pendingDownloads.emplace(m_currentId, std::move(*callback)); - clients[0]->downloadRequested(info); + QTimer::singleShot(0, m_profileAdapter, + [client = clients[0], info]() { client->downloadRequested(info); }); } else cancelDownload(std::move(*callback)); @@ -212,23 +236,13 @@ void DownloadManagerDelegateQt::downloadTargetDetermined(quint32 downloadId, boo QFileInfo suggestedFile(path); if (!suggestedFile.absoluteDir().mkpath(suggestedFile.absolutePath())) { - qWarning() << "Creating download path failed, download cancelled:" << suggestedFile.absolutePath(); + qWarning("Creating download path failed, download cancelled: %ls", + qUtf16Printable(suggestedFile.absolutePath())); cancelDownload(std::move(callback)); return; } base::FilePath targetPath(toFilePathString(suggestedFile.absoluteFilePath())); - - download::DownloadTargetInfo target_info; - target_info.target_disposition = download::DownloadItem::TARGET_DISPOSITION_OVERWRITE; - target_info.danger_type = download::DOWNLOAD_DANGER_TYPE_MAYBE_DANGEROUS_CONTENT; - target_info.insecure_download_status = download::DownloadItem::VALIDATED; - target_info.mime_type = item->GetMimeType(); - target_info.intermediate_path = - targetPath.AddExtension(toFilePathString("download")); - target_info.display_name = base::FilePath(); - target_info.target_path = targetPath; - target_info.interrupt_reason = download::DOWNLOAD_INTERRUPT_REASON_NONE; - std::move(callback).Run(std::move(target_info)); + provideDownloadTarget(item, &callback, targetPath); } void DownloadManagerDelegateQt::GetSaveDir(content::BrowserContext* browser_context, @@ -266,8 +280,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content } if (suggestedFilePath.isEmpty()) { - suggestedFilePath = QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName() - + QStringLiteral(".mhtml"); + suggestedFilePath += + QFileInfo(toQt(suggested_path.AsUTF8Unsafe())).completeBaseName() + ".mhtml"_L1; } else { acceptedByDefault = true; } @@ -290,7 +304,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content info.state = download::DownloadItem::IN_PROGRESS; info.totalBytes = -1; info.receivedBytes = 0; - info.mimeType = QStringLiteral("application/x-mimearchive"); + info.mimeType = u"application/x-mimearchive"_s; info.path = suggestedFilePath; info.savePageFormat = suggestedSaveFormat; info.accepted = acceptedByDefault; @@ -304,7 +318,8 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content info.startTime = QDateTime::currentMSecsSinceEpoch(); m_pendingSaves.emplace(m_currentId, std::move(callback)); - clients[0]->downloadRequested(info); + QTimer::singleShot(0, m_profileAdapter, + [client = clients[0], info]() { client->downloadRequested(info); }); } void DownloadManagerDelegateQt::savePathDetermined(quint32 downloadId, bool accepted, @@ -363,9 +378,8 @@ void DownloadManagerDelegateQt::OnDownloadUpdated(download::DownloadItem *downlo info.suggestedFileName = toQt(download->GetSuggestedFilename()); info.startTime = download->GetStartTime().ToTimeT(); - for (ProfileAdapterClient *client : std::as_const(clients)) { - client->downloadUpdated(info); - } + QTimer::singleShot(0, m_profileAdapter, + [client = clients[0], info]() { client->downloadUpdated(info); }); } } diff --git a/src/core/extensions/extension_host_delegate_qt.cpp b/src/core/extensions/extension_host_delegate_qt.cpp index 16133a598f8..b460cd6ce91 100644 --- a/src/core/extensions/extension_host_delegate_qt.cpp +++ b/src/core/extensions/extension_host_delegate_qt.cpp @@ -36,8 +36,7 @@ void ExtensionHostDelegateQt::OnMainFrameCreatedForBackgroundPage(ExtensionHost content::JavaScriptDialogManager *ExtensionHostDelegateQt::GetJavaScriptDialogManager() { - Q_UNREACHABLE(); - return nullptr; + Q_UNREACHABLE_RETURN(nullptr); } void ExtensionHostDelegateQt::CreateTab(std::unique_ptr web_contents, @@ -95,16 +94,14 @@ bool ExtensionHostDelegateQt::CheckMediaAccessPermission( Q_UNUSED(type); Q_UNUSED(extension); - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); } content::PictureInPictureResult ExtensionHostDelegateQt::EnterPictureInPicture(content::WebContents *web_contents) { Q_UNUSED(web_contents); - Q_UNREACHABLE(); - return content::PictureInPictureResult::kNotSupported; + Q_UNREACHABLE_RETURN(content::PictureInPictureResult::kNotSupported); } void ExtensionHostDelegateQt::ExitPictureInPicture() diff --git a/src/core/extensions/extension_system_qt.cpp b/src/core/extensions/extension_system_qt.cpp index 78c6bb4855d..b14239e9dc4 100644 --- a/src/core/extensions/extension_system_qt.cpp +++ b/src/core/extensions/extension_system_qt.cpp @@ -31,7 +31,6 @@ #include "content/public/browser/browser_context.h" #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" -#include "content/public/browser/notification_service.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/url_data_source.h" #include "content/public/common/webplugininfo.h" @@ -69,7 +68,7 @@ namespace extensions { namespace { // Implementation based on ComponentLoader::ParseManifest. -std::optional ParseManifest(base::StringPiece manifest_contents) +std::optional ParseManifest(std::string_view manifest_contents) { JSONStringValueDeserializer deserializer(manifest_contents); std::unique_ptr manifest = deserializer.Deserialize(nullptr, nullptr); diff --git a/src/core/extensions/extensions_browser_client_qt.cpp b/src/core/extensions/extensions_browser_client_qt.cpp index 155f9396376..bd95524f367 100644 --- a/src/core/extensions/extensions_browser_client_qt.cpp +++ b/src/core/extensions/extensions_browser_client_qt.cpp @@ -61,7 +61,7 @@ void DetermineCharset(const std::string &mime_type, if (base::StartsWith(mime_type, "text/", base::CompareCase::INSENSITIVE_ASCII)) { // All of our HTML files should be UTF-8 and for other resource types // (like images), charset doesn't matter. - DCHECK(base::IsStringUTF8(base::StringPiece(reinterpret_cast(data->front()), data->size()))); + DCHECK(base::IsStringUTF8(std::string_view(reinterpret_cast(data->front()), data->size()))); *out_charset = "utf-8"; } } @@ -76,7 +76,7 @@ scoped_refptr GetResource(int resource_id, const std::st : nullptr; if (replacements) { - base::StringPiece input(reinterpret_cast(bytes->front()), bytes->size()); + std::string_view input(reinterpret_cast(bytes->front()), bytes->size()); std::string temp_str = ui::ReplaceTemplateExpressions(input, *replacements); DCHECK(!temp_str.empty()); return base::MakeRefCounted(std::move(temp_str)); @@ -169,7 +169,7 @@ class ResourceBundleFileLoader : public network::mojom::URLLoader client_->OnReceiveResponse(std::move(head), std::move(consumer_handle), std::nullopt); size_t write_size = data->size(); - MojoResult result = producer_handle->WriteData(data->front(), &write_size, MOJO_WRITE_DATA_FLAG_NONE); + MojoResult result = producer_handle->WriteData((base::span)(*data), MOJO_WRITE_DATA_FLAG_NONE, write_size); OnFileWritten(result); } @@ -383,7 +383,8 @@ bool ExtensionsBrowserClientQt::AllowCrossRendererResourceLoad(const network::Re bool is_incognito, const Extension *extension, const ExtensionSet &extensions, - const ProcessMap &process_map) + const ProcessMap &process_map, + const GURL& upstream_url) { if (extension && extension->id() == extension_misc::kPdfExtensionId) return true; @@ -396,7 +397,7 @@ bool ExtensionsBrowserClientQt::AllowCrossRendererResourceLoad(const network::Re if (url_request_util::AllowCrossRendererResourceLoad(request, destination, page_transition, child_id, is_incognito, extension, extensions, - process_map, &allowed)) { + process_map, upstream_url, &allowed)) { return allowed; } // Couldn't determine if resource is allowed. Block the load. @@ -517,11 +518,18 @@ bool ExtensionsBrowserClientQt::IsInDemoMode() return false; } -ExtensionWebContentsObserver *ExtensionsBrowserClientQt::GetExtensionWebContentsObserver(content::WebContents *web_contents) +extensions::ExtensionWebContentsObserver * +ExtensionsBrowserClientQt::GetExtensionWebContentsObserver(content::WebContents *web_contents) { return ExtensionWebContentsObserverQt::FromWebContents(web_contents); } +void ExtensionsBrowserClientQt::CreateExtensionWebContentsObserver( + content::WebContents *web_contents) +{ + ExtensionWebContentsObserverQt::CreateForWebContents(web_contents); +} + KioskDelegate *ExtensionsBrowserClientQt::GetKioskDelegate() { return nullptr; @@ -543,8 +551,9 @@ media_device_salt::MediaDeviceSaltService *ExtensionsBrowserClientQt::GetMediaDe return nullptr; } mojo::PendingRemote -ExtensionsBrowserClientQt::GetControlledFrameEmbedderURLLoader(const url::Origin &, - int frame_tree_node_id, content::BrowserContext *browser_context) +ExtensionsBrowserClientQt::GetControlledFrameEmbedderURLLoader( + const url::Origin &, content::FrameTreeNodeId frame_tree_node_id, + content::BrowserContext *browser_context) { return mojo::PendingRemote(); } diff --git a/src/core/extensions/extensions_browser_client_qt.h b/src/core/extensions/extensions_browser_client_qt.h index 8ce0b0dd5e9..d0ffb4b9760 100644 --- a/src/core/extensions/extensions_browser_client_qt.h +++ b/src/core/extensions/extensions_browser_client_qt.h @@ -48,7 +48,8 @@ class ExtensionsBrowserClientQt : public ExtensionsBrowserClient bool is_incognito, const Extension *extension, const ExtensionSet &extensions, - const ProcessMap &process_map) override; + const ProcessMap &process_map, + const GURL& upstream_url) override; PrefService *GetPrefServiceForContext(content::BrowserContext *context) override; void GetEarlyExtensionPrefsObservers(content::BrowserContext *context, @@ -109,9 +110,12 @@ class ExtensionsBrowserClientQt : public ExtensionsBrowserClient media_device_salt::MediaDeviceSaltService *GetMediaDeviceSaltService(content::BrowserContext *context) override; mojo::PendingRemote - GetControlledFrameEmbedderURLLoader(const url::Origin &, int frame_tree_node_id, + GetControlledFrameEmbedderURLLoader(const url::Origin &, + content::FrameTreeNodeId frame_tree_node_id, content::BrowserContext *browser_context) override; + void CreateExtensionWebContentsObserver(content::WebContents *) override; + private: // Support for extension APIs. std::unique_ptr api_client_; diff --git a/src/core/extensions/file_system_delegate_qt.cpp b/src/core/extensions/file_system_delegate_qt.cpp index 6c5b3391913..b19ebf92b23 100644 --- a/src/core/extensions/file_system_delegate_qt.cpp +++ b/src/core/extensions/file_system_delegate_qt.cpp @@ -36,20 +36,18 @@ FileEntryPickerQt::FileEntryPickerQt( this, std::make_unique(web_contents)); m_selectFileDialog->SelectFile( picker_type, std::u16string(), suggested_name, file_type_info, 0, - base::FilePath::StringType(), nullptr, nullptr, &caller); + base::FilePath::StringType(), nullptr, &caller); } FileEntryPickerQt::~FileEntryPickerQt() = default; -void FileEntryPickerQt::FileSelected(const ui::SelectedFileInfo &file, int index, void *params) +void FileEntryPickerQt::FileSelected(const ui::SelectedFileInfo &file, int index) { - MultiFilesSelected({ file }, params); + MultiFilesSelected({ file }); } -void FileEntryPickerQt::MultiFilesSelected(const std::vector &files, - void *params) +void FileEntryPickerQt::MultiFilesSelected(const std::vector &files) { - Q_UNUSED(params); std::vector paths; for (const auto &file : files) { paths.push_back(file.file_path); @@ -58,7 +56,7 @@ void FileEntryPickerQt::MultiFilesSelected(const std::vector &files, void *params) override; - void FileSelectionCanceled(void *params) override; + void FileSelected(const ui::SelectedFileInfo &file, int index) override; + void MultiFilesSelected(const std::vector &files) override; + void FileSelectionCanceled() override; FileSystemDelegate::FilesSelectedCallback m_filesSelectedCallback; base::OnceClosure m_fileSelectionCanceledCallback; diff --git a/src/core/favicon_driver_qt.cpp b/src/core/favicon_driver_qt.cpp index b454ca90604..8b6c8bc3191 100644 --- a/src/core/favicon_driver_qt.cpp +++ b/src/core/favicon_driver_qt.cpp @@ -169,9 +169,11 @@ FaviconDriverQt::NavigationManifestData::NavigationManifestData( FaviconDriverQt::NavigationManifestData::~NavigationManifestData() = default; void FaviconDriverQt::OnDidDownloadManifest(ManifestDownloadCallback callback, + blink::mojom::ManifestRequestResult result, const GURL &manifest_url, blink::mojom::ManifestPtr manifest) { + Q_UNUSED(result); Q_UNUSED(manifest_url); // ~WebContentsImpl triggers running any pending callbacks for manifests. diff --git a/src/core/favicon_driver_qt.h b/src/core/favicon_driver_qt.h index a6307ea476d..1aaf0941fed 100644 --- a/src/core/favicon_driver_qt.h +++ b/src/core/favicon_driver_qt.h @@ -96,7 +96,9 @@ class FaviconDriverQt : public favicon::FaviconDriver, }; // Callback when a manifest is downloaded. - void OnDidDownloadManifest(ManifestDownloadCallback callback, const GURL &manifest_url, + void OnDidDownloadManifest(ManifestDownloadCallback callback, + blink::mojom::ManifestRequestResult result, + const GURL &manifest_url, blink::mojom::ManifestPtr manifest); // FaviconHandler::Delegate implementation. diff --git a/src/core/file_picker_controller.cpp b/src/core/file_picker_controller.cpp index fb124df7bb8..550ae0da026 100644 --- a/src/core/file_picker_controller.cpp +++ b/src/core/file_picker_controller.cpp @@ -18,6 +18,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { class FilePickerControllerPrivate { @@ -75,7 +77,7 @@ void FilePickerController::accepted(const QStringList &files) continue; } - if (urlString.startsWith("file:")) { + if (urlString.startsWith("file:"_L1)) { base::FilePath filePath = toFilePath(urlString).NormalizePathSeparators(); std::vector pathComponents; // Splits the file URL into scheme, host name, path and file name. @@ -83,18 +85,20 @@ void FilePickerController::accepted(const QStringList &files) QString absolutePath; #if !defined(Q_OS_WIN) - absolutePath = "/"; + absolutePath += u'/'; #endif QString scheme = toQt(pathComponents[0]); if (scheme.size() > 5) { #if defined(Q_OS_WIN) // There is no slash at the end of the file scheme and it is valid on Windows: file:C:/ - if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == ':') { - absolutePath += scheme.at(5) + ":/"; + if (scheme.size() == 7 && scheme.at(5).isLetter() && scheme.at(6) == u':') { + absolutePath += scheme.at(5) + ":/"_L1; } else { #endif - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + qWarning("Ignoring invalid item in " + "FilePickerController::accepted(QStringList): %ls", + qUtf16Printable(urlString)); continue; #if defined(Q_OS_WIN) } @@ -106,28 +110,34 @@ void FilePickerController::accepted(const QStringList &files) && base::FilePath::IsSeparator(urlString.at(6).toLatin1()) && !base::FilePath::IsSeparator(urlString.at(7).toLatin1())) { #if defined(Q_OS_WIN) - if (urlString.at(8) != ':' && pathComponents.size() > 2) { - absolutePath += "//"; + if (urlString.at(8) != u':' && pathComponents.size() > 2) { + absolutePath += "//"_L1; #else if (pathComponents.size() > 2) { - absolutePath += "/"; + absolutePath += u'/'; #endif } else { - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + qWarning("Ignoring invalid item in " + "FilePickerController::accepted(QStringList): %ls", + qUtf16Printable(urlString)); continue; } } - // Build absolute path from file URI componenets. - for (size_t j = 1; j < pathComponents.size(); j++) - absolutePath += toQt(pathComponents[j]) + (j != pathComponents.size()-1 ? "/" : ""); + // Build absolute path from file URI components. + for (size_t j = 1; j < pathComponents.size(); j++) { + absolutePath += toQt(pathComponents[j]); + if (j != pathComponents.size() - 1) + absolutePath += u'/'; + } if (toFilePath(absolutePath).IsAbsolute()) { stringList.append(absolutePath); continue; } } - qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %s", qPrintable(urlString)); + qWarning("Ignoring invalid item in FilePickerController::accepted(QStringList): %ls", + qUtf16Printable(urlString)); } FilePickerController::filesSelectedInChooser(stringList); @@ -161,7 +171,7 @@ static QStringList listRecursively(const QDir &dir) const QFileInfoList infoList(dir.entryInfoList(QDir::Dirs | QDir::Files | QDir::NoDotAndDotDot | QDir::Hidden)); for (const QFileInfo &fileInfo : infoList) { if (fileInfo.isDir()) { - ret.append(fileInfo.absolutePath() + QStringLiteral("/.")); // Match chromium's behavior. See chrome/browser/file_select_helper.cc + ret.append(fileInfo.absolutePath() + "/."_L1); // Match chromium's behavior. See chrome/browser/file_select_helper.cc ret.append(listRecursively(QDir(fileInfo.absoluteFilePath()))); } else ret.append(fileInfo.absoluteFilePath()); @@ -213,13 +223,13 @@ void FilePickerController::filesSelectedInChooser(const QStringList &filesList) } if (files.empty()) - d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled(nullptr); + d_ptr->fileSystemAccessDialogListener->FileSelectionCanceled(); else if (files.size() == 1) d_ptr->fileSystemAccessDialogListener->FileSelected( - ui::SelectedFileInfo(files[0]), 0, nullptr); + ui::SelectedFileInfo(files[0]), 0); else d_ptr->fileSystemAccessDialogListener->MultiFilesSelected( - ui::FilePathListToSelectedFileInfoList(files), nullptr); + ui::FilePathListToSelectedFileInfoList(files)); } } @@ -248,34 +258,34 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp return nameFilters; for (QString type : acceptedMimeTypes) { - if (type.startsWith(".")) { + if (type.startsWith(u'.')) { // A single suffix // Filename.type doesn't have to exist and mimeTypeForFile() supports // custom suffixes as valid (but unknown) MIME types. - const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename" + type); + const QMimeType &mimeType = mimeDatabase.mimeTypeForFile("filename"_L1 + type); if (mimeType.isValid()) { - QString glob = "*" + type; - acceptedGlobs.append(glob); - nameFilters.append(mimeType.comment() + " (" + glob + ")"); + QString glob = u'*' + type; + nameFilters.append(mimeType.comment() + " ("_L1 + glob + u')'); + acceptedGlobs.append(std::move(glob)); } - } else if (type.contains("/") && !type.endsWith("*")) { + } else if (type.contains(u'/') && !type.endsWith(u'*')) { // All suffixes for a given MIME type const QMimeType &mimeType = mimeDatabase.mimeTypeForName(type); if (mimeType.isValid() && !mimeType.globPatterns().isEmpty()) { - QString globs = mimeType.globPatterns().join(" "); + QString globs = mimeType.globPatterns().join(u' '); + nameFilters.append(mimeType.comment() + " ("_L1 + globs + u')'); acceptedGlobs.append(mimeType.globPatterns()); - nameFilters.append(mimeType.comment() + " (" + globs + ")"); } - } else if (type.endsWith("/*")) { + } else if (type.endsWith("/*"_L1)) { // All MIME types for audio/*, image/* or video/* // as separate filters as Chrome does static const QList &allMimeTypes = mimeDatabase.allMimeTypes(); - type = type.remove("/*"); + type.chop(2); for (const QMimeType &m : allMimeTypes) { if (m.name().startsWith(type) && !m.globPatterns().isEmpty()) { - QString globs = m.globPatterns().join(" "); + QString globs = m.globPatterns().join(u' '); + nameFilters.append(m.comment() + " ("_L1 + globs + u')'); acceptedGlobs.append(m.globPatterns()); - nameFilters.append(m.comment() + " (" + globs + ")"); } } } else { @@ -285,7 +295,7 @@ QStringList FilePickerController::nameFilters(const QStringList &acceptedMimeTyp const QString filter = QCoreApplication::translate("FilePickerController", - "Accepted types (%1)").arg(acceptedGlobs.join(' ')); + "Accepted types (%1)").arg(acceptedGlobs.join(u' ')); nameFilters.prepend(filter); return nameFilters; diff --git a/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp b/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp index 51c8a899191..6d1e8084afc 100644 --- a/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp +++ b/src/core/file_system_access/file_system_access_permission_context_factory_qt.cpp @@ -52,10 +52,4 @@ KeyedService *FileSystemAccessPermissionContextFactoryQt::BuildServiceInstanceFo return new FileSystemAccessPermissionContextQt(context); } -void FileSystemAccessPermissionContextFactoryQt::BrowserContextShutdown( - content::BrowserContext *context) -{ - Q_UNUSED(context); -} - } // namespace QtWebEngineCore diff --git a/src/core/file_system_access/file_system_access_permission_context_factory_qt.h b/src/core/file_system_access/file_system_access_permission_context_factory_qt.h index 1d98243d6e3..8589a37132d 100644 --- a/src/core/file_system_access/file_system_access_permission_context_factory_qt.h +++ b/src/core/file_system_access/file_system_access_permission_context_factory_qt.h @@ -29,7 +29,6 @@ class FileSystemAccessPermissionContextFactoryQt : public BrowserContextKeyedSer content::BrowserContext * GetBrowserContextToUse(content::BrowserContext *context) const override; KeyedService *BuildServiceInstanceFor(content::BrowserContext *profile) const override; - void BrowserContextShutdown(content::BrowserContext *context) override; }; } // namespace QtWebEngineCore diff --git a/src/core/file_system_access/file_system_access_permission_grant_qt.cpp b/src/core/file_system_access/file_system_access_permission_grant_qt.cpp index 67fa1c8cfbb..dc26a415ee8 100644 --- a/src/core/file_system_access/file_system_access_permission_grant_qt.cpp +++ b/src/core/file_system_access/file_system_access_permission_grant_qt.cpp @@ -3,6 +3,11 @@ #include "file_system_access_permission_grant_qt.h" +// based on chrome_file_system_access_permission_context.cc: +// Copyright 2019 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "file_system_access_permission_request_manager_qt.h" #include "components/permissions/permission_util.h" @@ -93,7 +98,8 @@ void FileSystemAccessPermissionGrantQt::RequestPermission( } // Drop fullscreen mode so that the user sees the URL bar. - base::ScopedClosureRunner fullscreen_block = web_contents->ForSecurityDropFullscreen(); + base::ScopedClosureRunner fullscreen_block = + web_contents->ForSecurityDropFullscreen(display::kInvalidDisplayId); FileSystemAccessPermissionRequestManagerQt::Access access = m_type == GrantType::kRead ? FileSystemAccessPermissionRequestManagerQt::Access::kRead diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index 728d6d04a4c..56df02412bd 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -126,7 +126,7 @@ std::optional GetZoomLevel(content::WebContents *capturer, } double zoom_level = - blink::PageZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(captured_wc)); + blink::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(captured_wc)); return std::round(100 * zoom_level); } @@ -366,8 +366,12 @@ void MediaCaptureDevicesDispatcher::handleMediaAccessPermissionResponse(content: bool securityOriginsMatch = (requestSecurityOrigin.host() == securityOrigin.host() && requestSecurityOrigin.scheme() == securityOrigin.scheme() && requestSecurityOrigin.port() == securityOrigin.port()); - if (!securityOriginsMatch) - qWarning("Security origin mismatch for media access permission: %s requested and %s provided\n", qPrintable(requestSecurityOrigin.toString()), qPrintable(securityOrigin.toString())); + if (!securityOriginsMatch) { + qWarning("Security origin mismatch for media access permission: %ls requested " + "and %ls provided\n", + qUtf16Printable(requestSecurityOrigin.toString()), + qUtf16Printable(securityOrigin.toString())); + } WebContentsAdapterClient::MediaRequestFlags requestFlags = mediaRequestFlagsForRequest(request); WebContentsAdapterClient::MediaRequestFlags finalFlags = requestFlags & authorizationFlags; diff --git a/src/core/native_web_keyboard_event_qt.cpp b/src/core/native_web_keyboard_event_qt.cpp index 9a5576fbbd8..23ce3c91124 100644 --- a/src/core/native_web_keyboard_event_qt.cpp +++ b/src/core/native_web_keyboard_event_qt.cpp @@ -10,6 +10,8 @@ #if !defined(Q_OS_MACOS) #include "native_web_keyboard_event_qt.h" +#include "components/input/native_web_keyboard_event.h" + #include namespace QtWebEngineCore { @@ -45,7 +47,7 @@ void DestroyEvent(gfx::NativeEvent nativeEvent) } // namespace -namespace content { +namespace input { NativeWebKeyboardEvent::NativeWebKeyboardEvent(const blink::WebKeyboardEvent &web_event, gfx::NativeView) : blink::WebKeyboardEvent(web_event) @@ -90,5 +92,5 @@ NativeWebKeyboardEvent::~NativeWebKeyboardEvent() { DestroyEvent(os_event); } -} // namespace content +} // namespace input #endif // !defined(Q_OS_MACOS) diff --git a/src/core/native_web_keyboard_event_qt.h b/src/core/native_web_keyboard_event_qt.h index 13179d07a82..7bcb65da92e 100644 --- a/src/core/native_web_keyboard_event_qt.h +++ b/src/core/native_web_keyboard_event_qt.h @@ -6,7 +6,8 @@ #include -#include "content/public/common/input/native_web_keyboard_event.h" +#include "ui/gfx/native_widget_types.h" +#include "components/input/native_web_keyboard_event.h" QT_FORWARD_DECLARE_CLASS(QKeyEvent) diff --git a/src/core/native_web_keyboard_event_qt_mac.mm b/src/core/native_web_keyboard_event_qt_mac.mm index 0f5b12db43d..b16ab2e2240 100644 --- a/src/core/native_web_keyboard_event_qt_mac.mm +++ b/src/core/native_web_keyboard_event_qt_mac.mm @@ -33,8 +33,7 @@ type = NSEventTypeKeyUp; break; default: - Q_UNREACHABLE(); - return base::apple::OwnedNSEvent(); + Q_UNREACHABLE_RETURN(base::apple::OwnedNSEvent()); } NSString *text = keyEvent->text().toNSString(); @@ -72,8 +71,7 @@ type = QEvent::KeyRelease; break; default: - Q_UNREACHABLE(); - return nullptr; + Q_UNREACHABLE_RETURN(nullptr); } // Scan codes are hardware dependent codes for each key. There is no way to get these @@ -103,7 +101,7 @@ key = QAppleKeyMapper::fromCocoaKey(character); } - QString text = QString::fromNSString(characters); + const QString text = QString::fromNSString(characters); bool autorep = nsevent.ARepeat; return new QKeyEvent(type, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, @@ -112,7 +110,7 @@ } // namespace QtWebEngineCore -namespace content { +namespace input { NativeWebKeyboardEvent::NativeWebKeyboardEvent(const blink::WebKeyboardEvent &web_event, gfx::NativeView) : blink::WebKeyboardEvent(web_event) @@ -152,4 +150,4 @@ NativeWebKeyboardEvent::~NativeWebKeyboardEvent() = default; -} // namespace content +} // namespace input diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp index 0de6885df85..5f9c8243af9 100644 --- a/src/core/net/client_cert_store_data.cpp +++ b/src/core/net/client_cert_store_data.cpp @@ -92,8 +92,8 @@ namespace QtWebEngineCore { void ClientCertificateStoreData::add(const QSslCertificate &certificate, const QSslKey &privateKey) { - QByteArray sslKeyInBytes = privateKey.toPem(); - QByteArray certInBytes = certificate.toDer(); + const QByteArray sslKeyInBytes = privateKey.toPem(); + const QByteArray certInBytes = certificate.toDer(); Entry *data = new Entry; data->keyPtr = wrapOpenSSLPrivateKey(sslKeyInBytes); diff --git a/src/core/net/cookie_monster_delegate_qt.cpp b/src/core/net/cookie_monster_delegate_qt.cpp index cdbf2e8e873..687a02955d9 100644 --- a/src/core/net/cookie_monster_delegate_qt.cpp +++ b/src/core/net/cookie_monster_delegate_qt.cpp @@ -50,7 +50,7 @@ class CookieAccessFilter : public network::mojom::CookieRemoteAccessFilter static GURL sourceUrlForCookie(const QNetworkCookie &cookie) { - QString urlFragment = QStringLiteral("%1%2").arg(cookie.domain()).arg(cookie.path()); + const QString urlFragment = cookie.domain() % cookie.path(); return net::cookie_util::CookieOriginToURL(urlFragment.toStdString(), /* is_https */ cookie.isSecure()); } @@ -98,7 +98,7 @@ void CookieMonsterDelegateQt::setCookie(const QNetworkCookie &cookie, const QUrl net::CookieInclusionStatus inclusion; auto canonCookie = net::CanonicalCookie::Create(gurl, cookie_line, base::Time::Now(), - std::nullopt, std::nullopt, true, + std::nullopt, std::nullopt, net::CookieSourceType::kOther, &inclusion); if (!canonCookie || !inclusion.IsInclude()) { LOG(WARNING) << "QWebEngineCookieStore::setCookie() - Tried to set invalid cookie"; diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp index edc103bceeb..eec3c5f7e1b 100644 --- a/src/core/net/custom_url_loader_factory.cpp +++ b/src/core/net/custom_url_loader_factory.cpp @@ -267,9 +267,8 @@ class CustomURLLoader : public network::mojom::URLLoader } } if (m_corsEnabled) { - std::string origin; - if (m_request.headers.GetHeader("Origin", &origin)) { - headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin.c_str()); + if (std::optional origin = m_request.headers.GetHeader("Origin")) { + headers += base::StringPrintf("Access-Control-Allow-Origin: %s\n", origin->c_str()); headers += "Access-Control-Allow-Credentials: true\n"; } } @@ -385,20 +384,21 @@ class CustomURLLoader : public network::mojom::URLLoader if (m_error || !m_device) break; - void *buffer = nullptr; - size_t bufferSize = 0; - MojoResult beginResult = m_pipeProducerHandle->BeginWriteData( - &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE); + base::span buffer; + MojoResult beginResult = + m_pipeProducerHandle->BeginWriteData( + 0, MOJO_BEGIN_WRITE_DATA_FLAG_NONE, buffer); if (beginResult == MOJO_RESULT_SHOULD_WAIT) { m_watcher->ArmOrNotify(); return false; // Wait for pipe watcher } if (beginResult != MOJO_RESULT_OK) break; + size_t bufferSize = buffer.size(); if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits::max()}) bufferSize = std::min(bufferSize, size_t(m_maxBytesToRead)); - int readResult = m_device->read(static_cast(buffer), bufferSize); + int readResult = m_device->read(reinterpret_cast(buffer.data()), bufferSize); uint32_t bytesRead = std::max(readResult, 0); m_pipeProducerHandle->EndWriteData(bytesRead); m_totalBytesRead += bytesRead; @@ -427,10 +427,9 @@ class CustomURLLoader : public network::mojom::URLLoader } bool ParseRange(const net::HttpRequestHeaders &headers) { - std::string range_header; - if (headers.GetHeader(net::HttpRequestHeaders::kRange, &range_header)) { + if (auto range_header = headers.GetHeader(net::HttpRequestHeaders::kRange)) { std::vector ranges; - if (net::HttpUtil::ParseRangeHeader(range_header, &ranges)) { + if (net::HttpUtil::ParseRangeHeader(*range_header, &ranges)) { // Chromium doesn't support multirange requests. if (ranges.size() == 1) { m_byteRange = ranges[0]; diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp index 3af8bf9e35f..bd2714dcb5b 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.cpp @@ -80,7 +80,7 @@ namespace QtWebEngineCore { PluginResponseInterceptorURLLoaderThrottle::PluginResponseInterceptorURLLoaderThrottle( network::mojom::RequestDestination request_destination, - int frame_tree_node_id) + content::FrameTreeNodeId frame_tree_node_id) : m_request_destination(request_destination), m_frame_tree_node_id(frame_tree_node_id) {} @@ -150,7 +150,8 @@ void PluginResponseInterceptorURLLoaderThrottle::WillProcessResponse(const GURL size_t len = payload.size(); CHECK_EQ(MOJO_RESULT_OK, producer_handle->WriteData( - payload.c_str(), &len, MOJO_WRITE_DATA_FLAG_ALL_OR_NONE)); + base::make_span(reinterpret_cast(payload.data()), len), + MOJO_WRITE_DATA_FLAG_ALL_OR_NONE, len)); network::URLLoaderCompletionStatus status(net::OK); status.decoded_body_length = len; diff --git a/src/core/net/plugin_response_interceptor_url_loader_throttle.h b/src/core/net/plugin_response_interceptor_url_loader_throttle.h index fb3918c45e3..dd47e2a4822 100644 --- a/src/core/net/plugin_response_interceptor_url_loader_throttle.h +++ b/src/core/net/plugin_response_interceptor_url_loader_throttle.h @@ -5,6 +5,7 @@ #define PLUGIN_RESPONSE_INTERCEPTOR_URL_LOADER_THROTTLE_H_ #include "base/memory/weak_ptr.h" +#include "content/public/browser/frame_tree_node_id.h" #include "services/network/public/mojom/fetch_api.mojom-shared.h" #include "third_party/blink/public/common/loader/url_loader_throttle.h" @@ -17,8 +18,9 @@ namespace QtWebEngineCore { class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrottle { public: - PluginResponseInterceptorURLLoaderThrottle(network::mojom::RequestDestination request_destination, - int frame_tree_node_id); + PluginResponseInterceptorURLLoaderThrottle( + network::mojom::RequestDestination request_destination, + content::FrameTreeNodeId frame_tree_node_id); ~PluginResponseInterceptorURLLoaderThrottle() override = default; private: @@ -30,7 +32,7 @@ class PluginResponseInterceptorURLLoaderThrottle : public blink::URLLoaderThrott void ResumeLoad(); const network::mojom::RequestDestination m_request_destination; - const int m_frame_tree_node_id; + const content::FrameTreeNodeId m_frame_tree_node_id; base::WeakPtrFactory weak_factory_{this}; diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.cpp b/src/core/net/proxying_restricted_cookie_manager_qt.cpp index 207ab2b466e..b07e239f2f1 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.cpp +++ b/src/core/net/proxying_restricted_cookie_manager_qt.cpp @@ -65,7 +65,8 @@ ProxyingRestrictedCookieManagerQt::~ProxyingRestrictedCookieManagerQt() void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url, const net::SiteForCookies &site_for_cookies, - const url::Origin &top_frame_origin, bool has_storage_access, + const url::Origin &top_frame_origin, + net::StorageAccessApiStatus storage_access_api_status, network::mojom::CookieManagerGetOptionsPtr options, bool is_ad_tagged, bool force_disable_third_party_cookies, @@ -74,7 +75,7 @@ void ProxyingRestrictedCookieManagerQt::GetAllForUrl(const GURL &url, DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, has_storage_access, + underlying_restricted_cookie_manager_->GetAllForUrl(url, site_for_cookies, top_frame_origin, storage_access_api_status, std::move(options), is_ad_tagged, force_disable_third_party_cookies, std::move(callback)); } else { std::move(callback).Run(std::vector()); @@ -85,7 +86,7 @@ void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalC const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, net::CookieInclusionStatus status, SetCanonicalCookieCallback callback) { @@ -93,7 +94,7 @@ void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalC if (allowCookies(url, site_for_cookies)) { underlying_restricted_cookie_manager_->SetCanonicalCookie(cookie, url, site_for_cookies, top_frame_origin, - has_storage_access, status, std::move(callback)); + storage_access_api_status, status, std::move(callback)); } else { std::move(callback).Run(false); } @@ -102,25 +103,26 @@ void ProxyingRestrictedCookieManagerQt::SetCanonicalCookie(const net::CanonicalC void ProxyingRestrictedCookieManagerQt::AddChangeListener(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, mojo::PendingRemote listener, AddChangeListenerCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); - underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, has_storage_access, + underlying_restricted_cookie_manager_->AddChangeListener(url, site_for_cookies, top_frame_origin, storage_access_api_status, std::move(listener), std::move(callback)); } void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url, const net::SiteForCookies &site_for_cookies, - const url::Origin &top_frame_origin, bool has_storage_access, + const url::Origin &top_frame_origin, + net::StorageAccessApiStatus storage_access_api_status, const std::string &cookie, SetCookieFromStringCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); if (allowCookies(url, site_for_cookies)) { - underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, has_storage_access, + underlying_restricted_cookie_manager_->SetCookieFromString(url, site_for_cookies, top_frame_origin, storage_access_api_status, cookie, std::move(callback)); } else { std::move(callback).Run(); @@ -130,7 +132,8 @@ void ProxyingRestrictedCookieManagerQt::SetCookieFromString(const GURL &url, void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, bool get_version_shared_memory, + net::StorageAccessApiStatus storage_access_api_status, + bool get_version_shared_memory, bool is_ad_tagged, bool force_disable_third_party_cookies, GetCookiesStringCallback callback) @@ -139,7 +142,7 @@ void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, if (allowCookies(url, site_for_cookies)) { underlying_restricted_cookie_manager_->GetCookiesString(url, site_for_cookies, top_frame_origin, - has_storage_access, get_version_shared_memory, + storage_access_api_status, get_version_shared_memory, is_ad_tagged, force_disable_third_party_cookies, std::move(callback)); } else { @@ -150,7 +153,7 @@ void ProxyingRestrictedCookieManagerQt::GetCookiesString(const GURL &url, void ProxyingRestrictedCookieManagerQt::CookiesEnabledFor(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin & /*top_frame_origin*/, - bool /*has_storage_access*/, + net::StorageAccessApiStatus /*storage_access_api_status*/, CookiesEnabledForCallback callback) { DCHECK_CURRENTLY_ON(content::BrowserThread::IO); diff --git a/src/core/net/proxying_restricted_cookie_manager_qt.h b/src/core/net/proxying_restricted_cookie_manager_qt.h index 403c235a787..658a09d5d6d 100644 --- a/src/core/net/proxying_restricted_cookie_manager_qt.h +++ b/src/core/net/proxying_restricted_cookie_manager_qt.h @@ -27,7 +27,7 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki void GetAllForUrl(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, network::mojom::CookieManagerGetOptionsPtr options, bool is_ad_tagged, bool force_disable_third_party_cookies, @@ -37,32 +37,33 @@ class ProxyingRestrictedCookieManagerQt : public network::mojom::RestrictedCooki const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, net::CookieInclusionStatus status, SetCanonicalCookieCallback callback) override; void AddChangeListener(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, mojo::PendingRemote listener, AddChangeListenerCallback callback) override; void SetCookieFromString(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, const std::string &cookie, SetCookieFromStringCallback callback) override; void GetCookiesString(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, bool get_version_shared_memory, + net::StorageAccessApiStatus storage_access_api_status, + bool get_version_shared_memory, bool is_ad_tagged, bool force_disable_third_party_cookies, GetCookiesStringCallback callback) override; void CookiesEnabledFor(const GURL &url, const net::SiteForCookies &site_for_cookies, const url::Origin &top_frame_origin, - bool has_storage_access, + net::StorageAccessApiStatus storage_access_api_status, CookiesEnabledForCallback callback) override; // Internal: diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp index a726bbce7d5..67b40f7dbcc 100644 --- a/src/core/net/proxying_url_loader_factory_qt.cpp +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -100,8 +100,9 @@ class InterceptedRequest : public network::mojom::URLLoader , public network::mojom::URLLoaderClient { public: - InterceptedRequest(ProfileAdapter *profile_adapter, int frame_tree_node_id, int32_t request_id, - uint32_t options, const network::ResourceRequest &request, + InterceptedRequest(ProfileAdapter *profile_adapter, content::FrameTreeNodeId frame_tree_node_id, + int32_t request_id, uint32_t options, + const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, mojo::PendingReceiver loader, mojo::PendingRemote client, @@ -150,7 +151,7 @@ class InterceptedRequest : public network::mojom::URLLoader QWebEngineUrlRequestInterceptor* getPageInterceptor(); QPointer profile_adapter_; - const int frame_tree_node_id_; + const content::FrameTreeNodeId frame_tree_node_id_; const int32_t request_id_; const uint32_t options_; bool allow_local_ = false; @@ -189,8 +190,8 @@ class InterceptedRequest : public network::mojom::URLLoader }; InterceptedRequest::InterceptedRequest( - ProfileAdapter *profile_adapter, int frame_tree_node_id, int32_t request_id, - uint32_t options, const network::ResourceRequest &request, + ProfileAdapter *profile_adapter, content::FrameTreeNodeId frame_tree_node_id, + int32_t request_id, uint32_t options, const network::ResourceRequest &request, const net::MutableNetworkTrafficAnnotationTag &traffic_annotation, mojo::PendingReceiver loader_receiver, mojo::PendingRemote client, @@ -243,7 +244,7 @@ InterceptedRequest::~InterceptedRequest() content::WebContents* InterceptedRequest::webContents() { - if (frame_tree_node_id_ == content::RenderFrameHost::kNoFrameTreeNodeId) + if (frame_tree_node_id_.is_null()) return nullptr; return content::WebContents::FromFrameTreeNodeId(frame_tree_node_id_); } @@ -551,7 +552,7 @@ void InterceptedRequest::SendErrorAndCompleteImmediately(int error_code) } ProxyingURLLoaderFactoryQt::ProxyingURLLoaderFactoryQt( - ProfileAdapter *adapter, int frame_tree_node_id, + ProfileAdapter *adapter, content::FrameTreeNodeId frame_tree_node_id, mojo::PendingReceiver loader_receiver, mojo::PendingRemote target_factory_info, content::ContentBrowserClient::URLLoaderFactoryType type) diff --git a/src/core/net/proxying_url_loader_factory_qt.h b/src/core/net/proxying_url_loader_factory_qt.h index 209450c9ab1..d7ffd48ea09 100644 --- a/src/core/net/proxying_url_loader_factory_qt.h +++ b/src/core/net/proxying_url_loader_factory_qt.h @@ -6,6 +6,7 @@ #include "base/memory/weak_ptr.h" #include "content/public/browser/content_browser_client.h" +#include "content/public/browser/frame_tree_node_id.h" #include "mojo/public/cpp/bindings/receiver_set.h" #include "net/traffic_annotation/network_traffic_annotation.h" #include "services/network/public/mojom/url_loader.mojom.h" @@ -29,7 +30,7 @@ class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory { public: ProxyingURLLoaderFactoryQt( - ProfileAdapter *adapter, int frameTreeNodeId, + ProfileAdapter *adapter, content::FrameTreeNodeId frameTreeNodeId, mojo::PendingReceiver loader_receiver, mojo::PendingRemote pending_target_factory_remote, content::ContentBrowserClient::URLLoaderFactoryType type); @@ -49,7 +50,7 @@ class ProxyingURLLoaderFactoryQt : public network::mojom::URLLoaderFactory void OnProxyBindingError(); QPointer m_profileAdapter; - int m_frameTreeNodeId; + content::FrameTreeNodeId m_frameTreeNodeId; mojo::ReceiverSet m_proxyReceivers; mojo::Remote m_targetFactory; base::WeakPtrFactory m_weakFactory; diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index a8b4e4388a2..876c7d2031f 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -12,19 +12,21 @@ #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) { - QByteArray requestMethod = job->requestMethod(); + const QByteArray requestMethod = job->requestMethod(); if (requestMethod != "GET") { job->fail(QWebEngineUrlRequestJob::RequestDenied); return; } - QUrl requestUrl = job->requestUrl(); - QString requestPath = requestUrl.path(); - auto file = std::make_unique(':' + requestPath, job); + const QUrl requestUrl = job->requestUrl(); + const QString requestPath = requestUrl.path(); + auto file = std::make_unique(u':' + requestPath, job); if (!file->exists() || file->size() == 0) { qWarning("QResource '%s' not found or is empty", qUtf8Printable(requestPath)); job->fail(QWebEngineUrlRequestJob::UrlNotFound); @@ -33,7 +35,7 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) QFileInfo fileInfo(*file); QMimeDatabase mimeDatabase; QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo); - if (mimeType.name() == QStringLiteral("application/x-extension-html")) + if (mimeType.name() == "application/x-extension-html"_L1) job->reply("text/html", file.release()); else job->reply(mimeType.name().toUtf8(), file.release()); diff --git a/src/core/net/resource_request_body_qt.cpp b/src/core/net/resource_request_body_qt.cpp index c0a00b0db0d..a82d01aae85 100644 --- a/src/core/net/resource_request_body_qt.cpp +++ b/src/core/net/resource_request_body_qt.cpp @@ -9,6 +9,8 @@ #include "services/network/public/mojom/url_request.mojom-shared.h" #include "mojo/public/cpp/bindings/remote.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { ResourceRequestBody::ResourceRequestBody(network::ResourceRequestBody *requestBody, QObject *parent) @@ -58,8 +60,8 @@ qint64 ResourceRequestBody::readData(char *data, qint64 maxSize) break; } case network::mojom::DataElementDataView::Tag::kChunkedDataPipe: { - setErrorString(QStringLiteral("Chunked data pipe is used in request body upload, which " - "is currently not supported")); + setErrorString(u"Chunked data pipe is used in request body upload, which " + "is currently not supported"_s); // Nothing should come before or after DataElementChunkedDataPipe return -1; } @@ -110,7 +112,14 @@ void ResourceRequestBody::readDataElementFile(const base::FilePath &filePath, co const std::size_t fileSize = std::min(file.size(), length) - realOffset; const std::size_t bytesToRead = std::min(fileSize, static_cast(maxSize)); - file.open(QFile::ReadOnly); + if (!file.open(QFile::ReadOnly)) { + m_dataElementsIdx++; + m_dataElementFileIdx = 0; + setErrorString(u"Error while reading from file, skipping remaining content of "_s + % file.fileName() % u": "_s % file.errorString()); + return; + } + file.seek(realOffset); std::memcpy(*data, file.read(bytesToRead).data(), bytesToRead); @@ -143,23 +152,25 @@ ResourceRequestBody::getConsumerHandleFromPipeGetter( void ResourceRequestBody::readDataElementPipe( const mojo::ScopedHandleBase &consumerHandle, - qint64 &bytesRead, const qint64 &maxSize, char **data) + qint64 &bytesRead, qint64 maxSize, char **data) { MojoResult result; do { size_t bytesToRead = 1; - result = consumerHandle->ReadData(*data, &bytesToRead, MOJO_READ_DATA_FLAG_NONE); + base::span buffer = base::make_span(reinterpret_cast(*data), reinterpret_cast(*data) + maxSize); + result = consumerHandle->ReadData(MOJO_READ_DATA_FLAG_NONE, buffer, bytesToRead); if (result == MOJO_RESULT_OK) { *data += bytesToRead; bytesRead += bytesToRead; + maxSize -= bytesToRead; } else if (result != MOJO_RESULT_SHOULD_WAIT && result != MOJO_RESULT_FAILED_PRECONDITION) { - setErrorString(QString::fromLatin1("Error while reading from data pipe, skipping" - "remaining content of data pipe. Mojo error code: ") + setErrorString("Error while reading from data pipe, skipping " + "remaining content of data pipe. Mojo error code: "_L1 + QString::number(result)); } } while ((result == MOJO_RESULT_SHOULD_WAIT || result == MOJO_RESULT_OK) - && bytesRead < maxSize); + && maxSize > 0); m_dataElementsIdx++; } diff --git a/src/core/net/resource_request_body_qt.h b/src/core/net/resource_request_body_qt.h index 43f95197e21..8c3be2bd806 100644 --- a/src/core/net/resource_request_body_qt.h +++ b/src/core/net/resource_request_body_qt.h @@ -59,7 +59,7 @@ class Q_WEBENGINECORE_EXPORT ResourceRequestBody : public QIODevice getConsumerHandleFromPipeGetter(mojo::Remote &pipeGetter); void readDataElementPipe(const mojo::ScopedHandleBase &consumerHandle, - qint64 &bytesRead, const qint64 &maxSize, char **data); + qint64 &bytesRead, qint64 maxSize, char **data); void pipeGetterOnReadComplete(int32_t status, uint64_t size); }; diff --git a/src/core/net/url_request_custom_job_proxy.cpp b/src/core/net/url_request_custom_job_proxy.cpp index cac50162ff5..4ec282f4243 100644 --- a/src/core/net/url_request_custom_job_proxy.cpp +++ b/src/core/net/url_request_custom_job_proxy.cpp @@ -55,7 +55,9 @@ void URLRequestCustomJobProxy::reply(std::string contentType, QIODevice *device, m_client->m_charset = qcontentType.mid(cidx + 8).trimmed().toStdString(); qcontentType = qcontentType.first(sidx); } else { - qWarning() << "QWebEngineUrlRequestJob::reply(): Unrecognized content-type format with ';'" << qcontentType; + qWarning("QWebEngineUrlRequestJob::reply(): Unrecognized content-type format with ';' " + "%s", + qcontentType.constData()); } } m_client->m_mimeType = qcontentType.trimmed().toStdString(); diff --git a/src/core/ozone/egl_helper.cpp b/src/core/ozone/egl_helper.cpp index 879e2fa4504..1ed679d2390 100644 --- a/src/core/ozone/egl_helper.cpp +++ b/src/core/ozone/egl_helper.cpp @@ -3,6 +3,7 @@ #include "egl_helper.h" #include "ozone_util_qt.h" +#include "web_engine_context.h" #include #include @@ -57,90 +58,14 @@ static const char *getEGLErrorString(uint32_t error) QT_BEGIN_NAMESPACE -class ScopedGLContext -{ -public: - ScopedGLContext(QOffscreenSurface *surface, EGLHelper::EGLFunctions *eglFun) - : m_context(new QOpenGLContext()), m_eglFun(eglFun) - { - if ((m_previousEGLContext = m_eglFun->eglGetCurrentContext())) { - m_previousEGLDrawSurface = m_eglFun->eglGetCurrentSurface(EGL_DRAW); - m_previousEGLReadSurface = m_eglFun->eglGetCurrentSurface(EGL_READ); - m_previousEGLDisplay = m_eglFun->eglGetCurrentDisplay(); - } - - if (!m_context->create()) { - qWarning("Failed to create OpenGL context."); - return; - } - - Q_ASSERT(surface->isValid()); - if (!m_context->makeCurrent(surface)) { - qWarning("Failed to make OpenGL context current."); - return; - } - } - - ~ScopedGLContext() - { - if (!m_textures.empty()) { - auto *glFun = m_context->functions(); - glFun->glDeleteTextures(m_textures.size(), m_textures.data()); - } - - if (m_previousEGLContext) { - // Make sure the scoped context is not current when restoring the previous - // EGL context otherwise the QOpenGLContext destructor resets the restored - // current context. - m_context->doneCurrent(); - - m_eglFun->eglMakeCurrent(m_previousEGLDisplay, m_previousEGLDrawSurface, - m_previousEGLReadSurface, m_previousEGLContext); - if (m_eglFun->eglGetError() != EGL_SUCCESS) - qWarning("Failed to restore EGL context."); - } - } - - bool isValid() const { return m_context->isValid() && (m_context->surface() != nullptr); } - - EGLContext eglContext() const - { - QNativeInterface::QEGLContext *nativeInterface = - m_context->nativeInterface(); - return nativeInterface->nativeContext(); - } - - uint createTexture(int width, int height) - { - auto *glFun = m_context->functions(); - - uint glTexture; - glFun->glGenTextures(1, &glTexture); - glFun->glBindTexture(GL_TEXTURE_2D, glTexture); - glFun->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, - NULL); - glFun->glBindTexture(GL_TEXTURE_2D, 0); - - m_textures.push_back(glTexture); - return glTexture; - } - -private: - QScopedPointer m_context; - EGLHelper::EGLFunctions *m_eglFun; - EGLContext m_previousEGLContext = nullptr; - EGLSurface m_previousEGLDrawSurface = nullptr; - EGLSurface m_previousEGLReadSurface = nullptr; - EGLDisplay m_previousEGLDisplay = nullptr; - std::vector m_textures; -}; - EGLHelper::EGLFunctions::EGLFunctions() { QOpenGLContext *context = OzoneUtilQt::getQOpenGLContext(); eglCreateImage = reinterpret_cast(context->getProcAddress("eglCreateImage")); + eglCreateDRMImageMESA = reinterpret_cast( + context->getProcAddress("eglCreateDRMImageMESA")); eglDestroyImage = reinterpret_cast(context->getProcAddress("eglDestroyImage")); eglExportDMABUFImageMESA = reinterpret_cast( @@ -190,23 +115,15 @@ EGLHelper::EGLHelper() Q_ASSERT(QThread::currentThread() == qApp->thread()); m_offscreenSurface->create(); - const char *displayExtensions = m_functions->eglQueryString(m_eglDisplay, EGL_EXTENSIONS); - m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import") - && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers") - && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export"); + m_isDmaBufSupported = QtWebEngineCore::WebEngineContext::isGbmSupported(); + // Check extensions. if (m_isDmaBufSupported) { - // FIXME: This disables GBM for nvidia. Remove this when nvidia fixes its GBM support. - // - // "Buffer allocation and submission to DRM KMS using gbm is not currently supported." - // See: https://download.nvidia.com/XFree86/Linux-x86_64/550.40.07/README/kms.html - // - // Chromium uses GBM to allocate scanout buffers. Scanout requires DRM KMS. If KMS is - // enabled, gbm_device and gbm_buffer are created without any issues but rendering to the - // buffer will malfunction. It is not known how to detect this problem before rendering - // so we just disable GBM for nvidia. - const char *displayVendor = m_functions->eglQueryString(m_eglDisplay, EGL_VENDOR); - m_isDmaBufSupported = !strstr(displayVendor, "NVIDIA"); + const char *displayExtensions = m_functions->eglQueryString(m_eglDisplay, EGL_EXTENSIONS); + m_isDmaBufSupported = strstr(displayExtensions, "EGL_EXT_image_dma_buf_import") + && strstr(displayExtensions, "EGL_EXT_image_dma_buf_import_modifiers") + && strstr(displayExtensions, "EGL_MESA_drm_image") + && strstr(displayExtensions, "EGL_MESA_image_dma_buf_export"); } // Try to create dma-buf. @@ -226,34 +143,34 @@ void EGLHelper::queryDmaBuf(const int width, const int height, int *fd, int *str if (!m_isDmaBufSupported) return; - ScopedGLContext context(m_offscreenSurface.get(), m_functions.get()); - if (!context.isValid()) - return; - - EGLContext eglContext = context.eglContext(); - if (!eglContext) { - qWarning("EGL: No EGLContext."); - return; - } - - uint64_t textureId = context.createTexture(width, height); - EGLImage eglImage = m_functions->eglCreateImage(m_eglDisplay, eglContext, EGL_GL_TEXTURE_2D, - (EGLClientBuffer)textureId, NULL); + // clang-format off + EGLint attribs[] = { + EGL_WIDTH, width, + EGL_HEIGHT, height, + EGL_DRM_BUFFER_FORMAT_MESA, EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, EGL_DRM_BUFFER_USE_SHARE_MESA, + EGL_NONE + }; + // clang-format on + + EGLImage eglImage = m_functions->eglCreateDRMImageMESA(m_eglDisplay, attribs); if (eglImage == EGL_NO_IMAGE) { - qWarning() << "EGL: Failed to create EGLImage:" << getLastEGLErrorString(); + qWarning("EGL: Failed to create EGLImage: %s", getLastEGLErrorString()); return; } int numPlanes = 0; if (!m_functions->eglExportDMABUFImageQueryMESA(m_eglDisplay, eglImage, nullptr, &numPlanes, - modifiers)) - qWarning() << "EGL: Failed to retrieve the pixel format of the buffer:" - << getLastEGLErrorString(); + modifiers)) { + qWarning("EGL: Failed to retrieve the pixel format of the buffer: %s", + getLastEGLErrorString()); + } Q_ASSERT(numPlanes == 1); - if (!m_functions->eglExportDMABUFImageMESA(m_eglDisplay, eglImage, fd, stride, offset)) - qWarning() << "EGL: Failed to retrieve the dma_buf file descriptor:" - << getLastEGLErrorString(); + if (!m_functions->eglExportDMABUFImageMESA(m_eglDisplay, eglImage, fd, stride, offset)) { + qWarning("EGL: Failed to retrieve the dma_buf file descriptor: %s", + getLastEGLErrorString()); + } m_functions->eglDestroyImage(m_eglDisplay, eglImage); } diff --git a/src/core/ozone/egl_helper.h b/src/core/ozone/egl_helper.h index a1a1aa0d667..7594e1f8469 100644 --- a/src/core/ozone/egl_helper.h +++ b/src/core/ozone/egl_helper.h @@ -11,6 +11,7 @@ #include #undef eglCreateImage +#undef eglCreateDRMImageMESA #undef eglDestroyImage #undef eglExportDMABUFImageMESA #undef eglExportDMABUFImageQueryMESA @@ -33,6 +34,7 @@ class EGLHelper EGLFunctions(); PFNEGLCREATEIMAGEPROC eglCreateImage; + PFNEGLCREATEDRMIMAGEMESAPROC eglCreateDRMImageMESA; PFNEGLDESTROYIMAGEPROC eglDestroyImage; PFNEGLEXPORTDMABUFIMAGEMESAPROC eglExportDMABUFImageMESA; PFNEGLEXPORTDMABUFIMAGEQUERYMESAPROC eglExportDMABUFImageQueryMESA; diff --git a/src/core/ozone/gl_helper.cpp b/src/core/ozone/gl_helper.cpp index 32236e9fea1..f5135e23480 100644 --- a/src/core/ozone/gl_helper.cpp +++ b/src/core/ozone/gl_helper.cpp @@ -8,6 +8,32 @@ QT_BEGIN_NAMESPACE +const char *getGLErrorString(uint32_t error) +{ + switch (error) { + case GL_INVALID_ENUM: + return "GL_INVALID_ENUM"; + case GL_INVALID_VALUE: + return "GL_INVALID_VALUE"; + case GL_INVALID_OPERATION: + return "GL_INVALID_OPERATION"; + case GL_STACK_OVERFLOW: + return "GL_STACK_OVERFLOW"; + case GL_STACK_UNDERFLOW: + return "GL_STACK_UNDERFLOW"; + case GL_OUT_OF_MEMORY: + return "GL_OUT_OF_MEMORY"; + case GL_INVALID_FRAMEBUFFER_OPERATION: + return "GL_INVALID_FRAMEBUFFER_OPERATION"; + case GL_CONTEXT_LOST: + return "GL_CONTEXT_LOST"; + case GL_NO_ERROR: + return "GL_NO_ERROR"; + default: + return "UNKNOWN"; + } +} + GLHelper::GLExtFunctions::GLExtFunctions() { QOpenGLContext *context = OzoneUtilQt::getQOpenGLContext(); @@ -20,8 +46,12 @@ GLHelper::GLExtFunctions::GLExtFunctions() context->getProcAddress("glEGLImageTargetTexture2DOES")); glImportMemoryFdEXT = reinterpret_cast( context->getProcAddress("glImportMemoryFdEXT")); - glTextureStorageMem2DEXT = reinterpret_cast( - context->getProcAddress("glTextureStorageMem2DEXT")); + glIsMemoryObjectEXT = reinterpret_cast( + context->getProcAddress("glIsMemoryObjectEXT")); + glMemoryObjectParameterivEXT = reinterpret_cast( + context->getProcAddress("glMemoryObjectParameterivEXT")); + glTexStorageMem2DEXT = reinterpret_cast( + context->getProcAddress("glTexStorageMem2DEXT")); } GLHelper *GLHelper::instance() diff --git a/src/core/ozone/gl_helper.h b/src/core/ozone/gl_helper.h index 050bf70316c..ae8639c84ee 100644 --- a/src/core/ozone/gl_helper.h +++ b/src/core/ozone/gl_helper.h @@ -19,6 +19,8 @@ QT_BEGIN_NAMESPACE +const char *getGLErrorString(uint32_t error); + class GLHelper { public: @@ -30,7 +32,9 @@ class GLHelper PFNGLDELETEMEMORYOBJECTSEXTPROC glDeleteMemoryObjectsEXT; PFNGLEGLIMAGETARGETTEXTURE2DOESPROC glEGLImageTargetTexture2DOES; PFNGLIMPORTMEMORYFDEXTPROC glImportMemoryFdEXT; - PFNGLTEXTURESTORAGEMEM2DEXTPROC glTextureStorageMem2DEXT; + PFNGLISMEMORYOBJECTEXTPROC glIsMemoryObjectEXT; + PFNGLMEMORYOBJECTPARAMETERIVEXTPROC glMemoryObjectParameterivEXT; + PFNGLTEXSTORAGEMEM2DEXTPROC glTexStorageMem2DEXT; }; static GLHelper *instance(); diff --git a/src/core/ozone/gl_ozone_angle_qt.cpp b/src/core/ozone/gl_ozone_angle_qt.cpp index b23f3c60fca..359d04a4545 100644 --- a/src/core/ozone/gl_ozone_angle_qt.cpp +++ b/src/core/ozone/gl_ozone_angle_qt.cpp @@ -1,6 +1,10 @@ -// Copyright (C) 2024 The Qt Company Ltd. +// Copyright (C) 2025 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only +// Copyright 2016 The Chromium Authors +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + #include "gl_ozone_angle_qt.h" #include "ui/base/ozone_buildflags.h" @@ -12,6 +16,8 @@ #if BUILDFLAG(IS_OZONE_X11) #include "ozone_util_qt.h" + +#include "ui/ozone/platform/x11/native_pixmap_egl_x11_binding.h" #endif extern "C" { @@ -20,6 +26,34 @@ extern __eglMustCastToProperFunctionPointerType EGL_GetProcAddress(const char *p } namespace ui { +namespace { +// Based on //ui/ozone/platform/x11/x11_surface_factory.cc +enum class NativePixmapSupportType { + // Importing native pixmaps not supported. + kNone, + + // Native pixmaps are imported directly into EGL using the + // EGL_EXT_image_dma_buf_import extension. + kDMABuf, + + // Native pixmaps are first imported as X11 pixmaps using DRI3 and then into + // EGL. + kX11Pixmap, +}; + +NativePixmapSupportType GetNativePixmapSupportType() +{ + if (gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import) + return NativePixmapSupportType::kDMABuf; + +#if BUILDFLAG(IS_OZONE_X11) + if (NativePixmapEGLX11Binding::CanImportNativeGLXPixmap()) + return NativePixmapSupportType::kX11Pixmap; +#endif + + return NativePixmapSupportType::kNone; +} +} // namespace bool GLOzoneANGLEQt::LoadGLES2Bindings(const gl::GLImplementationParts & /*implementation*/) { @@ -73,7 +107,16 @@ gl::EGLDisplayPlatform GLOzoneANGLEQt::GetNativeDisplay() bool GLOzoneANGLEQt::CanImportNativePixmap(gfx::BufferFormat format) { - return gl::GLSurfaceEGL::GetGLDisplayEGL()->ext->b_EGL_EXT_image_dma_buf_import; + switch (GetNativePixmapSupportType()) { + case NativePixmapSupportType::kDMABuf: + return NativePixmapEGLBinding::IsBufferFormatSupported(format); +#if BUILDFLAG(IS_OZONE_X11) + case NativePixmapSupportType::kX11Pixmap: + return NativePixmapEGLX11Binding::IsBufferFormatSupported(format); +#endif + default: + return false; + } } std::unique_ptr @@ -82,8 +125,19 @@ GLOzoneANGLEQt::ImportNativePixmap(scoped_refptr pixmap, gfx::Size plane_size, const gfx::ColorSpace &color_space, GLenum target, GLuint texture_id) { - return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space, - target, texture_id); + switch (GetNativePixmapSupportType()) { + case NativePixmapSupportType::kDMABuf: + return NativePixmapEGLBinding::Create(pixmap, plane_format, plane, plane_size, color_space, + target, texture_id); +#if BUILDFLAG(IS_OZONE_X11) + case NativePixmapSupportType::kX11Pixmap: + return NativePixmapEGLX11Binding::Create(pixmap, plane_format, plane_size, target, + texture_id); +#endif + default: + NOTREACHED(); + return nullptr; + } } } // namespace ui diff --git a/src/core/ozone/glx_helper.cpp b/src/core/ozone/glx_helper.cpp index 2581681c04c..35929b6a343 100644 --- a/src/core/ozone/glx_helper.cpp +++ b/src/core/ozone/glx_helper.cpp @@ -7,6 +7,9 @@ #include "glx_helper.h" #include "ozone_util_qt.h" +#include "web_engine_context.h" + +#include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" #include #include @@ -40,8 +43,17 @@ GLXHelper::GLXHelper() : m_functions(new GLXHelper::GLXFunctions()) m_display = x11Application->display(); m_connection = x11Application->connection(); + m_isDmaBufSupported = QtWebEngineCore::WebEngineContext::isGbmSupported() + && ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device(); +} + +GLXFBConfig GLXHelper::getFBConfig() +{ + if (m_configs) + return m_configs[0]; + // clang-format off - const int configAttribs[] = { + static const int configAttribs[] = { GLX_RED_SIZE, 8, GLX_GREEN_SIZE, 8, GLX_BLUE_SIZE, 8, @@ -56,10 +68,17 @@ GLXHelper::GLXHelper() : m_functions(new GLXHelper::GLXFunctions()) }; // clang-format on + if (Q_UNLIKELY(!m_isDmaBufSupported)) { + qWarning("GLX: Frame buffer configuration is not expected to be used without dma-buf " + "support."); + } + int numConfigs = 0; m_configs = glXChooseFBConfig(m_display, /* screen */ 0, configAttribs, &numConfigs); if (!m_configs || numConfigs < 1) qFatal("GLX: Failed to find frame buffer configuration."); + + return m_configs[0]; } GLXPixmap GLXHelper::importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t width, @@ -85,8 +104,8 @@ GLXPixmap GLXHelper::importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t height, stride, depth, bpp, dmaBufFd); xcb_generic_error_t *error = xcb_request_check(m_connection, cookie); if (error) { - qWarning() << "GLX: XCB_DRI3_PIXMAP_FROM_BUFFER failed with error code:" - << error->error_code; + qWarning("GLX: XCB_DRI3_PIXMAP_FROM_BUFFER failed with error code: 0x%x", + error->error_code); free(error); return 0; } @@ -94,4 +113,14 @@ GLXPixmap GLXHelper::importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t return pixmapId; } +void GLXHelper::freePixmap(uint32_t pixmapId) const +{ + xcb_void_cookie_t cookie = xcb_free_pixmap_checked(m_connection, pixmapId); + xcb_generic_error_t *error = xcb_request_check(m_connection, cookie); + if (error) { + qWarning("GLX: XCB_FREE_PIXMAP failed with error code: 0x%x", error->error_code); + free(error); + } +} + QT_END_NAMESPACE diff --git a/src/core/ozone/glx_helper.h b/src/core/ozone/glx_helper.h index bd61d253eb8..20bc7159cbe 100644 --- a/src/core/ozone/glx_helper.h +++ b/src/core/ozone/glx_helper.h @@ -7,6 +7,7 @@ #include #include +#include #undef glXBindTexImageEXT #undef glXReleaseTexImageEXT @@ -29,9 +30,11 @@ class GLXHelper Display *getXDisplay() const { return m_display; } GLXFunctions *functions() const { return m_functions.get(); } - GLXFBConfig getFBConfig() const { return m_configs[0]; } + GLXFBConfig getFBConfig(); GLXPixmap importBufferAsPixmap(int dmaBufFd, uint32_t size, uint16_t width, uint16_t height, uint16_t stride) const; + void freePixmap(uint32_t pixmapId) const; + bool isDmaBufSupported() const { return m_isDmaBufSupported; } private: GLXHelper(); @@ -40,6 +43,7 @@ class GLXHelper Display *m_display = nullptr; xcb_connection_t *m_connection = nullptr; GLXFBConfig *m_configs = nullptr; + bool m_isDmaBufSupported = false; }; QT_END_NAMESPACE diff --git a/src/core/ozone/surface_factory_qt.cpp b/src/core/ozone/surface_factory_qt.cpp index a6bc21de263..95af160a723 100644 --- a/src/core/ozone/surface_factory_qt.cpp +++ b/src/core/ozone/surface_factory_qt.cpp @@ -18,7 +18,8 @@ #include #include -#if QT_CONFIG(opengl) && BUILDFLAG(IS_OZONE_X11) +#if QT_CONFIG(opengl) && BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) +#include "ozone/glx_helper.h" #include "ui/gfx/linux/gpu_memory_buffer_support_x11.h" #endif @@ -57,7 +58,7 @@ ui::GLOzone *SurfaceFactoryQt::GetGLOzone(const gl::GLImplementationParts &imple return impl.second.get(); } - qFatal() << "GLOzone not found for" << gl::GetGLImplementationGLName(implementation); + qFatal("GLOzone not found for %s", gl::GetGLImplementationGLName(implementation)); return nullptr; } @@ -77,7 +78,7 @@ SurfaceFactoryQt::CreateVulkanImplementation(bool /*allow_protected_memory*/, bool SurfaceFactoryQt::CanCreateNativePixmapForFormat(gfx::BufferFormat format) { #if QT_CONFIG(opengl) -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) if (OzoneUtilQt::usingGLX()) return ui::GpuMemoryBufferSupportX11::GetInstance()->CanCreateNativePixmapForFormat(format); #endif @@ -116,7 +117,7 @@ scoped_refptr SurfaceFactoryQt::CreateNativePixmap( gfx::NativePixmapHandle handle; -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) if (OzoneUtilQt::usingGLX()) { auto gbmBuffer = ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBuffer(format, size, usage); @@ -182,7 +183,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( #if QT_CONFIG(opengl) gfx::NativePixmapHandle bufferHandle; -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) if (OzoneUtilQt::usingGLX()) { auto gbmBuffer = ui::GpuMemoryBufferSupportX11::GetInstance()->CreateBufferFromHandle( size, format, std::move(handle)); @@ -226,7 +227,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( eglFun->eglCreateImage(eglDisplay, EGL_NO_CONTEXT, EGL_LINUX_DMA_BUF_EXT, (EGLClientBuffer)NULL, attrs.data()); if (eglImage == EGL_NO_IMAGE_KHR) { - qFatal() << "Failed to import EGLImage:" << eglHelper->getLastEGLErrorString(); + qFatal("Failed to import EGLImage: %s", eglHelper->getLastEGLErrorString()); } Q_ASSERT(numPlanes <= 3); @@ -234,7 +235,7 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( int strides[3]; int offsets[3]; if (!eglFun->eglExportDMABUFImageMESA(eglDisplay, eglImage, fds, strides, offsets)) { - qFatal() << "Failed to export EGLImage:" << eglHelper->getLastEGLErrorString(); + qFatal("Failed to export EGLImage: %s", eglHelper->getLastEGLErrorString()); } bufferHandle.modifier = handle.modifier; @@ -267,10 +268,10 @@ SurfaceFactoryQt::CreateNativePixmapFromHandle( bool SurfaceFactoryQt::SupportsNativePixmaps() { #if QT_CONFIG(opengl) -#if BUILDFLAG(IS_OZONE_X11) +#if BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) if (OzoneUtilQt::usingGLX()) - return ui::GpuMemoryBufferSupportX11::GetInstance()->has_gbm_device(); -#endif // BUILDFLAG(IS_OZONE_X11) + return GLXHelper::instance()->isDmaBufSupported(); +#endif // BUILDFLAG(IS_OZONE_X11) && QT_CONFIG(xcb_glx_plugin) #if QT_CONFIG(egl) if (OzoneUtilQt::usingEGL()) diff --git a/src/core/permission_manager_qt.cpp b/src/core/permission_manager_qt.cpp index 31953fb6900..e57e12e3d0e 100644 --- a/src/core/permission_manager_qt.cpp +++ b/src/core/permission_manager_qt.cpp @@ -26,6 +26,8 @@ #include "web_contents_delegate_qt.h" #include "web_engine_settings.h" +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static QWebEnginePermission::PermissionType toQt(blink::PermissionType type) @@ -77,6 +79,9 @@ static QWebEnginePermission::PermissionType toQt(blink::PermissionType type) case blink::PermissionType::WEB_PRINTING: case blink::PermissionType::SPEAKER_SELECTION: case blink::PermissionType::KEYBOARD_LOCK: + case blink::PermissionType::AUTOMATIC_FULLSCREEN: + case blink::PermissionType::HAND_TRACKING: + case blink::PermissionType::WEB_APP_INSTALLATION: LOG(INFO) << "Unexpected unsupported Blink permission type: " << static_cast(type); break; } @@ -110,8 +115,7 @@ static blink::PermissionType toBlink(QWebEnginePermission::PermissionType permis return blink::PermissionType::NUM; } - Q_UNREACHABLE(); - return blink::PermissionType::NUM; + Q_UNREACHABLE_RETURN(blink::PermissionType::NUM); } static QWebEnginePermission::State toQt(blink::mojom::PermissionStatus state) @@ -162,8 +166,7 @@ std::string permissionTypeString(QWebEnginePermission::PermissionType permission case QWebEnginePermission::PermissionType::LocalFontsAccess: return "LocalFontsAccess"; default: - Q_UNREACHABLE(); - return nullptr; + Q_UNREACHABLE_RETURN(nullptr); } } @@ -195,14 +198,15 @@ PermissionManagerQt::PermissionManagerQt(ProfileAdapter *profileAdapter) factory.set_command_line_prefs(base::MakeRefCounted( base::CommandLine::ForCurrentProcess())); - QString userPrefStorePath = profileAdapter->dataPath(); + QString userPrefStorePath; + userPrefStorePath += profileAdapter->dataPath(); auto prefRegistry = base::MakeRefCounted(); auto policy = profileAdapter->persistentPermissionsPolicy(); if (!profileAdapter->isOffTheRecord() && policy == ProfileAdapter::PersistentPermissionsPolicy::StoreOnDisk && !userPrefStorePath.isEmpty() && profileAdapter->ensureDataPathExists()) { userPrefStorePath += QDir::separator(); - userPrefStorePath += QStringLiteral("permissions.json"); + userPrefStorePath += "permissions.json"_L1; factory.set_user_prefs(base::MakeRefCounted(toFilePath(userPrefStorePath))); } else { factory.set_user_prefs(new InMemoryPrefStore); @@ -275,9 +279,38 @@ void PermissionManagerQt::setPermission( } } - for (const auto &it : m_subscribers) { - if (it.second.origin == origin && it.second.type == permissionType) - it.second.callback.Run(blinkStatus); + // Notify subscribers + if (subscriptions()) { + std::vector callbacks; + callbacks.reserve(subscriptions()->size()); + for (content::PermissionController::SubscriptionsMap::iterator iter(subscriptions()); + !iter.IsAtEnd(); iter.Advance()) { + content::PermissionStatusSubscription *subscription = iter.GetCurrentValue(); + if (!subscription) + continue; + content::RenderFrameHost *targetRfh = content::RenderFrameHost::FromID( + subscription->render_process_id, subscription->render_frame_id); + + if (subscription->embedding_origin != gorigin) + continue; + if (subscription->permission != toBlink(permissionType)) + continue; + if ((!QWebEnginePermission::isPersistent(permissionType) || !m_persistence) + && targetRfh && targetRfh != rfh) + continue; + + // Behavior in callbacks may differ depending on the denial reason. Until we have + // a good reason to not do so, we just pass UNSPECIFIED to get the default behavior everywhere. + content::PermissionResult new_value(blinkStatus, content::PermissionStatusSource::UNSPECIFIED); + if (subscription->permission_result && subscription->permission_result->status == new_value.status) + continue; + subscription->permission_result = new_value; + + callbacks.push_back(base::BindOnce(subscription->callback, blinkStatus, + /*ignore_status_override=*/false)); + } + for (auto &callback : callbacks) + std::move(callback).Run(); } if (state == QWebEnginePermission::State::Ask) @@ -590,25 +623,6 @@ void PermissionManagerQt::ResetPermission( updater.Get().Remove(requesting_origin.spec()); } -content::PermissionControllerDelegate::SubscriptionId -PermissionManagerQt::SubscribeToPermissionStatusChange( - blink::PermissionType permission, content::RenderProcessHost * /*render_process_host*/, - content::RenderFrameHost * /* render_frame_host */, const GURL &requesting_origin, bool, - base::RepeatingCallback callback) -{ - auto subscriber_id = subscription_id_generator_.GenerateNextId(); - m_subscribers.insert( { subscriber_id, - Subscription { toQt(permission), toQt(requesting_origin), std::move(callback) } }); - return subscriber_id; -} - -void PermissionManagerQt::UnsubscribeFromPermissionStatusChange( - content::PermissionControllerDelegate::SubscriptionId subscription_id) -{ - if (!m_subscribers.erase(subscription_id)) - LOG(WARNING) << "PermissionManagerQt::UnsubscribePermissionStatusChange called on unknown subscription id" << subscription_id; -} - blink::mojom::PermissionStatus PermissionManagerQt::getTransientPermissionStatus(blink::PermissionType permission, const GURL& requesting_origin, content::GlobalRenderFrameHostToken token) diff --git a/src/core/permission_manager_qt.h b/src/core/permission_manager_qt.h index 9c0e2d77815..7468e9861c4 100644 --- a/src/core/permission_manager_qt.h +++ b/src/core/permission_manager_qt.h @@ -66,14 +66,6 @@ class PermissionManagerQt : public content::PermissionControllerDelegate const content::PermissionRequestDescription &request_description, base::OnceCallback &)> callback) override; - content::PermissionControllerDelegate::SubscriptionId SubscribeToPermissionStatusChange( - blink::PermissionType permission, content::RenderProcessHost *render_process_host, - content::RenderFrameHost *render_frame_host, const GURL &requesting_origin, bool, - const base::RepeatingCallback callback) override; - - void UnsubscribeFromPermissionStatusChange( - content::PermissionControllerDelegate::SubscriptionId subscription_id) override; - private: struct Request { int id; @@ -115,8 +107,6 @@ class PermissionManagerQt : public content::PermissionControllerDelegate std::vector m_permissionTypes; std::map>> m_transientPermissions; - std::map m_subscribers; - content::PermissionControllerDelegate::SubscriptionId::Generator subscription_id_generator_; int m_requestIdCount; int m_transientWriteCount; std::unique_ptr m_prefService; diff --git a/src/core/pref_service_adapter.cpp b/src/core/pref_service_adapter.cpp index 011aeb05c4f..0e11058395d 100644 --- a/src/core/pref_service_adapter.cpp +++ b/src/core/pref_service_adapter.cpp @@ -55,6 +55,8 @@ namespace { static const char kPrefMediaDeviceIDSalt[] = "qtwebengine.media_device_salt_id"; } +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) @@ -64,11 +66,12 @@ void PrefServiceAdapter::setup(const ProfileAdapter &profileAdapter) factory.set_command_line_prefs(base::MakeRefCounted( base::CommandLine::ForCurrentProcess())); - QString userPrefStorePath = profileAdapter.dataPath(); + QString userPrefStorePath; + userPrefStorePath += profileAdapter.dataPath(); if (!profileAdapter.isOffTheRecord() && !userPrefStorePath.isEmpty() && const_cast(&profileAdapter)->ensureDataPathExists()) { userPrefStorePath += QDir::separator(); - userPrefStorePath += QStringLiteral("user_prefs.json"); + userPrefStorePath += "user_prefs.json"_L1; factory.set_user_prefs(base::MakeRefCounted(toFilePath(userPrefStorePath))); } else { factory.set_user_prefs(new InMemoryPrefStore); @@ -205,7 +208,10 @@ QStringList PrefServiceAdapter::spellCheckLanguages() const void PrefServiceAdapter::setSpellCheckEnabled(bool enabled) { - if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, true).empty()) { + if (enabled == m_prefService->GetBoolean(spellcheck::prefs::kSpellCheckEnable)) + return; + + if (!WebEngineLibraryInfo::getPath(base::DIR_APP_DICTIONARIES, enabled).empty()) { m_prefService->SetBoolean(spellcheck::prefs::kSpellCheckEnable, enabled); m_prefService->SchedulePendingLossyWrites(); } diff --git a/src/core/printing/pdf_stream_delegate_qt.cpp b/src/core/printing/pdf_stream_delegate_qt.cpp index afb21e17d07..bb82c3302d1 100644 --- a/src/core/printing/pdf_stream_delegate_qt.cpp +++ b/src/core/printing/pdf_stream_delegate_qt.cpp @@ -98,7 +98,7 @@ PdfStreamDelegateQt::GetStreamInfo(content::RenderFrameHost* embedder_frame) return helper->TakeStreamInfo(); } -void PdfStreamDelegateQt::OnPdfEmbedderSandboxed(int) +void PdfStreamDelegateQt::OnPdfEmbedderSandboxed(content::FrameTreeNodeId) { NOTIMPLEMENTED(); } diff --git a/src/core/printing/pdf_stream_delegate_qt.h b/src/core/printing/pdf_stream_delegate_qt.h index 4999775d323..61ceed777d2 100644 --- a/src/core/printing/pdf_stream_delegate_qt.h +++ b/src/core/printing/pdf_stream_delegate_qt.h @@ -18,7 +18,7 @@ class PdfStreamDelegateQt : public pdf::PdfStreamDelegate // pdf::PdfStreamDelegate: std::optional MapToOriginalUrl(content::NavigationHandle &navigation_handle) override; std::optional GetStreamInfo(content::RenderFrameHost *embedder_frame) override; - void OnPdfEmbedderSandboxed(int) override; + void OnPdfEmbedderSandboxed(content::FrameTreeNodeId) override; bool ShouldAllowPdfFrameNavigation(content::NavigationHandle*) override; }; diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index a691bc2b64b..742862a53ef 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -27,12 +27,14 @@ #include "content/public/browser/render_frame_host.h" #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" -#include "content/public/browser/notification_service.h" -#include "content/public/browser/notification_types.h" #include "printing/metafile_skia.h" #include "printing/print_job_constants.h" #include "printing/printed_document.h" +#include + +using namespace std::string_literals; + namespace QtWebEngineCore { namespace { @@ -160,7 +162,7 @@ void PrintViewManagerBaseQt::NavigationStopped() std::u16string PrintViewManagerBaseQt::RenderSourceName() { - return toString16(QLatin1String("")); + return u""s; } void PrintViewManagerBaseQt::PrintDocument(scoped_refptr print_data, diff --git a/src/core/printing/print_view_manager_base_qt.h b/src/core/printing/print_view_manager_base_qt.h index d4b5bfe826b..f2d4149abd4 100644 --- a/src/core/printing/print_view_manager_base_qt.h +++ b/src/core/printing/print_view_manager_base_qt.h @@ -13,8 +13,6 @@ #include "components/prefs/pref_member.h" #include "components/printing/browser/print_manager.h" #include "components/printing/common/print.mojom-forward.h" -#include "content/public/browser/notification_observer.h" -#include "content/public/browser/notification_registrar.h" namespace base { class RefCountedBytes; @@ -130,7 +128,6 @@ class PrintViewManagerBaseQt : public printing::PrintManager void ReleasePrinterQuery(); private: - content::NotificationRegistrar m_registrar; scoped_refptr m_printJob; content::RenderFrameHost *m_printingRFH; bool m_didPrintingSucceed; diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index a2bafa741db..b0f1788fdd3 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -265,7 +265,8 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, FindPdfChildFrame(full_page_plugin ? full_page_plugin : rfh)) rfh = pdf_rfh; } else { - auto *ftn = content::FrameTreeNode::GloballyFindByID(static_cast(frameId)); + auto *ftn = content::FrameTreeNode::GloballyFindByID( + static_cast(frameId)); if (!ftn) return false; rfh = ftn->current_frame_host(); @@ -362,7 +363,8 @@ void PrintViewManagerQt::SetupScriptedPrintPreview(SetupScriptedPrintPreviewCall if (web_contents()->GetPrimaryMainFrame() == rfh) client->printRequested(); else - client->printRequestedByFrame(static_cast(rfh->GetFrameTreeNodeId())); + client->printRequestedByFrame( + static_cast(rfh->GetFrameTreeNodeId().GetUnsafeValue())); } void PrintViewManagerQt::ShowScriptedPrintPreview(bool /*source_is_modifiable*/) diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp index 8a7e491dca9..d3a00ad551e 100644 --- a/src/core/profile_adapter.cpp +++ b/src/core/profile_adapter.cpp @@ -41,13 +41,16 @@ #include #include +using namespace Qt::StringLiterals; + namespace { inline QString buildLocationFromStandardPath(const QString &standardPath, const QString &name) { - QString location = standardPath; + QString location; + location += standardPath; if (location.isEmpty()) - location = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); + location += QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); - location.append(QLatin1String("/QtWebEngine/") % name); + location += "/QtWebEngine/"_L1 % name; return location; } } @@ -270,9 +273,9 @@ QString ProfileAdapter::dataPath() const // a location to do so. QString name = m_name; if (m_offTheRecord) - name = QStringLiteral("OffTheRecord"); + name = u"OffTheRecord"_s; else if (m_name.isEmpty()) - name = QStringLiteral("UnknownProfile"); + name = u"UnknownProfile"_s; return buildLocationFromStandardPath(QStandardPaths::writableLocation(QStandardPaths::AppDataLocation), name); } @@ -322,9 +325,9 @@ QString ProfileAdapter::httpCachePath() const { if (m_offTheRecord) return QString(); - QString basePath = cachePath(); + const QString basePath = cachePath(); if (!basePath.isEmpty()) - return basePath % QLatin1String("/Cache"); + return basePath % "/Cache"_L1; return QString(); } @@ -537,7 +540,7 @@ void ProfileAdapter::removeUrlSchemeHandler(QWebEngineUrlSchemeHandler *handler) void ProfileAdapter::removeUrlScheme(const QByteArray &scheme) { - QByteArray canonicalScheme = scheme.toLower(); + const QByteArray canonicalScheme = scheme.toLower(); if (schemeType(canonicalScheme) == SchemeType::Protected) { qWarning("Cannot remove the URL scheme handler for an internal scheme: %s", scheme.constData()); return; @@ -549,7 +552,7 @@ void ProfileAdapter::removeUrlScheme(const QByteArray &scheme) void ProfileAdapter::installUrlSchemeHandler(const QByteArray &scheme, QWebEngineUrlSchemeHandler *handler) { Q_ASSERT(handler); - QByteArray canonicalScheme = scheme.toLower(); + const QByteArray canonicalScheme = scheme.toLower(); SchemeType type = schemeType(canonicalScheme); if (type == SchemeType::Protected) { @@ -608,12 +611,12 @@ QList ProfileAdapter::listPermissions(const QUrl &origin, QString ProfileAdapter::httpAcceptLanguageWithoutQualities() const { - const QStringList list = m_httpAcceptLanguage.split(QLatin1Char(',')); QString out; - for (const QString &str : list) { - if (!out.isEmpty()) - out.append(QLatin1Char(',')); - out.append(str.split(QLatin1Char(';')).first()); + auto sep = ""_L1; + for (auto lang : m_httpAcceptLanguage.tokenize(u',')) { + out += sep; + out += *lang.tokenize(u';').begin(); // tokenize() is never empty with KeepEmptyParts! + sep = ","_L1; } return out; } diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h index aaeefb5440a..cb83e82799b 100644 --- a/src/core/profile_adapter_client.h +++ b/src/core/profile_adapter_client.h @@ -103,7 +103,7 @@ class Q_WEBENGINECORE_EXPORT ProfileAdapterClient virtual ~ProfileAdapterClient() { } - virtual void downloadRequested(DownloadItemInfo &info) = 0; + virtual void downloadRequested(const DownloadItemInfo &info) = 0; virtual void downloadUpdated(const DownloadItemInfo &info) = 0; virtual void showNotification(QSharedPointer &) { } diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index dd448a66c90..d57af0b4023 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -62,7 +62,7 @@ void ProfileIODataQt::shutdownOnUIThread() bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this); if (!posted) { - qWarning() << "Could not delete ProfileIODataQt on io thread !"; + qWarning("Could not delete ProfileIODataQt on io thread !"); delete this; } } diff --git a/src/core/profile_qt.cpp b/src/core/profile_qt.cpp index a85685e81b6..04c58ac34e6 100644 --- a/src/core/profile_qt.cpp +++ b/src/core/profile_qt.cpp @@ -267,7 +267,8 @@ void ProfileQt::setupStoragePath() auto it = std::find(storagePaths.begin(), storagePaths.end(), thisStoragePath); if (it == storagePaths.end()) { if (storagePaths.size() >= (PATH_QT_END - PATH_QT_START)) { - qWarning() << "Number of profile paths exceeded " << PATH_QT_END - PATH_QT_START << ", storage may break"; + qWarning("Number of profile paths exceeded %ull, storage may break", + static_cast(PATH_QT_END - PATH_QT_START)); return; } diff --git a/src/core/render_view_context_menu_qt.cpp b/src/core/render_view_context_menu_qt.cpp index b7aabfd5b66..089b9202003 100644 --- a/src/core/render_view_context_menu_qt.cpp +++ b/src/core/render_view_context_menu_qt.cpp @@ -36,7 +36,7 @@ namespace QtWebEngineCore { QT_TRANSLATE_NOOP("RenderViewContextMenuQt", "Save page"), QT_TRANSLATE_NOOP("RenderViewContextMenuQt", "View page source") }; - return QCoreApplication::translate("RenderViewContextMenuQt", qUtf8Printable(names[menuItem])); + return QCoreApplication::translate("RenderViewContextMenuQt", names[menuItem]); } RenderViewContextMenuQt::RenderViewContextMenuQt(QWebEngineContextMenuRequest *request) diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index e17e5075c13..0808b664332 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -12,6 +12,8 @@ #include "web_contents_adapter_client.h" #include "web_event_factory.h" +#include "components/input/cursor_manager.h" +#include "components/input/render_widget_host_input_event_router.h" #include "components/viz/common/features.h" #include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" @@ -20,14 +22,12 @@ #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/frame_tree.h" #include "content/browser/renderer_host/frame_tree_node.h" -#include "content/browser/renderer_host/cursor_manager.h" #include "content/browser/renderer_host/render_frame_host_impl.h" #include "content/browser/renderer_host/render_view_host_delegate.h" #include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/render_widget_host_input_event_router.h" -#include "content/browser/renderer_host/ui_events_helper.h" #include "content/common/content_switches_internal.h" #include "content/common/cursors/webcursor.h" +#include "content/common/input/events_helper.h" #include "content/common/input/synthetic_gesture_target.h" #include "content/public/browser/web_contents.h" #include "third_party/skia/include/core/SkColor.h" @@ -96,7 +96,7 @@ static display::ScreenInfos screenInfosFromQtForUpdate(QScreen *currentScreen) { display::ScreenInfo screenInfo; const auto &screens = qApp->screens(); - if (screens.isEmpty()) { + if (!currentScreen || screens.isEmpty()) { screenInfo.device_scale_factor = qGuiApp->devicePixelRatio(); return display::ScreenInfos(screenInfo); } @@ -136,7 +136,7 @@ class FlingingCompositor : public ui::Compositor void BeginMainFrame(const viz::BeginFrameArgs &args) override { - if (args.type != viz::BeginFrameArgs::MISSED && !m_rwhv->is_currently_scrolling_viewport()) + if (args.type != viz::BeginFrameArgs::MISSED && !m_rwhv->GetViewRenderInputRouter()->is_currently_scrolling_viewport()) m_rwhv->host()->ProgressFlingIfNeeded(args.frame_time); ui::Compositor::BeginMainFrame(args); } @@ -176,7 +176,7 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget if (host()->delegate() && host()->delegate()->GetInputEventRouter()) host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this); - m_cursorManager.reset(new content::CursorManager(this)); + m_cursorManager.reset(new input::CursorManager(this)); m_touchSelectionControllerClient.reset(new TouchSelectionControllerClientQt(this)); resetTouchSelectionController(); @@ -460,12 +460,10 @@ bool RenderWidgetHostViewQt::updateCursorFromResource(ui::mojom::CursorType type hotY = 7; break; default: - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); } #else - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); #endif const gfx::ImageSkia *imageSkia = ui::ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resourceId); @@ -609,7 +607,7 @@ void RenderWidgetHostViewQt::DisplayCursor(const ui::Cursor &cursorInfo) m_delegate->updateCursor(QCursor(shape)); } -content::CursorManager *RenderWidgetHostViewQt::GetCursorManager() +input::CursorManager *RenderWidgetHostViewQt::GetCursorManager() { return m_cursorManager.get(); } @@ -638,7 +636,7 @@ void RenderWidgetHostViewQt::RenderProcessGone() } bool RenderWidgetHostViewQt::TransformPointToCoordSpaceForView(const gfx::PointF &point, - content::RenderWidgetHostViewInput *target_view, + input::RenderWidgetHostViewInput *target_view, gfx::PointF *transformed_point) { if (target_view == this) { @@ -763,9 +761,9 @@ void RenderWidgetHostViewQt::OnTextSelectionChanged(content::TextInputManager *t void RenderWidgetHostViewQt::OnGestureEvent(const ui::GestureEventData& gesture) { - if ((gesture.type() == ui::ET_GESTURE_PINCH_BEGIN - || gesture.type() == ui::ET_GESTURE_PINCH_UPDATE - || gesture.type() == ui::ET_GESTURE_PINCH_END) + if ((gesture.type() == ui::EventType::kGesturePinchBegin + || gesture.type() == ui::EventType::kGesturePinchUpdate + || gesture.type() == ui::EventType::kGesturePinchEnd) && !content::IsPinchToZoomEnabled()) { return; } @@ -845,7 +843,7 @@ void RenderWidgetHostViewQt::notifyHidden() m_delegatedFrameHost->DetachFromCompositor(); } -void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) +void RenderWidgetHostViewQt::ProcessAckedTouchEvent(const input::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) { const bool eventConsumed = (ack_result == blink::mojom::InputEventResultState::kConsumed); const bool isSetBlocking = content::InputEventResultStateIsSetBlocking(ack_result); @@ -925,6 +923,7 @@ void RenderWidgetHostViewQt::WheelEventAck(const blink::WebMouseWheelEvent &even } void RenderWidgetHostViewQt::GestureEventAck(const blink::WebGestureEvent &event, + blink::mojom::InputEventResultSource ack_source, blink::mojom::InputEventResultState ack_result) { ForwardTouchpadZoomEventIfNecessary(event, ack_result); diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 821e563d3ab..64c19acdbb2 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -8,7 +8,6 @@ #include "delegated_frame_host_client_qt.h" #include "render_widget_host_view_qt_delegate.h" -#include "base/memory/weak_ptr.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/host/host_frame_sink_client.h" @@ -39,7 +38,6 @@ class WebContentsAdapterClient; class RenderWidgetHostViewQt : public content::RenderWidgetHostViewBase , public ui::GestureProviderClient - , public base::SupportsWeakPtr , public content::TextInputManager::Observer , public content::RenderFrameMetadataProvider::Observer , public content::RenderWidgetHost::InputEventObserver @@ -79,7 +77,7 @@ class RenderWidgetHostViewQt void UnlockPointer() override; void UpdateCursor(const ui::Cursor&) override; void DisplayCursor(const ui::Cursor&) override; - content::CursorManager *GetCursorManager() override; + input::CursorManager *GetCursorManager() override; void SetIsLoading(bool) override; void ImeCancelComposition() override; void ImeCompositionRangeChanged(const gfx::Range &, @@ -87,7 +85,7 @@ class RenderWidgetHostViewQt const std::optional> &) override; void RenderProcessGone() override; bool TransformPointToCoordSpaceForView(const gfx::PointF &point, - content::RenderWidgetHostViewInput *target_view, + input::RenderWidgetHostViewInput *target_view, gfx::PointF *transformed_point) override; void Destroy() override; void UpdateTooltipUnderCursor(const std::u16string &tooltip_text) override; @@ -95,6 +93,7 @@ class RenderWidgetHostViewQt void WheelEventAck(const blink::WebMouseWheelEvent &event, blink::mojom::InputEventResultState ack_result) override; void GestureEventAck(const blink::WebGestureEvent &event, + blink::mojom::InputEventResultSource ack_source, blink::mojom::InputEventResultState ack_result) override; content::MouseWheelPhaseHandler *GetMouseWheelPhaseHandler() override; viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(const cc::RenderFrameMetadata &metadata) override; @@ -102,7 +101,7 @@ class RenderWidgetHostViewQt // Overridden from RenderWidgetHostViewBase: gfx::Rect GetBoundsInRootWindow() override; - void ProcessAckedTouchEvent(const content::TouchEventWithLatencyInfo &touch, + void ProcessAckedTouchEvent(const input::TouchEventWithLatencyInfo &touch, blink::mojom::InputEventResultState ack_result) override; viz::SurfaceId GetCurrentSurfaceId() const override; const viz::FrameSinkId &GetFrameSinkId() const override; @@ -194,7 +193,7 @@ class RenderWidgetHostViewQt scoped_refptr m_taskRunner; - std::unique_ptr m_cursorManager; + std::unique_ptr m_cursorManager; ui::FilteredGestureProvider m_gestureProvider; @@ -232,8 +231,6 @@ class RenderWidgetHostViewQt std::unique_ptr m_touchSelectionController; gfx::SelectionBound m_selectionStart; gfx::SelectionBound m_selectionEnd; - - base::WeakPtrFactory m_weakPtrFactory { this }; }; class WebContentsAccessibilityQt : public content::WebContentsAccessibility diff --git a/src/core/render_widget_host_view_qt_delegate_client.cpp b/src/core/render_widget_host_view_qt_delegate_client.cpp index 9bc69e9bfcf..43420beabf5 100644 --- a/src/core/render_widget_host_view_qt_delegate_client.cpp +++ b/src/core/render_widget_host_view_qt_delegate_client.cpp @@ -10,10 +10,11 @@ #include "web_contents_adapter_client.h" #include "web_event_factory.h" +#include "components/input/render_widget_host_input_event_router.h" #include "content/browser/renderer_host/render_view_host_impl.h" -#include "content/browser/renderer_host/render_widget_host_input_event_router.h" #include "ui/touch_selection/touch_selection_controller.h" +#include #include #include #include @@ -24,6 +25,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static inline int firstAvailableId(const QMap &map) @@ -76,12 +79,31 @@ class MotionEventQt : public ui::MotionEvent , flags(flagsFromModifiers(modifiers)) , index(index) { +#if !defined(QT_NO_DEBUG) || defined(QT_FORCE_ASSERTS) // index is only valid for POINTER_DOWN and POINTER_UP and should correspond to the point // causing it see blink_event_util.cc:ToWebTouchPointState for details - Q_ASSERT_X((action != Action::POINTER_DOWN && action != Action::POINTER_UP && index == -1) - || (action == Action::POINTER_DOWN && index >= 0 && touchPoint(index).state() == QEventPoint::Pressed) - || (action == Action::POINTER_UP && index >= 0 && touchPoint(index).state() == QEventPoint::Released), - "MotionEventQt", qPrintable(QString("action: %1, index: %2, state: %3").arg(int(action)).arg(index).arg(touchPoint(index).state()))); + if (action == Action::POINTER_DOWN || action == Action::POINTER_UP) { + const auto actionString = (action == Action::POINTER_DOWN ? "Action::POINTER_DOWN"_L1 + : "Action::POINTER_UP"_L1); + Q_ASSERT_X(index >= 0 && index < touchPoints.size(), "MotionEventQt", + qPrintable("Invalid index for "_L1 + actionString + ": "_L1 + + QString::number(index))); + + const QEventPoint::State state = touchPoint(index).state(); + QString stateString; + QDebug(&stateString) << state; + Q_ASSERT_X( + (action == Action::POINTER_DOWN && state == QEventPoint::Pressed) + || (action == Action::POINTER_UP && state == QEventPoint::Released), + "MotionEventQt", + qPrintable("Unexpected state for "_L1 + actionString + ": "_L1 + stateString)); + } else { + Q_ASSERT_X(index == -1, "MotionEventQt", + qPrintable("Unexpected index for action "_L1 + + QString::number(static_cast(action)) + ": "_L1 + + QString::number(index))); + } +#endif } uint32_t GetUniqueEventId() const override { return eventId; } @@ -486,10 +508,9 @@ void RenderWidgetHostViewQtDelegateClient::handleKeyEvent(QKeyEvent *event) if (!m_rwhv->GetFocusedWidget()) return; - content::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(event); + input::NativeWebKeyboardEvent webEvent = WebEventFactory::toWebKeyboardEvent(event); if (webEvent.GetType() == blink::WebInputEvent::Type::kRawKeyDown && !m_editCommand.empty()) { ui::LatencyInfo latency; - latency.set_source_event_type(ui::SourceEventType::KEY_PRESS); std::vector commands; commands.emplace_back(blink::mojom::EditCommand::New(m_editCommand, "")); m_editCommand.clear(); @@ -744,8 +765,8 @@ void RenderWidgetHostViewQtDelegateClient::handleInputMethodEvent(QInputMethodEv if (!m_rwhv->host()) return; - QString commitString = event->commitString(); - QString preeditString = event->preeditString(); + const QString commitString = event->commitString(); + const QString preeditString = event->preeditString(); int cursorPositionInPreeditString = -1; gfx::Range selectionRange = gfx::Range::InvalidRange(); diff --git a/src/core/render_widget_host_view_qt_delegate_item.cpp b/src/core/render_widget_host_view_qt_delegate_item.cpp index 6ece45f9bb2..0c38f0f7a02 100644 --- a/src/core/render_widget_host_view_qt_delegate_item.cpp +++ b/src/core/render_widget_host_view_qt_delegate_item.cpp @@ -14,6 +14,8 @@ #include #endif +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWidgetHostViewQtDelegateClient *client, bool isPopup) @@ -35,8 +37,8 @@ RenderWidgetHostViewQtDelegateItem::RenderWidgetHostViewQtDelegateItem(RenderWid RenderWidgetHostViewQtDelegateItem::~RenderWidgetHostViewQtDelegateItem() { - unbind(); // Compositor::Observer releaseTextureResources(); + unbind(); // Compositor::Observer if (m_widgetDelegate) { m_widgetDelegate->Unbind(); m_widgetDelegate->Destroy(); @@ -54,8 +56,8 @@ void RenderWidgetHostViewQtDelegateItem::initAsPopup(const QRect &screenRect) QRectF RenderWidgetHostViewQtDelegateItem::viewGeometry() const { // Transform the entire rect to find the correct top left corner. - const QPointF p1 = mapToGlobal(mapFromScene(QPointF(0, 0))); - const QPointF p2 = mapToGlobal(mapFromScene(QPointF(width(), height()))); + const QPointF p1 = mapToGlobal(mapFromItem(this, QPointF(0, 0))); + const QPointF p2 = mapToGlobal(mapFromItem(this, QPointF(width(), height()))); QRectF geometry = QRectF(p1, p2).normalized(); // But keep the size untransformed to behave like other QQuickItems. geometry.setSize(size()); @@ -368,6 +370,12 @@ QSGNode *RenderWidgetHostViewQtDelegateItem::updatePaintNode(QSGNode *oldNode, U if (!comp) return oldNode; + if (comp->type() == Compositor::Type::Native + && QGuiApplication::platformName() == "offscreen"_L1) { + comp->swapFrame(); + return oldNode; + } + QQuickWindow *win = QQuickItem::window(); QSGImageNode *node = nullptr; diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp index 5342cc63263..a88d407b4d7 100644 --- a/src/core/renderer/content_renderer_client_qt.cpp +++ b/src/core/renderer/content_renderer_client_qt.cpp @@ -311,7 +311,7 @@ void ContentRendererClientQt::GetNavigationErrorStringsInternal(content::RenderF resourceId = IDR_NET_ERROR_HTML; std::string extracted_string = ui::ResourceBundle::GetSharedInstance().LoadDataResourceString(resourceId); - const base::StringPiece template_html(extracted_string.data(), extracted_string.size()); + const std::string_view template_html(extracted_string.data(), extracted_string.size()); if (template_html.empty()) NOTREACHED() << "unable to load template. ID: " << resourceId; else // "t" is the id of the templates root node. @@ -494,13 +494,14 @@ void ContentRendererClientQt::InitSpellCheck() void ContentRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame, ui::PageTransition transition_type, - const blink::WebURL &url, + const blink::WebURL &upstream_url, + const blink::WebURL &target_url, const net::SiteForCookies &site_for_cookies, const url::Origin *initiator_origin, GURL *new_url) { #if BUILDFLAG(ENABLE_EXTENSIONS) - ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, url, site_for_cookies, + ExtensionsRendererClientQt::GetInstance()->WillSendRequest(frame, transition_type, target_url, site_for_cookies, initiator_origin, new_url); if (!new_url->is_empty()) return; diff --git a/src/core/renderer/content_renderer_client_qt.h b/src/core/renderer/content_renderer_client_qt.h index c93914f0842..36a2ffe0a4b 100644 --- a/src/core/renderer/content_renderer_client_qt.h +++ b/src/core/renderer/content_renderer_client_qt.h @@ -84,7 +84,8 @@ class ContentRendererClientQt void WillSendRequest(blink::WebLocalFrame *frame, ui::PageTransition transition_type, - const blink::WebURL &url, + const blink::WebURL &upstream_url, + const blink::WebURL &target_url, const net::SiteForCookies &site_for_cookies, const url::Origin *initiator_origin, GURL *new_url) override; diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp index 8b0c695d04b..f5be05cc477 100644 --- a/src/core/renderer/extensions/extensions_renderer_client_qt.cpp +++ b/src/core/renderer/extensions/extensions_renderer_client_qt.cpp @@ -69,49 +69,9 @@ ExtensionsRendererClientQt *ExtensionsRendererClientQt::GetInstance() return client.Pointer(); } -extensions::Dispatcher *ExtensionsRendererClientQt::GetDispatcher() +void ExtensionsRendererClientQt::FinishInitialization() { - return extension_dispatcher_.get(); -} - -void ExtensionsRendererClientQt::OnExtensionLoaded(const extensions::Extension &extension) -{ - resource_request_policy_->OnExtensionLoaded(extension); -} - -void ExtensionsRendererClientQt::OnExtensionUnloaded(const extensions::ExtensionId &extension_id) -{ - resource_request_policy_->OnExtensionUnloaded(extension_id); -} - -bool ExtensionsRendererClientQt::ExtensionAPIEnabledForServiceWorkerScript(const GURL &scope, const GURL &script_url) const -{ - if (!script_url.SchemeIs(extensions::kExtensionScheme)) - return false; - - const extensions::Extension* extension = - extensions::RendererExtensionRegistry::Get()->GetExtensionOrAppByURL(script_url); - - if (!extension || !extensions::BackgroundInfo::IsServiceWorkerBased(extension)) - return false; - - if (scope != extension->url()) - return false; - - const std::string& sw_script = extensions::BackgroundInfo::GetBackgroundServiceWorkerScript(extension); - - return extension->GetResourceURL(sw_script) == script_url; -} - -void ExtensionsRendererClientQt::RenderThreadStarted() -{ - content::RenderThread *thread = content::RenderThread::Get(); - if (!extension_dispatcher_) - extension_dispatcher_.reset(new extensions::Dispatcher(std::move(api_providers_))); - extension_dispatcher_->OnRenderThreadStarted(thread); - resource_request_policy_.reset(new extensions::ResourceRequestPolicyQt(extension_dispatcher_.get())); - - thread->AddObserver(extension_dispatcher_.get()); + resource_request_policy_.reset(new extensions::ResourceRequestPolicyQt(dispatcher())); } void ExtensionsRendererClientQt::WebViewCreated(blink::WebView *web_view, const url::Origin *outermost_origin) @@ -119,15 +79,6 @@ void ExtensionsRendererClientQt::WebViewCreated(blink::WebView *web_view, const new extensions::ExtensionWebViewHelper(web_view, outermost_origin); } -void ExtensionsRendererClientQt::RenderFrameCreated(content::RenderFrame *render_frame, - service_manager::BinderRegistry *registry) -{ - new extensions::ExtensionsRenderFrameObserver(render_frame, registry); - new extensions::ExtensionFrameHelper(render_frame, - extension_dispatcher_.get()); - extension_dispatcher_->OnRenderFrameCreated(render_frame); -} - bool ExtensionsRendererClientQt::OverrideCreatePlugin(content::RenderFrame *render_frame, const blink::WebPluginParams ¶ms) { @@ -154,17 +105,17 @@ void ExtensionsRendererClientQt::WillSendRequest(blink::WebLocalFrame *frame, void ExtensionsRendererClientQt::RunScriptsAtDocumentStart(content::RenderFrame *render_frame) { - extension_dispatcher_->RunScriptsAtDocumentStart(render_frame); + dispatcher()->RunScriptsAtDocumentStart(render_frame); } void ExtensionsRendererClientQt::RunScriptsAtDocumentEnd(content::RenderFrame *render_frame) { - extension_dispatcher_->RunScriptsAtDocumentEnd(render_frame); + dispatcher()->RunScriptsAtDocumentEnd(render_frame); } void ExtensionsRendererClientQt::RunScriptsAtDocumentIdle(content::RenderFrame *render_frame) { - extension_dispatcher_->RunScriptsAtDocumentIdle(render_frame); + dispatcher()->RunScriptsAtDocumentIdle(render_frame); } diff --git a/src/core/renderer/extensions/extensions_renderer_client_qt.h b/src/core/renderer/extensions/extensions_renderer_client_qt.h index 4b8d23b8d12..cfe4d56a60a 100644 --- a/src/core/renderer/extensions/extensions_renderer_client_qt.h +++ b/src/core/renderer/extensions/extensions_renderer_client_qt.h @@ -32,7 +32,6 @@ class Origin; } namespace extensions { -class Dispatcher; class ResourceRequestPolicyQt; } @@ -47,15 +46,11 @@ class ExtensionsRendererClientQt : public extensions::ExtensionsRendererClient // extensions::ExtensionsRendererClient implementation. bool IsIncognitoProcess() const override; int GetLowestIsolatedWorldId() const override; - extensions::Dispatcher *GetDispatcher() override; - void OnExtensionLoaded(const extensions::Extension &extension) override; - void OnExtensionUnloaded(const extensions::ExtensionId &extension_id) override; - void RenderThreadStarted() override; + void FinishInitialization() override; // Match ContentRendererClientQt's method names... void WebViewCreated(blink::WebView *web_view, const url::Origin *outermost_origin); - void RenderFrameCreated(content::RenderFrame *, service_manager::BinderRegistry *); bool OverrideCreatePlugin(content::RenderFrame *render_frame, const blink::WebPluginParams ¶ms); void WillSendRequest(blink::WebLocalFrame *frame, @@ -65,19 +60,13 @@ class ExtensionsRendererClientQt : public extensions::ExtensionsRendererClient const url::Origin *initiator_origin, GURL *new_url); - bool ExtensionAPIEnabledForServiceWorkerScript(const GURL &scope, const GURL &script_url) const override; - void RunScriptsAtDocumentStart(content::RenderFrame *render_frame); void RunScriptsAtDocumentEnd(content::RenderFrame *render_frame); void RunScriptsAtDocumentIdle(content::RenderFrame *render_frame); - extensions::Dispatcher *extension_dispatcher() - { return extension_dispatcher_.get(); } - static ExtensionsRendererClientQt *GetInstance(); private: - std::unique_ptr extension_dispatcher_; std::unique_ptr resource_request_policy_; }; diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp index 82579ea7d79..9ced854ffd4 100644 --- a/src/core/renderer/user_resource_controller.cpp +++ b/src/core/renderer/user_resource_controller.cpp @@ -124,11 +124,11 @@ class UserResourceController::RenderFrameObserverHelper // Helper class to create WeakPtrs so the AfterLoad tasks can be canceled and to // avoid running scripts more than once per injection point. -class UserResourceController::RenderFrameObserverHelper::Runner : public base::SupportsWeakPtr +class UserResourceController::RenderFrameObserverHelper::Runner { public: explicit Runner(blink::WebLocalFrame *frame, UserResourceController *controller) - : m_frame(frame), m_userResourceController(controller) + : m_frame(frame), m_userResourceController(controller), m_weakPtrFactory(this) { } @@ -140,11 +140,13 @@ class UserResourceController::RenderFrameObserverHelper::Runner : public base::S m_ran[p] = true; } } + base::WeakPtr AsWeakPtr() { return m_weakPtrFactory.GetWeakPtr(); } private: blink::WebLocalFrame *m_frame; std::bitset<3> m_ran; UserResourceController *m_userResourceController; + base::WeakPtrFactory m_weakPtrFactory; }; void UserResourceController::runScripts(QtWebEngineCore::UserScriptData::InjectionPoint p, diff --git a/src/core/renderer_host/web_channel_ipc_transport_host.cpp b/src/core/renderer_host/web_channel_ipc_transport_host.cpp index c1271702a73..0cc24014fa5 100644 --- a/src/core/renderer_host/web_channel_ipc_transport_host.cpp +++ b/src/core/renderer_host/web_channel_ipc_transport_host.cpp @@ -49,7 +49,7 @@ uint WebChannelIPCTransportHost::worldId() const void WebChannelIPCTransportHost::sendMessage(const QJsonObject &message) { QJsonDocument doc(message); - QByteArray json = doc.toJson(QJsonDocument::Compact); + const QByteArray json = doc.toJson(QJsonDocument::Compact); content::RenderFrameHost *frame = web_contents()->GetPrimaryMainFrame(); qCDebug(log).nospace() << "sending webchannel message to " << frame << ": " << doc; GetWebChannelIPCTransportRemote(frame)->DispatchWebChannelMessage( diff --git a/src/core/select_file_dialog_factory_qt.cpp b/src/core/select_file_dialog_factory_qt.cpp index 7035de77e28..8d0690628ae 100644 --- a/src/core/select_file_dialog_factory_qt.cpp +++ b/src/core/select_file_dialog_factory_qt.cpp @@ -65,7 +65,7 @@ class SelectFileDialogQt : public ui::SelectFileDialog void SelectFileImpl(Type type, const std::u16string &title, const base::FilePath &default_path, const FileTypeInfo *file_types, int file_type_index, const base::FilePath::StringType &default_extension, - gfx::NativeWindow owning_window, void *params, const GURL *) override; + gfx::NativeWindow owning_window, const GURL *) override; bool HasMultipleFileTypeChoicesImpl() override; @@ -106,20 +106,19 @@ void SelectFileDialogQt::SelectFileImpl(Type type, const std::u16string &title, const base::FilePath &default_path, const FileTypeInfo *file_types, int file_type_index, const base::FilePath::StringType &default_extension, - gfx::NativeWindow owning_window, void *params, const GURL *caller) + gfx::NativeWindow owning_window, const GURL *caller) { Q_UNUSED(title); Q_UNUSED(file_type_index); Q_UNUSED(default_extension); Q_UNUSED(owning_window); - Q_UNUSED(params); Q_UNUSED(caller); QStringList acceptedSuffixes; if (file_types) { for (const auto &typeExtensions : file_types->extensions) { for (const auto &extension : typeExtensions) - acceptedSuffixes.append("." + toQt(extension)); + acceptedSuffixes.append(u'.' + toQt(extension)); } } diff --git a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt index fcc11bdcb8c..4d36ca004fb 100644 --- a/src/core/tools/qwebengine_convert_dict/CMakeLists.txt +++ b/src/core/tools/qwebengine_convert_dict/CMakeLists.txt @@ -7,6 +7,7 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING) TARGET_DESCRIPTION "QtWebEngine Dictionary Conversion Tool" INSTALL_DIR ${INSTALL_LIBEXECDIR} TOOLS_TARGET WebEngineCore + DEFINES TOOLKIT_QT SOURCES main.cpp INCLUDE_DIRECTORIES ../../../3rdparty/chromium/third_party/abseil-cpp diff --git a/src/core/tools/qwebengine_convert_dict/main.cpp b/src/core/tools/qwebengine_convert_dict/main.cpp index ac5daab0b3c..3264e4c1395 100644 --- a/src/core/tools/qwebengine_convert_dict/main.cpp +++ b/src/core/tools/qwebengine_convert_dict/main.cpp @@ -32,6 +32,8 @@ #include #include +using namespace Qt::StringLiterals; + // see also src/core/type_conversion.h inline base::FilePath::StringType toFilePathString(const QString &str) { @@ -68,11 +70,11 @@ template QTextStream &operator<<(QTextStream &out, base::span span) { out << '['; - QString prefix; + QLatin1StringView prefix; for (const auto &element : span) { out << prefix; out << element; - prefix = QStringLiteral(","); + prefix = ","_L1; } out << ']'; return out; @@ -93,20 +95,20 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words, int affix_ids[hunspell::BDict::MAX_AFFIXES_PER_WORD]; - static const int buf_size = 128; - char buf[buf_size]; for (size_t i = 0; i < org_words.size(); i++) { - int affix_matches = iter.Advance(buf, buf_size, affix_ids); + auto buf_size = org_words[i].first.size() + 1; + std::string buf(buf_size, '\0'); + int affix_matches = iter.Advance(buf.data(), buf_size, affix_ids); if (affix_matches == 0) { out << "Found the end before we expected\n"; return false; } - if (org_words[i].first != buf) { + if (buf.back() != '\0' || buf.compare(0, buf_size - 1, org_words[i].first) != 0) { out << "Word does not match!\n" << " Index: " << i << "\n" << " Expected: " << QString::fromStdString(org_words[i].first) << "\n" - << " Actual: " << QString::fromUtf8(buf) << "\n"; + << " Actual: " << QString::fromStdString(buf) << "\n"; return false; } @@ -118,7 +120,7 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words, [](int a, int b) { return a == b; })) { out << "Affixes do not match!\n" << " Index: " << i << "\n" - << " Word: " << QString::fromUtf8(buf) << "\n" + << " Word: " << QString::fromStdString(buf) << "\n" << " Expected: " << expectedAffixes << "\n" << " Actual: " << actualAffixes << "\n"; return false; @@ -131,8 +133,8 @@ inline bool VerifyWords(const convert_dict::DicReader::WordList& org_words, #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) QString frameworkIcuDataPath() { - return QLibraryInfo::location(QLibraryInfo::LibrariesPath) + - QStringLiteral("/QtWebEngineCore.framework/Resources/"); + return QLibraryInfo::location(QLibraryInfo::LibrariesPath) + + "/QtWebEngineCore.framework/Resources/"_L1; } #endif @@ -155,15 +157,14 @@ int main(int argc, char *argv[]) } #if defined(USE_ICU_FILE) bool icuDataDirFound = false; - QString icuDataDir = QLibraryInfo::path(QLibraryInfo::DataPath) - % QLatin1String("/resources"); + QString icuDataDir = QLibraryInfo::path(QLibraryInfo::DataPath) % "/resources"_L1; // Try to look up the path to the ICU data directory via an environment variable // (e.g. for the case when the tool is ran during build phase, and regular installed // ICU data file is not available). const QString icuPossibleEnvDataDir = qEnvironmentVariable("QT_WEBENGINE_ICU_DATA_DIR"); const QString appPath = QCoreApplication::applicationDirPath(); - QLatin1String icuDataFilePath("/icudtl.dat"); + const auto icuDataFilePath = "/icudtl.dat"_L1; if (!icuPossibleEnvDataDir.isEmpty() && QFileInfo::exists(icuPossibleEnvDataDir)) { icuDataDir = icuPossibleEnvDataDir; icuDataDirFound = true; diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index 27143093b77..ba6414fe68a 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -23,8 +23,6 @@ QImage toQImage(const SkBitmap &bitmap) QImage image; switch (bitmap.colorType()) { case kUnknown_SkColorType: - case kRGBA_F16_SkColorType: - case kRGBA_F32_SkColorType: case kRGBA_F16Norm_SkColorType: case kR8G8_unorm_SkColorType: case kA16_float_SkColorType: @@ -138,6 +136,37 @@ QImage toQImage(const SkBitmap &bitmap) break; } break; + case kRGBA_F16_SkColorType: + case kRGB_F16F16F16x_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA16FPx4); + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBX16FPx4); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA16FPx4_Premultiplied); + break; + } + break; + case kRGBA_F32_SkColorType: + switch (bitmap.alphaType()) { + case kUnknown_SkAlphaType: + break; + case kUnpremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA32FPx4); + break; + case kOpaque_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBX32FPx4); + break; + case kPremul_SkAlphaType: + image = toQImage(bitmap, QImage::Format_RGBA32FPx4_Premultiplied); + break; + } + break; } return image; } diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index edaeb7a88b1..1a21351cee2 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -26,6 +26,8 @@ #include "url/gurl.h" #include "url/origin.h" +#include + QT_FORWARD_DECLARE_CLASS(QSslCertificate) namespace gfx { @@ -58,7 +60,7 @@ inline QString toQt(const std::optional &string) return QString::fromStdU16String(*string); } -inline QString toQString(const base::StringPiece &string) +inline QString toQString(const std::string_view &string) { return QString::fromUtf8(string.data(), string.size()); } @@ -68,7 +70,7 @@ inline QString toQString(const std::string &string) return QString::fromStdString(string); } -inline QByteArray toQByteArray(const base::StringPiece &string) +inline QByteArray toQByteArray(const std::string_view &string) { return QByteArray(string.data(), string.size()); } diff --git a/src/core/user_script.cpp b/src/core/user_script.cpp index c33fb908178..92030ed1db2 100644 --- a/src/core/user_script.cpp +++ b/src/core/user_script.cpp @@ -10,11 +10,11 @@ namespace { // Helper function to parse Greasemonkey headers -bool GetDeclarationValue(const base::StringPiece& line, - const base::StringPiece& prefix, +bool GetDeclarationValue(std::string_view line, + std::string_view prefix, std::string* value) { - base::StringPiece::size_type index = line.find(prefix); - if (index == base::StringPiece::npos) + std::string_view::size_type index = line.find(prefix); + if (index == std::string_view::npos) return false; std::string temp(line.data() + index + prefix.length(), @@ -62,7 +62,7 @@ QString UserScript::name() const void UserScript::setName(const QString &name) { m_name = name; - m_scriptData.url = GURL(QStringLiteral("userScript:%1").arg(name).toStdString()); + m_scriptData.url = GURL("userScript:" + name.toStdString()); } QString UserScript::sourceCode() const @@ -138,24 +138,24 @@ void UserScript::parseMetadataHeader() // Logic taken from Chromium (extensions/browser/user_script_loader.cc) // http://wiki.greasespot.net/Metadata_block const std::string &script_text = m_scriptData.source; - base::StringPiece line; + std::string_view line; size_t line_start = 0; size_t line_end = line_start; bool in_metadata = false; - static const base::StringPiece kUserScriptBegin("// ==UserScript=="); - static const base::StringPiece kUserScriptEnd("// ==/UserScript=="); - static const base::StringPiece kNameDeclaration("// @name"); - static const base::StringPiece kIncludeDeclaration("// @include"); - static const base::StringPiece kExcludeDeclaration("// @exclude"); - static const base::StringPiece kMatchDeclaration("// @match"); - static const base::StringPiece kRunAtDeclaration("// @run-at"); - static const base::StringPiece kRunAtDocumentStartValue("document-start"); - static const base::StringPiece kRunAtDocumentEndValue("document-end"); - static const base::StringPiece kRunAtDocumentIdleValue("document-idle"); + static const std::string_view kUserScriptBegin("// ==UserScript=="); + static const std::string_view kUserScriptEnd("// ==/UserScript=="); + static const std::string_view kNameDeclaration("// @name"); + static const std::string_view kIncludeDeclaration("// @include"); + static const std::string_view kExcludeDeclaration("// @exclude"); + static const std::string_view kMatchDeclaration("// @match"); + static const std::string_view kRunAtDeclaration("// @run-at"); + static const std::string_view kRunAtDocumentStartValue("document-start"); + static const std::string_view kRunAtDocumentEndValue("document-end"); + static const std::string_view kRunAtDocumentIdleValue("document-idle"); // FIXME: Scripts don't run in subframes by default. If we would like to // support @noframes rule, we have to change the current default behavior. - // static const base::StringPiece kNoFramesDeclaration("// @noframes"); + // static const std::string_view kNoFramesDeclaration("// @noframes"); while (line_start < script_text.length()) { line_end = script_text.find('\n', line_start); @@ -164,7 +164,7 @@ void UserScript::parseMetadataHeader() if (line_end == std::string::npos) line_end = script_text.length() - 1; - line = base::StringPiece(script_text.data() + line_start, line_end - line_start); + line = std::string_view(script_text.data() + line_start, line_end - line_start); if (!in_metadata) { if (base::StartsWith(line, kUserScriptBegin)) diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 42882fbe441..67f9362d1a9 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -76,7 +76,7 @@ #if QT_CONFIG(accessibility) #include "browser_accessibility_qt.h" -#include "content/browser/accessibility/browser_accessibility_manager.h" +#include "ui/accessibility/platform/browser_accessibility_manager.h" #include #endif @@ -93,6 +93,8 @@ #include "extensions/extension_web_contents_observer_qt.h" #endif +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { #define CHECK_INITIALIZED(return_value) \ @@ -659,13 +661,13 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) Q_UNUSED(guard); // Add URL scheme if missing from view-source URL. - if (request.url().scheme() == content::kViewSourceScheme) { + if (request.url().scheme() == QLatin1StringView(content::kViewSourceScheme)) { QUrl pageUrl = QUrl(request.url().toString().remove(0, strlen(content::kViewSourceScheme) + 1)); if (pageUrl.scheme().isEmpty()) { QUrl extendedUrl = QUrl::fromUserInput(pageUrl.toString()); - extendedUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, - extendedUrl.toString())); + extendedUrl = QUrl(QLatin1StringView(content::kViewSourceScheme) + u':' + + extendedUrl.toString()); gurl = toGurl(http://github.com/extendedUrl); } } @@ -733,7 +735,7 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT WebEngineSettings::get(m_adapterClient->webEngineSettings())->doApply(); - QByteArray encodedData = data.toPercentEncoding(); + const QByteArray encodedData = data.toPercentEncoding(); std::string urlString; if (!mimeType.isEmpty()) urlString = std::string("data:") + mimeType.toStdString() + std::string(","); @@ -750,7 +752,8 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT content::NavigationController::LoadURLParams params((dataUrlToLoad)); params.load_type = content::NavigationController::LOAD_TYPE_DATA; params.base_url_for_data_url = toGurl(http://github.com/baseUrl); - params.virtual_url_for_data_url = baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(http://github.com/baseUrl); + params.virtual_url_for_special_cases = + baseUrl.isEmpty() ? GURL(url::kAboutBlankURL) : toGurl(http://github.com/baseUrl); params.can_load_local_resources = true; params.transition_type = ui::PageTransitionFromInt(ui::PAGE_TRANSITION_TYPED | ui::PAGE_TRANSITION_FROM_API); params.override_user_agent = content::NavigationController::UA_OVERRIDE_TRUE; @@ -980,10 +983,10 @@ void WebContentsAdapter::serializeNavigationHistory(QDataStream &output) void WebContentsAdapter::setZoomFactor(qreal factor) { CHECK_INITIALIZED(); - if (factor < blink::kMinimumPageZoomFactor || factor > blink::kMaximumPageZoomFactor) + if (factor < blink::kMinimumBrowserZoomFactor || factor > blink::kMaximumBrowserZoomFactor) return; - double zoomLevel = blink::PageZoomFactorToZoomLevel(static_cast(factor)); + double zoomLevel = blink::ZoomFactorToZoomLevel(static_cast(factor)); content::HostZoomMap *zoomMap = content::HostZoomMap::GetForWebContents(m_webContents.get()); if (zoomMap) { @@ -998,7 +1001,7 @@ void WebContentsAdapter::setZoomFactor(qreal factor) qreal WebContentsAdapter::currentZoomFactor() const { CHECK_INITIALIZED(1); - return blink::PageZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get())); + return blink::ZoomLevelToZoomFactor(content::HostZoomMap::GetZoomLevel(m_webContents.get())); } ProfileQt* WebContentsAdapter::profile() @@ -1030,12 +1033,12 @@ QAccessibleInterface *WebContentsAdapter::browserAccessible() content::RenderFrameHostImpl *rfh = static_cast(m_webContents->GetPrimaryMainFrame()); if (!rfh) return nullptr; - content::BrowserAccessibilityManager *manager = rfh->GetOrCreateBrowserAccessibilityManager(); + ui::BrowserAccessibilityManager *manager = rfh->GetOrCreateBrowserAccessibilityManager(); if (!manager) // FIXME! return nullptr; - content::BrowserAccessibility *acc = manager->GetFromAXNode(manager->GetRoot()); + ui::BrowserAccessibility *acc = manager->GetFromAXNode(manager->GetRoot()); - return content::toQAccessibleInterface(acc); + return ui::toQAccessibleInterface(acc); } #endif // QT_CONFIG(accessibility) @@ -1045,7 +1048,8 @@ content::RenderFrameHost *WebContentsAdapter::renderFrameHostFromFrameId(quint64 if (frameId == kUseMainFrameId) { result = m_webContents->GetPrimaryMainFrame(); } else { - auto *ftn = content::FrameTreeNode::GloballyFindByID(static_cast(frameId)); + auto *ftn = content::FrameTreeNode::GloballyFindByID( + static_cast(frameId)); if (!ftn) return nullptr; @@ -1069,7 +1073,7 @@ void WebContentsAdapter::runJavaScript(const QString &javaScript, quint32 worldI if (!rfh) return exit(); if (!static_cast(rfh)->GetAssociatedLocalFrame()) { - qWarning() << "Local frame is gone, not running script"; + qWarning("Local frame is gone, not running script"); return exit(); } @@ -1620,7 +1624,9 @@ static QMimeData *mimeDataFromDropData(const content::DropData &dropData) if (!dropData.custom_data.empty()) { base::Pickle pickle; ui::WriteCustomDataToPickle(dropData.custom_data, &pickle); - mimeData->setData(QLatin1String(ui::kMimeTypeWebCustomData), QByteArray((const char*)pickle.data(), pickle.size())); + mimeData->setData(QString::fromStdString( + ui::ClipboardFormatType::DataTransferCustomType().Serialize()), + QByteArray((const char*)pickle.data(), pickle.size())); } return mimeData; } @@ -1750,8 +1756,10 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat dropData->html = toOptionalString16(mimeData->html()); if (mimeData->hasText()) dropData->text = toOptionalString16(mimeData->text()); - if (mimeData->hasFormat(QLatin1String(ui::kMimeTypeWebCustomData))) { - const QByteArray customData = mimeData->data(QLatin1String(ui::kMimeTypeWebCustomData)); + const QString serializedDataTransferCustomType = + QString::fromStdString(ui::ClipboardFormatType::DataTransferCustomType().Serialize()); + if (mimeData->hasFormat(serializedDataTransferCustomType)) { + const QByteArray customData = mimeData->data(serializedDataTransferCustomType); const base::span custom_data(customData.constData(), (long unsigned)customData.length()); if (auto maybe_data = ui::ReadCustomDataIntoMap(base::as_bytes(custom_data))) dropData->custom_data = *std::move(maybe_data); @@ -1942,17 +1950,18 @@ void WebContentsAdapter::changeTextDirection(bool leftToRight) quint64 WebContentsAdapter::mainFrameId() const { - CHECK_INITIALIZED(content::RenderFrameHost::kNoFrameTreeNodeId); - return static_cast(m_webContents->GetPrimaryMainFrame()->GetFrameTreeNodeId()); + CHECK_INITIALIZED(-1); // content::RenderFrameHost::kNoFrameTreeNodeId); + return static_cast( + m_webContents->GetPrimaryMainFrame()->GetFrameTreeNodeId().GetUnsafeValue()); } #define CHECK_INITIALIZED_AND_VALID_FRAME(webengine_frame_id_variable, frame_tree_node_variable, \ return_value) \ CHECK_INITIALIZED(return_value); \ - if (webengine_frame_id_variable == kInvalidFrameId) \ + if (webengine_frame_id_variable == -1) /* kInvalidFrameId)*/ \ return return_value; \ auto *frame_tree_node_variable = content::FrameTreeNode::GloballyFindByID( \ - static_cast(webengine_frame_id_variable)); \ + static_cast(webengine_frame_id_variable)); \ if (!frame_tree_node_variable) \ return return_value @@ -1966,7 +1975,7 @@ QString WebContentsAdapter::frameHtmlName(quint64 id) const { CHECK_INITIALIZED_AND_VALID_FRAME(id, ftn, QString()); auto &maybeName = ftn->html_name(); - return maybeName ? QString::fromStdString(*maybeName) : QString(""); + return maybeName ? QString::fromStdString(*maybeName) : ""_L1; } QList WebContentsAdapter::frameChildren(quint64 id) const @@ -1976,7 +1985,7 @@ QList WebContentsAdapter::frameChildren(quint64 id) const size_t numChildren = ftn->child_count(); result.reserve(numChildren); for (size_t i = 0; i < numChildren; ++i) { - result.push_back(ftn->child_at(i)->frame_tree_node_id()); + result.push_back(ftn->child_at(i)->frame_tree_node_id().GetUnsafeValue()); } return result; } @@ -2002,7 +2011,7 @@ std::optional WebContentsAdapter::findFrameIdByName(const QString &name auto *ftn = content::FrameTreeNode::From(m_webContents->GetPrimaryMainFrame()); Q_ASSERT(ftn); if (auto *foundFtn = ftn->frame_tree().FindByName(name.toStdString())) - return foundFtn->frame_tree_node_id(); + return foundFtn->frame_tree_node_id().GetUnsafeValue(); return {}; } @@ -2228,7 +2237,7 @@ void WebContentsAdapter::discard() if (m_webContents->IsLoading()) { m_webContentsDelegate->didFailLoad(m_webContentsDelegate->url(http://github.com/webContents()), net::Error::ERR_ABORTED, - QStringLiteral("Discarded")); + u"Discarded"_s); m_webContentsDelegate->DidStopLoading(); } diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index 33a90fcea06..92b1eb415db 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -57,6 +57,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(blink::mojom::ConsoleMessageLevel log_level) @@ -200,7 +202,8 @@ QUrl WebContentsDelegateQt::url(/service/content::WebContents *source) const if (source->GetVisibleURL().SchemeIs(content::kViewSourceScheme) && (url.has_password() || url.has_username() || url.has_ref())) { GURL strippedUrl = net::SimplifyUrlForRequest(url); - newUrl = QUrl(QString("%1:%2").arg(content::kViewSourceScheme, QString::fromStdString(strippedUrl.spec()))); + newUrl = QUrl(QLatin1StringView(content::kViewSourceScheme) + u':' + + QString::fromStdString(strippedUrl.spec())); } // If there is a visible entry there are special cases where we dont wan't to use the actual URL if (newUrl.isEmpty()) @@ -209,8 +212,10 @@ QUrl WebContentsDelegateQt::url(/service/content::WebContents *source) const m_pendingUrlUpdate = false; return newUrl; } -void WebContentsDelegateQt::AddNewContents(content::WebContents *source, std::unique_ptr new_contents, const GURL &target_url, - WindowOpenDisposition disposition, const blink::mojom::WindowFeatures &window_features, bool user_gesture, bool *was_blocked) +content::WebContents *WebContentsDelegateQt::AddNewContents( + content::WebContents *source, std::unique_ptr new_contents, + const GURL &target_url, WindowOpenDisposition disposition, + const blink::mojom::WindowFeatures &window_features, bool user_gesture, bool *was_blocked) { Q_UNUSED(source) QSharedPointer newAdapter = createWindow(std::move(new_contents), disposition, window_features.bounds, toQt(target_url), user_gesture); @@ -225,6 +230,8 @@ void WebContentsDelegateQt::AddNewContents(content::WebContents *source, std::un newAdapter->loadDefault(); if (was_blocked) *was_blocked = !newAdapter; + + return nullptr; } void WebContentsDelegateQt::CloseContents(content::WebContents *source) @@ -246,7 +253,7 @@ void WebContentsDelegateQt::LoadProgressChanged(double progress) } } -bool WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const content::NativeWebKeyboardEvent &event) +bool WebContentsDelegateQt::HandleKeyboardEvent(content::WebContents *, const input::NativeWebKeyboardEvent &event) { Q_ASSERT(!event.skip_if_unhandled); if (event.os_event) @@ -781,10 +788,13 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio if (!navigationAllowedByPolicy || !navigationRequestAccepted) { QString errorDescription; - if (!navigationAllowedByPolicy) - errorDescription = QStringLiteral("Launching external protocol forbidden by WebEngineSettings::UnknownUrlSchemePolicy"); - else - errorDescription = QStringLiteral("Launching external protocol suppressed by 'navigationRequested' API"); + if (!navigationAllowedByPolicy) { + errorDescription = u"Launching external protocol forbidden by " + "WebEngineSettings::UnknownUrlSchemePolicy"_s; + } else { + errorDescription = u"Launching external protocol suppressed by " + "'navigationRequested' API"_s; + } didFailLoad(url, net::Error::ERR_ABORTED, errorDescription); } } @@ -880,8 +890,7 @@ void WebContentsDelegateQt::ResourceLoadComplete(content::RenderFrameHost* rende } void WebContentsDelegateQt::InnerWebContentsAttached(content::WebContents *inner_web_contents, - content::RenderFrameHost *render_frame_host, - bool is_full_page) + content::RenderFrameHost *render_frame_host) { blink::web_pref::WebPreferences guestPrefs = inner_web_contents->GetOrCreateWebPreferences(); webEngineSettings()->overrideWebPreferences(inner_web_contents, &guestPrefs); diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 95f4ec4f0d1..114519a635f 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -82,11 +82,14 @@ class WebContentsDelegateQt : public content::WebContentsDelegate content::WebContents *OpenURLFromTab(content::WebContents *source, const content::OpenURLParams ¶ms, base::OnceCallback navigation_handle_callback) override; void NavigationStateChanged(content::WebContents* source, content::InvalidateTypes changed_flags) override; - void AddNewContents(content::WebContents *source, std::unique_ptr new_contents, const GURL &target_url, - WindowOpenDisposition disposition, const blink::mojom::WindowFeatures &window_features, bool user_gesture, bool *was_blocked) override; + content::WebContents *AddNewContents(content::WebContents *source, + std::unique_ptr new_contents, + const GURL &target_url, WindowOpenDisposition disposition, + const blink::mojom::WindowFeatures &window_features, + bool user_gesture, bool *was_blocked) override; void CloseContents(content::WebContents *source) override; void LoadProgressChanged(double progress) override; - bool HandleKeyboardEvent(content::WebContents *source, const content::NativeWebKeyboardEvent &event) override; + bool HandleKeyboardEvent(content::WebContents *source, const input::NativeWebKeyboardEvent &event) override; std::unique_ptr OpenColorChooser(content::WebContents *source, SkColor color, const std::vector &suggestions) override; void WebContentsCreated(content::WebContents *source_contents, int opener_render_process_id, int opener_render_frame_id, const std::string &frame_name, const GURL &target_url, content::WebContents *new_contents) override; @@ -132,8 +135,7 @@ class WebContentsDelegateQt : public content::WebContentsDelegate const content::GlobalRequestID& request_id, const blink::mojom::ResourceLoadInfo& resource_load_info) override; void InnerWebContentsAttached(content::WebContents *inner_web_contents, - content::RenderFrameHost *render_frame_host, - bool is_full_page) override; + content::RenderFrameHost *render_frame_host) override; using content::WebContentsObserver::BeforeUnloadFired; void emitLoadSucceeded(const QUrl &url); diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h index 862cda0c8c8..d04a4924f47 100644 --- a/src/core/web_contents_view_qt.h +++ b/src/core/web_contents_view_qt.h @@ -91,8 +91,6 @@ class WebContentsViewQt void UpdateDragOperation(ui::mojom::DragOperation dragOperation, bool document_is_handling_drag) override; - void TransferDragSecurityInfo(content::WebContentsView *) override {} - void ShowContextMenu(content::RenderFrameHost &, const content::ContextMenuParams ¶ms) override; void GotFocus(content::RenderWidgetHostImpl *render_widget_host) override; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index e15005e578f..c058a3ae16c 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -32,7 +32,10 @@ #endif #include "components/discardable_memory/service/discardable_shared_memory_manager.h" #include "components/download/public/common/download_task_runner.h" +#include "components/input/switches.h" +#include "components/power_monitor/make_power_monitor_device_source.h" #include "components/viz/common/features.h" +#include "components/variations/variations_ids_provider.h" #include "components/web_cache/browser/web_cache_manager.h" #include "content/app/mojo_ipc_support.h" #include "content/browser/devtools/devtools_http_handler.h" @@ -77,6 +80,7 @@ #include "ui/native_theme/native_theme_features.h" #include "ui/gl/gl_utils.h" #include "ui/gl/gl_switches.h" +#include "url/url_features.h" #if defined(Q_OS_WIN) #include "sandbox/win/src/sandbox_types.h" #include "content/public/app/sandbox_helper_win.h" @@ -123,6 +127,8 @@ #define STRINGIFY_LITERAL(x) #x #define STRINGIFY_EXPANDED(x) STRINGIFY_LITERAL(x) +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { Q_WEBENGINE_LOGGING_CATEGORY(webEngineContextLog, "qt.webenginecontext") @@ -145,7 +151,7 @@ class GPUInfo Qualcomm, Samsung, Broadcom, - VMWare, + VMware, VirtIO, // Khronos-registered vendors @@ -180,7 +186,7 @@ class GPUInfo {0x5143, Qualcomm}, {0x144D, Samsung}, {0x14E4, Broadcom}, - {0x15AD, VMWare}, + {0x15AD, VMware}, {0x1AF4, VirtIO}, {0x10001, Vivante}, {0x10002, VeriSilicon}, @@ -195,27 +201,29 @@ class GPUInfo if (it != vendorIdMap.end()) return it->second; - qWarning() << "Unknown Vendor ID:" << QStringLiteral("0x%1").arg(vendorId, 0, 16); + qWarning("Unknown Vendor ID: 0x%llx", vendorId); return Unknown; } - static Vendor deviceNameToVendor(const QString &deviceName) + static Vendor deviceNameToVendor(QLatin1StringView deviceName) { // TODO: Test and add more vendors to the list. - if (deviceName.contains(QLatin1StringView("AMD"), Qt::CaseInsensitive)) + if (deviceName.contains("AMD"_L1, Qt::CaseInsensitive)) return AMD; - if (deviceName.contains(QLatin1StringView("Intel"), Qt::CaseInsensitive)) + if (deviceName.contains("Intel"_L1, Qt::CaseInsensitive)) return Intel; - if (deviceName.contains(QLatin1StringView("Nvidia"), Qt::CaseInsensitive)) + if (deviceName.contains("Nvidia"_L1, Qt::CaseInsensitive)) return Nvidia; + if (deviceName.contains("VMware"_L1, Qt::CaseInsensitive)) + return VMware; #if BUILDFLAG(IS_OZONE) - if (deviceName.contains(QLatin1StringView("Mesa llvmpipe"))) + if (deviceName.contains("Mesa llvmpipe"_L1)) return Mesa; #endif #if defined(Q_OS_MACOS) - if (deviceName.contains(QLatin1StringView("Apple"))) + if (deviceName.contains("Apple"_L1)) return Apple; #endif @@ -238,7 +246,7 @@ class GPUInfo {Qualcomm, "Qualcomm"}, {Samsung, "Samsung"}, {Broadcom, "Broadcom"}, - {VMWare, "VMWare"}, + {VMware, "VMware"}, {VirtIO, "VirtIO"}, {Vivante, "Vivante"}, {VeriSilicon, "VeriSilicon"}, @@ -253,11 +261,11 @@ class GPUInfo if (it != vendorNameMap.end()) return it->second; - Q_UNREACHABLE(); - return "Unknown"; + Q_UNREACHABLE_RETURN("Unknown"); } Vendor vendor() const { return m_vendor; } + QString deviceName() const { return m_deviceName; } QString getAdapterLuid() const { return m_adapterLuid; } private: @@ -280,6 +288,7 @@ class GPUInfo } if (d3d11Rhi) { m_vendor = vendorIdToVendor(d3d11Rhi->driverInfo().vendorId); + m_deviceName = QString::fromUtf8(d3d11Rhi->driverInfo().deviceName); const QRhiD3D11NativeHandles *handles = static_cast(d3d11Rhi->nativeHandles()); @@ -293,8 +302,10 @@ class GPUInfo QRhiMetalInitParams params; QScopedPointer metalRhi( QRhi::create(QRhi::Metal, ¶ms, QRhi::Flags(), nullptr)); - if (metalRhi) + if (metalRhi) { m_vendor = deviceNameToVendor(QLatin1StringView(metalRhi->driverInfo().deviceName)); + m_deviceName = QString::fromUtf8(metalRhi->driverInfo().deviceName); + } } #endif @@ -304,8 +315,10 @@ class GPUInfo params.fallbackSurface = QRhiGles2InitParams::newFallbackSurface(); QScopedPointer glRhi( QRhi::create(QRhi::OpenGLES2, ¶ms, QRhi::Flags(), nullptr)); - if (glRhi) + if (glRhi) { m_vendor = deviceNameToVendor(QLatin1StringView(glRhi->driverInfo().deviceName)); + m_deviceName = QString::fromUtf8(glRhi->driverInfo().deviceName); + } } #endif @@ -325,6 +338,7 @@ class GPUInfo // see https://www.phoronix.com/news/Mesa-20.1-Vulkan-Dev-Selection // Try to detect this case and at least warn about it. m_vendor = vendorIdToVendor(vulkanRhi->driverInfo().vendorId); + m_deviceName = QString::fromUtf8(vulkanRhi->driverInfo().deviceName); } } } @@ -335,6 +349,7 @@ class GPUInfo } Vendor m_vendor = Unknown; + QString m_deviceName; QString m_adapterLuid; }; @@ -352,7 +367,7 @@ static bool usingSupportedSGBackend() QString device = QQuickWindow::sceneGraphBackend(); for (int index = 0; index < args.count(); ++index) { - if (args.at(index).startsWith(QLatin1StringView("--device="))) { + if (args.at(index).startsWith("--device="_L1)) { device = args.at(index).mid(9); break; } @@ -363,7 +378,7 @@ static bool usingSupportedSGBackend() if (device.isEmpty()) device = qEnvironmentVariable("QMLSCENE_DEVICE"); - return device.isEmpty() || device == QLatin1StringView("rhi"); + return device.isEmpty() || device == "rhi"_L1; } static std::string getGLType(bool disableGpu) @@ -411,44 +426,38 @@ void dummyGetPluginCallback(const std::vector&) static void logContext(const std::string &glType, base::CommandLine *cmd) { if (Q_UNLIKELY(webEngineContextLog().isDebugEnabled())) { - QStringList log; - log << QLatin1StringView("\n"); - - log << QLatin1StringView("Chromium GL Backend: " + glType) << QLatin1StringView("\n"); - log << QLatin1StringView("Chromium ANGLE Backend: " + getAngleType(glType, cmd)) - << QLatin1StringView("\n"); - log << QLatin1StringView("Chromium Vulkan Backend: " + getVulkanType(cmd)) - << QLatin1StringView("\n"); - log << QLatin1StringView("\n"); - - log << QLatin1StringView("QSG RHI Backend:") << QSGRhiSupport::instance()->rhiBackendName() - << QLatin1StringView("\n"); - log << QLatin1StringView("QSG RHI Backend Supported:") - << QLatin1StringView(usingSupportedSGBackend() ? "yes" : "no") - << QLatin1StringView("\n"); - log << QLatin1StringView("GPU Vendor: " - + GPUInfo::vendorToString(GPUInfo::instance()->vendor())) - << QLatin1StringView("\n"); - log << QLatin1StringView("\n"); + QString log; + log += u'\n'; + + log += "Chromium GL Backend: "_L1 + QLatin1StringView(glType) + "\n"_L1; + log += "Chromium ANGLE Backend: "_L1 + QLatin1StringView(getAngleType(glType, cmd)) + u'\n'; + log += "Chromium Vulkan Backend: "_L1 + QLatin1StringView(getVulkanType(cmd)) + u'\n'; + log += u'\n'; + + log += "QSG RHI Backend: "_L1 + QSGRhiSupport::instance()->rhiBackendName() + u'\n'; + log += "QSG RHI Backend Supported: "_L1 + (usingSupportedSGBackend() ? "yes"_L1 : "no"_L1) + + u'\n'; + log += "QSG RHI Device: "_L1 + GPUInfo::instance()->deviceName() + u'\n'; + log += "QSG RHI GPU Vendor: "_L1 + + QLatin1StringView(GPUInfo::vendorToString(GPUInfo::instance()->vendor())) + u'\n'; + log += u'\n'; #if QT_CONFIG(opengl) #if BUILDFLAG(IS_OZONE) - log << QLatin1StringView("Using GLX:") - << QLatin1StringView(OzoneUtilQt::usingGLX() ? "yes" : "no") << QLatin1StringView("\n"); - log << QLatin1StringView("Using EGL:") - << QLatin1StringView(OzoneUtilQt::usingEGL() ? "yes" : "no") << QLatin1StringView("\n"); + log += "Using GLX: "_L1 + (OzoneUtilQt::usingGLX() ? "yes"_L1 : "no"_L1) + u'\n'; + log += "Using EGL: "_L1 + (OzoneUtilQt::usingEGL() ? "yes"_L1 : "no"_L1) + u'\n'; #endif // BUILDFLAG(IS_OZONE) - log << QLatin1StringView("Using Shared GL:") - << QLatin1StringView(QOpenGLContext::globalShareContext() ? "yes" : "no") - << QLatin1StringView("\n"); + log += "Using Shared GL: "_L1 + (QOpenGLContext::globalShareContext() ? "yes"_L1 : "no"_L1) + + u'\n'; + log += u'\n'; #endif // QT_CONFIG(opengl) - log << QLatin1StringView("Init Parameters:\n"); + log += "Init Parameters:\n"_L1; const base::CommandLine::SwitchMap switchMap = cmd->GetSwitches(); for (const auto &pair : switchMap) - log << QStringLiteral(" * %1 %2\n").arg(toQt(pair.first)).arg(toQt(pair.second)); + log += " * "_L1 + toQt(pair.first) + u' ' + toQt(pair.second) + u'\n'; - qCDebug(webEngineContextLog) << qPrintable(log.join(QLatin1Char(' '))); + qCDebug(webEngineContextLog, "%ls", qUtf16Printable(log)); } } @@ -460,14 +469,14 @@ static void setupProxyPac(base::CommandLine *commandLine) QUrl pac_url(http://github.com/toQt(commandLine-%3EGetSwitchValueASCII(switches::kProxyPacUrl))); if (pac_url.isValid() && (pac_url.isLocalFile() - || !pac_url.scheme().compare(QLatin1StringView("qrc"), Qt::CaseInsensitive))) { + || !pac_url.scheme().compare("qrc"_L1, Qt::CaseInsensitive))) { QFile file; if (pac_url.isLocalFile()) file.setFileName(pac_url.toLocalFile()); else file.setFileName(pac_url.path().prepend(QLatin1Char(':'))); if (file.exists() && file.open(QIODevice::ReadOnly | QIODevice::Text)) { - QByteArray ba = file.readAll(); + const QByteArray ba = file.readAll(); commandLine->RemoveSwitch(switches::kProxyPacUrl); commandLine->AppendSwitchASCII(switches::kProxyPacUrl, ba.toBase64().prepend("data:application/x-javascript-config;base64,").toStdString()); @@ -484,6 +493,13 @@ static void cleanupVizProcess() content::GetHostFrameSinkManager()->SetConnectionLostCallback(base::DoNothing()); auto factory = static_cast(content::ImageTransportFactory::GetInstance()); factory->PrepareForShutDown(); + + // Wait for viz destroy tasks to be completed on the GPU thread. + base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL, + base::WaitableEvent::InitialState::NOT_SIGNALED); + gpuChildThread->main_thread_runner()->PostTask( + FROM_HERE, base::BindOnce([](base::WaitableEvent *event) { event->Signal(); }, &event)); + event.Wait(); } static QStringList parseEnvCommandLine(const QString &cmdLine) @@ -777,10 +793,6 @@ WebEngineContext::WebEngineContext() base::apple::SetOverrideAmIBundled(false); #endif - base::ThreadPoolInstance::Create("Browser"); - m_contentRunner = content::ContentMainRunner::Create(); - m_browserRunner = content::BrowserMainRunner::Create(); - #ifdef Q_OS_LINUX // Call qputenv before BrowserMainRunnerImpl::Initialize is called. // http://crbug.com/245466 @@ -818,7 +830,7 @@ WebEngineContext::WebEngineContext() #endif } else { parsedCommandLine->AppendSwitch(sandbox::policy::switches::kNoSandbox); - qInfo() << "Sandboxing disabled by user."; + qInfo("Sandboxing disabled by user."); } // Do not advertise a feature we have removed at compile time @@ -846,7 +858,6 @@ WebEngineContext::WebEngineContext() disableFeatures.push_back(features::kEyeDropper.name); // Explicitly tell Chromium about default-on features we do not support - disableFeatures.push_back(features::kAttributionReportingCrossAppWebOverride.name); disableFeatures.push_back(features::kBackgroundFetch.name); disableFeatures.push_back(features::kInstalledApp.name); parsedCommandLine->AppendSwitchASCII(switches::kDisableBlinkFeatures, "WebOTP"); @@ -854,16 +865,20 @@ WebEngineContext::WebEngineContext() disableFeatures.push_back(features::kWebPayments.name); disableFeatures.push_back(features::kWebUsb.name); + // Currently causing more issues than it fixes. + // Probably will be removed in 134, tst_origins should be updated in this case. + disableFeatures.push_back(url::kStandardCompliantNonSpecialSchemeURLParsing.name); + if (useEmbeddedSwitches) { // embedded switches are based on the switches for Android, see content/browser/android/content_startup_flags.cc enableFeatures.push_back(features::kOverlayScrollbar.name); parsedCommandLine->AppendSwitch(switches::kEnableViewport); - parsedCommandLine->AppendSwitch(switches::kValidateInputEventStream); + parsedCommandLine->AppendSwitch(input::switches::kValidateInputEventStream); parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } #if BUILDFLAG(IS_OZONE) - if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { + if (!isGbmSupported()) { disableFeatures.push_back(media::kVaapiVideoDecodeLinux.name); parsedCommandLine->AppendSwitch(switches::kDisableGpuMemoryBufferVideoFrames); } @@ -875,20 +890,11 @@ WebEngineContext::WebEngineContext() == gl::kGLImplementationANGLEName); } - if (usingANGLE && !parsedCommandLine->HasSwitch(switches::kUseANGLE)) { - parsedCommandLine->AppendSwitchASCII(switches::kUseANGLE, - gl::kANGLEImplementationOpenGLEGLName); - } - #if QT_CONFIG(webengine_vulkan) if (QQuickWindow::graphicsApi() == QSGRendererInterface::OpenGL && usingSupportedSGBackend()) { - if (usingANGLE && GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { - qWarning("Disable ANGLE because GBM is not supported with the current configuration. " + if (usingANGLE && !isGbmSupported()) { + qWarning("GBM is not supported with the current configuration. " "Fallback to Vulkan rendering in Chromium."); - parsedCommandLine->RemoveSwitch(switches::kUseANGLE); - parsedCommandLine->RemoveSwitch(switches::kUseGL); - parsedCommandLine->AppendSwitchASCII(switches::kUseGL, - gl::kGLImplementationDesktopName); parsedCommandLine->AppendSwitchASCII(switches::kUseVulkan, switches::kVulkanImplementationNameNative); enableFeatures.push_back(features::kVulkan.name); @@ -912,11 +918,10 @@ WebEngineContext::WebEngineContext() found++; } if (found != requiredDeviceExtensions.size()) { - qWarning().nospace() - << "Vulkan rendering may fail because " << deviceExtensionsVar - << " environment variable is already set but it doesn't contain" - << " some of the required Vulkan device extensions:\n" - << qPrintable(requiredDeviceExtensions.join('\n')); + qWarning("Vulkan rendering may fail because %s environment variable is already " + "set but it doesn't contain some of the required Vulkan device " + "extensions:\n%s", + deviceExtensionsVar, requiredDeviceExtensions.join('\n').constData()); } } else { qputenv(deviceExtensionsVar, requiredDeviceExtensions.join(';')); @@ -981,6 +986,7 @@ WebEngineContext::WebEngineContext() contentMainParams.sandbox_info = &sandbox_info; } #endif + m_contentRunner = content::ContentMainRunner::Create(); m_contentRunner->Initialize(std::move(contentMainParams)); mojo::core::Configuration mojoConfiguration; @@ -991,11 +997,16 @@ WebEngineContext::WebEngineContext() m_mainDelegate->PreBrowserMain(); base::MessagePump::OverrideMessagePumpForUIFactory(messagePumpFactory); content::BrowserTaskExecutor::Create(); + auto* provider = m_mainDelegate->CreateVariationsIdsProvider(); + if (!provider) { + variations::VariationsIdsProvider::Create( + variations::VariationsIdsProvider::Mode::kUseSignedInState); + } m_mainDelegate->PostEarlyInitialization({}); content::StartBrowserThreadPool(); content::BrowserTaskExecutor::PostFeatureListSetup(); tracing::InitTracingPostThreadPoolStartAndFeatureList(false); - base::PowerMonitor::Initialize(std::make_unique()); + base::PowerMonitor::GetInstance()->Initialize(MakePowerMonitorDeviceSource()); content::ProcessVisibilityTracker::GetInstance(); m_discardableSharedMemoryManager = std::make_unique(); @@ -1009,6 +1020,7 @@ WebEngineContext::WebEngineContext() content::MainFunctionParams mainParams(base::CommandLine::ForCurrentProcess()); mainParams.startup_data = std::move(startupData); + m_browserRunner = content::BrowserMainRunner::Create(); m_browserRunner->Initialize(std::move(mainParams)); m_devtoolsServer.reset(new DevToolsServerQt()); @@ -1066,7 +1078,7 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, } base::CommandLine *parsedCommandLine = base::CommandLine::ForCurrentProcess(); - int index = appArgs.indexOf(QRegularExpression(QLatin1StringView("--webEngineArgs"), + int index = appArgs.indexOf(QRegularExpression(u"--webEngineArgs"_s, QRegularExpression::CaseInsensitiveOption)); if (qEnvironmentVariableIsSet(kChromiumFlagsEnv)) { appArgs = appArgs.mid(0, 1); // Take application name and drop the rest @@ -1081,27 +1093,26 @@ base::CommandLine *WebEngineContext::initCommandLine(bool &useEmbeddedSwitches, } } #if defined(QTWEBENGINE_EMBEDDED_SWITCHES) - useEmbeddedSwitches = !appArgs.contains(QStringLiteral("--disable-embedded-switches")); + useEmbeddedSwitches = !appArgs.contains("--disable-embedded-switches"_L1); #else - useEmbeddedSwitches = appArgs.contains(QStringLiteral("--enable-embedded-switches")); + useEmbeddedSwitches = appArgs.contains("--enable-embedded-switches"_L1); #endif - enableGLSoftwareRendering = - appArgs.removeAll(QStringLiteral("--enable-webgl-software-rendering")); - appArgs.removeAll(QStringLiteral("--disable-embedded-switches")); - appArgs.removeAll(QStringLiteral("--enable-embedded-switches")); + enableGLSoftwareRendering = appArgs.removeAll("--enable-webgl-software-rendering"_L1); + appArgs.removeAll("--disable-embedded-switches"_L1); + appArgs.removeAll("--enable-embedded-switches"_L1); bool isRemoteDebugPort = (-1 - != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-debugging-port=.*"), + != appArgs.indexOf(QRegularExpression(u"--remote-debugging-port=.*"_s, QRegularExpression::CaseInsensitiveOption))) || !qEnvironmentVariable("QTWEBENGINE_REMOTE_DEBUGGING").isEmpty(); bool isRemoteAllowOrigins = (-1 - != appArgs.indexOf(QRegularExpression(QStringLiteral("--remote-allow-origins=.*"), + != appArgs.indexOf(QRegularExpression(u"--remote-allow-origins=.*"_s, QRegularExpression::CaseInsensitiveOption))); if (isRemoteDebugPort && !isRemoteAllowOrigins) { - appArgs.append(QStringLiteral("--remote-allow-origins=*")); + appArgs.append(u"--remote-allow-origins=*"_s); qWarning("Added {--remote-allow-origins=*} to command-line arguments " "to avoid web socket connection errors during remote debugging."); } @@ -1125,6 +1136,46 @@ bool WebEngineContext::closingDown() return m_closingDown; } +#if BUILDFLAG(IS_OZONE) +bool WebEngineContext::isGbmSupported() +{ + static bool supported = []() { + const static char kForceGbmEnv[] = "QTWEBENGINE_FORCE_USE_GBM"; + if (Q_UNLIKELY(qEnvironmentVariableIsSet(kForceGbmEnv))) { + qWarning("%s environment variable is set and it is for debugging purposes only.", + kForceGbmEnv); + bool ok; + int forceGbm = qEnvironmentVariableIntValue(kForceGbmEnv, &ok); + if (ok) { + qWarning("GBM support is force %s.", forceGbm != 0 ? "enabled" : "disabled"); + return (forceGbm != 0); + } + + qWarning("Ignoring invalid value of %s and do not force GBM. " + "Use 0 to force disable or 1 to force enable.", + kForceGbmEnv); + } + + if (GPUInfo::instance()->vendor() == GPUInfo::Nvidia) { + // FIXME: This disables GBM for Nvidia. Remove this when Nvidia fixes its GBM support. + // + // "Buffer allocation and submission to DRM KMS using gbm is not currently supported." + // See: https://download.nvidia.com/XFree86/Linux-x86_64/570.86.16/README/kms.html" + // + // Chromium uses GBM to allocate scanout buffers. Scanout requires DRM KMS. If KMS is + // enabled, gbm_device and gbm_buffer are created without any issues but rendering to + // the buffer will malfunction. It is not known how to detect this problem before + // rendering so we just disable GBM for Nvidia. + return false; + } + + return true; + }(); + + return supported; +} +#endif + void WebEngineContext::registerMainThreadFactories() { content::UtilityProcessHost::RegisterUtilityMainThreadFactory(content::CreateInProcessUtilityThread); @@ -1152,7 +1203,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "129.0.6668.58"; // FIXME: Remember to update + return "136.0.7103.114"; // FIXME: Remember to update } QT_END_NAMESPACE diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index 1a3d0feada7..6f2bf04c4b1 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -65,6 +65,9 @@ class WebEngineContext : public base::RefCounted { static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port); static void flushMessages(); static bool closingDown(); +#if BUILDFLAG(IS_OZONE) + static bool isGbmSupported(); +#endif ProfileAdapter *createDefaultProfileAdapter(); ProfileAdapter *defaultProfileAdapter(); diff --git a/src/core/web_engine_library_info.cpp b/src/core/web_engine_library_info.cpp index ac01cbc90e5..e9ef9d2f684 100644 --- a/src/core/web_engine_library_info.cpp +++ b/src/core/web_engine_library_info.cpp @@ -34,6 +34,7 @@ #error "No name defined for QtWebEngine's process" #endif +using namespace Qt::StringLiterals; using namespace QtWebEngineCore; Q_WEBENGINE_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo") @@ -41,7 +42,8 @@ Q_WEBENGINE_LOGGING_CATEGORY(webEngineLibraryInfoLog, "qt.webengine.libraryinfo" namespace { QString fallbackDir() { - static QString directory = QDir::homePath() % QLatin1String("/.") % QCoreApplication::applicationName(); + static const QString directory = + QDir::homePath() % "/."_L1 % QCoreApplication::applicationName(); return directory; } @@ -57,8 +59,8 @@ static QString getBundlePath(CFBundleRef frameworkBundle) // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before. // We use it for the other OS X versions as well to make sure it works and because // the directory structure should be the same. - if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) { - path = QDir::cleanPath(qApp->applicationDirPath() % QLatin1String("/../../../..")); + if (qApp->applicationName() == QLatin1StringView(qWebEngineProcessName())) { + path = QDir::cleanPath(qApp->applicationDirPath() % "/../../../.."_L1); } else if (frameworkBundle) { CFURLRef bundleUrl = CFBundleCopyBundleURL(frameworkBundle); CFStringRef bundlePath = CFURLCopyFileSystemPath(bundleUrl, kCFURLPOSIXPathStyle); @@ -75,8 +77,8 @@ static QString getResourcesPath(CFBundleRef frameworkBundle) // The following is a fix for QtWebEngineProcess crashes on OS X 10.7 and before. // We use it for the other OS X versions as well to make sure it works and because // the directory structure should be the same. - if (qApp->applicationName() == QLatin1String(qWebEngineProcessName())) { - path = getBundlePath(frameworkBundle) % QLatin1String("/Resources"); + if (qApp->applicationName() == QLatin1StringView(qWebEngineProcessName())) { + path = getBundlePath(frameworkBundle) % "/Resources"_L1; } else if (frameworkBundle) { CFURLRef resourcesRelativeUrl = CFBundleCopyResourcesDirectoryURL(frameworkBundle); CFStringRef resourcesRelativePath = CFURLCopyFileSystemPath(resourcesRelativeUrl, kCFURLPOSIXPathStyle); @@ -121,20 +123,18 @@ QString subProcessPath() static QString processPath; if (processPath.isEmpty()) { #if defined(Q_OS_WIN) - const QString processBinary = QLatin1String(qWebEngineProcessName()) % QLatin1String(".exe"); + const QString processBinary = QLatin1StringView(qWebEngineProcessName()) % ".exe"_L1; #else - const QString processBinary = QLatin1String(qWebEngineProcessName()); + const auto processBinary = QLatin1StringView(qWebEngineProcessName()); #endif QStringList candidatePaths; - const QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINEPROCESS_PATH if set - candidatePaths << fromEnv; - } else { + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINEPROCESS_PATH"); fromEnv.isEmpty()) { + includeOverrideMessage = true; #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) - candidatePaths << getBundlePath(frameworkBundle()) % QStringLiteral("/Helpers/") - % qWebEngineProcessName() % QStringLiteral(".app/Contents/MacOS/") + candidatePaths << getBundlePath(frameworkBundle()) % "/Helpers/"_L1 + % qWebEngineProcessName() % ".app/Contents/MacOS/"_L1 % qWebEngineProcessName(); #else candidatePaths << QLibraryInfo::path(QLibraryInfo::LibraryExecutablesPath) @@ -144,29 +144,30 @@ QString subProcessPath() #endif candidatePaths << QCoreApplication::applicationDirPath() % QLatin1Char('/') % processBinary; + } else { + // Only search in QTWEBENGINEPROCESS_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate)) { processPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine process path: %ls", + qUtf16Printable(candidate)); break; } } if (processPath.isEmpty()) { - QStringList errorMessage; - errorMessage.append( - QStringLiteral("The following paths were searched for Qt WebEngine Process:")); + QString errorMessage; + errorMessage += "The following paths were searched for Qt WebEngine Process:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - errorMessage.append(QStringLiteral(" ") % candidate); - errorMessage.append(QStringLiteral("but could not find it.")); - if (fromEnv.isEmpty()) { - errorMessage.append( - QStringLiteral("You may override the default search path by using " - "QTWEBENGINEPROCESS_PATH environment variable.")); + errorMessage += " "_L1 + candidate + u'\n'; + errorMessage += "but could not find it.\n"_L1; + if (includeOverrideMessage) { + errorMessage += "You may override the default search path by using " + "QTWEBENGINEPROCESS_PATH environment variable.\n"_L1; } - qFatal("%s", qPrintable(errorMessage.join('\n'))); + qFatal("%ls", qUtf16Printable(errorMessage)); } #if defined(Q_OS_WIN) @@ -189,51 +190,44 @@ QString localesPath() if (potentialLocalesPath.isEmpty()) { QStringList candidatePaths; const QString translationPakFilename = -#if QT_VERSION >= QT_VERSION_CHECK(6, 3, 0) - QLatin1String(WebEngineLibraryInfo::getResolvedLocale() + ".pak"); -#else - QLatin1String((WebEngineLibraryInfo::getResolvedLocale() + ".pak").c_str()); -#endif - const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINE_LOCALES_PATH if set - candidatePaths << fromEnv; - } else { + QLatin1StringView(WebEngineLibraryInfo::getResolvedLocale()) % ".pak"_L1; + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_LOCALES_PATH"); fromEnv.isEmpty()) { + includeOverrideMessage = true; #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getResourcesPath(frameworkBundle()) % QDir::separator() - % QLatin1String("qtwebengine_locales"); + % "qtwebengine_locales"_L1; #endif candidatePaths << QLibraryInfo::path(QLibraryInfo::TranslationsPath) % QDir::separator() - % QLatin1String("qtwebengine_locales"); + % "qtwebengine_locales"_L1; candidatePaths << fallbackDir(); + } else { + // Only search in QTWEBENGINE_LOCALES_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate % QDir::separator() % translationPakFilename)) { potentialLocalesPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine locales path: %ls", + qUtf16Printable(candidate)); break; } } if (potentialLocalesPath.isEmpty()) { - QStringList warningMessage; - warningMessage.append( - QStringLiteral("The following paths were searched for Qt WebEngine locales:")); + QString warningMessage; + warningMessage += "The following paths were searched for Qt WebEngine locales:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - warningMessage.append(QStringLiteral(" ") % candidate); - warningMessage.append( - QStringLiteral( - "but could not find the translation file for the current locale: ") - % translationPakFilename); - if (fromEnv.isEmpty()) { - warningMessage.append( - QStringLiteral("You may override the default search paths by using " - "QTWEBENGINE_LOCALES_PATH environment variable.")); + warningMessage += " "_L1 % candidate + u'\n'; + warningMessage += "but could not find the translation file for the current locale: "_L1 + + translationPakFilename + u'\n'; + if (includeOverrideMessage) { + warningMessage += "You may override the default search paths by using " + "QTWEBENGINE_LOCALES_PATH environment variable.\n"_L1; } - warningMessage.append(QStringLiteral("Translations WILL NOT be correct.")); - qWarning("%s", qPrintable(warningMessage.join('\n'))); + warningMessage += "Translations WILL NOT be correct.\n"_L1; + qWarning("%ls", qUtf16Printable(warningMessage)); } } @@ -244,64 +238,65 @@ QString localesPath() QString dictionariesPath(bool showWarnings) { static QString potentialDictionariesPath; - static QStringList warningMessage; + static QString warningMessage; static bool initialized = false; QStringList candidatePaths; if (!initialized) { initialized = true; - const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINE_DICTIONARIES_PATH if set - candidatePaths << fromEnv; - } else { + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_DICTIONARIES_PATH"); + fromEnv.isEmpty()) { + includeOverrideMessage = true; // First try to find dictionaries near the application. #ifdef Q_OS_DARWIN QString resourcesDictionariesPath = getMainApplicationResourcesPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << resourcesDictionariesPath; + % QDir::separator() % "qtwebengine_dictionaries"_L1; + candidatePaths.append(std::move(resourcesDictionariesPath)); #endif QString applicationDictionariesPath = QCoreApplication::applicationDirPath() - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << applicationDictionariesPath; + % QDir::separator() % "qtwebengine_dictionaries"_L1; + candidatePaths.append(std::move(applicationDictionariesPath)); // Then try to find dictionaries near the installed library. #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) - QString frameworkDictionariesPath = getResourcesPath(frameworkBundle()) - % QLatin1String("/qtwebengine_dictionaries"); - candidatePaths << frameworkDictionariesPath; + QString frameworkDictionariesPath = + getResourcesPath(frameworkBundle()) % "/qtwebengine_dictionaries"_L1; + candidatePaths.append(std::move(frameworkDictionariesPath)); #endif QString libraryDictionariesPath = QLibraryInfo::path(QLibraryInfo::DataPath) - % QDir::separator() % QLatin1String("qtwebengine_dictionaries"); - candidatePaths << libraryDictionariesPath; + % QDir::separator() % "qtwebengine_dictionaries"_L1; + candidatePaths.append(std::move(libraryDictionariesPath)); + } else { + // Only search in QTWEBENGINE_DICTIONARIES_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate)) { potentialDictionariesPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine dictionaries path: %ls", + qUtf16Printable(candidate)); break; } } if (potentialDictionariesPath.isEmpty()) { - warningMessage.append(QStringLiteral( - "The following paths were searched for Qt WebEngine dictionaries:")); + warningMessage += + "The following paths were searched for Qt WebEngine dictionaries:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - warningMessage.append(QStringLiteral(" ") % candidate); - warningMessage.append(QStringLiteral("but could not find it.")); - if (fromEnv.isEmpty()) { - warningMessage.append( - QStringLiteral("You may override the default search path by using " - "QTWEBENGINE_DICTIONARIES_PATH environment variable.")); + warningMessage += " "_L1 + candidate + u'\n'; + warningMessage += "but could not find it.\n"_L1; + if (includeOverrideMessage) { + warningMessage += "You may override the default search path by using " + "QTWEBENGINE_DICTIONARIES_PATH environment variable.\n"_L1; } - warningMessage.append(QStringLiteral("Spellchecking can not be enabled.")); + warningMessage += "Spellchecking can not be enabled.\n"_L1; } } if (showWarnings && !warningMessage.isEmpty()) { - qWarning("%s", qPrintable(warningMessage.join('\n'))); + qWarning("%ls", qUtf16Printable(warningMessage)); } return potentialDictionariesPath; @@ -313,44 +308,44 @@ QString resourcesPath() static QString potentialResourcesPath; if (potentialResourcesPath.isEmpty()) { QStringList candidatePaths; - const QString resourcesPakFilename = QLatin1String("qtwebengine_resources.pak"); - const QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH"); - if (!fromEnv.isEmpty()) { - // Only search in QTWEBENGINE_RESOURCES_PATH if set - candidatePaths << fromEnv; - } else { + const auto resourcesPakFilename = "qtwebengine_resources.pak"_L1; + bool includeOverrideMessage = false; + if (QString fromEnv = qEnvironmentVariable("QTWEBENGINE_RESOURCES_PATH"); + fromEnv.isEmpty()) { + includeOverrideMessage = true; #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) candidatePaths << getResourcesPath(frameworkBundle()); #endif candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath) % QDir::separator() - % QLatin1String("resources"); + % "resources"_L1; candidatePaths << QLibraryInfo::path(QLibraryInfo::DataPath); candidatePaths << QCoreApplication::applicationDirPath(); candidatePaths << fallbackDir(); + } else { + // Only search in QTWEBENGINE_RESOURCES_PATH if set + candidatePaths.append(std::move(fromEnv)); } for (const QString &candidate : std::as_const(candidatePaths)) { if (QFileInfo::exists(candidate % QDir::separator() % resourcesPakFilename)) { potentialResourcesPath = candidate; - qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %s", - qPrintable(candidate)); + qCDebug(webEngineLibraryInfoLog, "Qt WebEngine resources path: %ls", + qUtf16Printable(candidate)); break; } } if (potentialResourcesPath.isEmpty()) { - QStringList errorMessage; - errorMessage.append(QStringLiteral( - "The following paths were searched for Qt WebEngine resources:")); + QString errorMessage; + errorMessage += "The following paths were searched for Qt WebEngine resources:\n"_L1; for (const QString &candidate : std::as_const(candidatePaths)) - errorMessage.append(QStringLiteral(" ") % candidate); - errorMessage.append(QStringLiteral("but could not find any.")); - if (fromEnv.isEmpty()) { - errorMessage.append( - QStringLiteral("You may override the default search paths by using " - "QTWEBENGINE_RESOURCES_PATH environment variable.")); + errorMessage += " "_L1 + candidate + u'\n'; + errorMessage += "but could not find any.\n"_L1; + if (includeOverrideMessage) { + errorMessage += "You may override the default search paths by using " + "QTWEBENGINE_RESOURCES_PATH environment variable.\n"_L1; } - qFatal("%s", qPrintable(errorMessage.join('\n'))); + qFatal("%ls", qUtf16Printable(errorMessage)); } } @@ -363,13 +358,13 @@ base::FilePath WebEngineLibraryInfo::getPath(int key, bool showWarnings) QString directory; switch (key) { case QT_RESOURCES_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_resources.pak"_L1); case QT_RESOURCES_100P_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_100p.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_resources_100p.pak"_L1); case QT_RESOURCES_200P_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_resources_200p.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_resources_200p.pak"_L1); case QT_RESOURCES_DEVTOOLS_PAK: - return toFilePath(resourcesPath() % QLatin1String("/qtwebengine_devtools_resources.pak")); + return toFilePath(resourcesPath() % "/qtwebengine_devtools_resources.pak"_L1); #if defined(Q_OS_DARWIN) && defined(QT_MAC_FRAMEWORK_BUILD) case QT_FRAMEWORK_BUNDLE: return toFilePath(getBundlePath(frameworkBundle())); diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp index ec4d600e8ab..4138cce692a 100644 --- a/src/core/web_engine_settings.cpp +++ b/src/core/web_engine_settings.cpp @@ -24,6 +24,8 @@ #include #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { QHash WebEngineSettings::s_defaultAttributes; @@ -284,7 +286,7 @@ void WebEngineSettings::initDefaults() s_defaultAttributes.insert(QWebEngineSettings::ForceDarkMode, forceDarkMode); s_defaultAttributes.insert(QWebEngineSettings::PrintHeaderAndFooter, false); s_defaultAttributes.insert(QWebEngineSettings::PreferCSSMarginsForPrinting, false); - s_defaultAttributes.insert(QWebEngineSettings::JSTouchEventsEnabled, + s_defaultAttributes.insert(QWebEngineSettings::TouchEventsApiEnabled, isTouchScreenDetected()); } @@ -318,7 +320,7 @@ void WebEngineSettings::initDefaults() s_defaultFontSizes.insert(QWebEngineSettings::DefaultFontSize, 16); } - m_defaultEncoding = QStringLiteral("ISO-8859-1"); + m_defaultEncoding = u"ISO-8859-1"_s; m_unknownUrlSchemePolicy = QWebEngineSettings::InheritedUnknownUrlSchemePolicy; m_imageAnimationPolicy = QWebEngineSettings::ImageAnimationPolicy::Inherited; } @@ -399,8 +401,8 @@ void WebEngineSettings::applySettingsToWebPreferences(blink::web_pref::WebPrefer prefs->dns_prefetching_enabled = testAttribute(QWebEngineSettings::DnsPrefetchEnabled); prefs->disable_reading_from_canvas = !testAttribute(QWebEngineSettings::ReadingFromCanvasEnabled); prefs->animation_policy = toBlinkImageAnimationPolicy(imageAnimationPolicy()); - bool touchEventsEnabled = isAttributeExplicitlySet(QWebEngineSettings::JSTouchEventsEnabled) - ? testAttribute(QWebEngineSettings::JSTouchEventsEnabled) + bool touchEventsEnabled = isAttributeExplicitlySet(QWebEngineSettings::TouchEventsApiEnabled) + ? testAttribute(QWebEngineSettings::TouchEventsApiEnabled) : isTouchScreenDetected(); prefs->touch_event_feature_detection_enabled = touchEventsEnabled; diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 86f10315b2b..946c6874623 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -38,6 +38,7 @@ #include "native_web_keyboard_event_qt.h" #include "render_widget_host_view_qt_delegate.h" +#include #include #include @@ -51,6 +52,8 @@ #endif #include +using namespace Qt::StringLiterals; + namespace QtWebEngineCore { using namespace blink; @@ -59,26 +62,26 @@ enum class KeyboardDriver { Unknown, Windows, Cocoa, Xkb, Evdev }; static KeyboardDriver keyboardDriverImpl() { - QString platformName = QGuiApplication::platformName(); + const QString platformName = QGuiApplication::platformName(); - if (platformName == QLatin1String("windows")) + if (platformName == "windows"_L1) return KeyboardDriver::Windows; - if (platformName == QLatin1String("cocoa")) + if (platformName == "cocoa"_L1) return KeyboardDriver::Cocoa; - if (platformName == QLatin1String("xcb") || platformName == QLatin1String("wayland")) + if (platformName == "xcb"_L1 || platformName == "wayland"_L1) return KeyboardDriver::Xkb; #if QT_CONFIG(libinput) // Based on QEglFSIntegration::createInputHandlers and QLibInputKeyboard::processKey. - if (platformName == QLatin1String("eglfs") && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) + if (platformName == "eglfs"_L1 && !qEnvironmentVariableIntValue("QT_QPA_EGLFS_NO_LIBINPUT")) return KeyboardDriver::Xkb; #endif #if QT_CONFIG(evdev) // Based on QEglFSIntegration::createInputHandlers. - if (platformName == QLatin1String("eglfs")) + if (platformName == "eglfs"_L1) return KeyboardDriver::Evdev; #endif @@ -1249,9 +1252,9 @@ static WebInputEvent::Modifiers lockKeyModifiers(const quint32 nativeModifiers) { unsigned result = 0; if (keyboardDriver() == KeyboardDriver::Xkb) { - if (nativeModifiers & 0x42) /* Caps_Lock */ + if (nativeModifiers & 0x2) /* XCB_MOD_MASK_LOCK */ result |= WebInputEvent::kCapsLockOn; - if (nativeModifiers & 0x4d) /* Num_Lock */ + if (nativeModifiers & 0x10) /* XCB_MOD_MASK_2 */ result |= WebInputEvent::kNumLockOn; } else if (keyboardDriver() == KeyboardDriver::Windows) { if (nativeModifiers & 0x100) /* CapsLock */ @@ -1564,8 +1567,7 @@ blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev) case Qt::ScrollEnd: return blink::WebMouseWheelEvent::kPhaseEnded; } - Q_UNREACHABLE(); - return blink::WebMouseWheelEvent::kPhaseNone; + Q_UNREACHABLE_RETURN(blink::WebMouseWheelEvent::kPhaseNone); } blink::WebMouseWheelEvent::Phase getMomentumPhase(QWheelEvent *ev) @@ -1580,8 +1582,7 @@ blink::WebMouseWheelEvent::Phase getMomentumPhase(QWheelEvent *ev) case Qt::ScrollUpdate: return blink::WebMouseWheelEvent::kPhaseNone; } - Q_UNREACHABLE(); - return blink::WebMouseWheelEvent::kPhaseNone; + Q_UNREACHABLE_RETURN(blink::WebMouseWheelEvent::kPhaseNone); } blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev) @@ -1660,9 +1661,9 @@ void WebEventFactory::sendUnhandledWheelEvent(const blink::WebGestureEvent &even delegate->unhandledWheelEvent(&ev); } -content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) +input::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *ev) { - content::NativeWebKeyboardEvent webKitEvent(ToNativeEvent(ev)); + input::NativeWebKeyboardEvent webKitEvent(ToNativeEvent(ev)); webKitEvent.SetTimeStamp(base::TimeTicks::Now()); bool isBackTabWithoutModifier = ev->key() == Qt::Key_Backtab && ev->modifiers() == Qt::NoModifier; @@ -1673,16 +1674,17 @@ content::NativeWebKeyboardEvent WebEventFactory::toWebKeyboardEvent(QKeyEvent *e int qtKey = qtKeyForKeyEvent(ev); Qt::KeyboardModifiers qtModifiers = isBackTabWithoutModifier ? Qt::ShiftModifier : qtModifiersForEvent(ev); - QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers); + const QString qtText = qtTextForKeyEvent(ev, qtKey, qtModifiers); webKitEvent.native_key_code = nativeKeyCodeForKeyEvent(ev); webKitEvent.windows_key_code = windowsKeyCodeForQtKey(qtKey, qtModifiers & Qt::KeypadModifier); if (qtKey >= Qt::Key_Escape) webKitEvent.dom_key = domKeyForQtKey(qtKey); - else if (!qtText.isEmpty()) - webKitEvent.dom_key = ui::DomKey::FromCharacter(qtText.toUcs4().first()); - else { + else if (!qtText.isEmpty()) { + QStringIterator it(qtText); + webKitEvent.dom_key = ui::DomKey::FromCharacter(it.next()); + } else { QChar ch(qtKey); if (!(qtModifiers & Qt::ShiftModifier)) // No way to check for caps lock ch = ch.toLower(); diff --git a/src/core/web_event_factory.h b/src/core/web_event_factory.h index 53ebfb5096c..873a08a6350 100644 --- a/src/core/web_event_factory.h +++ b/src/core/web_event_factory.h @@ -6,7 +6,7 @@ #include "QtGui/qtguiglobal.h" -#include "content/public/common/input/native_web_keyboard_event.h" +#include "components/input/native_web_keyboard_event.h" #if QT_CONFIG(gestures) #include "third_party/blink/public/common/input/web_gesture_event.h" #endif @@ -46,7 +46,7 @@ class WebEventFactory { static blink::WebMouseWheelEvent toWebWheelEvent(QWheelEvent *); static bool coalesceWebWheelEvent(blink::WebMouseWheelEvent &, QWheelEvent *); static void sendUnhandledWheelEvent(const blink::WebGestureEvent &, RenderWidgetHostViewQtDelegate *); - static content::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*); + static input::NativeWebKeyboardEvent toWebKeyboardEvent(QKeyEvent*); static bool getEditCommand(QKeyEvent *event, std::string *editCommand); }; diff --git a/src/gn/CMakeLists.txt b/src/gn/CMakeLists.txt index 9782f17abc8..09202364e11 100644 --- a/src/gn/CMakeLists.txt +++ b/src/gn/CMakeLists.txt @@ -26,7 +26,7 @@ set(GN_BINARY_DIR ${CMAKE_CURRENT_BINARY_DIR}) set(GN_LINKER ${CMAKE_CXX_COMPILER}) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBENGINE_ROOT_SOURCE_DIR}/cmake") -find_package(Python3 REQUIRED) +find_package(Python3 3.8 REQUIRED) find_package(Ninja 1.7.2 REQUIRED) if(WIN32) @@ -70,8 +70,8 @@ add_custom_command( --platform ${platform} --ar ${CMAKE_AR} --qt-version "${QT_REPO_MODULE_VERSION}.qtwebengine.qt.io" - $<$:--isysroot> - $<$:${CMAKE_OSX_SYSROOT}> + $<$,$>:--isysroot> + $<$,$>:${CMAKE_OSX_SYSROOT}> $<$,$>:--osx-architectures> $<$,$>:${OSX_ARCH}> COMMAND Ninja::ninja -C ${GN_BINARY_DIR}/$ ${GN_EXECUTABLE} diff --git a/src/host/BUILD.clang-cl.toolchain.gn.in b/src/host/BUILD.clang-cl.toolchain.gn.in new file mode 100644 index 00000000000..b9b1fedc4cc --- /dev/null +++ b/src/host/BUILD.clang-cl.toolchain.gn.in @@ -0,0 +1,80 @@ +import("//build/config/sysroot.gni") +import("//build/toolchain/win/toolchain.gni") + +msvc_toolchain("x64") { + cl = "clang-cl.exe" + environment = "environment.x64" + toolchain_args = { + current_os = "win" + current_cpu = "x64" + is_clang = true + use_clang_coverage = false + } +} + +msvc_toolchain("x86") { + cl = "clang-cl.exe" + environment = "environment.x86" + toolchain_args = { + current_os = "win" + current_cpu = "x86" + is_clang = true + use_clang_coverage = false + } +} + +msvc_toolchain("arm64") { + cl = "clang-cl.exe" + environment = "environment.arm64" + toolchain_args = { + current_os = "win" + current_cpu = "arm64" + is_clang = true + use_clang_coverage = false + } +} + +#TODO: drop it after clean up breakpad, remove upload symbols exacutable +msvc_system_allocator_toolchain("x64_host_with_system_allocator") { + cl = "clang-cl.exe" + environment = "environment.x64" + toolchain_args = { + current_cpu = "x64" + current_os = "win" + is_clang = true + use_clang_coverage = false + } +} + +msvc_system_allocator_toolchain("arm64_host_with_system_allocator") { + cl = "clang-cl.exe" + environment = "environment.arm64" + toolchain_args = { + current_cpu = "arm64" + current_os = "win" + is_clang = true + use_clang_coverage = false + } +} + +msvc_system_allocator_toolchain("x64_with_system_allocator") { + cl = "clang-cl.exe" + environment = "environment.x64" + toolchain_args = { + current_cpu = "x64" + current_os = "win" + is_clang = true + use_clang_coverage = false + } +} + +msvc_system_allocator_toolchain("arm64_with_system_allocator") { + cl = "clang-cl.exe" + environment = "environment.arm64" + toolchain_args = { + current_cpu = "arm64" + current_os = "win" + is_clang = true + use_clang_coverage = false + } +} diff --git a/src/host/BUILD.msvc.toolchain.gn.in b/src/host/BUILD.msvc.toolchain.gn.in new file mode 100644 index 00000000000..827002affa9 --- /dev/null +++ b/src/host/BUILD.msvc.toolchain.gn.in @@ -0,0 +1,80 @@ +import("//build/config/sysroot.gni") +import("//build/toolchain/win/toolchain.gni") + +msvc_toolchain("x64") { + cl = "cl.exe" + environment = "environment.x64" + toolchain_args = { + current_os = "win" + current_cpu = "x64" + is_clang = false + use_clang_coverage = false + } +} + +msvc_toolchain("x86") { + cl = "cl.exe" + environment = "environment.x86" + toolchain_args = { + current_os = "win" + current_cpu = "x86" + is_clang = false + use_clang_coverage = false + } +} + +msvc_toolchain("arm64") { + cl = "cl.exe" + environment = "environment.arm64" + toolchain_args = { + current_os = "win" + current_cpu = "arm64" + is_clang = false + use_clang_coverage = false + } +} + +#TODO: drop it after clean up breakpad, remove upload symbols exacutable +msvc_system_allocator_toolchain("x64_host_with_system_allocator") { + cl = "cl.exe" + environment = "environment.x64" + toolchain_args = { + current_cpu = "x64" + current_os = "win" + is_clang = false + use_clang_coverage = false + } +} + +msvc_system_allocator_toolchain("arm64_host_with_system_allocator") { + cl = "cl.exe" + environment = "environment.arm64" + toolchain_args = { + current_cpu = "arm64" + current_os = "win" + is_clang = false + use_clang_coverage = false + } +} + +msvc_system_allocator_toolchain("x64_with_system_allocator") { + cl = "cl.exe" + environment = "environment.x64" + toolchain_args = { + current_cpu = "x64" + current_os = "win" + is_clang = false + use_clang_coverage = false + } +} + +msvc_system_allocator_toolchain("arm64_with_system_allocator") { + cl = "cl.exe" + environment = "environment.arm64" + toolchain_args = { + current_cpu = "arm64" + current_os = "win" + is_clang = false + use_clang_coverage = false + } +} diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt index d40275217bb..7e9eab365c3 100644 --- a/src/host/CMakeLists.txt +++ b/src/host/CMakeLists.txt @@ -12,6 +12,7 @@ endif() include(${WEBENGINE_ROOT_SOURCE_DIR}/.cmake.conf) include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/Functions.cmake) +include(${WEBENGINE_ROOT_SOURCE_DIR}/cmake/QtToolchainHelpers.cmake) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${WEBENGINE_ROOT_SOURCE_DIR}/cmake") diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt index 33d918f8c39..30369b9f9da 100644 --- a/src/pdf/CMakeLists.txt +++ b/src/pdf/CMakeLists.txt @@ -3,7 +3,6 @@ cmake_minimum_required(VERSION 3.19) find_package(Ninja 1.7.2 REQUIRED) -find_package(Nodejs 14.19 REQUIRED) find_package(PkgConfig) if(PkgConfig_FOUND) create_pkg_config_host_wrapper(${CMAKE_CURRENT_BINARY_DIR}) @@ -70,7 +69,7 @@ add_dependencies(prepare_docs_Pdf generate_pdf_attributions) # TOOLCHAIN SETUP ## -if(LINUX OR MINGW OR ANDROID) +if(LINUX OR MINGW OR ANDROID OR WIN32) setup_toolchains() endif() @@ -120,13 +119,18 @@ foreach(arch ${archs}) qt_libjpeg_config="${buildDir}/${config}/${arch}:qt_libjpeg_config" qt_harfbuzz_config="${buildDir}/${config}/${arch}:qt_harfbuzz_config" qt_freetype_config="${buildDir}/${config}/${arch}:qt_freetype_config" + is_qtwebengine=true + is_qtpdf=true + enable_bluetooth_emulation=false enable_swiftshader=false enable_swiftshader_vulkan=false angle_enable_swiftshader=false dawn_use_swiftshader=false + pdf_enable_fontations=false use_cups=false use_dawn=false build_dawn_tests=false + enable_nocompile_tests=false enable_ipc_fuzzer=false enable_remoting=false enable_resource_allowlist_generation=false @@ -135,14 +139,23 @@ foreach(arch ${archs}) chrome_pgo_phase=0 strip_absolute_paths_from_debug_symbols=false v8_enable_webassembly=false - ) + use_v8_context_snapshot=false + v8_use_external_startup_data=false + ) if(LINUX OR ANDROID) list(APPEND gnArgArg + enable_vr=false is_cfi=false ozone_auto_platforms=false enable_arcore=false use_ml_inliner=false + use_udev=false + use_gio=false + use_glib=false + use_nss_certs=false + use_xkbcommon=false + v8_use_external_startup_data=false ) extend_gn_list(gnArgArg ARGS use_system_icu @@ -165,7 +178,6 @@ foreach(arch ${archs}) endif() if(WIN32 OR ANDROID) list(APPEND gnArgArg - ninja_use_custom_environment_files=false safe_browsing_mode=0 ) extend_gn_list(gnArgArg @@ -252,6 +264,7 @@ add_gn_build_artifacts_to_target( CMAKE_TARGET Pdf NINJA_TARGET QtPdf MODULE pdf + DEPENDS Pdf_sync_headers BUILDDIR ${buildDir} COMPLETE_STATIC TRUE NINJA_STAMP QtPdf.stamp diff --git a/src/pdf/doc/qtpdf.qdocconf b/src/pdf/doc/qtpdf.qdocconf index 7f69c539ac9..15151ae0936 100644 --- a/src/pdf/doc/qtpdf.qdocconf +++ b/src/pdf/doc/qtpdf.qdocconf @@ -42,6 +42,7 @@ depends += qtcore \ qtdoc \ qmake \ qtdesigner \ + qtqml \ qtquick \ qtquickcontrols \ qtcmake \ diff --git a/src/pdf/qpdfbookmarkmodel.cpp b/src/pdf/qpdfbookmarkmodel.cpp index 41979e27db1..44fb07c621f 100644 --- a/src/pdf/qpdfbookmarkmodel.cpp +++ b/src/pdf/qpdfbookmarkmodel.cpp @@ -219,7 +219,7 @@ struct QPdfBookmarkModelPrivate \inmodule QtPdf \inherits QAbstractItemModel - \brief The QPdfBookmarkModel class holds a tree of of links (anchors) + \brief The QPdfBookmarkModel class holds a tree of links (anchors) within a PDF document, such as the table of contents. This is used in the \l {Model/View Programming} paradigm to display a diff --git a/src/pdfquick/qquickpdfdocument.cpp b/src/pdfquick/qquickpdfdocument.cpp index 7ffb0527e32..217e8db1cf7 100644 --- a/src/pdfquick/qquickpdfdocument.cpp +++ b/src/pdfquick/qquickpdfdocument.cpp @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -64,7 +65,13 @@ void QQuickPdfDocument::classBegin() This property holds a URL pointing to the PDF file to be loaded. - \note At this time, only local filesystem URLs are supported. + \note At this time, only local filesystem and + \l {The Qt Resource System} {resource} URLs are supported. Nevertheless, + the \c source property is a \l {QUrl}{URL}, not merely a filesystem path. + PdfDocument resolves it via QQmlContext::resolvedUrl(). You should + typically ensure that the URL starts with a \c {file://} scheme, unless you + mean to load the PDF file from resources, or it comes from some component + (such as \l {QtQuick.Controls::}{FileDialog}) that resolves it in advance. */ void QQuickPdfDocument::setSource(QUrl source) { @@ -85,6 +92,8 @@ void QQuickPdfDocument::setSource(QUrl source) m_resolvedSource = context ? context->resolvedUrl(source) : source; if (m_resolvedSource.isValid()) m_doc->load(QQmlFile::urlToLocalFileOrQrc(m_resolvedSource)); + else + qmlWarning(this) << QQuickPdfDocument::tr("Cannot open: %1").arg(m_resolvedSource.toString()); } /*! diff --git a/src/process/CMakeLists.txt b/src/process/CMakeLists.txt index 630ba42a8b0..37bca3b4c54 100644 --- a/src/process/CMakeLists.txt +++ b/src/process/CMakeLists.txt @@ -13,8 +13,16 @@ find_package(Qt6 COMPONENTS Gui) get_target_property(qtWebEngineProcessName WebEngineCore QTWEBENGINEPROCESS_NAME) get_target_property(isFramework WebEngineCore FRAMEWORK) -qt_internal_add_executable(${qtWebEngineProcessName} +if(isFramework) + set(install_dir "${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers") +else() + set(install_dir "${INSTALL_LIBEXECDIR}") +endif() + +qt_internal_add_app(${qtWebEngineProcessName} + TARGET_DESCRIPTION "QtWebEngine internal process" NO_INSTALL + INCLUDE_DIRECTORIES ../core SOURCES main.cpp ) @@ -43,21 +51,12 @@ qt_internal_extend_target(${qtWebEngineProcessName} Qt::WebEngineCorePrivate ) -target_include_directories(${qtWebEngineProcessName} PRIVATE ../core) - qt_get_cmake_configurations(configs) foreach(config ${configs}) string(TOUPPER "${config}" config_upper) - if(isFramework) - set(outputPath - "${QT_BUILD_DIR}/${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers" - ) - else() - set(outputPath "${QT_BUILD_DIR}/${INSTALL_LIBEXECDIR}") - endif() set_target_properties(${qtWebEngineProcessName} PROPERTIES - RUNTIME_OUTPUT_DIRECTORY_${config_upper} "${outputPath}" + RUNTIME_OUTPUT_DIRECTORY_${config_upper} "${QT_BUILD_DIR}/${install_dir}" ) if("${config}" STREQUAL "Debug") @@ -67,6 +66,8 @@ foreach(config ${configs}) endif() endforeach() +set_property(TARGET ${qtWebEngineProcessName} PROPERTY EXCLUDE_FROM_ALL OFF) + if(isFramework) set_target_properties(${qtWebEngineProcessName} PROPERTIES MACOSX_BUNDLE TRUE @@ -86,7 +87,7 @@ if(isFramework) USES_TERMINAL ) install(TARGETS ${qtWebEngineProcessName} - BUNDLE DESTINATION "${INSTALL_LIBDIR}/QtWebEngineCore.framework/Versions/A/Helpers" + BUNDLE DESTINATION "${install_dir}" COMPONENT Runtime ) qt_enable_separate_debug_info(${qtWebEngineProcessName} @@ -94,12 +95,12 @@ if(isFramework) DSYM_OUTPUT_DIR "${CMAKE_BINARY_DIR}/${INSTALL_LIBDIR}" ) else() - qt_apply_rpaths(TARGET ${qtWebEngineProcessName} INSTALL_PATH "${INSTALL_LIBEXECDIR}" RELATIVE_RPATH) + qt_apply_rpaths(TARGET ${qtWebEngineProcessName} INSTALL_PATH "${install_dir}" RELATIVE_RPATH) install(TARGETS ${qtWebEngineProcessName} CONFIGURATIONS ${configs} - RUNTIME DESTINATION "${INSTALL_LIBEXECDIR}" + RUNTIME DESTINATION "${install_dir}" ) - qt_enable_separate_debug_info(${qtWebEngineProcessName} "${INSTALL_LIBEXECDIR}" QT_EXECUTABLE) - qt_internal_install_pdb_files(${qtWebEngineProcessName} "${INSTALL_LIBEXECDIR}") + qt_enable_separate_debug_info(${qtWebEngineProcessName} "${install_dir}" QT_EXECUTABLE) + qt_internal_install_pdb_files(${qtWebEngineProcessName} "${install_dir}") endif() diff --git a/src/webenginequick/api/qquickwebengineprofile.cpp b/src/webenginequick/api/qquickwebengineprofile.cpp index 70343e5ce1c..7eb59d74876 100644 --- a/src/webenginequick/api/qquickwebengineprofile.cpp +++ b/src/webenginequick/api/qquickwebengineprofile.cpp @@ -243,7 +243,7 @@ void QQuickWebEngineProfilePrivate::cleanDownloads() m_ongoingDownloads.clear(); } -void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) +void QQuickWebEngineProfilePrivate::downloadRequested(const DownloadItemInfo &info) { Q_Q(QQuickWebEngineProfile); diff --git a/src/webenginequick/api/qquickwebengineprofile.h b/src/webenginequick/api/qquickwebengineprofile.h index df41404da36..17a0548688e 100644 --- a/src/webenginequick/api/qquickwebengineprofile.h +++ b/src/webenginequick/api/qquickwebengineprofile.h @@ -48,7 +48,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfile : public QObject { public: QQuickWebEngineProfile(QObject *parent = nullptr); - QQuickWebEngineProfile(const QString &storageName, QObject *parent = nullptr); + explicit QQuickWebEngineProfile(const QString &storageName, QObject *parent = nullptr); ~QQuickWebEngineProfile(); enum HttpCacheType { diff --git a/src/webenginequick/api/qquickwebengineprofile_p.h b/src/webenginequick/api/qquickwebengineprofile_p.h index 477936f98c4..fde24763665 100644 --- a/src/webenginequick/api/qquickwebengineprofile_p.h +++ b/src/webenginequick/api/qquickwebengineprofile_p.h @@ -50,7 +50,7 @@ class QQuickWebEngineProfilePrivate : public QtWebEngineCore::ProfileAdapterClie void cleanDownloads(); - void downloadRequested(DownloadItemInfo &info) override; + void downloadRequested(const DownloadItemInfo &info) override; void downloadUpdated(const DownloadItemInfo &info) override; void showNotification(QSharedPointer &controller) override; diff --git a/src/webenginequick/api/qquickwebengineprofileprototype_p.h b/src/webenginequick/api/qquickwebengineprofileprototype_p.h index 5573d2f5d0b..a29956e5b80 100644 --- a/src/webenginequick/api/qquickwebengineprofileprototype_p.h +++ b/src/webenginequick/api/qquickwebengineprofileprototype_p.h @@ -48,7 +48,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineProfilePrototype : public QObject, ~QQuickWebEngineProfilePrototype(); QString storageName() const; - void setStorageName(const QString &path); + void setStorageName(const QString &storageName); QString persistentStoragePath() const; void setPersistentStoragePath(const QString &path); diff --git a/src/webenginequick/api/qquickwebenginesettings.cpp b/src/webenginequick/api/qquickwebenginesettings.cpp index 29bf0f93e93..fadc1bfef0d 100644 --- a/src/webenginequick/api/qquickwebenginesettings.cpp +++ b/src/webenginequick/api/qquickwebenginesettings.cpp @@ -519,7 +519,7 @@ bool QQuickWebEngineSettings::scrollAnimatorEnabled() const } /*! - \qmlproperty bool WebEngineSettings::jsTouchEventsEnabled + \qmlproperty bool WebEngineSettings::touchEventsApiEnabled \since QtWebEngine 6.9 Enables support for JavaScript touch events API, meaning \c ontouchstart, @@ -532,9 +532,9 @@ bool QQuickWebEngineSettings::scrollAnimatorEnabled() const Enabled by default if a touch device detected by the system and disabled otherwise. */ -bool QQuickWebEngineSettings::jsTouchEventsEnabled() const +bool QQuickWebEngineSettings::touchEventsApiEnabled() const { - return d_ptr->testAttribute(QWebEngineSettings::JSTouchEventsEnabled); + return d_ptr->testAttribute(QWebEngineSettings::TouchEventsApiEnabled); } /*! @@ -921,12 +921,12 @@ void QQuickWebEngineSettings::setImageAnimationPolicy( Q_EMIT imageAnimationPolicyChanged(); } -void QQuickWebEngineSettings::setJSTouchEventsEnabled(bool on) +void QQuickWebEngineSettings::setTouchEventsApiEnabled(bool on) { - bool wasOn = d_ptr->testAttribute(QWebEngineSettings::JSTouchEventsEnabled); - d_ptr->setAttribute(QWebEngineSettings::JSTouchEventsEnabled, on); + bool wasOn = d_ptr->testAttribute(QWebEngineSettings::TouchEventsApiEnabled); + d_ptr->setAttribute(QWebEngineSettings::TouchEventsApiEnabled, on); if (wasOn != on) - Q_EMIT jsTouchEventsEnabledChanged(); + Q_EMIT touchEventsApiEnabledChanged(); } QT_END_NAMESPACE diff --git a/src/webenginequick/api/qquickwebenginesettings_p.h b/src/webenginequick/api/qquickwebenginesettings_p.h index 85b1a538e2d..843e21a4df9 100644 --- a/src/webenginequick/api/qquickwebenginesettings_p.h +++ b/src/webenginequick/api/qquickwebenginesettings_p.h @@ -63,7 +63,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject { Q_PROPERTY(ImageAnimationPolicy imageAnimationPolicy READ imageAnimationPolicy WRITE setImageAnimationPolicy NOTIFY imageAnimationPolicyChanged REVISION(6,8) FINAL) Q_PROPERTY(bool printHeaderAndFooter READ printHeaderAndFooter WRITE setPrintHeaderAndFooter NOTIFY printHeaderAndFooterChanged REVISION(6,9) FINAL) Q_PROPERTY(bool preferCSSMarginsForPrinting READ preferCSSMarginsForPrinting WRITE setPreferCSSMarginsForPrinting NOTIFY preferCSSMarginsForPrintingChanged REVISION(6,9) FINAL) - Q_PROPERTY(bool jsTouchEventsEnabled READ jsTouchEventsEnabled WRITE setJSTouchEventsEnabled NOTIFY jsTouchEventsEnabledChanged REVISION(6,9) FINAL) + Q_PROPERTY(bool touchEventsApiEnabled READ touchEventsApiEnabled WRITE setTouchEventsApiEnabled NOTIFY touchEventsApiEnabledChanged REVISION(6,9) FINAL) QML_NAMED_ELEMENT(WebEngineSettings) QML_ADDED_IN_VERSION(1, 1) @@ -126,7 +126,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject { ImageAnimationPolicy imageAnimationPolicy() const; bool printHeaderAndFooter() const; bool preferCSSMarginsForPrinting() const; - bool jsTouchEventsEnabled() const; + bool touchEventsApiEnabled() const; void setAutoLoadImages(bool on); void setJavascriptEnabled(bool on); @@ -166,7 +166,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject { void setImageAnimationPolicy(ImageAnimationPolicy policy); void setPrintHeaderAndFooter(bool on); void setPreferCSSMarginsForPrinting(bool on); - void setJSTouchEventsEnabled(bool on); + void setTouchEventsApiEnabled(bool on); signals: void autoLoadImagesChanged(); @@ -207,7 +207,7 @@ class Q_WEBENGINEQUICK_EXPORT QQuickWebEngineSettings : public QObject { Q_REVISION(6,8) void imageAnimationPolicyChanged(); Q_REVISION(6,9) void printHeaderAndFooterChanged(); Q_REVISION(6,9) void preferCSSMarginsForPrintingChanged(); - Q_REVISION(6,9) void jsTouchEventsEnabledChanged(); + Q_REVISION(6,9) void touchEventsApiEnabledChanged(); private: explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = nullptr); diff --git a/src/webenginequick/api/qquickwebengineview.cpp b/src/webenginequick/api/qquickwebengineview.cpp index f1b7c204657..dae4a375399 100644 --- a/src/webenginequick/api/qquickwebengineview.cpp +++ b/src/webenginequick/api/qquickwebengineview.cpp @@ -516,8 +516,7 @@ static QQuickWebEngineView::Feature toDeprecatedFeature(QWebEnginePermission::Pe break; } - Q_UNREACHABLE(); - return QQuickWebEngineView::Feature(-1); + Q_UNREACHABLE_RETURN(QQuickWebEngineView::Feature(-1)); } QT_WARNING_POP #endif // QT_DEPRECATED_SINCE(6, 8) @@ -879,6 +878,7 @@ QObject *QQuickWebEngineViewPrivate::accessibilityParentObject() ProfileAdapter *QQuickWebEngineViewPrivate::profileAdapter() { + initializeProfile(); return m_profile->d_ptr->profileAdapter(); } diff --git a/src/webenginequick/doc/src/webengineview_lgpl.qdoc b/src/webenginequick/doc/src/webengineview_lgpl.qdoc index 8c6b99dd7ea..3f042a8c3ef 100644 --- a/src/webenginequick/doc/src/webengineview_lgpl.qdoc +++ b/src/webenginequick/doc/src/webengineview_lgpl.qdoc @@ -1334,7 +1334,7 @@ If remote debugging is enabled (see \l{Qt WebEngine Developer Tools}), the id can be used to build the URL to connect to the developer tool websocket: - \c{ws://localhost:/devtools/page/)}. The websocket can be used to to interact + \c{ws://localhost:/devtools/page/)}. The websocket can be used to to interact with the page using the \l{https://chromedevtools.github.io/devtools-protocol/}{DevTools Protocol}. */ diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp index 090b0928109..b507d760b79 100644 --- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp +++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow.cpp @@ -7,6 +7,25 @@ namespace QtWebEngineCore { +struct ItemTransform { + qreal rotation = 0.; + qreal scale = 1.; +}; + +// Helper function to calculate the cumulative rotation and scale. +static inline struct ItemTransform getTransformValuesFromItemTree(QQuickItem *item) +{ + struct ItemTransform returnValue; + + while (item) { + returnValue.rotation += item->rotation(); + returnValue.scale *= item->scale(); + item = item->parentItem(); + } + + return returnValue; +} + static inline QPoint getOffset(QQuickItem *item) { // get parent window (scene) offset @@ -32,7 +51,7 @@ static inline QPointF transformPoint(const QPointF &point, const QTransform &tra RenderWidgetHostViewQtDelegateQuickWindow::RenderWidgetHostViewQtDelegateQuickWindow( RenderWidgetHostViewQtDelegateItem *realDelegate, QWindow *parent) - : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_rotated(false) + : QQuickWindow(parent), m_realDelegate(realDelegate), m_virtualParent(nullptr), m_transformed(false) { setFlags(Qt::Tool | Qt::WindowStaysOnTopHint | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus); realDelegate->setParentItem(contentItem()); @@ -56,9 +75,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::setVirtualParent(QQuickItem *vir // chromium knows nothing about local transformation void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) { - m_rotated = m_virtualParent->rotation() > 0 || m_virtualParent->parentItem()->rotation() > 0; - if (m_rotated) { - // code below tries to cover the case where webengine view is rotated, + // To decide if there is a scale or rotation, we check it from the transfrom + // to also cover the case where the scale is higher up in the item tree. + QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr); + m_transformed = transform.isRotating() || transform.isScaling(); + + if (m_transformed) { + // code below tries to cover the case where webengine view is rotated or scaled, // the code assumes the rotation is in the form of 90, 180, 270 degrees // to archive that we keep chromium unaware of transformation and we transform // just the window content. @@ -67,7 +90,6 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) QPointF offset = m_virtualParent->mapFromScene(QPoint(0, 0)); offset = m_virtualParent->mapToGlobal(offset); // get local transform - QTransform transform = m_virtualParent->itemTransform(nullptr, nullptr); QPointF tl = transformPoint(rect.topLeft(), transform, offset, m_virtualParent); QPointF br = transformPoint(rect.bottomRight(), transform, offset, m_virtualParent); QRectF popupRect(tl, br); @@ -80,7 +102,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) m_realDelegate->setX(-rect.width() / 2.0 + geometry().width() / 2.0); m_realDelegate->setY(-rect.height() / 2.0 + geometry().height() / 2.0); m_realDelegate->setTransformOrigin(QQuickItem::Center); - m_realDelegate->setRotation(m_virtualParent->parentItem()->rotation()); + + // We need to read the values for scale and rotation from the item tree as it is not + // sufficient to only use the virtual parent item and its parent for the case that the + // scale or rotation is applied higher up the item tree. + struct ItemTransform transformValues = getTransformValuesFromItemTree(m_virtualParent); + m_realDelegate->setRotation(transformValues.rotation); + m_realDelegate->setScale(transformValues.scale); } else { QRect geometry(rect); geometry.moveTo(rect.topLeft() - getOffset(m_virtualParent)); @@ -93,13 +121,13 @@ void RenderWidgetHostViewQtDelegateQuickWindow::InitAsPopup(const QRect &rect) void RenderWidgetHostViewQtDelegateQuickWindow::Resize(int width, int height) { - if (!m_rotated) + if (!m_transformed) QQuickWindow::resize(width, height); } void RenderWidgetHostViewQtDelegateQuickWindow::MoveWindow(const QPoint &screenPos) { - if (!m_rotated) + if (!m_transformed) QQuickWindow::setPosition(screenPos - getOffset(m_virtualParent)); } diff --git a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h index 3559bd2f080..691fceb5257 100644 --- a/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h +++ b/src/webenginequick/render_widget_host_view_qt_delegate_quickwindow_p.h @@ -49,7 +49,7 @@ class RenderWidgetHostViewQtDelegateQuickWindow : public QQuickWindow , public W QPointer m_realDelegate; QQuickItem *m_virtualParent; QRect m_rect; - bool m_rotated; + bool m_transformed; }; } // namespace QtWebEngineCore diff --git a/src/webenginequick/ui_delegates_manager.cpp b/src/webenginequick/ui_delegates_manager.cpp index f4036059d6a..f2488a7c285 100644 --- a/src/webenginequick/ui_delegates_manager.cpp +++ b/src/webenginequick/ui_delegates_manager.cpp @@ -122,8 +122,7 @@ bool UIDelegatesManager::ensureComponentLoaded(ComponentType type) switch (type) { FOR_EACH_COMPONENT_TYPE(COMPONENT_MEMBER_CASE_STATEMENT, NO_SEPARATOR) default: - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); } QString fileName(fileNameForComponent(type)); #ifndef UI_DELEGATES_DEBUG diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 0e2a1be3a34..8557ebb8f51 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -439,6 +439,7 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget { Q_Q(QWebEngineView); + bool hasFocus = oldWidget ? oldWidget->hasFocus() : false; if (oldWidget) { q->layout()->removeWidget(oldWidget); oldWidget->hide(); @@ -457,7 +458,7 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::WebEngineQuickWidget #endif q->layout()->addWidget(newWidget); q->setFocusProxy(newWidget); - if (oldWidget && oldWidget == QApplication::focusWidget()) + if (hasFocus) newWidget->setFocus(); newWidget->show(); } @@ -1480,7 +1481,7 @@ void QWebEngineView::printToPdf(const std::function &re When finished the signal printFinished() is emitted with the \c true for success or \c false for failure. - It is the users responsibility to ensure the \a printer remains valid until printFinished() + It is the user's responsibility to ensure the \a printer remains valid until printFinished() has been emitted. \note Printing runs on the browser process, which is by default not sandboxed. diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc index c9bd76bf4e3..2dd55c0369c 100644 --- a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc +++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc @@ -10,6 +10,6 @@ open source browser engine. These examples and demonstrations show a range of different uses for \QWE, - from displaying Web pages within a Qt user interface to an implementation of - a basic function Web browser. + from displaying web pages within a Qt user interface to an implementation of + a basic function web browser. */ diff --git a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp index 27ef7383a3b..42c394a847b 100644 --- a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp +++ b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp @@ -55,22 +55,22 @@ void tst_QWebEngineClientCertificateStore::addAndListCertificates() { // Load QSslCertificate QFile certFile(":/resources/certificate.crt"); - certFile.open(QIODevice::ReadOnly); + QVERIFY2(certFile.open(QIODevice::ReadOnly), qPrintable(certFile.errorString())); const QSslCertificate cert(certFile.readAll(), QSsl::Pem); // Load QSslKey QFile keyFile(":/resources/privatekey.key"); - keyFile.open(QIODevice::ReadOnly); + QVERIFY2(keyFile.open(QIODevice::ReadOnly), qPrintable(keyFile.errorString())); const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); // Load second QSslCertificate QFile certFileSecond(":/resources/certificate1.crt"); - certFileSecond.open(QIODevice::ReadOnly); + QVERIFY2(certFileSecond.open(QIODevice::ReadOnly), qPrintable(certFileSecond.errorString())); const QSslCertificate certSecond(certFileSecond.readAll(), QSsl::Pem); // Load second QSslKey QFile keyFileSecond(":/resources/privatekey1.key"); - keyFileSecond.open(QIODevice::ReadOnly); + QVERIFY2(keyFileSecond.open(QIODevice::ReadOnly), qPrintable(keyFileSecond.errorString())); const QSslKey sslKeySecond(keyFileSecond.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); // Add certificates to in-memory store @@ -138,11 +138,11 @@ void tst_QWebEngineClientCertificateStore::clientAuthentication() }); QFile certFile(client_certificate); - certFile.open(QIODevice::ReadOnly); + QVERIFY2(certFile.open(QIODevice::ReadOnly), qPrintable(certFile.errorString())); const QSslCertificate cert(certFile.readAll(), QSsl::Pem); QFile keyFile(client_key); - keyFile.open(QIODevice::ReadOnly); + QVERIFY2(keyFile.open(QIODevice::ReadOnly), qPrintable(keyFile.errorString())); const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, ""); if (in_memory) diff --git a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp index 4c8b0db6df4..16a96f8e33c 100644 --- a/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp +++ b/tests/auto/core/qwebenginesettings/tst_qwebenginesettings.cpp @@ -335,7 +335,7 @@ void tst_QWebEngineSettings::javaScriptTouchEvents() QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool))); if (isExplicitlySet) - page.settings()->setAttribute(QWebEngineSettings::JSTouchEventsEnabled, + page.settings()->setAttribute(QWebEngineSettings::TouchEventsApiEnabled, jsTouchEventsEnabled); page.settings()->setAttribute(QWebEngineSettings::JavascriptEnabled, true); diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index 2d8dcdd2838..ad9f91a939b 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -1,8 +1,6 @@ // Copyright (C) 2017 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses - #include #include #include @@ -162,7 +160,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor { QList infos; - foreach (auto requestInfo, requestInfos) { + for (const auto &requestInfo : requestInfos) { if (shouldSkipRequest(requestInfo)) continue; @@ -175,7 +173,7 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor bool hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceType type) { - foreach (auto requestInfo, requestInfos) { + for (const auto &requestInfo : requestInfos) { if (shouldSkipRequest(requestInfo)) continue; @@ -573,43 +571,43 @@ void tst_QWebEngineUrlRequestInterceptor::firstPartyUrlHttp() // Stylesheet QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Script QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Image QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // FontResource QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Media QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // Favicon QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); // XMLHttpRequest QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); } @@ -725,43 +723,43 @@ void tst_QWebEngineUrlRequestInterceptor::initiator() // Stylesheet QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeStylesheet); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Script QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeScript); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Image QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeImage); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // FontResource QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFontResource); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Media QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeMedia); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // Favicon QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeFavicon); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); // XMLHttpRequest QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeXhr); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QVERIFY(interceptor.requestInitiatorUrls[info.requestUrl].contains(info.initiator)); } @@ -794,7 +792,7 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker() // Service Worker QTRY_VERIFY(interceptor.hasUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker)); infos = interceptor.getUrlRequestForType(QWebEngineUrlRequestInfo::ResourceTypeServiceWorker); - foreach (auto info, infos) + for (const RequestInfo &info : std::as_const(infos)) QCOMPARE(info.firstPartyUrl, firstPartyUrl); QVERIFY(server.stop()); @@ -803,17 +801,17 @@ void tst_QWebEngineUrlRequestInterceptor::jsServiceWorker() void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor_data() { QTest::addColumn("firstInterceptIsInPage"); - QTest::addColumn("keepInterceptionPoint"); + QTest::addColumn("secondInterceptIsInPage"); QTest::newRow("page") << true << true; QTest::newRow("page-profile") << true << false; - QTest::newRow("profile") << false << true; - QTest::newRow("profile-page") << false << false; + QTest::newRow("profile") << false << false; + QTest::newRow("profile-page") << false << true; } void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() { QFETCH(bool, firstInterceptIsInPage); - QFETCH(bool, keepInterceptionPoint); + QFETCH(bool, secondInterceptIsInPage); HttpServer server; server.setResourceDirs({ ":/resources" }); @@ -838,17 +836,14 @@ void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() requestsOnReplace.push_back(interceptors[currentInterceptorIndex].requestInfos.size()); bool isFirstReinstall = currentInterceptorIndex == 0; - bool interceptInPage = keepInterceptionPoint ? firstInterceptIsInPage : (isFirstReinstall ^ firstInterceptIsInPage); + bool interceptInPage = isFirstReinstall ? firstInterceptIsInPage : secondInterceptIsInPage; setInterceptor(&interceptors[++currentInterceptorIndex], interceptInPage); - if (!keepInterceptionPoint) - setInterceptor(nullptr, !interceptInPage); + setInterceptor(nullptr, !interceptInPage); if (isFirstReinstall) { page.triggerAction(QWebEnginePage::Reload); } else { - page.runJavaScript("fetch('http://github.com/service/http://nonexistent.invalid/').catch(() => {})", [&, interceptInPage] (const QVariant &) { - requestsOnReplace.push_back(interceptors.back().requestInfos.size()); - setInterceptor(nullptr, interceptInPage); + page.runJavaScript("fetch('http://github.com/service/http://nonexistent.invalid/').catch(() => {})", [&fetchFinished] (const QVariant &) { fetchFinished = true; }); } @@ -857,6 +852,10 @@ void tst_QWebEngineUrlRequestInterceptor::replaceInterceptor() page.setUrl(server.url("http://github.com/favicon.html")); QTRY_COMPARE_WITH_TIMEOUT(spy.size(), 2, 20000); QTRY_VERIFY(fetchFinished); + QTRY_VERIFY(!interceptors.back().requestInfos.isEmpty()); + setInterceptor(nullptr, true); + setInterceptor(nullptr, false); + requestsOnReplace.push_back(interceptors.back().requestInfos.size()); QString s; QDebug d(&s); for (auto i = 0u; i < interceptors.size(); ++i) { @@ -958,7 +957,8 @@ class TestPostRequestInterceptor : public QWebEngineUrlRequestInterceptor QIODevice *requestBodyDevice = info.requestBody(); - requestBodyDevice->open(QIODevice::ReadOnly); + QVERIFY2(requestBodyDevice->open(QIODevice::ReadOnly), + qPrintable(requestBodyDevice->errorString())); const QString webKitBoundary = requestBodyDevice->read(40); QVERIFY(webKitBoundary.contains("------WebKitFormBoundary")); diff --git a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp index acddfb0e021..8552ba441b7 100644 --- a/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp +++ b/tests/auto/core/qwebengineurlrequestjob/tst_qwebengineurlrequestjob.cpp @@ -77,7 +77,7 @@ class AdditionalResponseHeadersHandler : public QWebEngineUrlSchemeHandler job->setAdditionalResponseHeaders(additionalResponseHeaders); QFile *file = new QFile(QStringLiteral(":additionalResponseHeadersScript.html"), job); - file->open(QIODevice::ReadOnly); + QVERIFY2(file->open(QIODevice::ReadOnly), qPrintable(file->errorString())); job->reply(QByteArrayLiteral("text/html"), file); } @@ -106,12 +106,13 @@ class RequestBodyHandler : public QWebEngineUrlSchemeHandler QCOMPARE(job->requestMethod(), QByteArrayLiteral("POST")); QIODevice *requestBodyDevice = job->requestBody(); - requestBodyDevice->open(QIODevice::ReadOnly); + QVERIFY2(requestBodyDevice->open(QIODevice::ReadOnly), + qPrintable(requestBodyDevice->errorString())); QByteArray requestBody = requestBodyDevice->readAll(); requestBodyDevice->close(); QBuffer *buf = new QBuffer(job); - buf->open(QBuffer::ReadWrite); + QVERIFY2(buf->open(QBuffer::ReadWrite), qPrintable(buf->errorString())); buf->write(requestBody); job->reply(QByteArrayLiteral("text/plain"), buf); buf->close(); diff --git a/tests/auto/core/webenginedriver/tst_webenginedriver.cpp b/tests/auto/core/webenginedriver/tst_webenginedriver.cpp index 66e14e68307..d83d850e2e0 100644 --- a/tests/auto/core/webenginedriver/tst_webenginedriver.cpp +++ b/tests/auto/core/webenginedriver/tst_webenginedriver.cpp @@ -116,8 +116,9 @@ class DriverServer : public QObject for (QString line : m_stdout) { if (line.contains( - QLatin1String("WebEngineDriver was started successfully."))) + QLatin1String("WebEngineDriver was started successfully"))) { return true; + } } return false; diff --git a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp index 45d1d5a7b01..1e90b221d2d 100644 --- a/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp +++ b/tests/auto/pdf/qpdfdocument/tst_qpdfdocument.cpp @@ -62,7 +62,7 @@ struct TemporaryPdf: public QTemporaryFile TemporaryPdf::TemporaryPdf():QTemporaryFile(QStringLiteral("qpdfdocument")) { - open(); + QVERIFY2(open(), qPrintable(errorString())); pageLayout = QPageLayout(QPageSize(QPageSize::A4), QPageLayout::Portrait, QMarginsF()); { diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp index 2bfaa8eaea7..3fca0b44af3 100644 --- a/tests/auto/quick/publicapi/tst_publicapi.cpp +++ b/tests/auto/quick/publicapi/tst_publicapi.cpp @@ -140,6 +140,7 @@ static const QStringList expectedAPI = QStringList() << "QWebEngineCertificateError.CertificateSymantecLegacy --> Type" << "QWebEngineCertificateError.SslObsoleteVersion --> Type" << "QWebEngineCertificateError.SslPinnedKeyNotInCertificateChain --> Type" + << "QWebEngineCertificateError.Ok --> Type" << "QWebEngineCertificateError.defer() --> void" << "QWebEngineCertificateError.description --> QString" << "QWebEngineCertificateError.type --> QWebEngineCertificateError::Type" @@ -523,8 +524,8 @@ static const QStringList expectedAPI = QStringList() << "QQuickWebEngineSettings.webRTCPublicInterfacesOnlyChanged() --> void" << "QQuickWebEngineSettings.readingFromCanvasEnabled --> bool" << "QQuickWebEngineSettings.readingFromCanvasEnabledChanged() --> void" - << "QQuickWebEngineSettings.jsTouchEventsEnabled --> bool" - << "QQuickWebEngineSettings.jsTouchEventsEnabledChanged() --> void" + << "QQuickWebEngineSettings.touchEventsApiEnabled --> bool" + << "QQuickWebEngineSettings.touchEventsApiEnabledChanged() --> void" << "QQuickWebEngineSingleton.defaultProfile --> QQuickWebEngineProfile*" << "QQuickWebEngineSingleton.settings --> QQuickWebEngineSettings*" << "QQuickWebEngineSingleton.script() --> QWebEngineScript" diff --git a/tests/auto/quick/qmltests/data/tst_loadUrl.qml b/tests/auto/quick/qmltests/data/tst_loadUrl.qml index 757343703c5..e43c8d5d983 100644 --- a/tests/auto/quick/qmltests/data/tst_loadUrl.qml +++ b/tests/auto/quick/qmltests/data/tst_loadUrl.qml @@ -265,7 +265,6 @@ TestWebEngineView { compare(loadRequest.status, WebEngineView.LoadStoppedStatus); compare(loadRequest.status, WebEngineLoadingInfo.LoadStoppedStatus); compare(loadRequest.url, stoppedUrl); - compare(loadRequest.activeUrl, initialUrl); webEngineView.clear(); } diff --git a/tests/auto/quick/qmltests/data/tst_userScripts.qml b/tests/auto/quick/qmltests/data/tst_userScripts.qml index a64de389d8e..d18c1f44a10 100644 --- a/tests/auto/quick/qmltests/data/tst_userScripts.qml +++ b/tests/auto/quick/qmltests/data/tst_userScripts.qml @@ -65,6 +65,23 @@ Item { } } + // This previously crashed. See change: https://codereview.qt-project.org/c/qt/qtwebengine/+/558237 + WebEngineView { + id: webEngineView3 + width: 400 + height: 300 + + userScripts { + collection: [ + { + injectionPoint: WebEngineScript.DocumentReady, + sourceCode: Qt.resolvedUrl("append-document-title.js"), + worldId: WebEngineScript.UserWorld + } + ] + } + } + TestCase { name: "UserScripts" diff --git a/tests/auto/quick/qquickwebengineview/html/resources/hello.js b/tests/auto/quick/qquickwebengineview/html/resources/hello.js new file mode 100644 index 00000000000..6f5e79ebf4d --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/html/resources/hello.js @@ -0,0 +1,7 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHello() +{ + console.warn("hello"); +} diff --git a/tests/auto/quick/qquickwebengineview/html/resources/hi.js b/tests/auto/quick/qquickwebengineview/html/resources/hi.js new file mode 100644 index 00000000000..30e7cc972d1 --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/html/resources/hi.js @@ -0,0 +1,8 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHi() +{ + // Placeholder + console.warn("hi"); +} diff --git a/tests/auto/quick/qquickwebengineview/html/script2.html b/tests/auto/quick/qquickwebengineview/html/script2.html new file mode 100644 index 00000000000..5faf58daab3 --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/html/script2.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 4521f94bbfe..d192a1886d8 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -1,8 +1,6 @@ // Copyright (C) 2016 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only -#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses - #include "testwindow.h" #include "quickutil.h" #include "util.h" @@ -27,6 +25,8 @@ #include +using namespace Qt::StringLiterals; + class tst_QQuickWebEngineView : public QObject { Q_OBJECT public: @@ -76,10 +76,12 @@ private Q_SLOTS: #if QT_CONFIG(accessibility) void focusChild_data(); void focusChild(); + void accessibilityRect(); #endif void htmlSelectPopup(); void savePage_data(); void savePage(); + void javaScriptConsoleMessage(); private: inline QQuickWebEngineView *newWebEngineView(); @@ -614,7 +616,7 @@ void tst_QQuickWebEngineView::inputContextQueryInput() QTest::mouseClick(view->window(), Qt::LeftButton, {}, textInputCenter); QTRY_COMPARE(testContext.infos.size(), 2); QCOMPARE(evaluateJavaScriptSync(view, "document.activeElement.id").toString(), QStringLiteral("input1")); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("")); @@ -709,7 +711,7 @@ void tst_QQuickWebEngineView::inputContextQueryInput() QGuiApplication::sendEvent(qApp->focusObject(), &event); } QTRY_COMPARE(testContext.infos.size(), 2); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!")); @@ -1256,6 +1258,74 @@ void tst_QQuickWebEngineView::focusChild() // -> -> QCOMPARE(traverseToWebDocumentAccessibleInterface(iface)->child(0)->child(0), iface->focusChild()); } + +void tst_QQuickWebEngineView::accessibilityRect() +{ + auto *engine = new QQmlEngine(this); + auto *component = new QQmlComponent(engine, this); + component->setData(QByteArrayLiteral("import QtQuick\n" + "import QtWebEngine\n" + "Window {\n" + " visible: true; width: 600; height: 400\n" + " Text { id: textId; text: \"text\"; width: 100; Accessible.focusable: true; Accessible.name: \"text\" }\n" + " WebEngineView { anchors.left: textId.right; anchors.top: textId.bottom; anchors.right: parent.right; anchors.bottom: parent.bottom }\n" + "}") + , QUrl()); + QObject *rootObject = component->create(); + QVERIFY(rootObject); + + QQuickWebEngineView *webView = rootObject->findChild(); + QVERIFY(webView); + + webView->loadHtml(""); + QVERIFY(waitForLoadSucceeded(webView)); + + QAccessibleInterface *rootObjectIface = QAccessible::queryAccessibleInterface(rootObject); + QVERIFY(rootObjectIface); + QCOMPARE(rootObjectIface->childCount(), 2); + + QAccessibleInterface *textIface = rootObjectIface->child(0); + QVERIFY(textIface); + QCOMPARE(textIface->role(), QAccessible::StaticText); + + QCOMPARE(textIface->rect().width(), 100); + QVERIFY(textIface->rect().height() > 0); + + // It takes a while for the webIface to get its width, unfortunately we can't have a + // QTRY_COMPARE since it seems in some platforms the iface gets recreated and we end up + // accessible the wrong pointer, so roll up our own try+compare + QAccessibleInterface *webIface = nullptr; + QElapsedTimer t; + t.start(); + bool isWebIfaceOfCorrectWidth = false; + while (!isWebIfaceOfCorrectWidth && t.elapsed() < 5000) { + QTest::qWait(100); + webIface = rootObjectIface->child(1)->child(0); + QVERIFY(webIface); + QCOMPARE(webIface->role(), QAccessible::WebDocument); + isWebIfaceOfCorrectWidth = webIface->rect().width() == 500; + } + + QVERIFY(isWebIfaceOfCorrectWidth); + QCOMPARE(webIface->rect().height(), 400 - textIface->rect().height()); + QCOMPARE(webIface->rect().x(), textIface->rect().x() + textIface->rect().width()); + QCOMPARE(webIface->rect().y(), textIface->rect().y() + textIface->rect().height()); + + // Set active focus on the input field. + webView->runJavaScript("document.getElementById('input1').focus();"); + QTRY_COMPARE(evaluateJavaScriptSync(webView, "document.activeElement.id").toString(), QStringLiteral("input1")); + + // Check that children of the web rect are inside it + QAccessibleInterface *inputIface = webIface->focusChild(); + QVERIFY(inputIface); + QTRY_COMPARE(inputIface->role(), QAccessible::EditableText); + QVERIFY(webIface->rect().contains(inputIface->rect())); + + delete rootObject; + delete component; + delete engine; +} + #endif // QT_CONFIG(accessibility) void tst_QQuickWebEngineView::htmlSelectPopup() @@ -1365,6 +1435,82 @@ void tst_QQuickWebEngineView::savePage() originalData); } +class TestJSMessageHandler +{ +public: + inline static QList levels; + inline static QStringList messages; + inline static QList lineNumbers; + inline static QStringList sourceIDs; + + static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) + { + if (strcmp(context.category, "js") != 0) { + m_originalHandler(type, context, msg); + return; + } + + levels.append(type); + messages.append(msg); + lineNumbers.append(context.line); + sourceIDs.append(context.file); + } + + TestJSMessageHandler() { m_originalHandler = qInstallMessageHandler(handler); } + ~TestJSMessageHandler() { qInstallMessageHandler(m_originalHandler); } + +private: + inline static QtMessageHandler m_originalHandler = nullptr; +}; + +void tst_QQuickWebEngineView::javaScriptConsoleMessage() +{ + QQuickWebEngineView *view = webEngineView(); + + // Test QQuickWebEngineView::javaScriptConsoleMessage() signal. + { + QSignalSpy jsSpy( + view, + SIGNAL(javaScriptConsoleMessage(QQuickWebEngineView::JavaScriptConsoleMessageLevel, + const QString &, int, const QString &))); + view->setUrl(urlFromTestPath("html/script2.html")); + QVERIFY(waitForLoadSucceeded(view)); + + runJavaScript("sayHello()"); + QTRY_COMPARE(jsSpy.size(), 1); + QCOMPARE(jsSpy.last().at(0).toInt(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(jsSpy.last().at(1).toString(), "hello"_L1); + QCOMPARE(jsSpy.last().at(2).toInt(), 6); + QCOMPARE(jsSpy.last().at(3).toString(), urlFromTestPath("html/resources/hello.js")); + + runJavaScript("sayHi()"); + QTRY_COMPARE(jsSpy.size(), 2); + QCOMPARE(jsSpy.last().at(0).toInt(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(jsSpy.last().at(1).toString(), "hi"_L1); + QCOMPARE(jsSpy.last().at(2).toInt(), 7); + QCOMPARE(jsSpy.last().at(3).toString(), urlFromTestPath("html/resources/hi.js")); + } + + // Test default QQuickWebEngineViewPrivate::javaScriptConsoleMessage() handler. + { + TestJSMessageHandler handler; + view->setUrl(urlFromTestPath("html/script2.html")); + QVERIFY(waitForLoadSucceeded(view)); + + evaluateJavaScriptSync(view, "sayHello()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hello"_L1); + QCOMPARE(handler.lineNumbers.last(), 6); + QCOMPARE(handler.sourceIDs.last(), urlFromTestPath("html/resources/hello.js")); + + evaluateJavaScriptSync(view, "sayHi()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hi"_L1); + QCOMPARE(handler.lineNumbers.last(), 7); + QCOMPARE(handler.sourceIDs.last(), urlFromTestPath("html/resources/hi.js")); + } +} + #if QT_CONFIG(accessibility) static QByteArrayList params = QByteArrayList() << "--force-renderer-accessibility"; diff --git a/tests/auto/widgets/accessibility/tst_accessibility.cpp b/tests/auto/widgets/accessibility/tst_accessibility.cpp index a4d87a7b256..6c26f624c2b 100644 --- a/tests/auto/widgets/accessibility/tst_accessibility.cpp +++ b/tests/auto/widgets/accessibility/tst_accessibility.cpp @@ -341,8 +341,8 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kAbbr") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kAlert") << QString("
alert
") << 0 << QAccessible::AlertMessage; - QTest::newRow("ax::mojom::Role::kAlertDialog") << QString("
alert
") << 0 << QAccessible::AlertMessage; - QTest::newRow("ax::mojom::Role::kAnchor") << QString("Chapter a") << 1 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kAlertDialog") + << QString("
alert
") << 0 << QAccessible::AlertMessage; QTest::newRow("ax::mojom::Role::kApplication") << QString("
landmark
") << 0 << QAccessible::Document; QTest::newRow("ax::mojom::Role::kArticle") << QString("
a
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kAudio") << QString("") << 1 << QAccessible::Sound; @@ -357,27 +357,33 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kClient") << QString("") << 0 << QAccessible::Client; QTest::newRow("ax::mojom::Role::kCode") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kColorWell") << QString("a") << 1 << QAccessible::ColorChooser; - //QTest::newRow("ax::mojom::Role::kColumn") << QString("
a
") << 0 << QAccessible::Column; // FIXME: The test case might be wrong (see AXTableColumn.h) + // QTest::newRow("ax::mojom::Role::kColumn"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kColumnHeader") << QString("
a
a
") << 2 << QAccessible::ColumnHeader; QTest::newRow("ax::mojom::Role::kComboBoxGrouping") << QString("
") << 0 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kComboBoxMenuButton") << QString("
Select
") << 0 << QAccessible::ComboBox; - QTest::newRow("ax::mojom::Role::kTextFieldWithComboBox") << QString("") << 1 << QAccessible::ComboBox; + // QTest::newRow("ax::mojom::Role::kComboBoxSelect"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kComplementary") << QString("") << 0 << QAccessible::ComplementaryContent; QTest::newRow("ax::mojom::Role::kComment") << QString("
") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kContentDeletion") << QString("
") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kContentInsertion") << QString("
") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kContentInfo") << QString("
") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kData") << QString("") << 1 << QAccessible::Clock; + QTest::newRow("ax::mojom::Role::kDate") + << QString("") << 1 << QAccessible::Clock; QTest::newRow("ax::mojom::Role::kDateTime") << QString("") << 1 << QAccessible::Clock; QTest::newRow("ax::mojom::Role::kDefinition") << QString("
landmark
") << 0 << QAccessible::Paragraph; QTest::newRow("ax::mojom::Role::kDescriptionList") << QString("
a
") << 0 << QAccessible::List; - QTest::newRow("ax::mojom::Role::kDescriptionListDetail") << QString("
a
") << 0 << QAccessible::Paragraph; + QTest::newRow("ax::mojom::Role::kDescriptionListDetailDeprecated") + << QString("
a
") << 0 << QAccessible::Paragraph; + // QTest::newRow("ax::mojom::Role::kDescriptionListTermDeprecated"); QTest::newRow("ax::mojom::Role::kDetails") << QString("
a
") << 0 << QAccessible::Grouping; //QTest::newRow("ax::mojom::Role::kDesktop"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kDialog") << QString("
") << 0 << QAccessible::Dialog; - //QTest::newRow("ax::mojom::Role::kDirectory") << QString("
    ") << 0 << QAccessible::List; // FIXME: Aria role 'directory' should work + QTest::newRow("ax::mojom::Role::kDirectoryDeprecated") + << QString("
      ") << 0 << QAccessible::List; QTest::newRow("ax::mojom::Role::kDisclosureTriangle") << QString("
      a
      ") << 1 << QAccessible::Button; - QTest::newRow("ax::mojom::Role::kDisclosureTriangleGroup") << QString("
      a
      ") << 1 << QAccessible::Button; + QTest::newRow("ax::mojom::Role::kDisclosureTriangleGrouped") + << QString("
      a
      ") << 1 + << QAccessible::Button; QTest::newRow("ax::mojom::Role::kGenericContainer") << QString("
      a
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocCover") << QString("
      ") << 0 << QAccessible::Graphic; QTest::newRow("ax::mojom::Role::kDocBackLink") << QString("
      ") << 0 << QAccessible::Link; @@ -389,7 +395,8 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kDocFootnote") << QString("
      ") << 0 << QAccessible::ListItem; QTest::newRow("ax::mojom::Role::kDocPageBreak") << QString("
      ") << 0 << QAccessible::Separator; QTest::newRow("ax::mojom::Role::kDocAbstract") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kDocAcknowledgements") << QString("
      ") << 0 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kDocAcknowledgments") + << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocAfterword") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocAppendix") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocBibliography") << QString("
      ") << 0 << QAccessible::Section; @@ -403,14 +410,18 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kDocEpigraph") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocEpilogue") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocErrata") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kDocExample") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kDocFooter") << QString("
      a
      ") << 0 << QAccessible::Footer; + QTest::newRow("ax::mojom::Role::kDocExample") + << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocForeword") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kDocGlossary") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kDocHeader") << QString("
      a
      ") << 0 << QAccessible::Heading; + QTest::newRow("ax::mojom::Role::kDocGlossary") + << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocIndex") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocIntroduction") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocNotice") << QString("
      ") << 0 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kDocPageFooter") + << QString("
      a
      ") << 0 << QAccessible::Footer; + QTest::newRow("ax::mojom::Role::kDocPageHeader") + << QString("
      a
      ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kDocPageList") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPart") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocPreface") << QString("
      ") << 0 << QAccessible::Section; @@ -421,34 +432,35 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kDocTip") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocToc") << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kDocument") << QString("
      a
      ") << 0 << QAccessible::Document; - QTest::newRow("ax::mojom::Role::kEmbeddedObject") << QString("") << 1 << QAccessible::Grouping; + QTest::newRow("ax::mojom::Role::kEmbeddedObject") + << QString("") << 1 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kEmphasis") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kFeed") << QString("
      a
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kFigcaption") << QString("
      a
      ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kFigure") << QString("
      a
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kFooter") << QString("
      a
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kFooterAsNonLandmark") << QString("
      a
      ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kForm") << QString("
      ") << 0 << QAccessible::Form; QTest::newRow("ax::mojom::Role::kGraphicsDocument") << QString("
      ") << 0 << QAccessible::Document; QTest::newRow("ax::mojom::Role::kGraphicsObject") << QString("
      ") << 0 << QAccessible::Pane; QTest::newRow("ax::mojom::Role::kGraphicsSymbol") << QString("
      ") << 0 << QAccessible::Graphic; QTest::newRow("ax::mojom::Role::kGrid") << QString("
      ") << 0 << QAccessible::Table; + QTest::newRow("ax::mojom::Role::kGridCell") + << QString("
      ") << 0 << QAccessible::Cell; QTest::newRow("ax::mojom::Role::kGroup") << QString("
      ") << 0 << QAccessible::Grouping; - QTest::newRow("ax::mojom::Role::Header") << QString("
      a
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::HeaderAsNonLandMark") << QString("
      a
      ") << 1 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kHeader") + << QString("
      a
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kHeading") << QString("

      a

      ") << 0 << QAccessible::Heading; QTest::newRow("ax::mojom::Role::kIframe") << QString("") << 1 << QAccessible::WebDocument; - QTest::newRow("ax::mojom::Role::kIframePresentational") << QString("") << 1 << QAccessible::Grouping; - //QTest::newRow("ax::mojom::Role::kIgnored") << QString("a") << 0 << QAccessible::NoRole; // FIXME: The HTML element should not be exposed as an element (see AXNodeObject.cpp) + QTest::newRow("ax::mojom::Role::kIframePresentational") + << QString("") << 1 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kImage") << QString("") << 1 << QAccessible::Graphic; - //QTest::newRow("ax::mojom::Role::kImageMap") << QString("") << 0 << QAccessible::Document; // FIXME: AXLayoutObject::DetermineAccessiblityRole returns kImageMap but something overrides it //QTest::newRow("ax::mojom::Role::kInlineTextBox"); // No mapping to ARIA role - QTest::newRow("ax::mojom::Role::kInputTime") << QString("") << 1 << QAccessible::SpinBox; - //QTest::newRow("ax::mojom::Role::kKeyboard"); // No mapping to ARIA role + QTest::newRow("ax::mojom::Role::kInputTime") + << QString("") << 1 << QAccessible::SpinBox; QTest::newRow("ax::mojom::Role::kLabelText") << QString("") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kLayoutTable") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kLayoutTableCell") << QString("
      ") << 2 << QAccessible::Section; - //QTest::newRow("ax::mojom::Role::kLayoutTableColumn") << QString("
      ") << 1 << QAccessible::Section; // FIXME: The test case might be wrong + QTest::newRow("ax::mojom::Role::kLayoutTableCell") + << QString("
      ") << 2 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kLayoutTableRow") << QString("
      ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kLegend") << QString("a") << 0 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kLineBreak") << QString("
      ") << 1 << QAccessible::Separator; @@ -463,13 +475,72 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kMain") << QString("
      a
      ") << 0 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kMark") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kMarquee") << QString("
      a
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kMath") << QString("a") << 1 << QAccessible::Equation; + QTest::newRow("ax::mojom::Role::kMath") + << QString("x") << 1 << QAccessible::Equation; + QTest::newRow("ax::mojom::Role::kMathMLMath") + << QString("x") << 1 << QAccessible::Equation; + QTest::newRow("ax::mojom::Role::kMathMLFraction") + << QString("12") << 2 + << QAccessible::Grouping; + QTest::newRow("ax::mojom::Role::kMathMLIdentifier") + << QString("x") << 2 << QAccessible::StaticText; + QTest::newRow("ax::mojom::Role::kMathMLMultiscripts") + << QString("Xab") + << 2 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLNoneScript") + << QString("") << 3 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLNumber") + << QString("1") << 2 << QAccessible::StaticText; + QTest::newRow("ax::mojom::Role::kMathMLOperator") + << QString("+") << 2 << QAccessible::StaticText; + QTest::newRow("ax::mojom::Role::kMathMLOver") + << QString("x-") << 2 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLPrescriptDelimiter") + << QString("") << 3 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLRoot") + << QString("x3") << 2 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLRow") + << QString("1") << 2 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLSquareRoot") + << QString("x") << 2 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLStringLiteral") + << QString("a") << 2 << QAccessible::StaticText; + QTest::newRow("ax::mojom::Role::kMathMLSub") + << QString("X1") << 2 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLSubSup") + << QString("X01") << 2 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLSup") + << QString("X1") << 2 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLTable") + << QString("x") << 2 + << QAccessible::Table; + QTest::newRow("ax::mojom::Role::kMathMLTableCell") + << QString("x") << 4 + << QAccessible::Cell; + QTest::newRow("ax::mojom::Role::kMathMLTableRow") + << QString("x") << 3 + << QAccessible::Row; + QTest::newRow("ax::mojom::Role::kMathMLText") + << QString("a") << 2 << QAccessible::StaticText; + QTest::newRow("ax::mojom::Role::kMathMLUnder") + << QString("x-") << 2 + << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kMathMLUnderOver") + << QString("x+-") << 2 + << QAccessible::Section; QTest::newRow("ax::mojom::Role::kMenu") << QString("
      a
      ") << 0 << QAccessible::PopupMenu; QTest::newRow("ax::mojom::Role::kMenuBar") << QString("
      a
      ") << 0 << QAccessible::MenuBar; QTest::newRow("ax::mojom::Role::kMenuItem") << QString("
      a
      ") << 1 << QAccessible::MenuItem; QTest::newRow("ax::mojom::Role::kMenuItemCheckBox") << QString("") << 1 << QAccessible::CheckBox; - QTest::newRow("ax::mojom::Role::kMenuItemRadio") << QString("") << 1 << QAccessible::RadioButton; - QTest::newRow("ax::mojom::Role::kMenuButton") << QString("") << 1 << QAccessible::Button; + QTest::newRow("ax::mojom::Role::kMenuItemRadio") + << QString("") << 1 + << QAccessible::RadioButton; QTest::newRow("ax::mojom::Role::kMenuListOption") << QString("") << 2 << QAccessible::MenuItem; QTest::newRow("ax::mojom::Role::kMenuListPopup") << QString("") << 1 << QAccessible::PopupMenu; QTest::newRow("ax::mojom::Role::kMeter") << QString("a") << 1 << QAccessible::Chart; @@ -477,13 +548,18 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kNote") << QString("
      a
      ") << 0 << QAccessible::Note; //QTest::newRow("ax::mojom::Role::kPane"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kParagraph") << QString("

      a

      ") << 0 << QAccessible::Paragraph; + // QTest::newRow("ax::mojom::Role::kPdfActionableHighlight"); // No mapping to ARIA role + // QTest::newRow("ax::mojom::Role::kPdfRoot"); // No mapping to ARIA role + QTest::newRow("ax::mojom::Role::kPluginObject") + << QString("") << 1 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kPopUpButton") << QString("") << 1 << QAccessible::PopupMenu; - QTest::newRow("ax::mojom::Role::kPre") << QString("
      a
      ") << 0 << QAccessible::Section; - //QTest::newRow("ax::mojom::Role::kPresentational") << QString("
      a
      ") << 0 << QAccessible::NoRole; // FIXME: Aria role 'presentation' should work + // QTest::newRow("ax::mojom::Role::kPortalDeprecated"); // No mapping to ARIA role + // QTest::newRow("ax::mojom::Role::kPreDeprecated"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kProgressIndicator") << QString("
      ") << 0 << QAccessible::ProgressBar; QTest::newRow("ax::mojom::Role::kRadioButton") << QString("") << 1 << QAccessible::RadioButton; QTest::newRow("ax::mojom::Role::kRadioGroup") << QString("
      ") << 0 << QAccessible::Grouping; - QTest::newRow("ax::mojom::Role::kRegion") << QString("
      a
      ") << 0 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kRegion") + << QString("
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kRow") << QString("
      a
      ") << 1 << QAccessible::Row; QTest::newRow("ax::mojom::Role::kRowGroup") << QString("
      a
      ") << 1 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kRowHeader") << QString("
      ab
      ") << 2 << QAccessible::RowHeader; @@ -493,15 +569,25 @@ void tst_Accessibility::roles_data() //QTest::newRow("ax::mojom::Role::kScrollView"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kSearch") << QString("
      landmark
      ") << 0 << QAccessible::Section; QTest::newRow("ax::mojom::Role::kSearchBox") << QString("") << 1 << QAccessible::EditableText; - QTest::newRow("ax::mojom::Role::kSection") << QString("
      ") << 0 << QAccessible::Section; - QTest::newRow("ax::mojom::Role::kSlider") << QString("") << 1 << QAccessible::Slider; - //QTest::newRow("ax::mojom::Role::kSliderThumb") << QString("") << 1 << QAccessible::Slider; // TODO: blink/renderer/modules/accessibility/ax_slider.cc + // QTest::newRow("ax::mojom::Role::kSection"); // Abstract role, not used + QTest::newRow("ax::mojom::Role::kSectionFooter") + << QString("
      a
      ") << 1 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kSectionHeader") + << QString("
      a
      ") << 1 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kSectionWithoutName") + << QString("
      ") << 0 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kSlider") + << QString("") << 1 << QAccessible::Slider; QTest::newRow("ax::mojom::Role::kSpinButton") << QString("") << 1 << QAccessible::SpinBox; QTest::newRow("ax::mojom::Role::kSplitter") << QString("
      ") << 0 << QAccessible::Splitter; QTest::newRow("ax::mojom::Role::kStaticText") << QString("a") << 1 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kStatus") << QString("a") << 1 << QAccessible::Indicator; QTest::newRow("ax::mojom::Role::kStrong") << QString("a") << 1 << QAccessible::StaticText; + QTest::newRow("ax::mojom::Role::kSubscript") + << QString("subscript") << 1 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kSuggestion") << QString("
      ") << 0 << QAccessible::Section; + QTest::newRow("ax::mojom::Role::kSuperscript") + << QString("superscript") << 1 << QAccessible::Grouping; QTest::newRow("ax::mojom::Role::kSvgRoot") << QString("SVG") << 1 << QAccessible::WebDocument; QTest::newRow("ax::mojom::Role::kSwitch") << QString("") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kTable") << QString("
      a
      ") << 0 << QAccessible::Table; @@ -511,12 +597,15 @@ void tst_Accessibility::roles_data() QTest::newRow("ax::mojom::Role::kTabPanel") << QString("
      a
      ") << 0 << QAccessible::Pane; QTest::newRow("ax::mojom::Role::kTerm") << QString("
      a
      ") << 0 << QAccessible::StaticText; QTest::newRow("ax::mojom::Role::kTextField") << QString("") << 1 << QAccessible::EditableText; + QTest::newRow("ax::mojom::Role::kTextFieldWithComboBox") + << QString("") << 1 << QAccessible::ComboBox; QTest::newRow("ax::mojom::Role::kTime") << QString("") << 1 << QAccessible::Clock; QTest::newRow("ax::mojom::Role::kTimer") << QString("
      a
      ") << 0 << QAccessible::Clock; //QTest::newRow("ax::mojom::Role::kTitleBar"); // No mapping to ARIA role QTest::newRow("ax::mojom::Role::kToggleButton") << QString("") << 1 << QAccessible::Button; QTest::newRow("ax::mojom::Role::kToolbar") << QString("
      a
      ") << 0 << QAccessible::ToolBar; - QTest::newRow("ax::mojom::Role::kToolTip") << QString("
      a
      ") << 0 << QAccessible::ToolTip; + QTest::newRow("ax::mojom::Role::kTooltip") + << QString("
      a
      ") << 0 << QAccessible::ToolTip; QTest::newRow("ax::mojom::Role::kTree") << QString("
      a
      ") << 0 << QAccessible::Tree; QTest::newRow("ax::mojom::Role::kTreeGrid") << QString("
      a
      ") << 0 << QAccessible::Tree; QTest::newRow("ax::mojom::Role::kTreeItem") << QString("
      a
      ") << 0 << QAccessible::TreeItem; diff --git a/tests/auto/widgets/printing/tst_printing.cpp b/tests/auto/widgets/printing/tst_printing.cpp index f08421b5ca3..58bfa144238 100644 --- a/tests/auto/widgets/printing/tst_printing.cpp +++ b/tests/auto/widgets/printing/tst_printing.cpp @@ -113,7 +113,7 @@ void tst_Printing::pdfContent() QBuffer buffer; buffer.setData((data)); - buffer.open(QBuffer::ReadWrite); + QVERIFY2(buffer.open(QBuffer::ReadWrite), qPrintable(buffer.errorString())); document.load(&buffer); QTRY_COMPARE(statusChangedSpy.size(), 2); QCOMPARE(statusChangedSpy[1][0].value(), QPdfDocument::Status::Ready); @@ -167,9 +167,12 @@ void tst_Printing::printFromPdfViewer() QBuffer buffer; buffer.setData((data)); - buffer.open(QBuffer::ReadWrite); + if (!buffer.open(QBuffer::ReadWrite)) { + qWarning("Failed to open buffer: %s", qPrintable(buffer.errorString())); + return false; + } document.load(&buffer); - statusChangedSpy.wait(500); + statusChangedSpy.wait(1000); if (document.status() != QPdfDocument::Status::Ready) return false; @@ -177,12 +180,12 @@ void tst_Printing::printFromPdfViewer() QSignalSpy countChangedSpy(&searchModel, &QPdfSearchModel::countChanged); searchModel.setDocument(&document); searchModel.setSearchString("Hello Paper World"); - countChangedSpy.wait(500); + countChangedSpy.wait(1000); if (searchModel.count() != 1) return false; return true; - }, 15000); + }, 30000); QVERIFY(ok); #endif } @@ -221,7 +224,7 @@ void tst_Printing::printHeaderAndFooter() QBuffer buffer; buffer.setData((data)); - buffer.open(QBuffer::ReadWrite); + QVERIFY2(buffer.open(QBuffer::ReadWrite), qPrintable(buffer.errorString())); document.load(&buffer); QTRY_COMPARE(document.status(), QPdfDocument::Status::Ready); diff --git a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp index 0a273828767..b01d7b8c933 100644 --- a/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp +++ b/tests/auto/widgets/qwebenginedownloadrequest/tst_qwebenginedownloadrequest.cpp @@ -16,6 +16,38 @@ #include #include +using namespace Qt::StringLiterals; + +// Based on PageWithPaintListeners in tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +// TODO: Factor PageWithPaintListeners out to tests/auto/util/util.h +class TestPage : public QWebEnginePage +{ + Q_OBJECT +public: + TestPage(QWebEngineProfile *profile) : QWebEnginePage(profile) + { + QObject::connect(this, &QWebEnginePage::loadFinished, [this]() { + const QString jsLCPObserver = QStringLiteral( + "new PerformanceObserver((list) => {" + " const entries = list.getEntries();" + " const lastEntry = entries[entries.length - 1];" + " console.log('largestContentfulPaint: ' + lastEntry.element);" + "}).observe({type: 'largest-contentful-paint', buffered: true});"); + runJavaScript(jsLCPObserver); + }); + } + + void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel, const QString &message, int, + const QString &) override + { + if (message == "largestContentfulPaint: [object HTMLBodyElement]"_L1) + emit htmlBodyElementPainted(); + } + +signals: + void htmlBodyElementPainted(); +}; + class tst_QWebEngineDownloadRequest : public QObject { Q_OBJECT @@ -60,6 +92,7 @@ private Q_SLOTS: void downloadToDirectoryWithFileName(); void downloadDataUrls_data(); void downloadDataUrls(); + void pauseDownload(); private: void saveLink(QPoint linkPos); @@ -68,7 +101,7 @@ private Q_SLOTS: HttpServer *m_server; QWebEngineProfile *m_profile; - QWebEnginePage *m_page; + TestPage *m_page; QWebEngineView *m_view; QSet m_requestedDownloads; QSet m_finishedDownloads; @@ -93,7 +126,7 @@ void tst_QWebEngineDownloadRequest::initTestCase() m_finishedDownloads.insert(item); }); }); - m_page = new QWebEnginePage(m_profile); + m_page = new TestPage(m_profile); m_view = new QWebEngineView; m_view->setPage(m_page); m_view->resize(640, 480); @@ -454,10 +487,12 @@ void tst_QWebEngineDownloadRequest::downloadLink() // The only variation being whether the element has a "download" // attribute or not. QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted); m_view->load(m_server->url()); QTRY_COMPARE(loadSpy.size(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); QCOMPARE(indexRequestCount, 1); + QTRY_COMPARE(paintSpy.size(), 1); simulateUserAction(QPoint(10, 10), userAction); @@ -552,9 +587,11 @@ void tst_QWebEngineDownloadRequest::downloadTwoLinks() }); QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted); m_view->load(m_server->url()); QTRY_COMPARE(loadSpy.size(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QTRY_COMPARE(paintSpy.size(), 1); // Trigger downloads simulateUserAction(QPoint(10, 10), action1); @@ -983,13 +1020,13 @@ void tst_QWebEngineDownloadRequest::downloadUniqueFilenameWithTimestamp() // Create the first empty file without uniquifier. { QFile file(m_profile->downloadPath() + "/" + fileName); - file.open(QIODevice::ReadWrite); + QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString())); } // Create 99 empty files with uniquifier. for (int i = 1; i < 100; i++) { QFile file(m_profile->downloadPath() + "/" + baseName + " (" + QString::number(i) + ")." + extension); - file.open(QIODevice::ReadWrite); + QVERIFY2(file.open(QIODevice::ReadWrite), qPrintable(file.errorString())); } // Create 100th (kMaxUniqueFiles) empty file with uniquifier. @@ -1336,14 +1373,65 @@ void tst_QWebEngineDownloadRequest::downloadDataUrls() }); QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + QSignalSpy paintSpy(m_page, &TestPage::htmlBodyElementPainted); m_view->load(m_server->url()); QTRY_COMPARE(loadSpy.size(), 1); QCOMPARE(loadSpy.takeFirst().value(0).toBool(), true); + QTRY_COMPARE(paintSpy.size(), 1); // Trigger download simulateUserAction(QPoint(10, 10), UserAction::ClickLink); QTRY_COMPARE(downloadRequestCount, 1); } +void tst_QWebEngineDownloadRequest::pauseDownload() +{ + const int fileSize = 1024 * 1024 * 512; + + // Set up HTTP server + ScopedConnection sc1 = connect(m_server, &HttpServer::newRequest, [&](HttpReqRep *rr) { + if (rr->requestMethod() == "GET" && rr->requestPath() == "/") { + rr->setResponseHeader(QByteArrayLiteral("content-type"), + QByteArrayLiteral("application/octet-stream")); + static const QByteArray bigfile(fileSize, '0'); + rr->setResponseBody(bigfile); + rr->sendResponse(); + } + }); + + // Set up profile and download handler + QTemporaryDir tmpDir; + QVERIFY(tmpDir.isValid()); + m_profile->setDownloadPath(tmpDir.path()); + + bool firstBytesReceived = true; + int pausedCount = 0; + ScopedConnection sc2 = connect( + m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadRequest *item) { + QCOMPARE(item->state(), QWebEngineDownloadRequest::DownloadRequested); + connect(item, &QWebEngineDownloadRequest::receivedBytesChanged, [item, &firstBytesReceived] { + if (firstBytesReceived) { + firstBytesReceived = false; + item->pause(); + } + }); + connect(item, &QWebEngineDownloadRequest::isPausedChanged, [item, &pausedCount]() { + if (item->isPaused()) { + pausedCount++; + item->resume(); + } + }); + item->accept(); + }); + + QSignalSpy loadSpy(m_page, &QWebEnginePage::loadFinished); + m_view->load(m_server->url()); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(pausedCount, 1, 10000); + QTRY_COMPARE_WITH_TIMEOUT(m_finishedDownloads.size(), 1, 10000); + QTRY_COMPARE(m_finishedDownloads.values()[0]->isPaused(), false); + QTRY_COMPARE(m_finishedDownloads.values()[0]->receivedBytes(), fileSize); +} + QTEST_MAIN(tst_QWebEngineDownloadRequest) #include "tst_qwebenginedownloadrequest.moc" diff --git a/tests/auto/widgets/qwebenginepage/CMakeLists.txt b/tests/auto/widgets/qwebenginepage/CMakeLists.txt index 55c35af8810..a0470e25a37 100644 --- a/tests/auto/widgets/qwebenginepage/CMakeLists.txt +++ b/tests/auto/widgets/qwebenginepage/CMakeLists.txt @@ -30,6 +30,8 @@ set(tst_qwebenginepage_resource_files "resources/frame_c.html" "resources/framedindex.html" "resources/fullscreen.html" + "resources/hello.js" + "resources/hi.js" "resources/iframe.html" "resources/iframe2.html" "resources/iframe3.html" @@ -40,6 +42,7 @@ set(tst_qwebenginepage_resource_files "resources/path with spaces.txt" "resources/reload.html" "resources/script.html" + "resources/script2.html" "resources/style.css" "resources/test1.html" "resources/test2.html" diff --git a/tests/auto/widgets/qwebenginepage/resources/hello.js b/tests/auto/widgets/qwebenginepage/resources/hello.js new file mode 100644 index 00000000000..6f5e79ebf4d --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/hello.js @@ -0,0 +1,7 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHello() +{ + console.warn("hello"); +} diff --git a/tests/auto/widgets/qwebenginepage/resources/hi.js b/tests/auto/widgets/qwebenginepage/resources/hi.js new file mode 100644 index 00000000000..30e7cc972d1 --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/hi.js @@ -0,0 +1,8 @@ +// Copyright (C) 2025 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only + +function sayHi() +{ + // Placeholder + console.warn("hi"); +} diff --git a/tests/auto/widgets/qwebenginepage/resources/script2.html b/tests/auto/widgets/qwebenginepage/resources/script2.html new file mode 100644 index 00000000000..7d511503771 --- /dev/null +++ b/tests/auto/widgets/qwebenginepage/resources/script2.html @@ -0,0 +1,4 @@ + + + + diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 23dda23bd64..fe8fc638310 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -77,6 +77,8 @@ #include #include +using namespace Qt::StringLiterals; + static void removeRecursive(const QString& dirname) { QDir dir(dirname); @@ -134,6 +136,7 @@ private Q_SLOTS: void backActionUpdate(); void localStorageVisibility(); void consoleOutput(); + void javaScriptConsoleMessage(); void userAgentNewlineStripping(); void renderWidgetHostViewNotShowTopLevel(); void getUserMediaRequest_data(); @@ -612,7 +615,7 @@ class ConsolePage : public QWebEnginePage sourceIDs.append(sourceID); } - QList levels; + QList levels; QStringList messages; QList lineNumbers; QStringList sourceIDs; @@ -627,6 +630,78 @@ void tst_QWebEnginePage::consoleOutput() QCOMPARE(page.lineNumbers.at(0), 1); } +class TestJSMessageHandler +{ +public: + inline static QList levels; + inline static QStringList messages; + inline static QList lineNumbers; + inline static QStringList sourceIDs; + + static void handler(QtMsgType type, const QMessageLogContext &context, const QString &msg) + { + if (strcmp(context.category, "js") != 0) { + m_originalHandler(type, context, msg); + return; + } + + levels.append(type); + messages.append(msg); + lineNumbers.append(context.line); + sourceIDs.append(context.file); + } + + TestJSMessageHandler() { m_originalHandler = qInstallMessageHandler(handler); } + ~TestJSMessageHandler() { qInstallMessageHandler(m_originalHandler); } + +private: + inline static QtMessageHandler m_originalHandler = nullptr; +}; + +void tst_QWebEnginePage::javaScriptConsoleMessage() +{ + // Test overridden QWebEnginePage::javaScriptConsoleMessage(). + { + ConsolePage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + page.load(QUrl("qrc:///resources/script2.html")); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000); + + evaluateJavaScriptSync(&page, "sayHello()"); + QCOMPARE(page.levels.last(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(page.messages.last(), "hello"_L1); + QCOMPARE(page.lineNumbers.last(), 6); + QCOMPARE(page.sourceIDs.last(), "qrc:///resources/hello.js"_L1); + + evaluateJavaScriptSync(&page, "sayHi()"); + QCOMPARE(page.levels.last(), QWebEnginePage::WarningMessageLevel); + QCOMPARE(page.messages.last(), "hi"_L1); + QCOMPARE(page.lineNumbers.last(), 7); + QCOMPARE(page.sourceIDs.last(), "qrc:///resources/hi.js"_L1); + } + + // Test default QWebEnginePage::javaScriptConsoleMessage() handler. + { + TestJSMessageHandler handler; + QWebEnginePage page; + QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool))); + page.load(QUrl("qrc:///resources/script2.html")); + QTRY_COMPARE_WITH_TIMEOUT(loadSpy.size(), 1, 20000); + + evaluateJavaScriptSync(&page, "sayHello()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hello"_L1); + QCOMPARE(handler.lineNumbers.last(), 6); + QCOMPARE(handler.sourceIDs.last(), "qrc:///resources/hello.js"_L1); + + evaluateJavaScriptSync(&page, "sayHi()"); + QCOMPARE(handler.levels.last(), QtMsgType::QtWarningMsg); + QCOMPARE(handler.messages.last(), "hi"_L1); + QCOMPARE(handler.lineNumbers.last(), 7); + QCOMPARE(handler.sourceIDs.last(), "qrc:///resources/hi.js"_L1); + } +} + class TestPage : public QWebEnginePage { Q_OBJECT public: @@ -2582,7 +2657,7 @@ void tst_QWebEnginePage::setContent_data() QTest::newRow("UTF-8 plain text") << "text/plain; charset=utf-8" << str.toUtf8() << str; QBuffer out16; - out16.open(QIODevice::WriteOnly); + QVERIFY2(out16.open(QIODevice::WriteOnly), qPrintable(out16.errorString())); QTextStream stream16(&out16); stream16.setEncoding(QStringConverter::Utf16); stream16 << str; @@ -4584,7 +4659,7 @@ void tst_QWebEnginePage::discardAbortsPendingLoadAndPreservesCommittedLoad() connect(&page, &QWebEnginePage::loadStarted, [&]() { page.setLifecycleState(QWebEnginePage::LifecycleState::Discarded); }); - QString url2 = QStringLiteral("about:blank"); + QString url2 = QStringLiteral("qrc:/resources/test1.html"); page.setUrl(url2); QTRY_COMPARE(loadStartedSpy.size(), 1); loadStartedSpy.clear(); diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp index d9997d50c36..97e5bd6017f 100644 --- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp +++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp @@ -26,6 +26,8 @@ #include #include +using namespace Qt::StringLiterals; + class tst_QWebEngineProfile : public QObject { Q_OBJECT @@ -173,7 +175,7 @@ class TestServer : public HttpServer } QFile file(resourceDir.filePath(path)); - file.open(QIODevice::ReadOnly); + QVERIFY2(file.open(QIODevice::ReadOnly), qPrintable(file.errorString())); QByteArray data = file.readAll(); rr->setResponseBody(data); QMimeDatabase db; @@ -205,6 +207,12 @@ void tst_QWebEngineProfile::clearDataFromCache() // Wait for GET /favicon.ico QTRY_COMPARE(serverSpy.size(), 3); +#if defined(Q_OS_WIN) + // FIXME: A http cache entry might be still in use after all the wait above and this blocks + // clearing the http cache. Find a better way to wait for cache entries. + QTest::qWait(500); +#endif + QVERIFY(cacheDir.exists("Cache")); qint64 sizeBeforeClear = totalSize(cacheDir); QCOMPARE_GT(sizeBeforeClear, 0); @@ -665,7 +673,7 @@ class XhrStatusUrlSchemeHandler : public QWebEngineUrlSchemeHandler QString path = job->requestUrl().path(); if (path == "/") { QBuffer *buffer = new QBuffer(job); - buffer->open(QBuffer::ReadWrite); + QVERIFY2(buffer->open(QBuffer::ReadWrite), qPrintable(buffer->errorString())); buffer->write(QByteArrayLiteral(R"( @@ -689,7 +697,7 @@ class XhrStatusUrlSchemeHandler : public QWebEngineUrlSchemeHandler job->reply("text/html", buffer); } else if (path == "/qwebchannel.js") { QFile *file = new QFile(":/qtwebchannel/qwebchannel.js", job); - file->open(QFile::ReadOnly); + QVERIFY2(file->open(QFile::ReadOnly), qPrintable(file->errorString())); job->reply("application/javascript", file); } else if (path == "/ok") { QBuffer *buffer = new QBuffer(job); @@ -841,6 +849,12 @@ void tst_QWebEngineProfile::httpAcceptLanguage() // Test changing an existing page and profile QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage(testLang); QCOMPARE(evaluateJavaScriptSync(&page, QStringLiteral("navigator.languages")).toStringList(), QStringList(testLang)); + + // Test language list with quality values + QWebEngineProfile::defaultProfile()->setHttpAcceptLanguage( + u"en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7"_s); + QCOMPARE(evaluateJavaScriptSync(&page, u"navigator.languages"_s).toStringList(), + QStringList({u"en-US"_s, u"en"_s, u"zh-CN"_s, u"zh"_s})); } void tst_QWebEngineProfile::downloadItem() diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp index 1a4ee9c4b4b..1dfa94565e7 100644 --- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp +++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp @@ -359,7 +359,10 @@ class TestObject : public QObject static QString readFile(const QString &path) { QFile file(path); - file.open(QFile::ReadOnly); + if (!file.open(QFile::ReadOnly)) { + qWarning("Failed to read file %s: %s", qPrintable(path), qPrintable(file.errorString())); + return QString(); + } QByteArray contents = file.readAll(); file.close(); return contents; diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index b8f2936b3e2..ee754c77af4 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -19,8 +19,6 @@ Boston, MA 02110-1301, USA. */ -#undef QT_NO_FOREACH // this file contains unported legacy Q_FOREACH uses - #include #include #include @@ -288,20 +286,20 @@ void tst_QWebEngineView::pageWithPaintListeners() page.setHtml(empty); QTest::qWait(500); // empty page should not trigger - QVERIFY(firstContentfulPaintSpy.size() == 0); - QVERIFY(largestContentfulPaintSpy.size() == 0); + QCOMPARE(firstContentfulPaintSpy.size(), 0); + QCOMPARE(largestContentfulPaintSpy.size(), 0); page.setHtml(backgroundColor); - QTRY_VERIFY(firstContentfulPaintSpy.size() == 1); + QTRY_COMPARE(firstContentfulPaintSpy.size(), 1); page.setHtml(text); - QTRY_VERIFY(firstContentfulPaintSpy.size() == 2); - QTRY_VERIFY(largestContentfulPaintSpy.size() == 1); + QTRY_COMPARE(firstContentfulPaintSpy.size(), 2); + QTRY_COMPARE(largestContentfulPaintSpy.size(), 1); -#if !QT_CONFIG(webengine_embedded_build) - // Embedded builds have different scrollbars that are only painted on hover +#if !QT_CONFIG(webengine_embedded_build) && !defined(Q_OS_MACOS) + // Embedded builds and macOS have different scrollbars that are only painted on hover page.setHtml(scrollBars); - QTRY_VERIFY(firstContentfulPaintSpy.size() == 3); + QTRY_COMPARE(firstContentfulPaintSpy.size(), 3); #endif } @@ -1619,6 +1617,7 @@ void tst_QWebEngineView::keyboardFocusAfterPopup() connect(window.lineEdit, &QLineEdit::editingFinished, [&] { window.webView->setHtml(html); }); window.webView->settings()->setAttribute(QWebEngineSettings::FocusOnNavigationEnabled, true); window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); // Focus will initially go to the QLineEdit. QTRY_COMPARE(QApplication::focusWidget(), window.lineEdit); @@ -2069,6 +2068,7 @@ void tst_QWebEngineView::inputContextQueryInput() ""); QTRY_COMPARE(loadFinishedSpy.size(), 1); QVERIFY(QTest::qWaitForWindowExposed(&view)); + QTRY_VERIFY(qApp->focusObject()); QCOMPARE(testContext.infos.size(), 0); // Set focus on an input field. @@ -2076,7 +2076,7 @@ void tst_QWebEngineView::inputContextQueryInput() QTest::mouseClick(view.focusProxy(), Qt::LeftButton, {}, textInputCenter); QTRY_COMPARE(testContext.infos.size(), 2); QCOMPARE(evaluateJavaScriptSync(view.page(), "document.activeElement.id").toString(), QStringLiteral("input1")); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("")); @@ -2175,7 +2175,7 @@ void tst_QWebEngineView::inputContextQueryInput() QApplication::sendEvent(view.focusProxy(), &event); } QTRY_COMPARE(testContext.infos.size(), 2); - foreach (const InputMethodInfo &info, testContext.infos) { + for (const InputMethodInfo &info : std::as_const(testContext.infos)) { QCOMPARE(info.cursorPosition, 0); QCOMPARE(info.anchorPosition, 0); QCOMPARE(info.surroundingText, QStringLiteral("QtWebEngine!")); @@ -4012,16 +4012,22 @@ void tst_QWebEngineView::longKeyEventText() void tst_QWebEngineView::deferredDelete() { + // TODO: Remove this workaround when temporary qt_desktopWidget is removed from + // qapplication.cpp. + const size_t desktopWidget = QApplication::allWidgets().size(); + QVERIFY(desktopWidget <= 1); + { QWebEngineView view; QSignalSpy loadFinishedSpy(view.page(), &QWebEnginePage::loadFinished); view.load(QUrl("chrome://qt")); view.show(); QTRY_VERIFY(loadFinishedSpy.size()); - QCOMPARE(QApplication::allWidgets().size(), 2); // QWebEngineView and WebEngineQuickWidget + // QWebEngineView and WebEngineQuickWidget + QCOMPARE(QApplication::allWidgets().size(), desktopWidget + 2); } - QCOMPARE(QApplication::allWidgets().size(), 0); + QCOMPARE(QApplication::allWidgets().size(), desktopWidget); } // QTBUG-111927 diff --git a/tests/auto/widgets/spellchecking/dict/en-US.dic b/tests/auto/widgets/spellchecking/dict/en-US.dic index 63e9164ccd5..93c7198a385 100644 --- a/tests/auto/widgets/spellchecking/dict/en-US.dic +++ b/tests/auto/widgets/spellchecking/dict/en-US.dic @@ -10,3 +10,4 @@ she/Q they/Q we/Q you/Q +very-long-word-to-test-old-fixed-size-buffer-limit-QTBUG-132564-aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa/Q diff --git a/tests/manual/quick/geopermission/CMakeLists.txt b/tests/manual/quick/geopermission/CMakeLists.txt index 6602ceb6ff6..e6f91356074 100644 --- a/tests/manual/quick/geopermission/CMakeLists.txt +++ b/tests/manual/quick/geopermission/CMakeLists.txt @@ -49,8 +49,13 @@ if (APPLE) if (NOT CMAKE_GENERATOR STREQUAL "Xcode") # Need to sign application for location permissions to work + if(QT_FEATURE_debug_and_release) + set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$/") + else() + unset(exe_path) + endif() add_custom_command(TARGET tst_geopermission - POST_BUILD COMMAND codesign -s - tst_geopermission.app) + POST_BUILD COMMAND codesign --force -s - ${exe_path}tst_geopermission.app) endif() endif() diff --git a/tests/manual/widgets/geolocation/CMakeLists.txt b/tests/manual/widgets/geolocation/CMakeLists.txt index 2ca8c2f524b..25704bfdff2 100644 --- a/tests/manual/widgets/geolocation/CMakeLists.txt +++ b/tests/manual/widgets/geolocation/CMakeLists.txt @@ -49,7 +49,12 @@ if (APPLE) if (NOT CMAKE_GENERATOR STREQUAL "Xcode") # Need to sign application for location permissions to work + if(QT_FEATURE_debug_and_release) + set(exe_path "${CMAKE_CURRENT_BINARY_DIR}/$/") + else() + unset(exe_path) + endif() add_custom_command(TARGET geolocation - POST_BUILD COMMAND codesign -s - geolocation.app) + POST_BUILD COMMAND codesign --force -s - ${exe_path}geolocation.app) endif() endif() diff --git a/tools/scripts/take_snapshot.py b/tools/scripts/take_snapshot.py index 4b4638381e4..aadf1cbf469 100755 --- a/tools/scripts/take_snapshot.py +++ b/tools/scripts/take_snapshot.py @@ -202,7 +202,7 @@ def isInChromiumBlacklist(file_path): and not file_path.startswith('third_party/node/node_modules/polymer-analyzer/') and not file_path.startswith('third_party/node/node_modules/polymer-css-build/') and not file_path.startswith('third_party/node/node_modules/resolve/') - and not file_path.startswith('third_party/node/node_modules/rollup/') + and not file_path.startswith('third_party/node/node_modules/@rollup/') and not file_path.startswith('third_party/node/node_modules/shady-css-parser/') and not file_path.startswith('third_party/node/node_modules/source-map/') and not file_path.startswith('third_party/node/node_modules/stable/') @@ -283,7 +283,7 @@ def isInChromiumBlacklist(file_path): )) or ('/test' in file_path and ('/testdata/' in file_path - or '/tests/' in file_path + or ('/tests/' in file_path and not file_path.startswith('third_party/rust/')) or ('/test/' in file_path and not '/webrtc/' in file_path and not file_path.startswith('net/test/') diff --git a/tools/scripts/version_resolver.py b/tools/scripts/version_resolver.py index f7cdec6fe96..aa3dfd088ec 100644 --- a/tools/scripts/version_resolver.py +++ b/tools/scripts/version_resolver.py @@ -43,8 +43,8 @@ def get_recursedeps(self): return self.local_scope["recursedeps"] -chromium_version = '126.0.6478.165' -chromium_branch = '6478' +chromium_version = '130.0.6723.192' +chromium_branch = '6723' json_url = 'http://omahaproxy.appspot.com/all.json'