diff options
author | Michael BrĂ¼ning <michael.bruning@qt.io> | 2024-02-02 22:00:28 +0100 |
---|---|---|
committer | Michael BrĂ¼ning <michael.bruning@qt.io> | 2024-02-02 22:00:28 +0100 |
commit | 4db1bad6da55e58ffecac225d98785813cac5f30 (patch) | |
tree | d0ec322c77a55cdd5c72d710ce631fde7266b3b1 | |
parent | 56319fbe0624f346e937e775921e917ae71fdc3e (diff) | |
parent | edf286f39d6fae7db53484d7c4b521f03129a054 (diff) |
Merge remote-tracking branch 'origin/6.6' into 6.5
Change-Id: I149f99b0672be030d5d7c5cf6763cd2d0cf4852c
32 files changed, 380 insertions, 220 deletions
diff --git a/.cmake.conf b/.cmake.conf index 20a6ff666..2991fa83b 100644 --- a/.cmake.conf +++ b/.cmake.conf @@ -1,4 +1,4 @@ -set(QT_REPO_MODULE_VERSION "6.5.4") +set(QT_REPO_MODULE_VERSION "6.5.5") set(QT_REPO_MODULE_PRERELEASE_VERSION_SEGMENT "alpha1") set(QT_SUPPORTED_MIN_CMAKE_VERSION_FOR_BUILDING_WEBENGINE "3.19") set(QT_EXTRA_INTERNAL_TARGET_DEFINES "QT_NO_AS_CONST=1") diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION index a928175d7..c481f19c8 100644 --- a/CHROMIUM_VERSION +++ b/CHROMIUM_VERSION @@ -1,3 +1,3 @@ Based on Chromium version: 112.0.5615.213 -Patched with security patches up to Chromium version: 119.0.6045.199 +Patched with security patches up to Chromium version: 121.0.6167.85 diff --git a/CMakeLists.txt b/CMakeLists.txt index 49ab0c785..e235794f2 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,7 @@ include(ExternalProject) include(cmake/Functions.cmake) project(QtWebEngineDummy) -find_package(Qt6 6.2 CONFIG REQUIRED COMPONENTS BuildInternals Core) +find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core) project(QtWebEngine VERSION ${Qt6Core_VERSION} diff --git a/cmake/Functions.cmake b/cmake/Functions.cmake index 0dc66c389..f22e96056 100644 --- a/cmake/Functions.cmake +++ b/cmake/Functions.cmake @@ -33,18 +33,6 @@ function(assertTargets) endforeach() endfunction() -#TODO: remove me -function(add_implicit_dependencies target) - if(TARGET ${target}) - list(REMOVE_ITEM ARGN ${target}) - foreach(qtTarget IN ITEMS ${ARGN}) - if(TARGET Qt::${qtTarget}) - add_dependencies(${target} Qt::${qtTarget}) - endif() - endforeach() - endif() -endfunction() - # TODO: this should be idealy in qtbase function(add_check_for_support) cmake_parse_arguments(PARSE_ARGV 0 arg @@ -74,23 +62,6 @@ function(add_check_for_support) endforeach() endfunction() -function(get_qt_features outList module) - get_cmake_property(variableList VARIABLES) - set(_featureList "") - foreach (variableKey ${variableList}) - unset(FOUND) - string(REGEX MATCH QT_FEATURE_${module} FOUND ${variableKey}) - if(FOUND) - list(APPEND _featureList "${variableKey}=${${variableKey}}") - endif() - endforeach() - if("${${outList}}" STREQUAL "") - set(${outList} ${_featureList} PARENT_SCOPE) - else() - set(${outList} "${${outList}}" "${_featureList}" PARENT_SCOPE) - endif() -endfunction() - function(create_cxx_config cmakeTarget arch configFileName) if(NOT QT_SUPERBUILD AND QT_WILL_INSTALL) get_target_property(mocFilePath Qt6::moc IMPORTED_LOCATION) @@ -334,13 +305,6 @@ function(get_install_config result) endif() endfunction() -macro(assertRunAsTopLevelBuild) - if(NOT DEFINED WEBENGINE_REPO_BUILD) - message(FATAL_ERROR "This cmake file should run as top level build.") - return() - endif() -endmacro() - # we need to pass -F or -iframework in case of frameworks builds, which gn treats as # compiler flag and cmake as include dir, so swap it. function(recoverFrameworkBuild includeDirs compilerFlags) @@ -479,6 +443,7 @@ function(add_linker_options target buildDir completeStatic) target_link_libraries(${cmakeTarget} PRIVATE "$<1:-Wl,--no-fatal-warnings $<$<CONFIG:${config}>:@${ldir_rsp}> $<$<CONFIG:${config}>:@${libs_rsp}> -Wl,--no-fatal-warnings>" ) + unset(cpu) endif() if(MACOS) target_link_options(${cmakeTarget} PRIVATE "$<$<CONFIG:${config}>:@${objects_rsp}>") @@ -657,46 +622,50 @@ function(qt_internal_add_external_project_dependency_to_root_project name) cmake_policy(POP) endfunction() +# Function maps TEST_architecture_arch or CMAKE_SYSTEM_PROCESSOR into gn architecture function(get_gn_arch result arch) - if(arch STREQUAL "i386") + set(armList arm armv7-a) + set(mips64List mips64 mipsel64) + set(x86List i386 i686) + set(x64List x86_64 AMD64 x86_64h aarch64) + if(arch IN_LIST x86List) set(${result} "x86" PARENT_SCOPE) - elseif(arch STREQUAL "x86_64") + elseif(arch IN_LIST x64List) set(${result} "x64" PARENT_SCOPE) - elseif(arch STREQUAL "arm") + elseif(arch IN_LIST armList) set(${result} "arm" PARENT_SCOPE) elseif(arch STREQUAL "arm64") set(${result} "arm64" PARENT_SCOPE) elseif(arch STREQUAL "mipsel") set(${result} "mipsel" PARENT_SCOPE) - elseif(arch STREQUAL "mipsel64") + elseif(arch IN_LIST mipsList) set(${result} "mips64el" PARENT_SCOPE) elseif(arch STREQUAL "riscv64") set(${result} "riscv64" PARENT_SCOPE) else() - message(DEBUG "Unsupported architecture: ${arch}") + message(FATAL_ERROR "Unknown architecture: ${arch}") endif() endfunction() +# Function maps gn architecture for v8 function(get_v8_arch result targetArch hostArch) - set(list32 i386 arm mipsel) + set(list32 x86 arm mipsel riscv32) if(hostArch STREQUAL targetArch) set(${result} "${targetArch}" PARENT_SCOPE) elseif(targetArch IN_LIST list32) # 32bit target which needs a 32bit compatible host - if(hostArch STREQUAL "x86_64") - set(${result} "i386" PARENT_SCOPE) + if(hostArch STREQUAL "x64") + set(${result} "x86" PARENT_SCOPE) elseif(hostArch STREQUAL "arm64") set(${result} "arm" PARENT_SCOPE) - elseif(hostArch STREQUAL "mips64") - set(${result} "mipsel" PARENT_SCOPE) - elseif(hostArch STREQUAL "mipsel64") + elseif(hostArch STREQUAL "mips64el") set(${result} "mipsel" PARENT_SCOPE) elseif(hostArch STREQUAL "riscv64") - set(${result} "riscv64" PARENT_SCOPE) + set(${result} "riscv32" PARENT_SCOPE) elseif(hostArch IN_LIST list32) set(${result} "${hostArch}" PARENT_SCOPE) else() - message(FATAL_ERROR "Unsupported architecture: ${hostArch}") + message(FATAL_ERROR "Unknown architecture: ${hostArch}") endif() else() # assume 64bit target which matches 64bit host @@ -739,12 +708,12 @@ function(get_ios_sysroot result arch) set(${result} ${sysroot} PARENT_SCOPE) endfunction() -function(configure_gn_toolchain name binTargetCpu v8TargetCpu toolchainIn toolchainOut) +function(configure_gn_toolchain name cpu v8Cpu toolchainIn toolchainOut) set(GN_TOOLCHAIN ${name}) get_gn_os(GN_OS) get_gn_is_clang(GN_IS_CLANG) - get_gn_arch(GN_CPU ${binTargetCpu}) - get_gn_arch(GN_V8_CPU ${v8TargetCpu}) + set(GN_CPU ${cpu}) + set(GN_V8_CPU ${v8Cpu}) configure_file(${toolchainIn} ${toolchainOut}/BUILD.gn @ONLY) endfunction() @@ -826,17 +795,19 @@ macro(create_pkg_config_host_wrapper buildDir) endmacro() macro(setup_toolchains) + get_gn_arch(gn_arch ${TEST_architecture_arch}) if(NOT CMAKE_CROSSCOMPILING) # delivered by hostBuild project - configure_gn_toolchain(host ${TEST_architecture_arch} ${TEST_architecture_arch} + configure_gn_toolchain(host ${gn_arch} ${gn_arch} ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in ${buildDir}/host_toolchain) - configure_gn_toolchain(v8 ${TEST_architecture_arch} ${TEST_architecture_arch} + configure_gn_toolchain(v8 ${gn_arch} ${gn_arch} ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in ${buildDir}/v8_toolchain) endif() - configure_gn_toolchain(target ${TEST_architecture_arch} ${TEST_architecture_arch} + configure_gn_toolchain(target ${gn_arch} ${gn_arch} ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in ${buildDir}/target_toolchain) + unset(gn_arch) endmacro() macro(append_build_type_setup) @@ -1036,6 +1007,7 @@ macro(append_compiler_linker_sdk_setup) ARGS use_lld CONDITION QT_FEATURE_use_lld_linker ) + unset(cpu) endmacro() macro(append_sanitizer_setup) @@ -1065,20 +1037,24 @@ macro(append_sanitizer_setup) endmacro() macro(append_toolchain_setup) - if(MINGW) - list(APPEND gnArgArg - # note '/' prefix - custom_toolchain="/${buildDir}/target_toolchain:target" - host_toolchain="/${buildDir}/host_toolchain:host" - ) - list(APPEND gnArgArg host_cpu="${cpu}") - endif() - if(LINUX) + if(WIN32) + get_gn_arch(cpu ${arch}) + list(APPEND gnArgArg target_cpu="${cpu}") + if(MINGW) + get_gn_arch(cpu ${TEST_architecture_arch}) + list(APPEND gnArgArg + # note '/' prefix + custom_toolchain="/${buildDir}/target_toolchain:target" + host_toolchain="/${buildDir}/host_toolchain:host" + host_cpu="${cpu}" + ) + endif() + elseif(LINUX) + get_gn_arch(cpu ${TEST_architecture_arch}) list(APPEND gnArgArg custom_toolchain="${buildDir}/target_toolchain:target" host_toolchain="${buildDir}/host_toolchain:host" ) - get_gn_arch(cpu ${TEST_architecture_arch}) if(CMAKE_CROSSCOMPILING) list(APPEND gnArgArg v8_snapshot_toolchain="${buildDir}/v8_toolchain:v8" @@ -1090,17 +1066,18 @@ macro(append_toolchain_setup) if(CMAKE_SYSROOT) list(APPEND gnArgArg target_sysroot="${CMAKE_SYSROOT}") endif() - else() + elseif(MACOS) get_gn_arch(cpu ${arch}) list(APPEND gnArgArg target_cpu="${cpu}") - if(IOS) - get_ios_sysroot(sysroot ${arch}) - list(APPEND gnArgArg target_sysroot="${sysroot}" target_os="ios") - endif() - endif() - if(ANDROID) - list(APPEND gnArgArg target_os="android") + elseif(IOS) + get_gn_arch(cpu ${arch}) + get_ios_sysroot(sysroot ${arch}) + list(APPEND gnArgArg target_cpu="${cpu}" target_sysroot="${sysroot}" target_os="ios") + elseif(ANDROID) + get_gn_arch(cpu ${TEST_architecture_arch}) + list(APPEND gnArgArg target_os="android" target_cpu="${cpu}") endif() + unset(cpu) endmacro() @@ -1163,7 +1140,7 @@ function(get_architectures result) set(${result} ${${result}} PARENT_SCOPE) endfunction() -function(add_gn_build_aritfacts_to_target) +function(add_gn_build_artifacts_to_target) cmake_parse_arguments(PARSE_ARGV 0 arg "" "CMAKE_TARGET;NINJA_TARGET;BUILDDIR;MODULE;COMPLETE_STATIC;NINJA_STAMP;NINJA_DATA_STAMP" "" ) @@ -1313,16 +1290,6 @@ function(addCopyCommand target src dst) ) endfunction() -function(addCopyDirCommand target src dst) - add_custom_command( - POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy_directory ${src} ${dst} - TARGET ${target} - DEPENDS ${src} - USES_TERMINAL - ) -endfunction() - function(check_for_ulimit) message("-- Checking 'ulimit -n'") execute_process(COMMAND bash -c "ulimit -n" diff --git a/configure.cmake b/configure.cmake index 54d0f542f..033315d5d 100644 --- a/configure.cmake +++ b/configure.cmake @@ -493,12 +493,13 @@ add_check_for_support( MESSAGE "Build can be done only on Linux, Windows, macO, iOS and Android(on non-Windows hosts only)." ) if(LINUX AND CMAKE_CROSSCOMPILING) - get_gn_arch(testArch ${TEST_architecture_arch}) + set(supportedTargets "arm" "arm64" "armv7-a" "x86_64") add_check_for_support( MODULES QtWebEngine QtPdf - CONDITION testArch + CONDITION TEST_architecture_arch IN_LIST supportedTargets MESSAGE "Cross compiling is not supported for ${TEST_architecture_arch}." ) + unset(supportedTargets) endif() add_check_for_support( MODULES QtWebEngine diff --git a/src/3rdparty b/src/3rdparty -Subproject 028cbdb7a0d37dfe0eea8cf3a2dad94c7ffdda0 +Subproject e257d6513927fa24df48075bce9b33c4b5f546f diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 570055840..20ef91637 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -78,6 +78,7 @@ foreach(arch ${archs}) ${gnCxxCompileOptions} SOURCES accessibility_tree_formatter_qt.cpp + browser_accessibility_qt.cpp browser_accessibility_qt.h authentication_dialog_controller.cpp authentication_dialog_controller.h authentication_dialog_controller_p.h autofill_client_qt.cpp autofill_client_qt.h autofill_popup_controller.cpp autofill_popup_controller.h autofill_popup_controller_p.h @@ -152,6 +153,7 @@ foreach(arch ${archs}) ozone/platform_window_qt.cpp ozone/platform_window_qt.h ozone/surface_factory_qt.cpp ozone/surface_factory_qt.h permission_manager_qt.cpp permission_manager_qt.h + pdf_util_qt.cpp pdf_util_qt.h platform_notification_service_qt.cpp platform_notification_service_qt.h pointer_device_qt.cpp pref_service_adapter.cpp pref_service_adapter.h @@ -201,7 +203,6 @@ foreach(arch ${archs}) extend_gn_target(${buildGn} CONDITION QT_FEATURE_accessibility SOURCES accessibility_activation_observer.cpp accessibility_activation_observer.h - browser_accessibility_qt.cpp browser_accessibility_qt.h ) extend_gn_target(${buildGn} CONDITION QT_FEATURE_webengine_ozone_x11 @@ -497,7 +498,7 @@ foreach(arch ${archs}) external_gssapi_include_dir="${GSSAPI_INCLUDE_DIRS}/gssapi" ) endif() - + get_gn_arch(cpu ${TEST_architecture_arch}) if(CMAKE_CROSSCOMPILING AND cpu STREQUAL "arm") check_thumb(armThumb) if(NOT armThumb AND NOT QT_FEATURE_webengine_system_ffmpeg) @@ -514,6 +515,7 @@ foreach(arch ${archs}) ) endif() endif() + unset(cpu) endif() if(MACOS) @@ -566,7 +568,7 @@ if(QT_FEATURE_webengine_v8_context_snapshot) set(dataStamp obj/tools/v8_context_snapshot/v8_context_snapshot.stamp) endif() -add_gn_build_aritfacts_to_target( +add_gn_build_artifacts_to_target( CMAKE_TARGET WebEngineCore NINJA_TARGET QtWebEngineCore MODULE core @@ -616,7 +618,7 @@ if(QT_FEATURE_webengine_spellchecker AND NOT CMAKE_CROSSCOMPILING) ../3rdparty/chromium/third_party/boringssl/src/include ${buildDir}/$<CONFIG>/${arch}/gen ) - add_gn_build_aritfacts_to_target( + add_gn_build_artifacts_to_target( CMAKE_TARGET ${dict_target_name} NINJA_TARGET convert_dict MODULE core diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt index da587119d..5bd8b9e2f 100644 --- a/src/core/api/CMakeLists.txt +++ b/src/core/api/CMakeLists.txt @@ -133,6 +133,10 @@ if(QT_FEATURE_webengine_v8_context_snapshot) foreach(config ${configs}) if(MACOS) set(ext_arch ".${arch}") + # QTBUG-118120 gn does not support x86_64h + if(ext_arch STREQUAL "x86_64h") + set(ext_arch "x86_64") + endif() else() unset(ext_arch) endif() diff --git a/src/core/api/configure.cmake b/src/core/api/configure.cmake index 762f4bdd6..48f7cacc0 100644 --- a/src/core/api/configure.cmake +++ b/src/core/api/configure.cmake @@ -168,7 +168,7 @@ qt_feature("webengine-vaapi" PRIVATE ) # internal testing feature qt_feature("webengine-system-poppler" PRIVATE - LABEL "popler" + LABEL "poppler" CONDITION UNIX AND TEST_poppler ) qt_configure_add_summary_section(NAME "Qt WebEngineCore") diff --git a/src/core/api/qwebengineglobalsettings.cpp b/src/core/api/qwebengineglobalsettings.cpp index 5eeff9fc5..95138516b 100644 --- a/src/core/api/qwebengineglobalsettings.cpp +++ b/src/core/api/qwebengineglobalsettings.cpp @@ -3,7 +3,6 @@ #include "qwebengineglobalsettings.h" #include "qwebengineglobalsettings_p.h" -#include <QDebug> #ifdef signals #undef signals @@ -126,12 +125,6 @@ void QWebEngineGlobalSettingsPrivate::configureStubHostResolver() != content::NetworkServiceAvailability::NOT_CREATED) { network::mojom::NetworkService *networkService = content::GetNetworkService(); if (networkService) { - qDebug() << "doh set to" << dnsOverHttpsTemplates << " -- " - << (dnsMode == QWebEngineGlobalSettings::SecureDnsMode::SecureOnly - ? "SecureOnly" - : dnsMode == QWebEngineGlobalSettings::SecureDnsMode::SystemOnly - ? "SystemOnly" - : "SecureWithFallback"); absl::optional<net::DnsOverHttpsConfig> dohConfig = dnsOverHttpsTemplates.empty() ? net::DnsOverHttpsConfig() : net::DnsOverHttpsConfig::FromString(dnsOverHttpsTemplates); diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp index 4b8e947c0..de3347df3 100644 --- a/src/core/browser_accessibility_qt.cpp +++ b/src/core/browser_accessibility_qt.cpp @@ -10,6 +10,7 @@ #include "qtwebenginecoreglobal_p.h" #include "type_conversion.h" +#if QT_CONFIG(accessibility) #include "content/browser/accessibility/browser_accessibility.h" #include "ui/accessibility/ax_enums.mojom.h" @@ -1151,14 +1152,22 @@ void BrowserAccessibilityInterface::modelChange(QAccessibleTableModelChangeEvent } // namespace QtWebEngineCore +#endif // QT_CONFIG(accessibility) namespace content { // static std::unique_ptr<BrowserAccessibility> BrowserAccessibility::Create(BrowserAccessibilityManager *man, ui::AXNode *node) { +#if QT_CONFIG(accessibility) return std::unique_ptr<BrowserAccessibility>(new QtWebEngineCore::BrowserAccessibilityQt(man, node)); +#else + Q_UNUSED(man); + Q_UNUSED(node); + return nullptr; +#endif // #if QT_CONFIG(accessibility) } +#if QT_CONFIG(accessibility) QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj) { return static_cast<QtWebEngineCore::BrowserAccessibilityQt *>(obj)->interface; @@ -1168,5 +1177,6 @@ const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *o { return static_cast<const QtWebEngineCore::BrowserAccessibilityQt *>(obj)->interface; } +#endif // #if QT_CONFIG(accessibility) } // namespace content diff --git a/src/core/browser_accessibility_qt.h b/src/core/browser_accessibility_qt.h index 455478247..598aa3ef5 100644 --- a/src/core/browser_accessibility_qt.h +++ b/src/core/browser_accessibility_qt.h @@ -4,8 +4,9 @@ #ifndef BROWSER_ACCESSIBILITY_QT_H #define BROWSER_ACCESSIBILITY_QT_H -#include <QtCore/qtconfigmacros.h> +#include <QtGui/qtguiglobal.h> +#if QT_CONFIG(accessibility) QT_FORWARD_DECLARE_CLASS(QAccessibleInterface) namespace content { @@ -15,5 +16,6 @@ QAccessibleInterface *toQAccessibleInterface(BrowserAccessibility *obj); const QAccessibleInterface *toQAccessibleInterface(const BrowserAccessibility *obj); } // namespace content +#endif // QT_CONFIG(accessibility) #endif // BROWSER_ACCESSIBILITY_QT_H diff --git a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp index 9b6b38a52..9a2feb816 100644 --- a/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp +++ b/src/core/extensions/pdf_iframe_navigation_throttle_qt.cpp @@ -26,12 +26,12 @@ #include "ui/base/webui/jstemplate_builder.h" #include "ui/base/webui/web_ui_util.h" +#include "pdf_util_qt.h" + #include <QtGlobal> namespace extensions { -constexpr char kPDFMimeType[] = "application/pdf"; - // Used to scope the posted navigation task to the lifetime of |web_contents|. class PdfWebContentsLifetimeHelper : public content::WebContentsUserData<PdfWebContentsLifetimeHelper> { @@ -76,7 +76,7 @@ bool IsPDFPluginEnabled(content::NavigationHandle *navigation_handle, bool *is_s process_id, routing_id, navigation_handle->GetWebContents()->GetBrowserContext(), navigation_handle->GetURL(), - kPDFMimeType, false /* allow_wildcard */, + QtWebEngineCore::kPDFMimeType, false /* allow_wildcard */, is_stale, &plugin_info, nullptr /* actual_mime_type */); } @@ -119,7 +119,7 @@ content::NavigationThrottle::ThrottleCheckResult PDFIFrameNavigationThrottleQt:: std::string mime_type; response_headers->GetMimeType(&mime_type); - if (mime_type != kPDFMimeType) + if (mime_type != QtWebEngineCore::kPDFMimeType) return content::NavigationThrottle::PROCEED; // We MUST download responses marked as attachments rather than showing diff --git a/src/core/pdf_util_qt.cpp b/src/core/pdf_util_qt.cpp new file mode 100644 index 000000000..9503f5910 --- /dev/null +++ b/src/core/pdf_util_qt.cpp @@ -0,0 +1,92 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.Chromium file. + +#include "pdf_util_qt.h" + +#include <QtGlobal> + +#include "base/check.h" +#include "chrome/common/webui_url_constants.h" +#include "content/public/browser/render_frame_host.h" +#include "content/public/browser/render_process_host.h" +#include "content/public/browser/web_contents.h" +#include "extensions/buildflags/buildflags.h" +#include "url/gurl.h" +#include "url/origin.h" + +#if BUILDFLAG(ENABLE_EXTENSIONS) +#include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" +#include "extensions/common/constants.h" +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + +namespace QtWebEngineCore { + +bool IsPdfExtensionOrigin(const url::Origin &origin) +{ +#if BUILDFLAG(ENABLE_EXTENSIONS) + return origin.scheme() == extensions::kExtensionScheme + && origin.host() == extension_misc::kPdfExtensionId; +#else + Q_UNUSED(origin); + return false; +#endif +} + +bool IsPdfInternalPluginAllowedOrigin(const url::Origin &origin) +{ + if (IsPdfExtensionOrigin(origin)) + return true; + + // Allow embedding the internal PDF plugin in chrome://print. + if (origin == url::Origin::Create(GURL(chrome::kChromeUIPrintURL))) + return true; + + // Only allow the PDF plugin in the known, trustworthy origins that are + // allowlisted above. See also https://crbug.com/520422 and + // https://crbug.com/1027173. + return false; +} + +content::RenderFrameHost *GetFullPagePlugin(content::WebContents *contents) +{ + content::RenderFrameHost *full_page_plugin = nullptr; +#if BUILDFLAG(ENABLE_EXTENSIONS) + contents->ForEachRenderFrameHostWithAction([&full_page_plugin](content::RenderFrameHost *rfh) { + auto* guest_view = extensions::MimeHandlerViewGuest::FromRenderFrameHost(rfh); + if (guest_view && guest_view->is_full_page_plugin()) { + DCHECK_EQ(guest_view->GetGuestMainFrame(), rfh); + full_page_plugin = rfh; + return content::RenderFrameHost::FrameIterationAction::kStop; + } + return content::RenderFrameHost::FrameIterationAction::kContinue; + }); +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + return full_page_plugin; +} + +content::RenderFrameHost *FindPdfChildFrame(content::RenderFrameHost *rfh) +{ + if (!rfh) + return nullptr; + + if (!IsPdfExtensionOrigin(rfh->GetLastCommittedOrigin())) + return nullptr; + + content::RenderFrameHost *pdf_rfh = nullptr; + rfh->ForEachRenderFrameHost([&pdf_rfh](content::RenderFrameHost *rfh) { + if (!rfh->GetProcess()->IsPdf()) + return; + + DCHECK(IsPdfExtensionOrigin(rfh->GetParent()->GetLastCommittedOrigin())); + DCHECK(!pdf_rfh); + pdf_rfh = rfh; + }); + + return pdf_rfh; +} + +} // namespace QtWebEngineCore diff --git a/src/core/pdf_util_qt.h b/src/core/pdf_util_qt.h new file mode 100644 index 000000000..5ee211800 --- /dev/null +++ b/src/core/pdf_util_qt.h @@ -0,0 +1,34 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +// Copyright 2021 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE.Chromium file. + +#ifndef PDF_UTIL_QT_H +#define PDF_UTIL_QT_H + +namespace content { +class RenderFrameHost; +class WebContents; +} // namespace content + +namespace url { +class Origin; +} // namespace url + +namespace QtWebEngineCore { + +// from chrome/common/pdf_util.cc: +constexpr char kPDFMimeType[] = "application/pdf"; + +bool IsPdfExtensionOrigin(const url::Origin &origin); +bool IsPdfInternalPluginAllowedOrigin(const url::Origin &origin); + +// from chrome/browser/pdf/pdf_frame_util.cc: +content::RenderFrameHost *GetFullPagePlugin(content::WebContents *contents); +content::RenderFrameHost *FindPdfChildFrame(content::RenderFrameHost *rfh); + +} // namespace QtWebEngineCore + +#endif // PDF_UTIL_QT_H diff --git a/src/core/printing/pdf_web_contents_helper_client_qt.cpp b/src/core/printing/pdf_web_contents_helper_client_qt.cpp index 4deb398c6..0ff7499c3 100644 --- a/src/core/printing/pdf_web_contents_helper_client_qt.cpp +++ b/src/core/printing/pdf_web_contents_helper_client_qt.cpp @@ -9,33 +9,7 @@ #include "extensions/browser/guest_view/mime_handler_view/mime_handler_view_guest.h" #include "extensions/common/constants.h" -namespace { -bool IsPdfExtensionOrigin(const url::Origin &origin) -{ - return origin.scheme() == extensions::kExtensionScheme && - origin.host() == extension_misc::kPdfExtensionId; -} - -// from chrome/browser/pdf/pdf_frame_util.cc: -content::RenderFrameHost *FindPdfChildFrame(content::RenderFrameHost *rfh) -{ - if (!IsPdfExtensionOrigin(rfh->GetLastCommittedOrigin())) - return nullptr; - - content::RenderFrameHost *pdf_rfh = nullptr; - rfh->ForEachRenderFrameHost( - [&pdf_rfh](content::RenderFrameHost *rfh) { - if (!rfh->GetProcess()->IsPdf()) - return; - - DCHECK(IsPdfExtensionOrigin(rfh->GetParent()->GetLastCommittedOrigin())); - DCHECK(!pdf_rfh); - pdf_rfh = rfh; - }); - - return pdf_rfh; -} -} // namespace +#include "pdf_util_qt.h" PDFWebContentsHelperClientQt::PDFWebContentsHelperClientQt() = default; PDFWebContentsHelperClientQt::~PDFWebContentsHelperClientQt() = default; @@ -43,7 +17,7 @@ PDFWebContentsHelperClientQt::~PDFWebContentsHelperClientQt() = default; content::RenderFrameHost *PDFWebContentsHelperClientQt::FindPdfFrame(content::WebContents *contents) { content::RenderFrameHost *main_frame = contents->GetPrimaryMainFrame(); - content::RenderFrameHost *pdf_frame = FindPdfChildFrame(main_frame); + content::RenderFrameHost *pdf_frame = QtWebEngineCore::FindPdfChildFrame(main_frame); return pdf_frame ? pdf_frame : main_frame; } diff --git a/src/core/printing/print_view_manager_qt.cpp b/src/core/printing/print_view_manager_qt.cpp index 892c9e406..060417e5b 100644 --- a/src/core/printing/print_view_manager_qt.cpp +++ b/src/core/printing/print_view_manager_qt.cpp @@ -8,6 +8,7 @@ #include "print_view_manager_qt.h" +#include "pdf_util_qt.h" #include "type_conversion.h" #include "web_contents_adapter_client.h" #include "web_contents_view_qt.h" @@ -238,7 +239,11 @@ bool PrintViewManagerQt::PrintToPDFInternal(const QPageLayout &pageLayout, if (web_contents()->IsCrashed()) return false; - content::RenderFrameHost* rfh = web_contents()->GetPrimaryMainFrame(); + content::RenderFrameHost *rfh = web_contents()->GetPrimaryMainFrame(); + // Use the plugin frame for printing if web_contents() is a PDF viewer guest + content::RenderFrameHost *full_page_plugin = GetFullPagePlugin(web_contents()); + if (content::RenderFrameHost *pdf_rfh = FindPdfChildFrame(full_page_plugin ? full_page_plugin : rfh)) + rfh = pdf_rfh; GetPrintRenderFrame(rfh)->InitiatePrintPreview(mojo::PendingAssociatedRemote<printing::mojom::PrintRenderer>(), false); DCHECK(!m_printPreviewRfh); diff --git a/src/core/printing/printer_worker.cpp b/src/core/printing/printer_worker.cpp index da7165623..6032f2211 100644 --- a/src/core/printing/printer_worker.cpp +++ b/src/core/printing/printer_worker.cpp @@ -27,22 +27,8 @@ void PrinterWorker::print() PdfiumDocumentWrapperQt pdfiumWrapper(m_data->constData(), m_data->size()); - const QPageRanges ranges = m_device->pageRanges(); - int toPage = ranges.firstPage(); - int fromPage = ranges.lastPage(); - bool ascendingOrder = true; - - if (fromPage == 0 && toPage == 0) { - fromPage = 1; - toPage = pdfiumWrapper.pageCount(); - } - fromPage = qMax(1, fromPage); - toPage = qMin(pdfiumWrapper.pageCount(), toPage); - - if (!m_firstPageFirst) { - qSwap(fromPage, toPage); - ascendingOrder = false; - } + const int fromPage = m_firstPageFirst ? 0 : pdfiumWrapper.pageCount() - 1; + const int toPage = m_firstPageFirst ? pdfiumWrapper.pageCount() : -1; int pageCopies = 1; if (m_collateCopies) { @@ -58,10 +44,8 @@ void PrinterWorker::print() if (printedDocuments > 0) m_device->newPage(); - int currentPageIndex = fromPage; - - for (int i = 0; true; i++) { - QSizeF documentSize = (pdfiumWrapper.pageSize(currentPageIndex - 1) * resolution); + for (int i = fromPage; i != toPage; m_firstPageFirst ? i++ : i--) { + QSizeF documentSize = (pdfiumWrapper.pageSize(i) * resolution); bool isLandscape = documentSize.width() > documentSize.height(); m_device->setPageOrientation(isLandscape ? QPageLayout::Landscape : QPageLayout::Portrait); @@ -77,29 +61,21 @@ void PrinterWorker::print() return; } - if (i > 0) + if (i != fromPage) m_device->newPage(); for (int printedPages = 0; printedPages < pageCopies; printedPages++) { if (printedPages > 0) m_device->newPage(); - QImage currentImage = pdfiumWrapper.pageAsQImage( - currentPageIndex - 1, documentSize.width(), documentSize.height()); + QImage currentImage = + pdfiumWrapper.pageAsQImage(i, documentSize.width(), documentSize.height()); if (currentImage.isNull()) { Q_EMIT resultReady(false); return; } painter.drawImage(0, 0, currentImage); } - - if (currentPageIndex == toPage) - break; - - if (ascendingOrder) - currentPageIndex++; - else - currentPageIndex--; } } painter.end(); diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 7561c5d79..4e52041d4 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -683,9 +683,11 @@ void RenderWidgetHostViewQt::OnUpdateTextInputStateCalled(content::TextInputMana // In case of text selection, the update is expected in RenderWidgetHostViewQt::selectionChanged(). if (GetSelectedText().empty()) { - // At this point it is unknown whether the text input state has been updated due to a text selection. - // Keep the cursor position updated for cursor movements too. - delegateClient()->setCursorPosition(state->selection.start()); + if (state->composition.has_value()) { + delegateClient()->setCursorPosition(state->composition->start()); + } else { + delegateClient()->setCursorPosition(state->selection.start()); + } m_delegate->inputMethodStateChanged(type != ui::TEXT_INPUT_TYPE_NONE, type == ui::TEXT_INPUT_TYPE_PASSWORD); } diff --git a/src/core/renderer/print_web_view_helper_delegate_qt.cpp b/src/core/renderer/print_web_view_helper_delegate_qt.cpp index f77b6fbbc..f01568e65 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp +++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp @@ -15,8 +15,10 @@ #include "chrome/common/webui_url_constants.h" #include "extensions/common/constants.h" #include "third_party/blink/public/web/web_document.h" +#include "extensions/renderer/guest_view/mime_handler_view/post_message_support.h" #endif // BUILDFLAG(ENABLE_EXTENSIONS) +#include "pdf_util_qt.h" #include "print_web_view_helper_delegate_qt.h" #include "web_engine_library_info.h" @@ -24,33 +26,13 @@ namespace QtWebEngineCore { PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() {} -bool IsPdfExtensionOrigin(const url::Origin& origin) -{ -#if BUILDFLAG(ENABLE_EXTENSIONS) - return origin.scheme() == extensions::kExtensionScheme - && origin.host() == extension_misc::kPdfExtensionId; -#else - Q_UNUSED(origin); - return false; -#endif -} - blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame *frame) { #if BUILDFLAG(ENABLE_EXTENSIONS) - const url::Origin origin = frame->GetDocument().GetSecurityOrigin(); - bool inside_print_preview = origin == url::Origin::Create(GURL(chrome::kChromeUIPrintURL)); - bool inside_pdf_extension = IsPdfExtensionOrigin(origin); - if (inside_print_preview || inside_pdf_extension) { - // <object> with id="plugin" is created in - // chrome/browser/resources/pdf/pdf_viewer_base.js. - auto viewer_element = frame->GetDocument().GetElementById("viewer"); - if (!viewer_element.IsNull() && !viewer_element.ShadowRoot().IsNull()) { - auto plugin_element = viewer_element.ShadowRoot().QuerySelector("#plugin"); - if (!plugin_element.IsNull()) - return plugin_element; - } - NOTREACHED(); + if (frame->Parent() && IsPdfInternalPluginAllowedOrigin(frame->Parent()->GetSecurityOrigin())) { + auto plugin_element = frame->GetDocument().QuerySelector("embed"); + DCHECK(!plugin_element.IsNull()); + return plugin_element; } #endif // BUILDFLAG(ENABLE_EXTENSIONS) return blink::WebElement(); diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index fe30206ce..f44675171 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -15,6 +15,7 @@ #include "favicon_service_factory_qt.h" #include "find_text_helper.h" #include "media_capture_devices_dispatcher.h" +#include "pdf_util_qt.h" #include "profile_adapter.h" #include "profile_qt.h" #include "qwebengineloadinginfo.h" @@ -1974,7 +1975,7 @@ WebContentsAdapter::LifecycleState WebContentsAdapter::determineRecommendedState // Do not discard PDFs as they might contain entry that is not saved and they // don't remember their scrolling positions. See crbug.com/547286 and // crbug.com/65244. - if (m_webContents->GetContentsMimeType() == "application/pdf") + if (m_webContents->GetContentsMimeType() == kPDFMimeType) return LifecycleState::Frozen; return LifecycleState::Discarded; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index 9df0221d6..fb183bea1 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -985,7 +985,7 @@ const char *qWebEngineChromiumVersion() noexcept const char *qWebEngineChromiumSecurityPatchVersion() noexcept { - return "119.0.6045.199"; // FIXME: Remember to update + return "121.0.6167.85"; // FIXME: Remember to update } QT_END_NAMESPACE diff --git a/src/host/CMakeLists.txt b/src/host/CMakeLists.txt index 6d327a330..2f7642593 100644 --- a/src/host/CMakeLists.txt +++ b/src/host/CMakeLists.txt @@ -19,19 +19,21 @@ project(QtWebEngineConfigure VERSION "${QT_REPO_MODULE_VERSION}" LANGUAGES CXX C) -find_package(Qt6 ${PROJECT_VERSION} CONFIG REQUIRED COMPONENTS BuildInternals Core) +find_package(Qt6 6.5 CONFIG REQUIRED COMPONENTS BuildInternals Core) if(COMMAND qt_internal_project_setup) qt_internal_project_setup() endif() +get_gn_arch(target_arch ${GN_TARGET_CPU}) +get_gn_arch(host_arch ${TEST_architecture_arch}) +get_v8_arch(v8_arch ${target_arch} ${host_arch}) set(buildDir ${CMAKE_CURRENT_BINARY_DIR}) -configure_gn_toolchain(host ${TEST_architecture_arch} ${TEST_architecture_arch} +configure_gn_toolchain(host ${host_arch} ${host_arch} ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in ${buildDir}/host_toolchain ) -get_v8_arch(GN_V8_HOST_CPU ${GN_TARGET_CPU} ${TEST_architecture_arch}) -configure_gn_toolchain(v8 ${GN_V8_HOST_CPU} ${GN_TARGET_CPU} +configure_gn_toolchain(v8 ${v8_arch} ${target_arch} ${WEBENGINE_ROOT_SOURCE_DIR}/src/host/BUILD.toolchain.gn.in ${buildDir}/v8_toolchain) diff --git a/src/pdf/CMakeLists.txt b/src/pdf/CMakeLists.txt index 256180441..1775d598c 100644 --- a/src/pdf/CMakeLists.txt +++ b/src/pdf/CMakeLists.txt @@ -65,7 +65,7 @@ add_code_attributions_target( BUILDDIR ${buildDir}/${config}/${arch} ) add_dependencies(generate_pdf_attributions run_pdf_GnDone) -add_dependencies(docs generate_pdf_attributions) +add_dependencies(prepare_docs_Pdf generate_pdf_attributions) ## # TOOLCHAIN SETUP @@ -245,7 +245,7 @@ endforeach() get_architectures(archs) list(GET archs 0 arch) target_include_directories(Pdf PRIVATE ${buildDir}/$<CONFIG>/${arch}/gen) -add_gn_build_aritfacts_to_target( +add_gn_build_artifacts_to_target( CMAKE_TARGET Pdf NINJA_TARGET QtPdf MODULE pdf diff --git a/src/webenginequick/ui/AlertDialog.qml b/src/webenginequick/ui/AlertDialog.qml index 53911f0bc..e4c17b056 100644 --- a/src/webenginequick/ui/AlertDialog.qml +++ b/src/webenginequick/ui/AlertDialog.qml @@ -49,6 +49,7 @@ Dialog { id: message Layout.fillWidth: true color: palette.windowText + textFormat: Text.PlainText } } Item { diff --git a/src/webenginequick/ui/AuthenticationDialog.qml b/src/webenginequick/ui/AuthenticationDialog.qml index f9de8d79f..d0611b84f 100644 --- a/src/webenginequick/ui/AuthenticationDialog.qml +++ b/src/webenginequick/ui/AuthenticationDialog.qml @@ -50,6 +50,7 @@ Dialog { Label { id: message color: palette.windowText + textFormat: Text.PlainText } GridLayout { columns: 2 diff --git a/src/webenginequick/ui/ConfirmDialog.qml b/src/webenginequick/ui/ConfirmDialog.qml index 7b5f1f5cf..cfffe7c4d 100644 --- a/src/webenginequick/ui/ConfirmDialog.qml +++ b/src/webenginequick/ui/ConfirmDialog.qml @@ -55,6 +55,7 @@ Dialog { id: message Layout.fillWidth: true color: palette.windowText + textFormat: Text.PlainText } } Item { diff --git a/src/webenginequick/ui/PromptDialog.qml b/src/webenginequick/ui/PromptDialog.qml index f3a15d48d..275deace8 100644 --- a/src/webenginequick/ui/PromptDialog.qml +++ b/src/webenginequick/ui/PromptDialog.qml @@ -52,6 +52,7 @@ Dialog { id: message Layout.fillWidth: true color: palette.windowText + textFormat: Text.PlainText } TextField { id:field diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index 952ebe7cd..c4a0da4d9 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -553,8 +553,10 @@ bool QWebEngineViewPrivate::showAuthorizationDialog(const QString &title, const { #if QT_CONFIG(messagebox) Q_Q(QWebEngineView); - return QMessageBox::question(q, title, message, QMessageBox::Yes, QMessageBox::No) - == QMessageBox::Yes; + QMessageBox msgBox(QMessageBox::Question, title, message, QMessageBox::Yes | QMessageBox::No, + q, Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); + msgBox.setTextFormat(Qt::PlainText); + return msgBox.exec() == QMessageBox::Yes; #else return false; #endif // QT_CONFIG(messagebox) @@ -564,8 +566,12 @@ void QWebEngineViewPrivate::javaScriptAlert(const QUrl &url, const QString &msg) { #if QT_CONFIG(messagebox) Q_Q(QWebEngineView); - QMessageBox::information(q, QStringLiteral("Javascript Alert - %1").arg(url.toString()), - msg.toHtmlEscaped()); + QMessageBox msgBox(QMessageBox::Information, + QStringLiteral("Javascript Alert - %1").arg(url.toString()), + msg, QMessageBox::Ok, q, + Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); + msgBox.setTextFormat(Qt::PlainText); + msgBox.exec(); #else Q_UNUSED(msg); #endif // QT_CONFIG(messagebox) @@ -575,10 +581,12 @@ bool QWebEngineViewPrivate::javaScriptConfirm(const QUrl &url, const QString &ms { #if QT_CONFIG(messagebox) Q_Q(QWebEngineView); - return (QMessageBox::information(q, - QStringLiteral("Javascript Confirm - %1").arg(url.toString()), - msg.toHtmlEscaped(), QMessageBox::Ok, QMessageBox::Cancel) - == QMessageBox::Ok); + QMessageBox msgBox(QMessageBox::Information, + QStringLiteral("Javascript Confirm - %1").arg(url.toString()), + msg, QMessageBox::Ok | QMessageBox::Cancel, q, + Qt::Dialog | Qt::MSWindowsFixedSizeDialogHint); + msgBox.setTextFormat(Qt::PlainText); + return msgBox.exec() == QMessageBox::Ok; #else Q_UNUSED(msg); return false; @@ -591,10 +599,16 @@ bool QWebEngineViewPrivate::javaScriptPrompt(const QUrl &url, const QString &msg #if QT_CONFIG(inputdialog) Q_Q(QWebEngineView); bool ret = false; + + // Workaround: Do not interpret text as Qt::RichText + // QInputDialog uses Qt::AutoText that interprets the text string as + // Qt::RichText if Qt::mightBeRichText() returns true, otherwise as Qt::PlainText. + const QString message = Qt::mightBeRichText(msg) ? msg.toHtmlEscaped() : msg; + if (result) *result = QInputDialog::getText( q, QStringLiteral("Javascript Prompt - %1").arg(url.toString()), - msg.toHtmlEscaped(), QLineEdit::Normal, defaultValue.toHtmlEscaped(), &ret); + message, QLineEdit::Normal, defaultValue, &ret); return ret; #else Q_UNUSED(msg); diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index bf68fb048..1e79466a3 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -693,8 +693,8 @@ void tst_QQuickWebEngineView::inputContextQueryInput() QGuiApplication::sendEvent(qApp->focusObject(), &event); } QTRY_COMPARE(testContext.infos.size(), 1); - QCOMPARE(testContext.infos[0].cursorPosition, 3); - QCOMPARE(testContext.infos[0].anchorPosition, 3); + QCOMPARE(testContext.infos[0].cursorPosition, 0); + QCOMPARE(testContext.infos[0].anchorPosition, 0); QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!")); QCOMPARE(testContext.infos[0].selectedText, QStringLiteral("")); QCOMPARE(evaluateJavaScriptSync(view, "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!")); diff --git a/tests/auto/widgets/printing/tst_printing.cpp b/tests/auto/widgets/printing/tst_printing.cpp index 1f9b5059c..605fb57b5 100644 --- a/tests/auto/widgets/printing/tst_printing.cpp +++ b/tests/auto/widgets/printing/tst_printing.cpp @@ -3,6 +3,7 @@ #include <QtWebEngineCore/private/qtwebenginecoreglobal_p.h> #include <QtWebEngineCore/qtwebenginecore-config.h> +#include <QWebEngineSettings> #include <QWebEngineView> #include <QTemporaryDir> #include <QTest> @@ -22,6 +23,7 @@ private slots: void printRequest(); #if QT_CONFIG(webengine_system_poppler) void printToPdfPoppler(); + void printFromPdfViewer(); #endif void interruptPrinting(); }; @@ -116,6 +118,50 @@ void tst_Printing::printToPdfPoppler() QVERIFY2(pdfPage->search(ustring::from_latin1("Hello Paper World"), rect, page::search_from_top, case_sensitive ), "Could not find text"); } + +void tst_Printing::printFromPdfViewer() +{ + using namespace poppler; + + QWebEngineView view; + view.page()->settings()->setAttribute(QWebEngineSettings::PluginsEnabled, true); + view.page()->settings()->setAttribute(QWebEngineSettings::PdfViewerEnabled, true); + + // Load a basic HTML + QSignalSpy spy(&view, &QWebEngineView::loadFinished); + view.load(QUrl("qrc:///resources/basic_printing_page.html")); + QTRY_COMPARE(spy.size(), 1); + + // Create a PDF + QTemporaryDir tempDir(QDir::tempPath() + "/tst_printing-XXXXXX"); + QVERIFY(tempDir.isValid()); + QString path = tempDir.path() + "/basic_page.pdf"; + QSignalSpy savePdfSpy(view.page(), &QWebEnginePage::pdfPrintingFinished); + view.page()->printToPdf(path); + QTRY_COMPARE(savePdfSpy.size(), 1); + + // Open the new file with the PDF viewer plugin + view.load(QUrl("file://" + path)); + QTRY_COMPARE(spy.size(), 2); + + // Print from the plugin + // loadFinished signal is not reliable when loading a PDF file, because it has multiple phases. + // Workaround: Try to print it a couple of times until the result matches the expected. + CallbackSpy<QByteArray> resultSpy; + bool ok = QTest::qWaitFor([&]() -> bool { + view.printToPdf(resultSpy.ref()); + QByteArray data = resultSpy.waitForResult(); + + // Check if the result contains text from the original basic HTML + // This catches all the typical issues: empty result or printing the WebUI without PDF content. + QScopedPointer<document> pdf(document::load_from_raw_data(data.constData(), data.length())); + QScopedPointer<page> pdfPage(pdf->create_page(0)); + rectf rect; + return pdfPage->search(ustring::from_latin1("Hello Paper World"), rect, page::search_from_top, + case_sensitive); + }, 10000); + QVERIFY(ok); +} #endif void tst_Printing::interruptPrinting() diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 47874c791..4331a5e36 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -2062,8 +2062,8 @@ void tst_QWebEngineView::inputContextQueryInput() QApplication::sendEvent(view.focusProxy(), &event); } QTRY_COMPARE(testContext.infos.size(), 1); - QCOMPARE(testContext.infos[0].cursorPosition, 3); - QCOMPARE(testContext.infos[0].anchorPosition, 3); + QCOMPARE(testContext.infos[0].cursorPosition, 0); + QCOMPARE(testContext.infos[0].anchorPosition, 0); QCOMPARE(testContext.infos[0].surroundingText, QStringLiteral("QtWebEngine!")); QCOMPARE(testContext.infos[0].selectedText, QStringLiteral("")); QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QStringLiteral("123QtWebEngine!")); @@ -2659,8 +2659,8 @@ void tst_QWebEngineView::imeComposition() QApplication::sendEvent(view.focusProxy(), &event); } QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImSurroundingText).toString(), QString("")); - QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11); - QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 11); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0); + QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImAnchorPosition).toInt(), 0); QCOMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCurrentSelection).toString(), QString("")); QCOMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QString("QtWebEngine")); @@ -2971,7 +2971,7 @@ void tst_QWebEngineView::imeCompositionQueryEvent() qApp->processEvents(); } QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value").toString(), QString("composition")); - QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11); + QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 0); QApplication::sendEvent(input, &srrndTextQuery); QApplication::sendEvent(input, &absolutePosQuery); @@ -2980,9 +2980,9 @@ void tst_QWebEngineView::imeCompositionQueryEvent() qApp->processEvents(); QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString("")); - QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 11); - QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 11); - QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11); + QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 0); + QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 0); + QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 0); // Send commit { @@ -3005,6 +3005,55 @@ void tst_QWebEngineView::imeCompositionQueryEvent() QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 11); QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 11); QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11); + + // Test another composition to ensure that the cursor position is set correctly. + // In this case cursor will be at position 11 during input composition. + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("123", attributes); + QApplication::sendEvent(input, &event); + qApp->processEvents(); + } + QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value") + .toString(), + QString("composition123")); + QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 11); + + QApplication::sendEvent(input, &srrndTextQuery); + QApplication::sendEvent(input, &absolutePosQuery); + QApplication::sendEvent(input, &cursorPosQuery); + QApplication::sendEvent(input, &anchorPosQuery); + qApp->processEvents(); + + QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString("composition")); + QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 11); + QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 11); + QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 11); + + // Send commit + { + QList<QInputMethodEvent::Attribute> attributes; + QInputMethodEvent event("", attributes); + event.setCommitString("123"); + QApplication::sendEvent(input, &event); + qApp->processEvents(); + } + + QTRY_COMPARE(evaluateJavaScriptSync(view.page(), "document.getElementById('input1').value") + .toString(), + QString("composition123")); + QTRY_COMPARE(view.focusProxy()->inputMethodQuery(Qt::ImCursorPosition).toInt(), 14); + + QApplication::sendEvent(input, &srrndTextQuery); + QApplication::sendEvent(input, &absolutePosQuery); + QApplication::sendEvent(input, &cursorPosQuery); + QApplication::sendEvent(input, &anchorPosQuery); + qApp->processEvents(); + + QTRY_COMPARE(srrndTextQuery.value(Qt::ImSurroundingText).toString(), QString("composition123")); + QTRY_COMPARE(absolutePosQuery.value(Qt::ImAbsolutePosition).toInt(), 14); + QTRY_COMPARE(cursorPosQuery.value(Qt::ImCursorPosition).toInt(), 14); + QTRY_COMPARE(anchorPosQuery.value(Qt::ImAnchorPosition).toInt(), 14); } #if QT_CONFIG(clipboard) |