diff --git a/.qmake.conf b/.qmake.conf index d5e64505d65..716f138c91d 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -5,4 +5,4 @@ QTWEBENGINE_OUT_ROOT = $$shadowed($$PWD) load(qt_build_config) CONFIG += warning_clean -MODULE_VERSION = 5.15.4 +MODULE_VERSION = 5.15.19 diff --git a/CHROMIUM_VERSION b/CHROMIUM_VERSION new file mode 100644 index 00000000000..b6d2fbfd3a3 --- /dev/null +++ b/CHROMIUM_VERSION @@ -0,0 +1,2 @@ +Based on Chromium version: 87.0.4280.144 +Patched with security patches up to Chromium version: 135.0.7049.95 diff --git a/coin/qt-installer-package-config.json b/coin/qt-installer-package-config.json index 0ba69adacfb..d556d245f9b 100644 --- a/coin/qt-installer-package-config.json +++ b/coin/qt-installer-package-config.json @@ -2,16 +2,19 @@ "version": "1", "module-split": { "qtpdf": [ + "**/bin/*Pdf*", "**/include/*QtPdf*/**/*", - "**/lib/cmake/Qt5Gui/*", - "**/lib/cmake/Qt5Pdf/*", - "**/lib/cmake/Qt5PdfWidgets/*", - "**/lib/pkgconfig/Qt5Pdf*", - "**/lib/libQt5Pdf*", + "**/lib/cmake/Qt*Gui/*Pdf*", + "**/lib/cmake/Qt*Pdf*/*", + "**/lib/cmake/Qt*Qml/QmlPlugins/*pdf*", + "**/lib/metatypes/*pdf*", + "**/lib/pkgconfig/*Pdf*", + "**/lib/*Pdf*", "**/lib/static_chrome/*", - "**/lib/QtPdf.framework/*", + "**/lib/QtPdf*.framework/**", "**/mkspecs/modules/qt_lib_pdf*", "**/mkspecs/modules/qt_plugin_qpdf.pri", + "**/modules/Pdf*", "**/plugins/imageformats/*", "**/qml/QtQuick/**/*" ] diff --git a/config_help.txt b/config_help.txt index 48236c18ab5..d50892121cb 100644 --- a/config_help.txt +++ b/config_help.txt @@ -15,6 +15,7 @@ WebEngine options: (Linux only) -webengine-pepper-plugins ...... Enable use of Pepper Flash and Widevine plugins [auto] + -webengine-python-version ...... Use specific python version for building [python2/python3] -webengine-printing-and-pdf .... Enable use of printing and output to PDF [auto] -webengine-proprietary-codecs .. Enable support for proprietary codecs [no] diff --git a/configure.pri b/configure.pri index e072961f057..cb53c93b0aa 100644 --- a/configure.pri +++ b/configure.pri @@ -12,12 +12,9 @@ defineTest(isPythonVersionSupported) { python_version ~= s/[()]//g python_version = $$split(python_version, ',') python_major_version = $$first(python_version) - greaterThan(python_major_version, 2) { - qtLog("Python version 3 is not supported by Chromium.") - return(false) - } python_minor_version = $$member(python_version, 1) python_patch_version = $$member(python_version, 2) + greaterThan(python_major_version, 2): greaterThan(python_minor_version, 7): return(true) greaterThan(python_major_version, 1): greaterThan(python_minor_version, 6): greaterThan(python_patch_version, 4): return(true) qtLog("Unsupported python version: $${python_major_version}.$${python_minor_version}.$${python_patch_version}.") return(false) @@ -53,21 +50,37 @@ defineTest(qtConfReport_jumboBuild) { } defineTest(qtConfTest_detectPython2) { - python = $$qtConfFindInPath("python2$$EXE_SUFFIX") - isEmpty(python) { - qtLog("'python2$$EXE_SUFFIX' not found in PATH. Checking for 'python$$EXE_SUFFIX'.") - python = $$qtConfFindInPath("python$$EXE_SUFFIX") + pythonOverride = $$eval(config.input.python_override) + !isEmpty(pythonOverride) { + python = $$qtConfFindInPath("$$pythonOverride$$EXE_SUFFIX") + isEmpty(python) { + qtLog("User selected '$$pythonOverride$$EXE_SUFFIX' was not found in PATH. Giving up.") + return(false) + } } + + win32 { + # the default name of the python 2 executable on windows is just + # python, so try that first + isEmpty(python):python = $$qtConfFindInPath("python$$EXE_SUFFIX") + isEmpty(python):python = $$qtConfFindInPath("python2$$EXE_SUFFIX") + isEmpty(python):python = $$qtConfFindInPath("python3$$EXE_SUFFIX") + } else { + isEmpty(python):python = $$qtConfFindInPath("python2$$EXE_SUFFIX") + isEmpty(python):python = $$qtConfFindInPath("python3$$EXE_SUFFIX") + isEmpty(python):python = $$qtConfFindInPath("python$$EXE_SUFFIX") + } + isEmpty(python) { - qtLog("'python$$EXE_SUFFIX' not found in PATH. Giving up.") + qtLog("Python not found in PATH. Giving up.") return(false) } !isPythonVersionSupported($$python) { - qtLog("A suitable Python 2 executable could not be located.") + qtLog("A suitable Python executable could not be located.") return(false) } - # Make tests.python2.location available in configure.json. + # Make tests.python.location available in configure.json. $${1}.location = $$clean_path($$python) export($${1}.location) $${1}.cache += location @@ -460,6 +473,10 @@ defineTest(qtwebengine_isMacOsPlatformSupported) { qtwebengine_platformError("requires a macOS SDK version of 10.13 or newer. Current version is $${WEBENGINE_OSX_SDK_PRODUCT_VERSION}.") return(false) } + CONFIG(debug, debug|release):isUniversal(){ + qtwebengine_platformError("Universal builds can not be done with debug configuration due to large binary size.") + return(false) + } return(true) } diff --git a/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml b/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml index 8b852338875..ecbe8d3afd7 100644 --- a/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml +++ b/examples/webengine/customdialogs/forms/AuthenticationForm.ui.qml @@ -122,6 +122,7 @@ Item { height: 22 Layout.fillWidth: true font.pointSize: 12 + textColor: "black" } Text { @@ -136,6 +137,8 @@ Item { height: 26 Layout.fillWidth: true font.pointSize: 12 + textColor: "black" + echoMode: TextInput.Password } Item { diff --git a/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml b/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml index 1c7fd29ed81..7dad1090ad6 100644 --- a/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml +++ b/examples/webengine/customdialogs/forms/JavaScriptForm.ui.qml @@ -124,6 +124,7 @@ Item { height: 22 Layout.fillWidth: true font.pointSize: 12 + textColor: "black" } Item { diff --git a/examples/webenginewidgets/cookiebrowser/mainwindow.cpp b/examples/webenginewidgets/cookiebrowser/mainwindow.cpp index 970381d4d42..0171b9c7f4d 100644 --- a/examples/webenginewidgets/cookiebrowser/mainwindow.cpp +++ b/examples/webenginewidgets/cookiebrowser/mainwindow.cpp @@ -107,7 +107,7 @@ CookieWidget::CookieWidget(const QNetworkCookie &cookie, QWidget *parent): QWidg void CookieWidget::setHighlighted(bool enabled) { QPalette p = palette(); - p.setColor(backgroundRole(), enabled ? QColor(0xF0, 0xF8, 0xFF) : Qt::white); + p.setColor(backgroundRole(), enabled ? p.alternateBase().color() : p.base().color()); setPalette(p); } diff --git a/examples/webenginewidgets/markdowneditor/mainwindow.cpp b/examples/webenginewidgets/markdowneditor/mainwindow.cpp index 28d6f56412d..4ce2c1618c4 100644 --- a/examples/webenginewidgets/markdowneditor/mainwindow.cpp +++ b/examples/webenginewidgets/markdowneditor/mainwindow.cpp @@ -170,7 +170,7 @@ void MainWindow::onFileSave() void MainWindow::onFileSaveAs() { QString path = QFileDialog::getSaveFileName(this, - tr("Save MarkDown File"), "", tr("MarkDown File (*.md, *.markdown)")); + tr("Save MarkDown File"), "", tr("MarkDown File (*.md *.markdown)")); if (path.isEmpty()) return; m_filePath = path; diff --git a/examples/webenginewidgets/webenginewidgets.pro b/examples/webenginewidgets/webenginewidgets.pro index deb42a8cd42..31a214ceb59 100644 --- a/examples/webenginewidgets/webenginewidgets.pro +++ b/examples/webenginewidgets/webenginewidgets.pro @@ -1,3 +1,5 @@ +load(functions) + include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) # workaround for QTBUG-68093 QT_FOR_CONFIG += webenginecore webenginecore-private @@ -20,7 +22,7 @@ qtConfig(webengine-printing-and-pdf) { SUBDIRS += printme html2pdf } -qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile { +qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile:!isUniversal() { SUBDIRS += spellchecker } else { message("Spellcheck example will not be built because it depends on usage of Hunspell dictionaries.") diff --git a/mkspecs/features/functions.prf b/mkspecs/features/functions.prf index 2750d707171..7f630588a10 100644 --- a/mkspecs/features/functions.prf +++ b/mkspecs/features/functions.prf @@ -5,6 +5,11 @@ defineReplace(getConfigDir) { return("debug") } +defineTest(isUniversal) { + macos:count(QT_ARCHS, 1, >):return(true) + return(false) +} + defineReplace(getChromiumSrcDir) { exists($$QTWEBENGINE_ROOT/.git): git_chromium_src_dir = $$system("git config qtwebengine.chromiumsrcdir") # Fall back to the snapshot path if git does not know about chromium sources (i.e. init-repository.py has not been used) diff --git a/mkspecs/features/gn_generator.prf b/mkspecs/features/gn_generator.prf index a83b59847a9..306e58db164 100644 --- a/mkspecs/features/gn_generator.prf +++ b/mkspecs/features/gn_generator.prf @@ -27,7 +27,7 @@ defineReplace(filter_flag_values) { return($$value_to_check) } -isEmpty(GN_FILE): GN_FILE = $$system_path($$_PRO_FILE_PWD_/BUILD.gn) +isEmpty(GN_FILES): GN_FILES = $$system_path($$_PRO_FILE_PWD_/BUILD.gn) isEmpty(GN_RUN_BINARY_SCRIPT): GN_RUN_BINARY_SCRIPT = "//build/gn_run_binary.py" isEmpty(GN_FIND_MOCABLES_SCRIPT): GN_FIND_MOCABLES_SCRIPT = "//build/gn_find_mocables.py" @@ -260,12 +260,13 @@ GN_CONTENTS += "}" for (inc, GN_INCLUDES): GN_CONTENTS += $$cat($$inc,lines) } -build_pass|!debug_and_release: write_file($$GN_FILE, GN_CONTENTS) - +build_pass|!debug_and_release { + for(gnFile, GN_FILES): write_file($$gnFile, GN_CONTENTS) +} # The generated Makefile shouldn't build anything by itself, just re-run qmake if necessary TEMPLATE = aux SOURCES = HEADERS = RESOURCES = -QMAKE_DISTCLEAN += $$GN_FILE +QMAKE_DISTCLEAN += $$GN_FILES diff --git a/src/3rdparty b/src/3rdparty index 1d3b13e9634..6d29e9cfcff 160000 --- a/src/3rdparty +++ b/src/3rdparty @@ -1 +1 @@ -Subproject commit 1d3b13e963467a19ebdd515431464771f513f6ef +Subproject commit 6d29e9cfcfffa7632cc3858ceaf8940677ba9c91 diff --git a/src/buildtools/config/lipo.pri b/src/buildtools/config/lipo.pri new file mode 100644 index 00000000000..f065c8ee9b4 --- /dev/null +++ b/src/buildtools/config/lipo.pri @@ -0,0 +1,85 @@ +for(arch, QT_ARCHS) { + + linking_pri = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}.pri + + !include($$linking_pri) { + message("Could not find the linking information that gn should have generated.") + } + + # Do not precompile any headers. We are only interested in the linker step. + PRECOMPILED_HEADER = + + isEmpty(NINJA_OBJECTS): error("Missing object files from linking pri.") + isEmpty(NINJA_LFLAGS): error("Missing linker flags from linking pri") + isEmpty(NINJA_ARCHIVES): error("Missing archive files from linking pri") + isEmpty(NINJA_LIBS): error("Missing library files from linking pri") + NINJA_OBJECTS = $$eval($$list($$NINJA_OBJECTS)) + # Do manual response files + + + RSP_OBJECT_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_objects.rsp + for(object, NINJA_OBJECTS): RSP_OBJECTS_CONTENT += $$object + write_file($$RSP_OBJECT_FILE, RSP_OBJECTS_CONTENT) + RSP_ARCHIVE_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_archives.rsp + for(archive, NINJA_ARCHIVES): RSP_ARCHIVES_CONTENT += $$archive + write_file($$RSP_ARCHIVE_FILE, RSP_ARCHIVES_CONTENT) + RSP_LIBS_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_libs.rsp + for(lib, NINJA_LIBS): RSP_LIBS_CONTENT += $$lib + write_file($$RSP_LIBS_FILE, RSP_LIBS_CONTENT) + + unset(RSP_OBJECTS_CONTENT) + unset(RSP_ARCHIVES_CONTENT) + unset(RSP_LIBS_CONTENT) + unset(NINJA_OBJECTS) + unset(NINJA_LFLAGS) + unset(NINJA_ARCHIVES) + unset(NINJA_LIBS) +} + +LIPO_OUT_FILE = $$OUT_PWD/$$getConfigDir()/$${TARGET}.a +INPUT_FILE = . +lipo.name = lipo +lipo.output = $$LIPO_OUT_FILE +lipo.input = INPUT_FILE +lipo.CONFIG += target_predeps no_link +lipo.commands = lipo -create -output $$LIPO_OUT_FILE +QMAKE_EXTRA_COMPILERS += lipo + +include($$QTWEBENGINE_ROOT/src/buildtools/config/mac_osx.pri) + +for(arch, QT_ARCHS) { + + RSP_OBJECT_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_objects.rsp + OBJECT_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_objects.o + RSP_ARCHIVE_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_archives.rsp + ARCHIVE_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}_archives.o + OUT_FILE = $$OUT_PWD/$$arch/$$getConfigDir()/$${TARGET}.a + + intermediate_archive_$${arch}.name = build_intermediate_archive_$${arch} + intermediate_archive_$${arch}.output= $$OUT_FILE + intermediate_archive_$${arch}.input = INPUT_FILE + intermediate_archive_$${arch}.depends = $$RSP_OBJECT_FILE $$RSP_ARCHIVE_FILE $$NINJA_TARGETDEPS + intermediate_archive_$${arch}.CONFIG += target_predeps no_link + intermediate_archive_$${arch}.commands = \ + clang++ -r -nostdlib -arch $$arch \ + -mmacosx-version-min=$${QMAKE_MACOSX_DEPLOYMENT_TARGET} \ + -o $$OBJECT_FILE \ + -Wl,-keep_private_externs \ + @$$RSP_OBJECT_FILE ;\ + $$QMAKE_CC -r -nostdlib -arch $$arch \ + -mmacosx-version-min=$${QMAKE_MACOSX_DEPLOYMENT_TARGET} \ + -o $$ARCHIVE_FILE \ + -Wl,-keep_private_externs \ + -Wl,-all_load \ + @$$RSP_ARCHIVE_FILE ;\ + ar -crs $$OUT_FILE $$OBJECT_FILE $$ARCHIVE_FILE + lipo.depends += $$OUT_FILE + lipo.commands += $$OUT_FILE + QMAKE_EXTRA_COMPILERS += intermediate_archive_$$arch + + unset(RSP_OBJECT_FILE) + unset(OBJECT_FILE) + unset(RSP_ARCHVIE_FILE) + unset(OUT_FILE) +} + diff --git a/src/buildtools/config/lipo_linking.pri b/src/buildtools/config/lipo_linking.pri new file mode 100644 index 00000000000..c65fef059da --- /dev/null +++ b/src/buildtools/config/lipo_linking.pri @@ -0,0 +1,15 @@ +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) +QT_FOR_CONFIG += buildtools-private + +LIPO_OUT_FILE = $$OUT_PWD/$$getConfigDir()/$${TARGET}.a +!static { + QMAKE_LFLAGS += $${LIPO_OUT_FILE} +} else { + LIBS_PRIVATE += $${LIPO_OUT_FILE} +} + +LIBS_PRIVATE += @$$OUT_PWD/$$QT_ARCH/$$getConfigDir()/$${TARGET}_libs.rsp + +qtConfig(webengine-noexecstack): QMAKE_LFLAGS += -Wl,-z,noexecstack + +POST_TARGETDEPS += $$LIPO_OUT_FILE diff --git a/src/buildtools/config/mac_osx.pri b/src/buildtools/config/mac_osx.pri index b53f9170647..b821860833b 100644 --- a/src/buildtools/config/mac_osx.pri +++ b/src/buildtools/config/mac_osx.pri @@ -34,5 +34,9 @@ gn_args += \ mac_deployment_target=\"$${QMAKE_MACOSX_DEPLOYMENT_TARGET}\" \ mac_sdk_min=\"$${QMAKE_MAC_SDK_VERSION_MAJOR_MINOR}\" \ use_external_popup_menu=false \ - angle_enable_vulkan=false + angle_enable_vulkan=false \ + fatal_linker_warnings=false +cross_compile:!host_build { + gn_args += target_cpu=\"$$gnArch($$QT_ARCH)\" +} diff --git a/src/buildtools/config/support.pri b/src/buildtools/config/support.pri index e7f869a15f9..a9df3d2432c 100644 --- a/src/buildtools/config/support.pri +++ b/src/buildtools/config/support.pri @@ -21,7 +21,7 @@ defineReplace(qtwebengine_checkWebEngineCoreError) { !qtwebengine_checkForGperf(QtWebEngine):return(false) !qtwebengine_checkForBison(QtWebEngine):return(false) !qtwebengine_checkForFlex(QtWebEngine):return(false) - !qtwebengine_checkForPython2(QtWebEngine):return(false) + !qtwebengine_checkForPython(QtWebEngine):return(false) !qtwebengine_checkForNodejs(QtWebEngine):return(false) !qtwebengine_checkForSanitizer(QtWebEngine):return(false) linux:!qtwebengine_checkForPkgCfg(QtWebEngine):return(false) @@ -51,7 +51,7 @@ defineReplace(qtwebengine_checkPdfError) { !qtwebengine_checkForGperf(QtPdf):return(false) !qtwebengine_checkForBison(QtPdf):return(false) !qtwebengine_checkForFlex(QtPdf):return(false) - !qtwebengine_checkForPython2(QtPdf):return(false) + !qtwebengine_checkForPython(QtPdf):return(false) !qtwebengine_checkForSanitizer(QtPdf):return(false) linux:!qtwebengine_checkForPkgCfg(QtPdf):return(false) linux:!qtwebengine_checkForHostPkgCfg(QtPdf):return(false) @@ -143,10 +143,10 @@ defineTest(qtwebengine_checkForFlex) { return(true) } -defineTest(qtwebengine_checkForPython2) { +defineTest(qtwebengine_checkForPython) { module = $$1 - !qtConfig(webengine-python2) { - qtwebengine_skipBuild("Python version 2 (2.7.5 or later) is required to build $${module}.") + !qtConfig(webengine-python) { + qtwebengine_skipBuild("Python version 2 (2.7.5 or later) or Python version 3 (3.6 or later) is required to build $${module}.") return(false) } return(true) diff --git a/src/buildtools/config/windows.pri b/src/buildtools/config/windows.pri index 843d6f2b16c..f7b80e6e4a0 100644 --- a/src/buildtools/config/windows.pri +++ b/src/buildtools/config/windows.pri @@ -71,7 +71,7 @@ msvc:contains(QT_ARCH, "i386"):!usingMSVC32BitCrossCompiler() { msvc { equals(MSVC_VER, 15.0) { MSVS_VERSION = 2017 - } else: equals(MSVC_VER, 16.0) { + } else: versionAtLeast(MSVC_VER, 16.0) { MSVS_VERSION = 2019 } else { error("Visual Studio compiler version \"$$MSVC_VER\" is not supported by gn.") diff --git a/src/buildtools/configure.json b/src/buildtools/configure.json index 88d1790c17c..5e5d9d725e9 100644 --- a/src/buildtools/configure.json +++ b/src/buildtools/configure.json @@ -10,7 +10,8 @@ "options": { "build-qtwebengine-core": "boolean", "build-qtpdf": "boolean", - "webengine-jumbo-build": { "type": "optionalString", "name": "merge_limit"} + "webengine-jumbo-build": { "type": "optionalString", "name": "merge_limit"}, + "webengine-python-version": { "type": "optionalString", "name": "python_override", "values": ["python2", "python3"] } } }, "libraries": { @@ -212,6 +213,27 @@ { "type": "pkgConfig", "args": "libavcodec libavformat libavutil" } ] }, + "webengine-ffmpeg-support": { + "label": "compatible ffmpeg", + "type": "compile", + "test": { + "head": [ + "#include ", + "extern \"C\" {", + "#include ", + "}" + ], + "main": [ + "#if LIBAVFORMAT_VERSION_MAJOR >= 59", + "AVStream stream;", + "auto first_dts = av_stream_get_first_dts(&stream);", + "#endif" + ] + }, + "sources": [ + { "type": "pkgConfig", "args": "libavformat" } + ] + }, "webengine-opus": { "label": "opus", "sources": [ @@ -295,7 +317,7 @@ "label": "system ninja", "type": "detectNinja" }, - "webengine-python2": { + "webengine-python": { "label": "python2", "type": "detectPython2", "log": "location" @@ -374,7 +396,7 @@ && features.webengine-gperf && features.webengine-bison && features.webengine-flex - && features.webengine-python2 + && features.webengine-python && features.webengine-nodejs && (!config.sanitizer || features.webengine-sanitizer) && (!config.linux || features.pkg-config) @@ -400,7 +422,7 @@ && features.webengine-gperf && features.webengine-bison && features.webengine-flex - && features.webengine-python2 + && features.webengine-python && (!config.sanitizer || features.webengine-sanitizer) && (!config.linux || features.pkg-config) && (!config.linux || features.webengine-host-pkg-config) @@ -423,12 +445,12 @@ "autoDetect": "features.private_tests", "output": [ "privateFeature" ] }, - "webengine-python2": { + "webengine-python": { "label": "python2", - "condition": "tests.webengine-python2", + "condition": "tests.webengine-python", "output": [ "privateFeature", - { "type": "varAssign", "name": "QMAKE_PYTHON2", "value": "tests.webengine-python2.location" } + { "type": "varAssign", "name": "QMAKE_PYTHON2", "value": "tests.webengine-python.location" } ] }, "webengine-gperf": { @@ -758,6 +780,11 @@ "type": "warning", "condition": "config.ios && config.simulator && config.device && features.build-qtpdf", "message": "Building fat libray with device and simulator architectures will disable NEON." + }, + { + "type": "fatal", + "condition": "features.webengine-system-ffmpeg && !libs.webengine-ffmpeg-support", + "message": "Unmodified ffmpeg >= 5.0 is not supported. Please configure with -qt-webengine-ffmpeg." } ], "summary": [ diff --git a/src/buildtools/gn.pro b/src/buildtools/gn.pro index 033202e6eab..f94694da02d 100644 --- a/src/buildtools/gn.pro +++ b/src/buildtools/gn.pro @@ -21,6 +21,7 @@ build_pass|!debug_and_release { gn_gen_args = --no-last-commit-position --out-path $$out_path \ --cc \"$$which($$QMAKE_CC)\" --cxx \"$$which($$QMAKE_CXX)\" \ --ld \"$$which($$QMAKE_LINK)\" + !isEmpty(QMAKE_AR): gn_gen_args += --ar \"$$which($$first(QMAKE_AR))\" msvc:!clang_cl: gn_gen_args += --use-lto diff --git a/src/core/accessibility_activation_observer.cpp b/src/core/accessibility_activation_observer.cpp index 83319084402..b9d73cb6865 100644 --- a/src/core/accessibility_activation_observer.cpp +++ b/src/core/accessibility_activation_observer.cpp @@ -48,12 +48,13 @@ namespace QtWebEngineCore { namespace { bool isAccessibilityEnabled() { - // On Linux accessibility is disabled by default due to performance issues, - // and can be re-enabled by setting the QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment - // variable. For details, see QTBUG-59922. + // On Linux accessibility can be disabled due to performance issues by setting the + // QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to 0. For details, + // see QTBUG-59922. #ifdef Q_OS_LINUX static bool accessibility_enabled - = qEnvironmentVariableIsSet("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY"); + = qEnvironmentVariable("QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY", QLatin1String("1")) + == QLatin1String("1"); #else const bool accessibility_enabled = true; #endif diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 2ddd0d69f5e..28d5586ba8c 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -23,7 +23,12 @@ DEFINES += \ NOMINMAX CHROMIUM_SRC_DIR = $$QTWEBENGINE_ROOT/$$getChromiumSrcDir() -CHROMIUM_GEN_DIR = $$OUT_PWD/../$$getConfigDir()/gen + +isUniversal() { + CHROMIUM_GEN_DIR = $$OUT_PWD/../$$QT_ARCH/$$getConfigDir()/gen +} else { + CHROMIUM_GEN_DIR = $$OUT_PWD/../$$getConfigDir()/gen +} INCLUDEPATH += $$QTWEBENGINE_ROOT/src/core \ $$CHROMIUM_GEN_DIR \ $$CHROMIUM_SRC_DIR/third_party/abseil-cpp \ diff --git a/src/core/api/qtwebenginecoreglobal.cpp b/src/core/api/qtwebenginecoreglobal.cpp index 3c9387a10c0..f51aa25c3d5 100644 --- a/src/core/api/qtwebenginecoreglobal.cpp +++ b/src/core/api/qtwebenginecoreglobal.cpp @@ -50,6 +50,7 @@ #endif #endif #include +#include "web_engine_context.h" #if QT_CONFIG(opengl) QT_BEGIN_NAMESPACE @@ -184,4 +185,10 @@ Q_WEBENGINECORE_PRIVATE_EXPORT void initialize() app->setAttribute(Qt::AA_ShareOpenGLContexts); #endif // QT_CONFIG(opengl) } + +bool closingDown() +{ + return WebEngineContext::closingDown(); +} + } // namespace QtWebEngineCore diff --git a/src/core/api/qtwebenginecoreglobal_p.h b/src/core/api/qtwebenginecoreglobal_p.h index 655b2a81495..3a3496e0457 100644 --- a/src/core/api/qtwebenginecoreglobal_p.h +++ b/src/core/api/qtwebenginecoreglobal_p.h @@ -65,4 +65,7 @@ #define Q_WEBENGINECORE_PRIVATE_EXPORT Q_WEBENGINECORE_EXPORT +namespace QtWebEngineCore { +Q_WEBENGINECORE_PRIVATE_EXPORT bool closingDown(); +} // namespace #endif // QTWEBENGINECOREGLOBAL_P_H diff --git a/src/core/browsing_data_remover_delegate_qt.h b/src/core/browsing_data_remover_delegate_qt.h index a10409f3971..5adfbbe7ebe 100644 --- a/src/core/browsing_data_remover_delegate_qt.h +++ b/src/core/browsing_data_remover_delegate_qt.h @@ -40,6 +40,8 @@ #ifndef BROWSING_DATA_REMOVER_DELEGATE_QT_H #define BROWSING_DATA_REMOVER_DELEGATE_QT_H +#include + #include "content/public/browser/browsing_data_remover_delegate.h" namespace QtWebEngineCore { diff --git a/src/core/compositor/content_gpu_client_qt.cpp b/src/core/compositor/content_gpu_client_qt.cpp index f934979a0f9..2c0f7854839 100644 --- a/src/core/compositor/content_gpu_client_qt.cpp +++ b/src/core/compositor/content_gpu_client_qt.cpp @@ -38,22 +38,151 @@ ****************************************************************************/ #include "content_gpu_client_qt.h" - #include "web_engine_context.h" +#include "ui/gl/gl_share_group.h" +#include "ui/gl/gl_context.h" +#include "ui/gl/gl_implementation.h" +#include "ui/gl/gpu_timing.h" + +#if QT_CONFIG(opengl) +#include +#include +#endif + +#include +#include + +#if QT_CONFIG(opengl) +QT_BEGIN_NAMESPACE +Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); +QT_END_NAMESPACE +#endif namespace QtWebEngineCore { -ContentGpuClientQt::ContentGpuClientQt() +class QtShareGLContext : public gl::GLContext { -} +public: + QtShareGLContext(QOpenGLContext *qtContext) : gl::GLContext(0), m_handle(0) + { + QString platform = qApp->platformName().toLower(); + QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface(); + if (platform == QLatin1String("xcb") || platform == QLatin1String("offscreen")) { + if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) + m_handle = + pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else + m_handle = + pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext); + } else if (platform == QLatin1String("cocoa")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); + else if (platform == QLatin1String("qnx")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland") + || platform == QLatin1String("wayland-egl")) + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); + else if (platform == QLatin1String("windows")) { + if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) + m_handle = + pni->nativeResourceForContext(QByteArrayLiteral("eglContext"), qtContext); + else + m_handle = pni->nativeResourceForContext(QByteArrayLiteral("renderingcontext"), + qtContext); + } else { + qFatal("%s platform not yet supported", platform.toLatin1().constData()); + // Add missing platforms once they work. + Q_UNREACHABLE(); + } + } + + void *GetHandle() override { return m_handle; } + unsigned int CheckStickyGraphicsResetStatusImpl() override + { +#if QT_CONFIG(opengl) + if (QOpenGLContext *context = qt_gl_global_share_context()) { + if (context->format().testOption(QSurfaceFormat::ResetNotification)) + return context->extraFunctions()->glGetGraphicsResetStatus(); + } +#endif + return 0 /*GL_NO_ERROR*/; + } + + // We don't care about the rest, this context shouldn't be used except for its handle. + bool Initialize(gl::GLSurface *, const gl::GLContextAttribs &) override + { + Q_UNREACHABLE(); + return false; + } + bool MakeCurrentImpl(gl::GLSurface *) override + { + Q_UNREACHABLE(); + return false; + } + void ReleaseCurrent(gl::GLSurface *) override + { + Q_UNREACHABLE(); + } + bool IsCurrent(gl::GLSurface *) override + { + Q_UNREACHABLE(); + return false; + } + scoped_refptr CreateGPUTimingClient() override + { + return nullptr; + } + const gfx::ExtensionSet &GetExtensions() override + { + static const gfx::ExtensionSet s_emptySet; + return s_emptySet; + } + void ResetExtensions() override { } + +private: + void *m_handle; +}; -ContentGpuClientQt::~ContentGpuClientQt() +class ShareGroupQtQuick : public gl::GLShareGroup { +public: + gl::GLContext *GetContext() override { return m_shareContextQtQuick.get(); } + void AboutToAddFirstContext() override; + +private: + scoped_refptr m_shareContextQtQuick; +}; + +void ShareGroupQtQuick::AboutToAddFirstContext() +{ +#if QT_CONFIG(opengl) + // This currently has to be setup by ::main in all applications using QQuickWebEngineView + // with de legated rendering. + QOpenGLContext *shareContext = qt_gl_global_share_context(); + if (!shareContext) { + qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure " + "to" + "call QtWebEngine::initialize() in your main() function before QCoreApplication " + "is " + "created."); + } + m_shareContextQtQuick = new QtShareGLContext(shareContext); +#endif } +ContentGpuClientQt::ContentGpuClientQt() { } + +ContentGpuClientQt::~ContentGpuClientQt() { } + gpu::SyncPointManager *ContentGpuClientQt::GetSyncPointManager() { return WebEngineContext::syncPointManager(); } +gl::GLShareGroup *ContentGpuClientQt::GetInProcessGpuShareGroup() +{ + if (!m_shareGroupQtQuick.get()) + m_shareGroupQtQuick = new ShareGroupQtQuick; + return m_shareGroupQtQuick.get(); +} + } // namespace diff --git a/src/core/compositor/content_gpu_client_qt.h b/src/core/compositor/content_gpu_client_qt.h index d7ad43881e6..5288c65bdf1 100644 --- a/src/core/compositor/content_gpu_client_qt.h +++ b/src/core/compositor/content_gpu_client_qt.h @@ -43,6 +43,8 @@ namespace QtWebEngineCore { +class ShareGroupQtQuick; + class ContentGpuClientQt : public content::ContentGpuClient { public: explicit ContentGpuClientQt(); @@ -50,6 +52,10 @@ class ContentGpuClientQt : public content::ContentGpuClient { // content::ContentGpuClient implementation. gpu::SyncPointManager *GetSyncPointManager() override; + gl::GLShareGroup *GetInProcessGpuShareGroup() override; + +private: + scoped_refptr m_shareGroupQtQuick; }; } diff --git a/src/core/config/common.pri b/src/core/config/common.pri index d9d64e76b9e..fc46d55ce8f 100644 --- a/src/core/config/common.pri +++ b/src/core/config/common.pri @@ -46,3 +46,4 @@ qtConfig(webengine-kerberos) { } !qtConfig(webengine-nodejs10): gn_args += use_rollup=false +gn_args += enable_ipc_logging=false diff --git a/src/core/config/linux.pri b/src/core/config/linux.pri index 3e490a0d58e..33dd28b42f5 100644 --- a/src/core/config/linux.pri +++ b/src/core/config/linux.pri @@ -27,6 +27,8 @@ qtConfig(webengine-embedded-build) { gn_args += use_xkbcommon=true packagesExist(xscrnsaver): gn_args += use_xscrnsaver=true qtConfig(webengine-webrtc): gn_args += rtc_use_x11=true + } else { + gn_args += use_xkbcommon=false } qtConfig(webengine-webrtc): qtConfig(webengine-webrtc-pipewire): gn_args += rtc_use_pipewire=true diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp index 24aa19c91dd..e15bd05f39b 100644 --- a/src/core/content_browser_client_qt.cpp +++ b/src/core/content_browser_client_qt.cpp @@ -80,7 +80,6 @@ #include "ui/base/ui_base_switches.h" #include "ui/gl/gl_context.h" #include "ui/gl/gl_implementation.h" -#include "ui/gl/gl_share_group.h" #include "ui/gl/gpu_timing.h" #include "url/url_util_qt.h" @@ -118,11 +117,6 @@ #include "api/qwebenginecookiestore.h" #include "api/qwebenginecookiestore_p.h" -#if QT_CONFIG(opengl) -#include -#include -#endif - #if QT_CONFIG(webengine_geolocation) #include "base/memory/ptr_util.h" #include "location_provider_qt.h" @@ -179,11 +173,6 @@ #include #include -#include - -QT_BEGIN_NAMESPACE -Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); -QT_END_NAMESPACE // Implement IsHandledProtocol as declared in //url/url_util_qt.h. namespace url { @@ -231,93 +220,6 @@ void MaybeAddThrottle( throttles->push_back(std::move(maybe_throttle)); } -class QtShareGLContext : public gl::GLContext { -public: - QtShareGLContext(QOpenGLContext *qtContext) - : gl::GLContext(0) - , m_handle(0) - { - QString platform = qApp->platformName().toLower(); - QPlatformNativeInterface *pni = QGuiApplication::platformNativeInterface(); - if (platform == QLatin1String("xcb") || platform == QLatin1String("offscreen")) { - if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("glxcontext"), qtContext); - } else if (platform == QLatin1String("cocoa")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("cglcontextobj"), qtContext); - else if (platform == QLatin1String("qnx")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("eglfs") || platform == QLatin1String("wayland") - || platform == QLatin1String("wayland-egl")) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglcontext"), qtContext); - else if (platform == QLatin1String("windows")) { - if (gl::GetGLImplementation() == gl::kGLImplementationEGLGLES2) - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("eglContext"), qtContext); - else - m_handle = pni->nativeResourceForContext(QByteArrayLiteral("renderingcontext"), qtContext); - } else { - qFatal("%s platform not yet supported", platform.toLatin1().constData()); - // Add missing platforms once they work. - Q_UNREACHABLE(); - } - } - - void* GetHandle() override { return m_handle; } - unsigned int CheckStickyGraphicsResetStatusImpl() override - { -#if QT_CONFIG(opengl) - if (QOpenGLContext *context = qt_gl_global_share_context()) { - if (context->format().testOption(QSurfaceFormat::ResetNotification)) - return context->extraFunctions()->glGetGraphicsResetStatus(); - } -#endif - return 0 /*GL_NO_ERROR*/; - } - - // We don't care about the rest, this context shouldn't be used except for its handle. - bool Initialize(gl::GLSurface *, const gl::GLContextAttribs &) override { Q_UNREACHABLE(); return false; } - bool MakeCurrentImpl(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - void ReleaseCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); } - bool IsCurrent(gl::GLSurface *) override { Q_UNREACHABLE(); return false; } - scoped_refptr CreateGPUTimingClient() override - { - return nullptr; - } - const gfx::ExtensionSet& GetExtensions() override - { - static const gfx::ExtensionSet s_emptySet; - return s_emptySet; - } - void ResetExtensions() override - { - } - -private: - void *m_handle; -}; - -class ShareGroupQtQuick : public gl::GLShareGroup { -public: - gl::GLContext* GetContext() override { return m_shareContextQtQuick.get(); } - void AboutToAddFirstContext() override; - -private: - scoped_refptr m_shareContextQtQuick; -}; - -void ShareGroupQtQuick::AboutToAddFirstContext() -{ -#if QT_CONFIG(opengl) - // This currently has to be setup by ::main in all applications using QQuickWebEngineView with delegated rendering. - QOpenGLContext *shareContext = qt_gl_global_share_context(); - if (!shareContext) { - qFatal("QWebEngine: OpenGL resource sharing is not set up in QtQuick. Please make sure to call QtWebEngine::initialize() in your main() function before QCoreApplication is created."); - } - m_shareContextQtQuick = new QtShareGLContext(shareContext); -#endif -} - ContentBrowserClientQt::ContentBrowserClientQt() { } @@ -364,13 +266,6 @@ void ContentBrowserClientQt::RenderProcessWillLaunch(content::RenderProcessHost renderer_configuration->SetInitialConfiguration(is_incognito_process); } -gl::GLShareGroup *ContentBrowserClientQt::GetInProcessGpuShareGroup() -{ - if (!m_shareGroupQtQuick.get()) - m_shareGroupQtQuick = new ShareGroupQtQuick; - return m_shareGroupQtQuick.get(); -} - content::MediaObserver *ContentBrowserClientQt::GetMediaObserver() { return MediaCaptureDevicesDispatcher::GetInstance(); @@ -868,6 +763,15 @@ static void LaunchURL(const GURL& url, protocolHandlerRegistry->IsHandledProtocol(url.scheme())) return; +#if BUILDFLAG(ENABLE_EXTENSIONS) + if (guest_view::GuestViewBase::IsGuest(webContents)) { + // Use parent / top level contents delegate for launching URLs from guest views. + webContents = guest_view::GuestViewBase::GetTopLevelWebContents(webContents); + if (!webContents) + return; + } +#endif //BUILDFLAG(ENABLE_EXTENSIONS) + WebContentsDelegateQt *contentsDelegate = static_cast(webContents->GetDelegate()); contentsDelegate->launchExternalURL(toQt(url), page_transition, is_main_frame, has_user_gesture); } @@ -1247,7 +1151,7 @@ void ContentBrowserClientQt::RegisterNonNetworkSubresourceURLLoaderFactories(int install_file_scheme = install_file_scheme || url.SchemeIs(extensions::kExtensionScheme); #endif if (!install_file_scheme && web_contents) { - const auto *settings = static_cast(web_contents->GetDelegate())->webEngineSettings(); + const auto *settings = static_cast(web_contents->GetResponsibleWebContents()->GetDelegate())->webEngineSettings(); if (settings->testAttribute(WebEngineSettings::LocalContentCanAccessFileUrls)) { for (const auto &local_scheme : url::GetLocalSchemes()) { if (url.SchemeIs(local_scheme)) { diff --git a/src/core/content_browser_client_qt.h b/src/core/content_browser_client_qt.h index 7c8aa3ac944..06e2e9a20a5 100644 --- a/src/core/content_browser_client_qt.h +++ b/src/core/content_browser_client_qt.h @@ -60,14 +60,8 @@ struct MainFunctionParams; struct Referrer; } -namespace gl { -class GLShareGroup; -} - namespace QtWebEngineCore { -class ShareGroupQtQuick; - class ContentBrowserClientQt : public content::ContentBrowserClient { public: @@ -75,7 +69,6 @@ class ContentBrowserClientQt : public content::ContentBrowserClient ~ContentBrowserClientQt(); std::unique_ptr CreateBrowserMainParts(const content::MainFunctionParams&) override; void RenderProcessWillLaunch(content::RenderProcessHost *host) override; - gl::GLShareGroup* GetInProcessGpuShareGroup() override; content::MediaObserver* GetMediaObserver() override; scoped_refptr CreateQuotaPermissionContext() override; void OverrideWebkitPrefs(content::RenderViewHost *render_view_host, @@ -266,9 +259,6 @@ class ContentBrowserClientQt : public content::ContentBrowserClient std::string GetUserAgent() override { return getUserAgent(); } std::string GetProduct() override; - -private: - scoped_refptr m_shareGroupQtQuick; }; } // namespace QtWebEngineCore diff --git a/src/core/core.pro b/src/core/core.pro index f2d3fd30722..fa1d7f6a7b4 100644 --- a/src/core/core.pro +++ b/src/core/core.pro @@ -7,9 +7,13 @@ TEMPLATE = subdirs core_headers.file = core_headers.pro core_api.file = api/core_api.pro +core_lipo.file = core_lipo.pro +core_lipo.depends = gn_run + # This will take the compile output of ninja, and link+deploy the final binary. core_module.file = core_module.pro core_module.depends = core_api +isUniversal(): core_module.depends += core_lipo core_generator.file = core_generator.pro core_generator.depends = core_headers @@ -44,5 +48,7 @@ core_project.depends = gn_run core_api \ core_module + isUniversal(): SUBDIRS += core_lipo + false: SUBDIRS += core_project } diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index e978d20a186..a846f2fbc19 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -21,9 +21,13 @@ DEFINES += QT_NO_KEYWORDS \ BUILDING_CHROMIUM # Ensure that response files, generated by qtbase/mkspecs/features/moc.prf, are found by moc. -MOC_DIR = $$OUT_PWD/$$getConfigDir()/.moc -RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc - +isUniversal() { + MOC_DIR = $$OUT_PWD/$$QT_ARCH/$$getConfigDir()/.moc + RCC_DIR = $$OUT_PWD/$$QT_ARCH/$$getConfigDir()/.rcc +} else { + MOC_DIR = $$OUT_PWD/$$getConfigDir()/.moc + RCC_DIR = $$OUT_PWD/$$getConfigDir()/.rcc +} # Assume that we want mobile touch and low-end hardware behaviors # whenever we are cross compiling. qtConfig(webengine-embedded-build): DEFINES += QTWEBENGINE_EMBEDDED_SWITCHES diff --git a/src/core/core_gn_config.pri b/src/core/core_gn_config.pri index 2b8f2e18f93..379bbac9424 100644 --- a/src/core/core_gn_config.pri +++ b/src/core/core_gn_config.pri @@ -1,10 +1,16 @@ CONFIG = gn_generator $$CONFIG GN_SRC_DIR = $$PWD -GN_FILE = $$OUT_PWD/$$getConfigDir()/BUILD.gn +isUniversal() { + for(arch, QT_ARCHS) { + GN_FILES += $$OUT_PWD/$$arch/$$getConfigDir()/BUILD.gn + } +} else { + GN_FILES = $$OUT_PWD/$$getConfigDir()/BUILD.gn +} GN_FIND_MOCABLES_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_find_mocables.py) GN_RUN_BINARY_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_run_binary.py) GN_IMPORTS = $$PWD/qtwebengine.gni -qtConfig (webengine-extensions) { +qtConfig(webengine-extensions) { GN_INCLUDES += $$PWD/qtwebengine_sources.gni $$PWD/qtwebengine_resources.gni $$PWD/common/extensions/api/qtwebengine_extensions_features.gni } else { GN_INCLUDES = $$PWD/qtwebengine_sources.gni $$PWD/qtwebengine_resources.gni diff --git a/src/core/core_lipo.pro b/src/core/core_lipo.pro new file mode 100644 index 00000000000..41846b7f20a --- /dev/null +++ b/src/core/core_lipo.pro @@ -0,0 +1,9 @@ +TEMPLATE = aux + +qtConfig(debug_and_release): CONFIG += debug_and_release +qtConfig(build_all): CONFIG += build_all + +TARGET= QtWebEngineCore +include($${QTWEBENGINE_ROOT}/src/buildtools/config/lipo.pri) + + diff --git a/src/core/core_module.pro b/src/core/core_module.pro index 520b452f774..9e087c81524 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -1,7 +1,11 @@ MODULE = webenginecore include(core_common.pri) -include($${QTWEBENGINE_ROOT}/src/buildtools/config/linking.pri) +isUniversal() { + include($${QTWEBENGINE_ROOT}/src/buildtools/config/lipo_linking.pri) +} else { + include($${QTWEBENGINE_ROOT}/src/buildtools/config/linking.pri) +} api_library_name = qtwebenginecoreapi$$qtPlatformTargetSuffix() api_library_path = $$OUT_PWD/api/$$getConfigDir() @@ -49,7 +53,11 @@ linux { qtConfig(separate_debug_info): QMAKE_POST_LINK="cd $(DESTDIR) && $(STRIP) --strip-unneeded $(TARGET)" } -REPACK_DIR = $$OUT_PWD/$$getConfigDir() +isUniversal() { + REPACK_DIR = $$OUT_PWD/$$QT_ARCH/$$getConfigDir() +} else { + REPACK_DIR = $$OUT_PWD/$$getConfigDir() +} # Duplicated from resources/resources.gyp LOCALE_LIST = am ar bg bn ca cs da de el en-GB en-US es-419 es et fa fi fil fr gu he hi hr hu id it ja kn ko lt lv ml mr ms nb nl pl pt-BR pt-PT ro ru sk sl sr sv sw ta te th tr uk vi zh-CN zh-TW @@ -61,7 +69,7 @@ resources.files = $$REPACK_DIR/qtwebengine_resources.pak \ $$REPACK_DIR/qtwebengine_resources_200p.pak \ $$REPACK_DIR/qtwebengine_devtools_resources.pak -icu.files = $$OUT_PWD/$$getConfigDir()/icudtl.dat +icu.files = $$REPACK_DIR/icudtl.dat !qtConfig(debug_and_release)|!qtConfig(build_all)|CONFIG(release, debug|release) { qtConfig(framework) { diff --git a/src/core/download_manager_delegate_qt.cpp b/src/core/download_manager_delegate_qt.cpp index f1ad1e677d9..b694d175903 100644 --- a/src/core/download_manager_delegate_qt.cpp +++ b/src/core/download_manager_delegate_qt.cpp @@ -295,7 +295,7 @@ void DownloadManagerDelegateQt::ChooseSavePath(content::WebContents *web_content ++m_currentId, toQt(web_contents->GetURL()), download::DownloadItem::IN_PROGRESS, - 0, /* totalBytes */ + -1, /* totalBytes */ 0, /* receivedBytes */ QStringLiteral("application/x-mimearchive"), suggestedFilePath, diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro index 3d6fda80eaa..9f6e64504ef 100644 --- a/src/core/gn_run.pro +++ b/src/core/gn_run.pro @@ -28,36 +28,55 @@ build_pass|!debug_and_release { gn_binary = gn runninja.target = run_ninja + QMAKE_EXTRA_TARGETS += runninja gn_args = $$gnWebEngineArgs() - gn_args += "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\"" !qtConfig(webengine-system-gn) { gn_binary = $$system_quote($$system_path($$gnPath())) } - gn_args = $$system_quote($$gn_args) gn_src_root = $$system_quote($$system_path($$QTWEBENGINE_ROOT/$$getChromiumSrcDir())) - gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$getConfigDir())) gn_python = "--script-executable=$$pythonPathForSystem()" - gn_run = $$gn_binary gen $$gn_build_root $$gn_python --args=$$gn_args --root=$$gn_src_root - - message("Running: $$gn_run ") - !system($$gn_run) { - error("GN run error!") - } ninjaflags = $$(NINJAFLAGS) + enableThreads = $$(GN_MORE_THREADS) + isEmpty(enableThreads):macos { + gn_threads = "--threads=1" + } isEmpty(ninjaflags):!silent: ninjaflags = "-v" - - runninja.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore - QMAKE_EXTRA_TARGETS += runninja - build_pass:build_all: default_target.target = all else: default_target.target = first default_target.depends = runninja QMAKE_EXTRA_TARGETS += default_target + + isUniversal(){ + for(arch, QT_ARCHS) { + gn_target = "qtwebengine_target=\"$$system_path($$OUT_PWD/$$arch/$$getConfigDir()):QtWebEngineCore\"" + gn_args_per_arch = $$system_quote($$gn_args $$gn_target target_cpu=\"$$gnArch($$arch)\") + gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$arch/$$getConfigDir())) + gn_run = $$gn_binary gen $$gn_build_root $$gn_python $$gn_threads --args=$$gn_args_per_arch --root=$$gn_src_root + message("Running for $$arch: $$gn_run") + !system($$gn_run) { + error("GN run error for $$arch!") + } + runninja_$${arch}.target = run_ninja_$${arch} + runninja_$${arch}.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore + QMAKE_EXTRA_TARGETS += runninja_$${arch} + runninja.depends += runninja_$${arch} + } + } else { + gn_args+= "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtWebEngineCore\"" + gn_args = $$system_quote($$gn_args) + gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$getConfigDir())) + gn_run = $$gn_binary gen $$gn_build_root $$gn_python $$gn_threads --args=$$gn_args --root=$$gn_src_root + message("Running: $$gn_run") + !system($$gn_run) { + error("GN run error!") + } + runninja.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore + } } !build_pass:debug_and_release { diff --git a/src/core/media_capture_devices_dispatcher.cpp b/src/core/media_capture_devices_dispatcher.cpp index ef5d657458a..fc436cff2fb 100644 --- a/src/core/media_capture_devices_dispatcher.cpp +++ b/src/core/media_capture_devices_dispatcher.cpp @@ -70,6 +70,7 @@ #endif #include +#include #if defined(WEBRTC_USE_X11) #include @@ -184,7 +185,7 @@ content::DesktopMediaID getDefaultScreenId() GetMonitorsFunc getMonitors = reinterpret_cast(dlsym(RTLD_DEFAULT, "XRRGetMonitors")); typedef void (*FreeMonitorsFunc)(XRRMonitorInfo*); FreeMonitorsFunc freeMonitors = reinterpret_cast(dlsym(RTLD_DEFAULT, "XRRFreeMonitors")); - if (!getMonitors && !freeMonitors) { + if (!getMonitors || !freeMonitors) { qWarning("Unable to link XRandR monitor functions."); return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, 0); } @@ -197,6 +198,7 @@ content::DesktopMediaID getDefaultScreenId() int numMonitors = 0; XRRMonitorInfo *monitors = getMonitors(display, rootWindow, true, &numMonitors); + auto cleanup = qScopeGuard([&] () { freeMonitors(monitors); }); if (numMonitors > 0) return content::DesktopMediaID(content::DesktopMediaID::TYPE_SCREEN, monitors[0].name); #endif // !defined(WEBRTC_USE_X11) diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp index 314e6414518..a96e247b2c5 100644 --- a/src/core/net/client_cert_store_data.cpp +++ b/src/core/net/client_cert_store_data.cpp @@ -104,8 +104,8 @@ class SSLPlatformKeyOverride : public net::ThreadedSSLPrivateKey::Delegate std::vector GetAlgorithmPreferences() override { - return { SSL_SIGN_RSA_PKCS1_SHA1, SSL_SIGN_RSA_PKCS1_SHA512 - , SSL_SIGN_RSA_PKCS1_SHA384, SSL_SIGN_RSA_PKCS1_SHA256 }; + return net::SSLPrivateKey::DefaultAlgorithmPreferences(EVP_PKEY_id(m_key), + /* supports pss */ true); } std::string GetProviderName() override { return "qtwebengine"; diff --git a/src/core/net/custom_url_loader_factory.cpp b/src/core/net/custom_url_loader_factory.cpp index 10b4a9e0f3c..c7426a5b99f 100644 --- a/src/core/net/custom_url_loader_factory.cpp +++ b/src/core/net/custom_url_loader_factory.cpp @@ -310,15 +310,14 @@ class CustomURLLoader : public network::mojom::URLLoader m_client->OnStartLoadingResponseBody(std::move(m_pipe.consumer_handle)); m_head = nullptr; - if (readAvailableData()) // May delete this - return; - m_watcher = std::make_unique( - FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::AUTOMATIC, m_taskRunner); + FROM_HERE, mojo::SimpleWatcher::ArmingPolicy::MANUAL, m_taskRunner); m_watcher->Watch(m_pipe.producer_handle.get(), MOJO_HANDLE_SIGNAL_WRITABLE, MOJO_WATCH_CONDITION_SATISFIED, base::BindRepeating(&CustomURLLoader::notifyReadyWrite, m_weakPtrFactory.GetWeakPtr())); + + readAvailableData(); // May delete this } void notifyCanceled() override { @@ -386,8 +385,10 @@ class CustomURLLoader : public network::mojom::URLLoader uint32_t bufferSize = 0; MojoResult beginResult = m_pipe.producer_handle->BeginWriteData( &buffer, &bufferSize, MOJO_BEGIN_WRITE_DATA_FLAG_NONE); - if (beginResult == MOJO_RESULT_SHOULD_WAIT) + if (beginResult == MOJO_RESULT_SHOULD_WAIT) { + m_watcher->ArmOrNotify(); return false; // Wait for pipe watcher + } if (beginResult != MOJO_RESULT_OK) break; if (m_maxBytesToRead > 0 && m_maxBytesToRead <= int64_t{std::numeric_limits::max()}) diff --git a/src/core/net/proxying_url_loader_factory_qt.cpp b/src/core/net/proxying_url_loader_factory_qt.cpp index fe9176f1fee..a016cbc72e5 100644 --- a/src/core/net/proxying_url_loader_factory_qt.cpp +++ b/src/core/net/proxying_url_loader_factory_qt.cpp @@ -47,8 +47,11 @@ #include "content/public/browser/browser_task_traits.h" #include "content/public/browser/browser_thread.h" #include "content/public/browser/web_contents.h" +#include "content/public/common/content_switches.h" #include "net/http/http_status_code.h" +#include "services/network/public/cpp/cors/cors.h" #include "third_party/blink/public/mojom/loader/resource_load_info.mojom-shared.h" +#include "url/url_util.h" #include "api/qwebengineurlrequestinfo_p.h" #include "type_conversion.h" @@ -63,6 +66,18 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +namespace { + network::mojom::URLResponseHeadPtr createResponse(const network::ResourceRequest &request) { + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + network::mojom::URLResponseHeadPtr response = network::mojom::URLResponseHead::New(); + response->response_type = network::cors::CalculateResponseType( + request.mode, disable_web_security || ( + request.request_initiator && request.request_initiator->IsSameOriginWith(url::Origin::Create(request.url)))); + + return response; + } +} + namespace QtWebEngineCore { ASSERT_ENUMS_MATCH(QWebEngineUrlRequestInfo::ResourceTypeMainFrame, blink::mojom::ResourceType::kMainFrame) @@ -162,6 +177,9 @@ class InterceptedRequest : public network::mojom::URLLoader const uint64_t request_id_; const int32_t routing_id_; const uint32_t options_; + bool allowed_cors_ = true; + + bool loader_error_seen_ = false; // If the |target_loader_| called OnComplete with an error this stores it. // That way the destructor can send it to OnReceivedError if safe browsing @@ -204,12 +222,33 @@ InterceptedRequest::InterceptedRequest(ProfileAdapter *profile_adapter, , target_factory_(std::move(target_factory)) , weak_factory_(this) { - current_response_ = network::mojom::URLResponseHead::New(); + const bool disable_web_security = base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kDisableWebSecurity); + current_response_ = createResponse(request_); // If there is a client error, clean up the request. target_client_.set_disconnect_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, weak_factory_.GetWeakPtr())); + base::BindOnce(&InterceptedRequest::OnURLLoaderClientError, base::Unretained(this))); proxied_loader_receiver_.set_disconnect_with_reason_handler( - base::BindOnce(&InterceptedRequest::OnURLLoaderError, weak_factory_.GetWeakPtr())); + base::BindOnce(&InterceptedRequest::OnURLLoaderError, base::Unretained(this))); + if (!disable_web_security && request_.request_initiator) { + const std::vector &localSchemes = url::GetLocalSchemes(); + std::string fromScheme = request_.request_initiator->GetTupleOrPrecursorTupleIfOpaque().scheme(); + if (base::Contains(localSchemes, fromScheme)) { + content::WebContents *wc = webContents(); + std::string toScheme = request_.url.scheme(); + // local schemes must have universal access, or be accessing something local and have local access. + if (fromScheme != toScheme) { + // note allow_file_access_from_file_urls maps to LocalContentCanAccessFileUrls in our API + // and allow_universal_access_from_file_urls to LocalContentCanAccessRemoteUrls, so we are + // using them as proxies for our API here. + if (toScheme == "file") + allowed_cors_ = wc && wc->GetOrCreateWebPreferences().allow_file_access_from_file_urls; + else if (!base::Contains(localSchemes, toScheme)) + allowed_cors_ = wc && wc->GetOrCreateWebPreferences().allow_universal_access_from_file_urls; + else + allowed_cors_ = true; // We should think about this for future patches + } + } + } } InterceptedRequest::~InterceptedRequest() @@ -246,6 +285,14 @@ void InterceptedRequest::Restart() { DCHECK_CURRENTLY_ON(content::BrowserThread::UI); + // This is a CORS check on the from URL, the normal check on the to URL is applied later + if (!allowed_cors_ && current_response_->response_type == network::mojom::FetchResponseType::kCors) { + target_client_->OnComplete(network::URLLoaderCompletionStatus( + network::CorsErrorStatus(network::mojom::CorsError::kCorsDisabledScheme))); + delete this; + return; + } + // MEMO since all codepatch leading to Restart scheduled and executed as asynchronous tasks in main thread, // interceptors may change in meantime and also during intercept call, so they should be resolved anew. // Set here only profile's interceptor since it runs first without going to user code. @@ -342,9 +389,6 @@ void InterceptedRequest::ContinueAfterIntercept() first_party_url_policy, request_.referrer_policy, request_.referrer.spec(), net::HTTP_TEMPORARY_REDIRECT, toGurl(http://github.com/info.url), base::nullopt, false /*insecure_scheme_was_upgraded*/); - - // FIXME: Should probably create a new header. - current_response_->encoded_data_length = 0; request_.method = redirectInfo.new_method; request_.url = redirectInfo.new_url; request_.site_for_cookies = redirectInfo.new_site_for_cookies; @@ -352,6 +396,11 @@ void InterceptedRequest::ContinueAfterIntercept() request_.referrer_policy = redirectInfo.new_referrer_policy; if (request_.method == net::HttpRequestHeaders::kGetMethod) request_.request_body = nullptr; + // In case of multiple sequential rediredts, current_response_ has previously been moved to target_client_ + // so we create a new one using the redirect url. + if (!current_response_) + current_response_ = createResponse(request_); + current_response_->encoded_data_length = 0; target_client_->OnReceiveRedirect(redirectInfo, std::move(current_response_)); return; } @@ -359,6 +408,7 @@ void InterceptedRequest::ContinueAfterIntercept() } if (!target_loader_ && target_factory_) { + loader_error_seen_ = false; target_factory_->CreateLoaderAndStart(target_loader_.BindNewPipeAndPassReceiver(), routing_id_, request_id_, options_, request_, proxied_client_receiver_.BindNewPipeAndPassRemote(), traffic_annotation_); @@ -464,6 +514,8 @@ void InterceptedRequest::OnURLLoaderError(uint32_t custom_reason, const std::str // If CallOnComplete was already called, then this object is ready to be deleted. if (!target_client_) delete this; + else + loader_error_seen_ = true; } void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus &status, bool wait_for_loader_error) @@ -477,7 +529,7 @@ void InterceptedRequest::CallOnComplete(const network::URLLoaderCompletionStatus if (target_client_) target_client_->OnComplete(status); - if (proxied_loader_receiver_.is_bound() && wait_for_loader_error) { + if (proxied_loader_receiver_.is_bound() && wait_for_loader_error && !loader_error_seen_) { // Since the original client is gone no need to continue loading the // request. proxied_client_receiver_.reset(); diff --git a/src/core/net/qrc_url_scheme_handler.cpp b/src/core/net/qrc_url_scheme_handler.cpp index 73bf24f1d18..0a994343100 100644 --- a/src/core/net/qrc_url_scheme_handler.cpp +++ b/src/core/net/qrc_url_scheme_handler.cpp @@ -67,7 +67,10 @@ void QrcUrlSchemeHandler::requestStarted(QWebEngineUrlRequestJob *job) QFileInfo fileInfo(*file); QMimeDatabase mimeDatabase; QMimeType mimeType = mimeDatabase.mimeTypeForFile(fileInfo); - job->reply(mimeType.name().toUtf8(), file.take()); + if (mimeType.name() == QStringLiteral("application/x-extension-html")) + job->reply("text/html", file.take()); + else + job->reply(mimeType.name().toUtf8(), file.take()); } } // namespace QtWebEngineCore diff --git a/src/core/ozone/gl_context_qt.cpp b/src/core/ozone/gl_context_qt.cpp index 9a24f6bf4a3..0e7213a3a89 100644 --- a/src/core/ozone/gl_context_qt.cpp +++ b/src/core/ozone/gl_context_qt.cpp @@ -51,8 +51,10 @@ #endif QT_BEGIN_NAMESPACE - +#if QT_CONFIG(opengl) Q_GUI_EXPORT QOpenGLContext *qt_gl_global_share_context(); +#endif + GLContextHelper* GLContextHelper::contextHelper = 0; namespace { diff --git a/src/core/ozone/gl_surface_egl_qt.cpp b/src/core/ozone/gl_surface_egl_qt.cpp index 91402abfece..447826baa2d 100644 --- a/src/core/ozone/gl_surface_egl_qt.cpp +++ b/src/core/ozone/gl_surface_egl_qt.cpp @@ -93,7 +93,7 @@ bool GLSurfaceEGLQt::InitializeOneOff() } g_extensions = eglQueryString(g_display, EGL_EXTENSIONS); - g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions, "EGL_KHR_surfaceless_context"); + g_egl_surfaceless_context_supported = ExtensionsContain(g_extensions.c_str(), "EGL_KHR_surfaceless_context"); if (g_egl_surfaceless_context_supported) { scoped_refptr surface = new GLSurfacelessQtEGL(gfx::Size(1, 1)); gl::GLContextAttribs attribs; @@ -202,7 +202,7 @@ void GLSurfaceEGL::ShutdownOneOff() const char* GLSurfaceEGL::GetEGLExtensions() { - return GLSurfaceQt::g_extensions; + return GLSurfaceQt::g_extensions.c_str(); } bool GLSurfaceEGL::HasEGLExtension(const char* name) diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp index 188a9272917..c796444b160 100644 --- a/src/core/ozone/gl_surface_glx_qt.cpp +++ b/src/core/ozone/gl_surface_glx_qt.cpp @@ -62,7 +62,7 @@ void GLSurfaceGLX::ShutdownOneOff() bool GLSurfaceGLX::IsCreateContextSupported() { - return ExtensionsContain(GLSurfaceQt::g_extensions, "GLX_ARB_create_context"); + return HasGLXExtension("GLX_ARB_create_context"); } bool GLSurfaceGLX::IsCreateContextRobustnessSupported() @@ -87,7 +87,7 @@ bool GLSurfaceGLX::IsCreateContextProfileSupported() bool GLSurfaceGLX::IsCreateContextES2ProfileSupported() { - return ExtensionsContain(GLSurfaceQt::g_extensions, "GLX_ARB_create_context_es2_profile"); + return HasGLXExtension("GLX_ARB_create_context_es2_profile"); } bool GLSurfaceGLX::IsOMLSyncControlSupported() @@ -97,12 +97,12 @@ bool GLSurfaceGLX::IsOMLSyncControlSupported() bool GLSurfaceGLX::HasGLXExtension(const char *name) { - return ExtensionsContain(GLSurfaceQt::g_extensions, name); + return ExtensionsContain(GLSurfaceQt::g_extensions.c_str(), name); } bool GLSurfaceGLX::IsTextureFromPixmapSupported() { - return ExtensionsContain(GLSurfaceQt::g_extensions, "GLX_EXT_texture_from_pixmap"); + return HasGLXExtension("GLX_EXT_texture_from_pixmap"); } bool GLSurfaceGLX::IsRobustnessVideoMemoryPurgeSupported() @@ -112,7 +112,7 @@ bool GLSurfaceGLX::IsRobustnessVideoMemoryPurgeSupported() const char* GLSurfaceGLX::GetGLXExtensions() { - return GLSurfaceQt::g_extensions; + return GLSurfaceQt::g_extensions.c_str(); } bool GLSurfaceGLXQt::InitializeOneOff() @@ -158,7 +158,7 @@ bool GLSurfaceGLXQt::InitializeExtensionSettingsOneOff() Display* display = static_cast(g_display); GLSurfaceQt::g_extensions = glXQueryExtensionsString(display, 0); - g_driver_glx.InitializeExtensionBindings(g_extensions); + g_driver_glx.InitializeExtensionBindings(g_extensions.c_str()); return true; } diff --git a/src/core/ozone/gl_surface_qt.cpp b/src/core/ozone/gl_surface_qt.cpp index 2c464c11c36..990a62f8b59 100644 --- a/src/core/ozone/gl_surface_qt.cpp +++ b/src/core/ozone/gl_surface_qt.cpp @@ -78,7 +78,7 @@ bool g_initializedEGL = false; void* GLSurfaceQt::g_display = nullptr; void* GLSurfaceQt::g_config = nullptr; -const char* GLSurfaceQt::g_extensions = nullptr; +std::string GLSurfaceQt::g_extensions; GLSurfaceQt::~GLSurfaceQt() { @@ -99,7 +99,7 @@ GLSurfaceQt::GLSurfaceQt(const gfx::Size& size) bool GLSurfaceQt::HasEGLExtension(const char* name) { - return ExtensionsContain(g_extensions, name); + return ExtensionsContain(g_extensions.c_str(), name); } bool GLSurfaceQt::IsOffscreen() diff --git a/src/core/ozone/gl_surface_qt.h b/src/core/ozone/gl_surface_qt.h index cbdc8876a6a..b3a53d6b395 100644 --- a/src/core/ozone/gl_surface_qt.h +++ b/src/core/ozone/gl_surface_qt.h @@ -37,11 +37,11 @@ ** ****************************************************************************/ - - #ifndef GL_SURFACE_QT_H_ #define GL_SURFACE_QT_H_ +#include + #include "ui/gfx/geometry/size.h" #include "ui/gl/gl_surface.h" @@ -71,7 +71,7 @@ class GLSurfaceQt: public GLSurface { public: static void* g_config; static void* g_display; - static const char* g_extensions; + static std::string g_extensions; private: DISALLOW_COPY_AND_ASSIGN(GLSurfaceQt); diff --git a/src/core/ozone/ozone_platform_qt.cpp b/src/core/ozone/ozone_platform_qt.cpp index c547cf783f1..1d6fa1ed557 100644 --- a/src/core/ozone/ozone_platform_qt.cpp +++ b/src/core/ozone/ozone_platform_qt.cpp @@ -164,7 +164,17 @@ static std::string getCurrentKeyboardLayout() if (XkbGetState(dpy, XkbUseCoreKbd, &state) != 0) return std::string(); - XkbRF_VarDefsRec vdr; + XkbRF_VarDefsRec vdr {}; // zero initialize it + struct Cleanup { + XkbRF_VarDefsRec &vdr; + Cleanup(XkbRF_VarDefsRec &vdr) : vdr(vdr) { } + ~Cleanup() { + free (vdr.model); + free (vdr.layout); + free (vdr.variant); + free (vdr.options); + } + } cleanup(vdr); if (XkbRF_GetNamesProp(dpy, nullptr, &vdr) == 0) return std::string(); diff --git a/src/core/printing/print_view_manager_base_qt.cpp b/src/core/printing/print_view_manager_base_qt.cpp index ad35209f111..fe365df5309 100644 --- a/src/core/printing/print_view_manager_base_qt.cpp +++ b/src/core/printing/print_view_manager_base_qt.cpp @@ -254,6 +254,11 @@ void PrintViewManagerBaseQt::GetDefaultPrintSettings(GetDefaultPrintSettingsCall void PrintViewManagerBaseQt::PrintingFailed(int32_t cookie) { + // Note: Not redundant with cookie checks in the same method in other parts of + // the class hierarchy. + if (!IsValidCookie(cookie)) + return; + PrintManager::PrintingFailed(cookie); ReleasePrinterQuery(); diff --git a/src/core/qtwebengine_sources.gni b/src/core/qtwebengine_sources.gni index 81a48cab494..97d51d68e60 100644 --- a/src/core/qtwebengine_sources.gni +++ b/src/core/qtwebengine_sources.gni @@ -53,6 +53,7 @@ source_set("qtwebengine_sources") { "//components/performance_manager", "//components/plugins/renderer/", "//extensions/buildflags:buildflags", + "//qtwebengine/common:mojo_bindings", "//rlz/buildflags:buildflags", "//third_party/blink/public/mojom:mojom_platform", ] diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index bee3c4ca47b..7acef2b1521 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -1378,12 +1378,6 @@ void RenderWidgetHostViewQt::handleMouseEvent(QMouseEvent* event) if (event->type() == QEvent::MouseButtonRelease) m_mouseButtonPressed--; - // Don't forward mouse events synthesized by the system, which are caused by genuine touch - // events. Chromium would then process for e.g. a mouse click handler twice, once due to the - // system synthesized mouse event, and another time due to a touch-to-gesture-to-mouse - // transformation done by Chromium. - if (event->source() == Qt::MouseEventSynthesizedBySystem) - return; handlePointerEvent(event); } @@ -1662,7 +1656,8 @@ void RenderWidgetHostViewQt::handleGestureEvent(QNativeGestureEvent *ev) { const Qt::NativeGestureType type = ev->gestureType(); // These are the only supported gestures by Chromium so far. - if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture) { + if (type == Qt::ZoomNativeGesture || type == Qt::SmartZoomNativeGesture + || type == Qt::BeginNativeGesture || type == Qt::EndNativeGesture) { if (host()->delegate() && host()->delegate()->GetInputEventRouter()) { auto webEvent = WebEventFactory::toWebGestureEvent(ev); host()->delegate()->GetInputEventRouter()->RouteGestureEvent(this, &webEvent, ui::LatencyInfo()); 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 beae6ecfa07..5dcfaafd6a8 100644 --- a/src/core/renderer/print_web_view_helper_delegate_qt.cpp +++ b/src/core/renderer/print_web_view_helper_delegate_qt.cpp @@ -43,11 +43,17 @@ #include "content/public/renderer/render_frame.h" #include "content/public/renderer/render_view.h" +#include "extensions/buildflags/buildflags.h" #include "extensions/common/constants.h" #include "third_party/blink/public/web/web_document.h" #include "third_party/blink/public/web/web_element.h" #include "third_party/blink/public/web/web_local_frame.h" +#if BUILDFLAG(ENABLE_EXTENSIONS) +#include "chrome/common/webui_url_constants.h" +#include "extensions/common/constants.h" +#endif // BUILDFLAG(ENABLE_EXTENSIONS) + #include "print_web_view_helper_delegate_qt.h" #include "web_engine_library_info.h" @@ -56,14 +62,23 @@ PrintWebViewHelperDelegateQt::~PrintWebViewHelperDelegateQt() {} blink::WebElement PrintWebViewHelperDelegateQt::GetPdfElement(blink::WebLocalFrame *frame) { +#if BUILDFLAG(ENABLE_EXTENSIONS) GURL url = frame->GetDocument().Url(); - if (url.SchemeIs(extensions::kExtensionScheme) && url.host() == extension_misc::kPdfExtensionId) { + bool inside_print_preview = url.GetOrigin() == chrome::kChromeUIPrintURL; + bool inside_pdf_extension = url.SchemeIs(extensions::kExtensionScheme) && + url.host_piece() == extension_misc::kPdfExtensionId; + if (inside_print_preview || inside_pdf_extension) { // with id="plugin" is created in - // chrome/browser/resources/pdf/pdf.js. - auto plugin_element = frame->GetDocument().GetElementById("plugin"); - CHECK(!plugin_element.IsNull()); - return plugin_element; + // 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(); } +#endif // BUILDFLAG(ENABLE_EXTENSIONS) return blink::WebElement(); } diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index 2cd48907b3e..cca31e144cc 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -1332,10 +1332,13 @@ void WebContentsAdapter::printToPDF(const QPageLayout &pageLayout, const QString PrintViewManagerQt::PrintToPDFFileCallback callback = base::Bind(&callbackOnPdfSavingFinished, m_adapterClient, filePath); - PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFFileWithCallback(pageLayout, - true, - filePath, - callback); + content::WebContents *webContents = m_webContents.get(); + if (content::WebContents *guest = guestWebContents()) + webContents = guest; + PrintViewManagerQt::FromWebContents(webContents)->PrintToPDFFileWithCallback(pageLayout, + true, + filePath, + callback); #endif // QT_CONFIG(webengine_printing_and_pdf) } @@ -1348,10 +1351,13 @@ quint64 WebContentsAdapter::printToPDFCallbackResult(const QPageLayout &pageLayo PrintViewManagerQt::PrintToPDFCallback callback = base::Bind(&callbackOnPrintingFinished, m_adapterClient, m_nextRequestId); - PrintViewManagerQt::FromWebContents(m_webContents.get())->PrintToPDFWithCallback(pageLayout, - colorMode, - useCustomMargins, - callback); + content::WebContents *webContents = m_webContents.get(); + if (content::WebContents *guest = guestWebContents()) + webContents = guest; + PrintViewManagerQt::FromWebContents(webContents)->PrintToPDFWithCallback(pageLayout, + colorMode, + useCustomMargins, + callback); return m_nextRequestId++; #else Q_UNUSED(pageLayout); @@ -1444,6 +1450,12 @@ content::WebContents *WebContentsAdapter::webContents() const return m_webContents.get(); } +content::WebContents *WebContentsAdapter::guestWebContents() const +{ + std::vector innerWebContents = m_webContents->GetInnerWebContents(); + return !innerWebContents.empty() ? innerWebContents[0] : nullptr; +} + #if QT_CONFIG(webengine_webchannel) QWebChannel *WebContentsAdapter::webChannel() const { @@ -1484,8 +1496,10 @@ static QMimeData *mimeDataFromDropData(const content::DropData &dropData) mimeData->setText(toQt(*dropData.text)); if (dropData.html.has_value()) mimeData->setHtml(toQt(*dropData.html)); - if (dropData.url.is_valid()) + if (dropData.url.is_valid()) { mimeData->setUrls(QList() << toQt(dropData.url)); + mimeData->setText(toQt(dropData.url_title)); + } if (!dropData.custom_data.empty()) { base::Pickle pickle; ui::WriteCustomDataToPickle(dropData.custom_data, &pickle); @@ -1551,9 +1565,8 @@ void WebContentsAdapter::startDragging(QObject *dragSource, const content::DropD // dropping data into them. We don't even try to support dropping into PDF input fields, // since it's not working in Chrome right now. content::WebContents *targetWebContents = m_webContents.get(); - std::vector innerWebContents = m_webContents->GetInnerWebContents(); - if (!innerWebContents.empty()) - targetWebContents = innerWebContents[0]; + if (content::WebContents *guest = guestWebContents()) + targetWebContents = guest; content::RenderViewHost *rvh = targetWebContents->GetRenderViewHost(); if (rvh) { @@ -1610,6 +1623,11 @@ static void fillDropDataFromMimeData(content::DropData *dropData, const QMimeDat } if (!dropData->filenames.empty()) return; + if (mimeData->hasUrls()) { + dropData->url = toGurl(http://github.com/urls.first()); + if (mimeData->hasText()) + dropData->url_title = toString16(mimeData->text()); + } if (mimeData->hasHtml()) dropData->html = toOptionalString16(mimeData->html()); if (mimeData->hasText()) diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index 78dda6060ee..ba02a0418c9 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -242,6 +242,7 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT WebContentsAdapter : public QEnableSharedFr // meant to be used within WebEngineCore only void initialize(content::SiteInstance *site); content::WebContents *webContents() const; + content::WebContents *guestWebContents() const; void updateRecommendedState(); void setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor); QWebEngineUrlRequestInterceptor* requestInterceptor() const; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index afc43806a68..8203ce65096 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -459,6 +459,7 @@ class Q_WEBENGINECORE_PRIVATE_EXPORT WebContentsAdapterClient { virtual void loadProgressChanged(int progress) = 0; virtual void didUpdateTargetURL(const QUrl&) = 0; virtual void selectionChanged() = 0; + virtual void zoomUpdateIsNeeded() = 0; virtual void recentlyAudibleChanged(bool recentlyAudible) = 0; virtual void renderProcessPidChanged(qint64 pid) = 0; virtual QRectF viewportRect() const = 0; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index d52b07df360..d211bdbfc9c 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -318,8 +318,10 @@ void WebContentsDelegateQt::RenderFrameHostChanged(content::RenderFrameHost *old if (new_host->GetFrameOwnerElementType() == blink::mojom::FrameOwnerElementType::kNone) { content::RenderProcessHost *renderProcessHost = new_host->GetProcess(); const base::Process &process = renderProcessHost->GetProcess(); - if (process.IsValid()) + if (process.IsValid()) { m_viewClient->renderProcessPidChanged(process.Pid()); + m_viewClient->zoomUpdateIsNeeded(); + } } } } @@ -329,6 +331,7 @@ void WebContentsDelegateQt::RenderViewHostChanged(content::RenderViewHost *, con if (newHost && newHost->GetWidget() && newHost->GetWidget()->GetView()) { auto rwhv = static_cast(newHost->GetWidget()->GetView()); m_viewClient->widgetChanged(rwhv->delegate()); + m_viewClient->zoomUpdateIsNeeded(); } } @@ -354,7 +357,7 @@ void WebContentsDelegateQt::DidStartNavigation(content::NavigationHandle *naviga if (!webEngineSettings()->testAttribute(WebEngineSettings::ErrorPageEnabled)) navigation_handle->SetSilentlyIgnoreErrors(); - if (!navigation_handle->IsInMainFrame() || !web_contents()->IsLoadingToDifferentDocument()) + if (!navigation_handle->IsInMainFrame() || navigation_handle->IsSameDocument()) return; m_faviconManager->resetCandidates(); diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index f342e788db7..184f78c3bed 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -315,7 +315,7 @@ static QStringList parseEnvCommandLine(const QString &cmdLine) scoped_refptr WebEngineContext::m_handle; bool WebEngineContext::m_destroyed = false; - +bool WebEngineContext::m_closingDown = false; void WebEngineContext::destroyProfileAdapter() { if (content::RenderProcessHost::run_renderer_in_process()) { @@ -484,6 +484,7 @@ void WebEngineContext::destroyContextPostRoutine() // Destroy WebEngineContext before its static pointer is zeroed and destructor called. // Before destroying MessageLoop via destroying BrowserMainRunner destructor // WebEngineContext's pointer is used. + m_closingDown = true; m_handle->destroy(); #if !defined(NDEBUG) if (!m_handle->HasOneRef()) @@ -636,6 +637,7 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kEnableThreadedCompositing); +#if QT_CONFIG(opengl) #if defined(Q_OS_WIN) // This switch is used in Chromium's gl_context_wgl.cc file to determine whether to create // an OpenGL Core Profile context. If the switch is not set, it would always try to create a @@ -658,7 +660,8 @@ WebEngineContext::WebEngineContext() if (isDesktopGLOrSoftware || isGLES2Context) parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); -#endif +#endif // defined(Q_OS_WIN) +#endif // QT_CONFIG(opengl) // Do not advertise a feature we have removed at compile time parsedCommandLine->AppendSwitch(switches::kDisableSpeechAPI); @@ -671,6 +674,7 @@ WebEngineContext::WebEngineContext() // upstream Chromium commit ba52f56207a4b9d70b34880fbff2352e71a06422. enableFeatures.push_back(features::kAllowContentInitiatedDataUrlNavigations.name); + enableFeatures.push_back(features::kNetworkServiceInProcess.name); enableFeatures.push_back(features::kTracingServiceInProcess.name); // The video-capture service is not functioning at this moment (since 69) @@ -794,6 +798,7 @@ WebEngineContext::WebEngineContext() registerMainThreadFactories(); content::ContentMainParams contentMainParams(m_mainDelegate.get()); + contentMainParams.setup_signal_handlers = false; #if defined(OS_WIN) contentMainParams.sandbox_info = staticSandboxInterfaceInfo(); sandbox::SandboxInterfaceInfo sandbox_info = {0}; @@ -931,4 +936,9 @@ base::CommandLine* WebEngineContext::commandLine() { } } +bool WebEngineContext::closingDown() +{ + return m_closingDown; +} + } // namespace diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h index f60082059ab..2e74a766c5f 100644 --- a/src/core/web_engine_context.h +++ b/src/core/web_engine_context.h @@ -109,7 +109,7 @@ class WebEngineContext : public base::RefCounted { static void destroyContextPostRoutine(); static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port); static void flushMessages(); - + static bool closingDown(); ProfileAdapter *createDefaultProfileAdapter(); ProfileAdapter *defaultProfileAdapter(); @@ -162,6 +162,7 @@ class WebEngineContext : public base::RefCounted { #endif static scoped_refptr m_handle; static bool m_destroyed; + static bool m_closingDown; static QAtomicPointer s_syncPointManager; }; diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 3beb913a749..b6ca7029468 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -1540,7 +1540,13 @@ WebGestureEvent WebEventFactory::toWebGestureEvent(QNativeGestureEvent *ev) webKitEvent.data.tap.tap_count = 1; break; case Qt::BeginNativeGesture: + webKitEvent.SetType(WebInputEvent::Type::kGesturePinchBegin); + webKitEvent.SetNeedsWheelEvent(true); + break; case Qt::EndNativeGesture: + webKitEvent.SetType(WebInputEvent::Type::kGesturePinchEnd); + webKitEvent.SetNeedsWheelEvent(true); + break; case Qt::RotateNativeGesture: case Qt::PanNativeGesture: case Qt::SwipeNativeGesture: @@ -1581,7 +1587,7 @@ blink::WebMouseWheelEvent::Phase toBlinkPhase(QWheelEvent *ev) #endif return blink::WebMouseWheelEvent::kPhaseNone; case Qt::ScrollBegin: - return ev->angleDelta().isNull() ? blink::WebMouseWheelEvent::kPhaseMayBegin : blink::WebMouseWheelEvent::kPhaseBegan; + return blink::WebMouseWheelEvent::kPhaseBegan; case Qt::ScrollUpdate: return blink::WebMouseWheelEvent::kPhaseChanged; case Qt::ScrollEnd: diff --git a/src/pdf/config/common.pri b/src/pdf/config/common.pri index f688caded12..ec65b7bff15 100644 --- a/src/pdf/config/common.pri +++ b/src/pdf/config/common.pri @@ -41,6 +41,10 @@ qtConfig(webengine-qt-zlib) { gn_args += "qt_zlib=\"$$system_path($$[QT_INSTALL_LIBS]/$$qtzlib)\"" } +linux:!qtConfig(webengine-ozone-x11) { + gn_args += use_xkbcommon=false +} + qtConfig(pdf-v8) { gn_args += pdf_enable_v8=true } else { @@ -76,3 +80,9 @@ qtConfig(pdf-xfa-tiff) { } else { gn_args += pdf_enable_xfa_tiff=false } +qtConfig(pdf-bitcode) { + gn_args += enable_ios_bitcode=true +} +qtConfig(pdf-static-runtime) { + gn_args += qt_uses_static_runtime=true +} diff --git a/src/pdf/configure.json b/src/pdf/configure.json index 069893660de..b1f872982f6 100644 --- a/src/pdf/configure.json +++ b/src/pdf/configure.json @@ -44,7 +44,19 @@ "purpose": "Enables XFA-TIFF support.", "condition": "features.pdf-xfa", "output": ["privateFeature" ] - } + }, + "pdf-bitcode": { + "label": "Bitcode support", + "purpose": "Enables bitcode", + "condition": "config.ios", + "output": ["privateFeature"] + }, + "pdf-static-runtime": { + "label": "Use static runtime", + "purpose": "Enables static runtime", + "condition": "config.static && config.static_runtime", + "output": ["privateFeature"] + } }, "report": [ ], @@ -57,7 +69,9 @@ "pdf-xfa-bmp", "pdf-xfa-gif", "pdf-xfa-png", - "pdf-xfa-tiff" + "pdf-xfa-tiff", + "pdf-bitcode", + "pdf-static-runtime" ] } ] diff --git a/src/pdf/gn_run.pro b/src/pdf/gn_run.pro index 70ee582a9a8..0e559472a95 100644 --- a/src/pdf/gn_run.pro +++ b/src/pdf/gn_run.pro @@ -27,39 +27,60 @@ build_pass|!debug_and_release { gn_binary = gn runninja.target = run_ninja + QMAKE_EXTRA_TARGETS += runninja # fixme: refine args gn_args = $$gnPdfArgs() - # fixme: qtwebengine_target - gn_args += "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtPdf\"" - # fixme: !qtConfig(webengine-system-gn) { gn_binary = $$system_quote($$system_path($$gnPath())) } - gn_args = $$system_quote($$gn_args) gn_src_root = $$system_quote($$system_path($$QTWEBENGINE_ROOT/$$getChromiumSrcDir())) - gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$getConfigDir())) gn_python = "--script-executable=$$pythonPathForSystem()" - gn_run = $$gn_binary gen $$gn_build_root $$gn_python --args=$$gn_args --root=$$gn_src_root - - message("Running: $$gn_run ") - !system($$gn_run) { - error("GN run error!") - } ninjaflags = $$(NINJAFLAGS) isEmpty(ninjaflags):!silent: ninjaflags = "-v" - runninja.commands = $$NINJA $$ninjaflags -C $$gn_build_root QtPdf - QMAKE_EXTRA_TARGETS += runninja + enableThreads = $$(GN_MORE_THREADS) + isEmpty(enableThreads):macos { + gn_threads = "--threads=1" + } build_pass:build_all: default_target.target = all else: default_target.target = first default_target.depends = runninja QMAKE_EXTRA_TARGETS += default_target + + isUniversal(){ + for(arch, QT_ARCHS) { + # fixme: qtwebengine_target + gn_target = "qtwebengine_target=\"$$system_path($$OUT_PWD/$$arch/$$getConfigDir()):QtPdf\"" + gn_args_per_arch = $$system_quote($$gn_args $$gn_target target_cpu=\"$$gnArch($$arch)\") + gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$arch/$$getConfigDir())) + gn_run = $$gn_binary gen $$gn_build_root $$gn_python $$gn_threads --args=$$gn_args_per_arch --root=$$gn_src_root + message("Running for $$arch: $$gn_run") + !system($$gn_run) { + error("GN run error for $$arch!") + } + runninja_$${arch}.target = run_ninja_$${arch} + runninja_$${arch}.commands = $$NINJA $$ninjaflags -C $$gn_build_root QtPdf + QMAKE_EXTRA_TARGETS += runninja_$${arch} + runninja.depends += runninja_$${arch} + } + } else { + gn_args+= "qtwebengine_target=\"$$system_path($$OUT_PWD/$$getConfigDir()):QtPdf\"" + gn_args = $$system_quote($$gn_args) + gn_build_root = $$system_quote($$system_path($$OUT_PWD/$$getConfigDir())) + gn_run = $$gn_binary gen $$gn_build_root $$gn_python $$gn_threads --args=$$gn_args --root=$$gn_src_root + message("Running: $$gn_run") + !system($$gn_run) { + error("GN run error!") + } + runninja.commands = $$NINJA $$ninjaflags -C $$gn_build_root QtPdf + } + } !build_pass:debug_and_release { diff --git a/src/pdf/pdf.pro b/src/pdf/pdf.pro index 9f98c32b041..6f95a55fd85 100644 --- a/src/pdf/pdf.pro +++ b/src/pdf/pdf.pro @@ -3,14 +3,23 @@ QT_FOR_CONFIG += buildtools-private TEMPLATE = subdirs pdfcore.file = pdfcore.pro pdfcore_generator.file = pdfcore_generator.pro + +pdfcore_lipo.file = pdfcore_lipo.pro +pdfcore_lipo.depends = gn_run + gn_run.file = gn_run.pro pdfcore_prl_generator.file = pdfcore_prl_generator.pro gn_run.depends = pdfcore_generator pdfcore_prl_generator.depends = gn_run -pdfcore.depends = pdfcore_prl_generator quick.depends = pdfcore -!qtConfig(webengine-qtpdf-support):qtConfig(build-qtpdf)::!build_pass { +isUniversal() { + pdfcore.depends += pdfcore_lipo +} else { + pdfcore.depends += pdfcore_prl_generator +} + +!qtConfig(webengine-qtpdf-support):qtConfig(build-qtpdf):!build_pass { !qtwebengine_makeCheckPdfError() { errorbuild.commands = @echo $$shell_quote("QtPdf will not be built. $${skipBuildReason}") } else { @@ -24,8 +33,13 @@ quick.depends = pdfcore SUBDIRS += \ pdfcore_generator \ gn_run \ - pdfcore_prl_generator \ pdfcore \ quick + + isUniversal() { + SUBDIRS += pdfcore_lipo + } else { + SUBDIRS += pdfcore_prl_generator + } } diff --git a/src/pdf/pdfcore.pro b/src/pdf/pdfcore.pro index 23e0cec79f1..c2626a48a6b 100644 --- a/src/pdf/pdfcore.pro +++ b/src/pdf/pdfcore.pro @@ -27,11 +27,15 @@ msvc { QMAKE_CXXFLAGS_WARN_ON += -wd"4100" } -include($${QTWEBENGINE_ROOT}/src/buildtools/config/linking.pri) +isUniversal() { + include($${QTWEBENGINE_ROOT}/src/buildtools/config/lipo_linking.pri) +} else { + include($${QTWEBENGINE_ROOT}/src/buildtools/config/linking.pri) +} # install static dependencies and handle prl files for static builds -static:!isEmpty(NINJA_ARCHIVES) { +static:!isEmpty(NINJA_ARCHIVES):!isUniversal() { static_dep_pri = $$OUT_PWD/$$getConfigDir()/$${TARGET}_static_dep.pri !include($${static_dep_pri}) { error("Could not find the prl information.") diff --git a/src/pdf/pdfcore_generator.pro b/src/pdf/pdfcore_generator.pro index e5c7258b7a3..0930256ca03 100644 --- a/src/pdf/pdfcore_generator.pro +++ b/src/pdf/pdfcore_generator.pro @@ -5,7 +5,13 @@ TEMPLATE = lib CONFIG = gn_generator $$CONFIG CONFIG -=static # note we still do static when linking GN_SRC_DIR = $$PWD -GN_FILE = $$OUT_PWD/$$getConfigDir()/BUILD.gn +isUniversal() { + for(arch, QT_ARCHS) { + GN_FILES += $$OUT_PWD/$$arch/$$getConfigDir()/BUILD.gn + } +} else { + GN_FILES = $$OUT_PWD/$$getConfigDir()/BUILD.gn +} GN_FIND_MOCABLES_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_find_mocables.py) GN_RUN_BINARY_SCRIPT = $$shell_path($$QTWEBENGINE_ROOT/tools/scripts/gn_run_binary.py) GN_IMPORTS = $$PWD/qtpdf.gni diff --git a/src/pdf/pdfcore_lipo.pro b/src/pdf/pdfcore_lipo.pro new file mode 100644 index 00000000000..6caf2ac75e7 --- /dev/null +++ b/src/pdf/pdfcore_lipo.pro @@ -0,0 +1,5 @@ +TEMPLATE = aux + +TARGET= QtPdf +include($${QTWEBENGINE_ROOT}/src/buildtools/config/lipo.pri) + diff --git a/src/pdf/qpdfdocument.cpp b/src/pdf/qpdfdocument.cpp index e4ec363ce50..c07ec90c4d8 100644 --- a/src/pdf/qpdfdocument.cpp +++ b/src/pdf/qpdfdocument.cpp @@ -424,6 +424,8 @@ QRectF QPdfDocumentPrivate::getCharBox(FPDF_TEXTPAGE textPage, double pageHeight QPdfDocumentPrivate::TextPosition QPdfDocumentPrivate::hitTest(int page, QPointF position) { const QPdfMutexLocker lock; + + TextPosition result; FPDF_PAGE pdfPage = FPDF_LoadPage(doc, page); double pageHeight = FPDF_GetPageHeight(pdfPage); FPDF_TEXTPAGE textPage = FPDFText_LoadPage(pdfPage); @@ -440,10 +442,14 @@ QPdfDocumentPrivate::TextPosition QPdfDocumentPrivate::hitTest(int page, QPointF ++hitIndex; } qCDebug(qLcDoc) << "on page" << page << "@" << position << "got char position" << charPos << "index" << hitIndex; - return { charPos, charBox.height(), hitIndex }; + result = { charPos, charBox.height(), hitIndex }; } } - return {}; + + FPDFText_ClosePage(textPage); + FPDF_ClosePage(pdfPage); + + return result; } /*! @@ -789,6 +795,9 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end) CharacterHitTolerance, CharacterHitTolerance); int endIndex = FPDFText_GetCharIndexAtPos(textPage, end.x(), pageHeight - end.y(), CharacterHitTolerance, CharacterHitTolerance); + + QPdfSelection result; + if (startIndex >= 0 && endIndex != startIndex) { if (startIndex > endIndex) qSwap(startIndex, endIndex); @@ -815,11 +824,15 @@ QPdfSelection QPdfDocument::getSelection(int page, QPointF start, QPointF end) bounds << QPolygonF(rect); } qCDebug(qLcDoc) << page << start << "->" << end << "found" << startIndex << "->" << endIndex << text; - return QPdfSelection(text, bounds, hull, startIndex, endIndex); + result = QPdfSelection(text, bounds, hull, startIndex, endIndex); + } else { + qCDebug(qLcDoc) << page << start << "->" << end << "nothing found"; } - qCDebug(qLcDoc) << page << start << "->" << end << "nothing found"; - return QPdfSelection(); + FPDFText_ClosePage(textPage); + FPDF_ClosePage(pdfPage); + + return result; } /*! @@ -860,6 +873,10 @@ QPdfSelection QPdfDocument::getSelectionAtIndex(int page, int startIndex, int ma hull = QRectF(d->getCharPosition(textPage, pageHeight, startIndex), QSizeF()); qCDebug(qLcDoc) << "on page" << page << "at index" << startIndex << "maxLength" << maxLength << "got" << text.length() << "chars," << rectCount << "rects within" << hull; + + FPDFText_ClosePage(textPage); + FPDF_ClosePage(pdfPage); + return QPdfSelection(text, bounds, hull, startIndex, startIndex + text.length()); } @@ -890,6 +907,10 @@ QPdfSelection QPdfDocument::getAllText(int page) bounds << QPolygonF(rect); } qCDebug(qLcDoc) << "on page" << page << "got" << count << "chars," << rectCount << "rects within" << hull; + + FPDFText_ClosePage(textPage); + FPDF_ClosePage(pdfPage); + return QPdfSelection(text, bounds, hull, 0, count); } diff --git a/src/pdfwidgets/configure.json b/src/pdfwidgets/configure.json index b33f0855514..bef08ef721c 100644 --- a/src/pdfwidgets/configure.json +++ b/src/pdfwidgets/configure.json @@ -13,7 +13,7 @@ "pdf-widgets": { "label": "Support Qt PDF Widgets", "purpose": "Provides Qt PDF Widgets support.", - "condition": "module.widgets", + "condition": "features.widgets", "output": [ "privateFeature" ] } }, diff --git a/src/pdfwidgets/qpdfview.cpp b/src/pdfwidgets/qpdfview.cpp index 35e3686337f..32d0826af27 100644 --- a/src/pdfwidgets/qpdfview.cpp +++ b/src/pdfwidgets/qpdfview.cpp @@ -461,9 +461,9 @@ void QPdfView::paintEvent(QPaintEvent *event) const auto pageIt = d->m_pageCache.constFind(page); if (pageIt != d->m_pageCache.cend()) { const QImage &img = pageIt.value(); - painter.drawImage(pageGeometry.topLeft(), img); + painter.drawImage(pageGeometry, img); } else { - d->m_pageRenderer->requestPage(page, pageGeometry.size()); + d->m_pageRenderer->requestPage(page, pageGeometry.size() * devicePixelRatioF()); } } } diff --git a/src/plugins/qwebengineview/qwebengineview.pro b/src/plugins/qwebengineview/qwebengineview.pro index c18b6fe94db..6c82cdb4cf4 100644 --- a/src/plugins/qwebengineview/qwebengineview.pro +++ b/src/plugins/qwebengineview/qwebengineview.pro @@ -3,7 +3,6 @@ QT += designer webenginewidgets PLUGIN_CLASS_NAME = QWebEngineViewPlugin PLUGIN_TYPE = designer -CONFIG += tool_plugin load(qt_plugin) SOURCES += qwebengineview_plugin.cpp diff --git a/src/src.pro b/src/src.pro index 6f8bc2fe4ba..c9990430952 100644 --- a/src/src.pro +++ b/src/src.pro @@ -29,7 +29,7 @@ qtConfig(build-qtwebengine-core):qtConfig(webengine-core-support) { SUBDIRS += buildtools core process - qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile { + qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile:!isUniversal() { SUBDIRS += qwebengine_convert_dict qwebengine_convert_dict.subdir = tools/qwebengine_convert_dict qwebengine_convert_dict.depends = core diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 1de7f1c7fe4..50e0711af99 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -434,6 +434,12 @@ void QQuickWebEngineViewPrivate::selectionChanged() updateEditActions(); } +void QQuickWebEngineViewPrivate::zoomUpdateIsNeeded() +{ + Q_Q(QQuickWebEngineView); + q->setZoomFactor(m_zoomFactor); +} + void QQuickWebEngineViewPrivate::recentlyAudibleChanged(bool recentlyAudible) { Q_Q(QQuickWebEngineView); @@ -908,10 +914,8 @@ void QQuickWebEngineViewPrivate::initializationFinished() emit q->backgroundColorChanged(); } - if (!qFuzzyCompare(adapter->currentZoomFactor(), m_zoomFactor)) { - adapter->setZoomFactor(m_zoomFactor); - emit q->zoomFactorChanged(m_zoomFactor); - } + // apply if it was set before first ever navigation already + q->setZoomFactor(m_zoomFactor); #if QT_CONFIG(webengine_webchannel) if (m_webChannel) @@ -991,11 +995,14 @@ void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegateQui if (oldWidget) { oldWidget->setParentItem(nullptr); #if QT_CONFIG(accessibility) - QAccessible::deleteAccessibleInterface(QAccessible::uniqueId(QAccessible::queryAccessibleInterface(oldWidget))); + if (!QtWebEngineCore::closingDown()) + QAccessible::deleteAccessibleInterface( + QAccessible::uniqueId(QAccessible::queryAccessibleInterface(oldWidget))); #endif } if (newWidget) { + Q_ASSERT(!QtWebEngineCore::closingDown()); #if QT_CONFIG(accessibility) QAccessible::registerAccessibleInterface(new QtWebEngineCore::RenderWidgetHostViewQtDelegateQuickAccessible(newWidget, q)); #endif @@ -1146,9 +1153,11 @@ void QQuickWebEngineView::stop() void QQuickWebEngineView::setZoomFactor(qreal arg) { Q_D(QQuickWebEngineView); - if (d->adapter->isInitialized() && !qFuzzyCompare(d->m_zoomFactor, d->adapter->currentZoomFactor())) { + if (d->adapter->isInitialized() && !qFuzzyCompare(arg, zoomFactor())) { d->adapter->setZoomFactor(arg); - emit zoomFactorChanged(arg); + // MEMO: should reset if factor was not applied due to being invalid + d->m_zoomFactor = zoomFactor(); + emit zoomFactorChanged(d->m_zoomFactor); } else { d->m_zoomFactor = arg; } diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index ec535298b8c..a03f009f9bd 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -109,6 +109,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineViewPrivate : public QtWebEngine void loadProgressChanged(int progress) override; void didUpdateTargetURL(const QUrl&) override; void selectionChanged() override; + void zoomUpdateIsNeeded() override; void recentlyAudibleChanged(bool recentlyAudible) override; void renderProcessPidChanged(qint64 pid) override; QRectF viewportRect() const override; diff --git a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc index e32424eea4b..9f75beb8500 100644 --- a/src/webengine/doc/src/qtwebengine-platform-notes.qdoc +++ b/src/webengine/doc/src/qtwebengine-platform-notes.qdoc @@ -126,6 +126,10 @@ \note \QWE cannot be built for the 32-bit mode of \macos (using the \c macx-clang-32 \c mkspec). + \note Universal debug or debug-and-release builds of \QWE on \macos are not supported in Qt 5 + due to memory constraints of the build toolchain. Use the configure options \c -force-debug-info + and \c -separate-debug-info for a build that can be used with a debugger. + \section1 Using Earlier Qt Versions to Build \QWE Building \QWE with earlier Qt versions (down to the last LTS @@ -221,13 +225,11 @@ or VoiceOver on \macos. \endlist - Due to some limitations, the Linux QPA plugin almost always reports that accessibility should - be activated. On big HTML pages, this can cause a significant slowdown in rendering speed. + On some old Linux configurations, accessibility can cause a significant slowdown + on large HTML pages. - Because of that, from Qt 5.9 onwards, \QWE accessibility support is disabled by default - on Linux. - It can be re-enabled by setting the \c QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment - variable to a non-empty value. + Because of that, \QWE accessibility support can be disabled on Linux, by setting the + \c QTWEBENGINE_ENABLE_LINUX_ACCESSIBILITY environment variable to 0. \section1 Popups in Fullscreen Applications on Windows Because of a limitation in the Windows compositor, applications that show a fullscreen web diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc index 0cd8441cffe..0a78d65d519 100644 --- a/src/webengine/doc/src/webengineview_lgpl.qdoc +++ b/src/webengine/doc/src/webengineview_lgpl.qdoc @@ -1156,8 +1156,6 @@ Also if the audio is paused, this signal is emitted with an approximate \b{two-second delay}, from the moment the audio is paused. - This signal is also emitted for Flash plugin audio. - If a web page contains two videos that are started in sequence, this signal gets emitted only once, for the first video to generate sound. After both videos are stopped, the signal is emitted upon the last sound generated. @@ -1233,8 +1231,6 @@ \a wasRecentlyAudible, is changed, due to audio being played or stopped. \note The signal is also emitted when calling the setAudioMuted method. - Also if the audio is paused, this signal is emitted with an approximate \b{2 second - delay}, from the moment the audio is paused. */ /*! diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index 7366dbf596f..d44b9e4e99b 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -465,7 +465,7 @@ QWebEngineDownloadItem::DownloadState QWebEngineDownloadItem::state() const } /*! - Returns the the total amount of data to download in bytes. + Returns the total amount of data to download in bytes. \c -1 means the size is unknown. */ diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index b32c150397b..3c16ede5627 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -247,6 +247,12 @@ void QWebEnginePagePrivate::selectionChanged() }); } +void QWebEnginePagePrivate::zoomUpdateIsNeeded() +{ + Q_Q(QWebEnginePage); + q->setZoomFactor(defaultZoomFactor); +} + void QWebEnginePagePrivate::recentlyAudibleChanged(bool recentlyAudible) { Q_Q(QWebEnginePage); @@ -473,6 +479,10 @@ void QWebEnginePagePrivate::showColorDialog(QSharedPointersetOption(QColorDialog::DontUseNativeDialog); +#endif + dialog->open(); #else Q_UNUSED(controller); @@ -907,8 +917,6 @@ QWebEnginePage::QWebEnginePage(QObject* parent) the audio is played or stopped. \note The signal is also emitted when calling the setAudioMuted() method. - Also, if the audio is paused, this signal is emitted with an approximate \b{two-second - delay}, from the moment the audio is paused. */ /*! @@ -2144,8 +2152,12 @@ void QWebEnginePage::setZoomFactor(qreal factor) { Q_D(QWebEnginePage); d->defaultZoomFactor = factor; - if (d->adapter->isInitialized()) + + if (d->adapter->isInitialized()) { d->adapter->setZoomFactor(factor); + // MEMO: should reset if factor was not applied due to being invalid + d->defaultZoomFactor = zoomFactor(); + } } void QWebEnginePage::runJavaScript(const QString &scriptSource) diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index ae3ab5d25d5..65252f8d842 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -100,6 +100,7 @@ class QWebEnginePagePrivate : public QtWebEngineCore::WebContentsAdapterClient void loadProgressChanged(int progress) override; void didUpdateTargetURL(const QUrl&) override; void selectionChanged() override; + void zoomUpdateIsNeeded() override; void recentlyAudibleChanged(bool recentlyAudible) override; void renderProcessPidChanged(qint64 pid) override; QRectF viewportRect() const override; diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 223d3b114f9..b25055d79e7 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -228,6 +228,7 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info) itemPrivate->downloadState = info.accepted ? QWebEngineDownloadItem::DownloadInProgress : QWebEngineDownloadItem::DownloadRequested; itemPrivate->startTime = info.startTime; + itemPrivate->totalBytes = info.totalBytes; itemPrivate->downloadDirectory = QFileInfo(info.path).path(); itemPrivate->downloadFileName = QFileInfo(info.path).fileName(); itemPrivate->suggestedFileName = info.suggestedFileName; diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp index b1346f65e36..46a4887f25a 100644 --- a/src/webenginewidgets/api/qwebengineview.cpp +++ b/src/webenginewidgets/api/qwebengineview.cpp @@ -116,11 +116,14 @@ void QWebEngineViewPrivate::widgetChanged(QtWebEngineCore::RenderWidgetHostViewQ q->layout()->removeWidget(oldWidget); oldWidget->hide(); #if QT_CONFIG(accessibility) - QAccessible::deleteAccessibleInterface(QAccessible::uniqueId(QAccessible::queryAccessibleInterface(oldWidget))); + if (!QtWebEngineCore::closingDown()) + QAccessible::deleteAccessibleInterface( + QAccessible::uniqueId(QAccessible::queryAccessibleInterface(oldWidget))); #endif } if (newWidget) { + Q_ASSERT(!QtWebEngineCore::closingDown()); #if QT_CONFIG(accessibility) // An earlier QAccessible::queryAccessibleInterface() call may have already registered a default // QAccessibleInterface for newWidget: remove it first to avoid assert in QAccessibleCache::insert(). diff --git a/src/webenginewidgets/configure.json b/src/webenginewidgets/configure.json index a27faf78d5e..8aa41abcee6 100644 --- a/src/webenginewidgets/configure.json +++ b/src/webenginewidgets/configure.json @@ -13,7 +13,7 @@ "webengine-widgets": { "label": "Support Qt WebEngine Widgets", "purpose": "Provides WebEngine Widgets support.", - "condition": "module.widgets", + "condition": "features.widgets", "output": [ "privateFeature" ] } }, diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index b83da944008..b7000b30dbd 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -106,13 +106,11 @@ Enables support for the HTML 5 local storage feature. Enabled by default. \value LocalContentCanAccessRemoteUrls Allows locally loaded documents to ignore cross-origin rules so that they can access - remote resources that would normally be blocked, because all remote resources are - considered cross-origin for a local file. Remote access that would not be blocked by + remote resources that would normally be blocked, since remote resources are + considered cross-origin for a local document. Remote access that would not be blocked by cross-origin rules is still possible when this setting is disabled (default). - Note that disabling this setting does not stop XMLHttpRequests or media elements in - local files from accessing remote content. Basically, it only stops some HTML - subresources, such as scripts, and therefore disabling this setting is not a safety - mechanism. + Note that disabling this setting does not prevent media elements in local files from + accessing remote content. Disabled by default. \value XSSAuditingEnabled Obsolete and has no effect. \value SpatialNavigationEnabled @@ -123,7 +121,8 @@ trying to reach towards the right and which element they probably want. Disabled by default. \value LocalContentCanAccessFileUrls - Allows locally loaded documents to access other local URLs. Enabled by default. + Allows locally loaded documents to access other local URLs. Disabling this makes QtWebEngine + behave more like Chrome and Firefox does by default. Enabled by default. \value HyperlinkAuditingEnabled Enables support for the \c ping attribute for hyperlinks. Disabled by default. \value ScrollAnimatorEnabled diff --git a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp index 5124eabed19..a559c15d0b3 100644 --- a/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp +++ b/src/webenginewidgets/render_widget_host_view_qt_delegate_widget.cpp @@ -270,6 +270,10 @@ void RenderWidgetHostViewQtDelegateWidget::show() // want to show anything else than popups as top-level. if (parent() || m_isPopup) { QQuickWidget::show(); + + QWebEngineView *view = static_cast(parent()); + if (view && view->isWindow()) + update(); } } @@ -448,6 +452,26 @@ bool RenderWidgetHostViewQtDelegateWidget::event(QEvent *event) break; } + switch (event->type()) { + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + case QEvent::MouseButtonDblClick: + case QEvent::MouseMove: + // Don't forward mouse events synthesized by the system, which are caused by genuine touch + // events. Chromium would then process for e.g. a mouse click handler twice, once due to the + // system synthesized mouse event, and another time due to a touch-to-gesture-to-mouse + // transformation done by Chromium. + // Only allow them for popup type, since QWidgetWindow will ignore them for Qt::Popup flag, + // which is expected to get input through synthesized mouse events (either by system or Qt) + if (!m_isPopup && static_cast(event)->source() == Qt::MouseEventSynthesizedBySystem) { + Q_ASSERT(!windowFlags().testFlag(Qt::Popup)); + return true; + } + break; + default: + break; + } + if (event->type() == QEvent::MouseButtonDblClick) { // QWidget keeps the Qt4 behavior where the DblClick event would replace the Press event. // QtQuick is different by sending both the Press and DblClick events for the second press diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html new file mode 100644 index 00000000000..84bf550362a --- /dev/null +++ b/tests/auto/core/qwebengineurlrequestinterceptor/resources/content3.html @@ -0,0 +1,6 @@ + + + +Simple test page without favicon (meaning no separate request from http server) + + diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp index 642e5db7c2e..32a618de33e 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp @@ -79,6 +79,7 @@ private Q_SLOTS: void replaceInterceptor_data(); void replaceInterceptor(); void replaceOnIntercept(); + void multipleRedirects(); }; tst_QWebEngineUrlRequestInterceptor::tst_QWebEngineUrlRequestInterceptor() @@ -211,6 +212,29 @@ class TestRequestInterceptor : public QWebEngineUrlRequestInterceptor } }; +class TestMultipleRedirectsInterceptor : public QWebEngineUrlRequestInterceptor { +public: + QList requestInfos; + QMap redirectPairs; + int redirectCount = 0; + void interceptRequest(QWebEngineUrlRequestInfo &info) override + { + QVERIFY(QThread::currentThread() == QCoreApplication::instance()->thread()); + qCDebug(lc) << this << "Type:" << info.resourceType() << info.requestMethod() << "Navigation:" << info.navigationType() + << info.requestUrl() << "Initiator:" << info.initiator(); + auto redirectUrl = redirectPairs.constFind(info.requestUrl()); + if (redirectUrl != redirectPairs.constEnd()) { + info.redirect(redirectUrl.value()); + requestInfos.append(info); + redirectCount++; + } + } + + TestMultipleRedirectsInterceptor() + { + } +}; + class ConsolePage : public QWebEnginePage { Q_OBJECT public: @@ -915,5 +939,28 @@ void tst_QWebEngineUrlRequestInterceptor::replaceOnIntercept() QCOMPARE(profileInterceptor.requestInfos.size(), pageInterceptor2.requestInfos.size()); } +void tst_QWebEngineUrlRequestInterceptor::multipleRedirects() +{ + HttpServer server; + server.setResourceDirs({ ":/resources" }); + QVERIFY(server.start()); + + TestMultipleRedirectsInterceptor multiInterceptor; + multiInterceptor.redirectPairs.insert(QUrl(server.url("http://github.com/content.html")), QUrl(server.url("http://github.com/content2.html"))); + multiInterceptor.redirectPairs.insert(QUrl(server.url("http://github.com/content2.html")), QUrl(server.url("http://github.com/content3.html"))); + + QWebEngineProfile profile; + profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false); + profile.setUrlRequestInterceptor(&multiInterceptor); + QWebEnginePage page(&profile); + QSignalSpy spy(&page, SIGNAL(loadFinished(bool))); + + page.setUrl(server.url("http://github.com/content.html")); + + QTRY_COMPARE_WITH_TIMEOUT(spy.count(), 1, 20000); + QTRY_COMPARE(multiInterceptor.redirectCount, 2); + QTRY_COMPARE(multiInterceptor.requestInfos.size(), 2); +} + QTEST_MAIN(tst_QWebEngineUrlRequestInterceptor) #include "tst_qwebengineurlrequestinterceptor.moc" diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc index 6a34635f708..df9c81a7bb0 100644 --- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc +++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.qrc @@ -1,6 +1,8 @@ resources/content.html + resources/content2.html + resources/content3.html resources/favicon.html resources/firstparty.html resources/fontawesome.woff diff --git a/tests/auto/quick/qmltests/BLACKLIST b/tests/auto/quick/qmltests/BLACKLIST index 3d98566f5ee..55be5b6443f 100644 --- a/tests/auto/quick/qmltests/BLACKLIST +++ b/tests/auto/quick/qmltests/BLACKLIST @@ -1,2 +1,5 @@ [NewViewRequest::test_loadNewViewRequest] macos + +[CertificateError::test_fatalError] +* diff --git a/tests/auto/quick/qquickwebengineview/BLACKLIST b/tests/auto/quick/qquickwebengineview/BLACKLIST new file mode 100644 index 00000000000..d4a35a76a57 --- /dev/null +++ b/tests/auto/quick/qquickwebengineview/BLACKLIST @@ -0,0 +1,2 @@ +[javascriptClipboard] +ubuntu-20.04 diff --git a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp index 09998eaca19..c3796062b1f 100644 --- a/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp +++ b/tests/auto/quick/qquickwebengineview/tst_qquickwebengineview.cpp @@ -791,20 +791,44 @@ void tst_QQuickWebEngineView::inputMethodHints() void tst_QQuickWebEngineView::setZoomFactor() { QQuickWebEngineView *view = webEngineView(); + m_window->show(); + view->setSize(QSizeF(320, 240)); - QVERIFY(qFuzzyCompare(view->zoomFactor(), 1.0)); + QCOMPARE(view->zoomFactor(), 1.0); view->setZoomFactor(2.5); - QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + QCOMPARE(view->zoomFactor(), 2.5); - view->setUrl(urlFromTestPath("html/basic_page.html")); + const QUrl url1 = urlFromTestPath("html/basic_page.html"), url2 = urlFromTestPath("html/basic_page2.html"); + + view->setUrl(url1); QVERIFY(waitForLoadSucceeded(view)); - QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + QCOMPARE(view->zoomFactor(), 2.5); view->setZoomFactor(0.1); - QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + QCOMPARE(view->zoomFactor(), 2.5); view->setZoomFactor(5.5); - QVERIFY(qFuzzyCompare(view->zoomFactor(), 2.5)); + QCOMPARE(view->zoomFactor(), 2.5); + + QScopedPointer view2(newWebEngineView()); + view2->setSize(QSizeF(320, 240)); + view2->setParentItem(m_window->contentItem()); + + // try loading different url and check new values after load + for (auto &&p : { + qMakePair(view, 2.5), // navigating away to different url should keep zoom + qMakePair(view2.get(), 1.0), // same url navigation in diffent page shouldn't be affected + }) { + auto &&view = p.first; auto zoomFactor = p.second; + view->setUrl(url2); + QVERIFY(waitForLoadSucceeded(view)); + QCOMPARE(view->zoomFactor(), zoomFactor); + } + + // should have no influence on first page + view2->setZoomFactor(3.5); + for (auto &&p : { qMakePair(view, 2.5), qMakePair(view2.get(), 3.5), }) + QCOMPARE(p.first->zoomFactor(), p.second); } void tst_QQuickWebEngineView::printToPdf() diff --git a/tests/auto/shared/resources/cert.pem b/tests/auto/shared/resources/cert.pem index 3aaaf289ca9..a201ed08eb3 100644 --- a/tests/auto/shared/resources/cert.pem +++ b/tests/auto/shared/resources/cert.pem @@ -1,64 +1,41 @@ -----BEGIN CERTIFICATE----- -MIIEpDCCAoygAwIBAgIUO90aty9AMjvBvzfUhr1WwdBrKkMwDQYJKoZIhvcNAQEL -BQAwfzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcM -DVNhbiBGcmFuY2lzY28xDzANBgNVBAoMBkJhZFNTTDEyMDAGA1UEAwwpQmFkU1NM -IEludGVybWVkaWF0ZSBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTkwODI2MTQ0 -NDIxWhcNMTkwODI3MTQ0NDIxWjBjMQswCQYDVQQGEwJVUzETMBEGA1UECAwKQ2Fs -aWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5jaXNjbzEPMA0GA1UECgwGQmFkU1NM -MRYwFAYDVQQDDA0qLmJhZHNzbC50ZXN0MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A -MIIBCgKCAQEAkybT/L4zJCqefpd+eYT6aQ0PtobQfFgP+n+z5wWoUxIAJnjb5ZW4 -7IJxka/2/ggzJOfrUBur54LkTfFQ+yX85eKYCuH0GLz+Rve50LDn0ya6qSgmEhDG -0bend2tMZY+Nl3B+5Ane1vua8hdJjv3ZO3e5UgpQwysL54eYyhEWWlbFWF11LhEd -MYp953UGLqoV4Mlw+Li8TmFwdKQx6icgBTuloXLzk9aUU+b6NbXdadNXkmzg09IC -sb8pnMXiF2P9Xm5rK0IoiRkSHxVnU12nQXh65Ns/2Dj5DcbHmVdvallfr4wnLeFP -UotysZnvFmE7FLMSr/eQfkTG+Jlb7ZhoGwIDAQABozQwMjAJBgNVHRMEAjAAMCUG -A1UdEQQeMByCDSouYmFkc3NsLnRlc3SCC2JhZHNzbC50ZXN0MA0GCSqGSIb3DQEB -CwUAA4ICAQA7Yc+QQzqSK15ibmaYrkqq+cumggsWLCprW8jvzhpWBt9IjToP5nsy -sKinYPoZR8jvZ1YVotcts7uQT7DkqeWkB+l+88c7gQdgujvBo6v9/g+jrXFKgsJD -IBmkho8hpd63Slqv2Yp4bYT20O5EvR9CQvwSkwTs+ylBNEs1Q+AbekxmBjuYUxHn -9xL4/GZ6ufoNv676iCoXo4mnDrCD8e8MRiZoU9Lq4G41HGiLWV0tM/M6BdVJYGzl -FcBg0ZKnQT9OCWEPRe3zyRS6a+MivPAzxS8z/kYaRN+C7H68Mib3xPDsEETz1MnO -uzGAPHAAgtYWYJi+CaaNWkgAv4n+UIQa0oyqPn4z5hLcsO+nMBws2Sg0mkQLilBX -N1ciCdVMi7sHKuLa7GVksq/RQrXnZcQhoYQRrZAaAHKbxyo/M2pNqmDiFJppdH7a -6Rj2vYf6ig/FXAzDGsDvf/tsGCxgJTFzGly+GsWVe40vyjfWHxWWDU/eGjfGO05k -Xzjm+kYGJnH2hfiIlX1Jeu/jjIodiSy31F0hvuKlJu8PfaQ7oo5neRzwRO6Wq9rR -7DMsQN6OtXGnnA+ogC0korA+aXev6wzbwYUhzMf1YTzEjrFNIXeIHsQSzq6lPcIE -JOly5wjyO/eNF7mpHyDX8brY6Hn+bgyDeKAmsUvhOCEXgaPpKlP4gQ== +MIIDezCCAmOgAwIBAgIUFZEIIzeR7lEA10rb14w7MfhP87MwDQYJKoZIhvcNAQEL +BQAwWjELMAkGA1UEBhMCREUxDzANBgNVBAgMBkJlcmxpbjEPMA0GA1UEBwwGQmVy +bGluMRUwEwYDVQQKDAxUaGVRdENvbXBhbnkxEjAQBgNVBAsMCXdlYmVuZ2luZTAe +Fw0yMTA1MTAyMTM1MTJaFw0yMjA1MTAyMTM1MTJaMGAxCzAJBgNVBAYTAkRFMQ8w +DQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEVMBMGA1UECgwMVGhlUXRD +b21wYW55MRgwFgYDVQQDDA93ZWJlbmdpbmUucXQuaW8wggEiMA0GCSqGSIb3DQEB +AQUAA4IBDwAwggEKAoIBAQCoDKAU8bkgstvcbnUPQ4g3gqmbm3c6HWcHJOe+LWQz +P6wIEF0JK6C3g2cqQHqSIa0wSysSbX/GDwGR9ul63e/f6MCJ1GmO8IhKrLdn0PVy +AIUzjqGKhv8C8tmmohOICCxTh8nhq64gqEWmUgasgoy/aAryFqgEYGhFQPVEz6Kv +CMSvpM1dNC3YCn467Gznc0s+EA6C6al/PNFHz9SZuF6f4bkyEf5dPPOt6IKXPZXo +Dv148mPLW5Dw0nv19445YENGLNENbDGyc13bgaOSm9xpPBp+IrpV2p65v5dO2IHl +E9qXaicKPRNANydppx5yX/OZRawgU2Q0lYNx3f+8R3I5AgMBAAGjMzAxMBoGA1Ud +EQQTMBGCD3dlYmVuZ2luZS5xdC5pbzATBgNVHSUEDDAKBggrBgEFBQcDATANBgkq +hkiG9w0BAQsFAAOCAQEAjThKpP0sBv1vEmaqBc1wTu//7RHmFcoStTt3scADzb2C +9gjOVC4NzxBneLkv01444Z1p/Iiu/ZZ+VKu7aJElJgnBWEisYwJ09t3cdZRA0UY7 +XRvTVAqV0OlsB1Jn0afE+aTLGjWo+jSYzua0O+NK74e23p9jkdSmXxH9w0FB/oyM +FGIOFnnfP0+QR4ZVvAGk2H60tBHQKmCM6b87TiD4GQIfOghCQWH+qJYSuyGu4hkE +uis+n1KHHhed3GIJOHpm7gt1C9qtjcp1nOpv0ycQjfc9CGvr02BcQjhMeO65hX0A +TvCgKN9/XMFv5jwwjjPCL12GBhwnN2k9hM/tEYpe2A== -----END CERTIFICATE----- -----BEGIN CERTIFICATE----- -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 -Adpix0jvG1Ys4Ayq6K2wQFdGFjtl6LsiGC7pWWU= +MIIDOzCCAiMCFDwWg4NZxCplj3qyBxAUTi1wmj4jMA0GCSqGSIb3DQEBCwUAMFox +CzAJBgNVBAYTAkRFMQ8wDQYDVQQIDAZCZXJsaW4xDzANBgNVBAcMBkJlcmxpbjEV +MBMGA1UECgwMVGhlUXRDb21wYW55MRIwEAYDVQQLDAl3ZWJlbmdpbmUwHhcNMjEw +NTEwMjEzMTE4WhcNMjIwNTEwMjEzMTE4WjBaMQswCQYDVQQGEwJERTEPMA0GA1UE +CAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xFTATBgNVBAoMDFRoZVF0Q29tcGFu +eTESMBAGA1UECwwJd2ViZW5naW5lMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB +CgKCAQEAuc/8xVrfSzOsI6kYul+o1QIPBh1I86eQm1PhTBDMAAPHuzyPaEMgBkn2 +XAUmvkynGpNioaJDU2ndV2fBHvsoeQCdNNmjFTe1rKYjrN6U2X5KoYSzN93TOYzK +aR38fEFx+w4qV76nnxSjYtGNe9z74GrfWFMdDQ0NJKzvaO4gaZ+OOg0OzWy4MJQ0 +aINo3UV55Y7Nt92AxFweiuHucKu+rjf3BX7n0Af/Tcs2c84f0R3HA7euReSibVvX +f33eHLRKwu2bvDjXiUzOdkxBn9GTo6Q09LyY6wDG0ZdWnyCKj3NBQKBVrq+bs3Q0 +ATsWhj/PvYlZhhZh4EOlqYOhCpwv4wIDAQABMA0GCSqGSIb3DQEBCwUAA4IBAQCC +pLSFGJcG0zhHW+2A6ogmpn2tA8gKUZx7f0J1nwgPEoAXQqWQv/299ZtmWfMKHUkk +ygG4u80C87wWPH42XWXo/KDrP9iYzoqAvtqbRuPG9PAxefQ/JUSnuhikA51g9+Mu +IDKKKSI+y/JW9u0Qo77fp/5n2DaFn5B+pBYvn/xLfaEa9bRdJMTEMsElGbPBzMZd +I/7X6B78X6Ow5TuRKSeZA7E1AZ/+e5A4Hj65bLAugoSKz3zaS0dV26LwAo18c2zP +TqtwHyIVj4QCoI6Z694q9KH4Pkml3fz8VSkk+MvZMWapvUhHu/DneTgqGbp9POYg +nx6oWME6idhnvN6DljxB -----END CERTIFICATE----- diff --git a/tests/auto/shared/resources/key.pem b/tests/auto/shared/resources/key.pem index 89922679a43..9bf87aee363 100644 --- a/tests/auto/shared/resources/key.pem +++ b/tests/auto/shared/resources/key.pem @@ -1,27 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -MIIEowIBAAKCAQEAkybT/L4zJCqefpd+eYT6aQ0PtobQfFgP+n+z5wWoUxIAJnjb -5ZW47IJxka/2/ggzJOfrUBur54LkTfFQ+yX85eKYCuH0GLz+Rve50LDn0ya6qSgm -EhDG0bend2tMZY+Nl3B+5Ane1vua8hdJjv3ZO3e5UgpQwysL54eYyhEWWlbFWF11 -LhEdMYp953UGLqoV4Mlw+Li8TmFwdKQx6icgBTuloXLzk9aUU+b6NbXdadNXkmzg -09ICsb8pnMXiF2P9Xm5rK0IoiRkSHxVnU12nQXh65Ns/2Dj5DcbHmVdvallfr4wn -LeFPUotysZnvFmE7FLMSr/eQfkTG+Jlb7ZhoGwIDAQABAoIBADRXy3BL98UVo+tD -2ClBtBFKJBy5N9ADQyvH4SZ8TLO/423L7+xqpaz7eYppHWKfaBHorTuBnFRtquhO -vo+Xo63iPFMirMFf+NMlq2MgilYBoMQrE9+5N//BZECGWlaGCcekrH5RRIMUXLlg -rzm98lfE7pbQNIo39bQV97NpAJqBWPuoIvCrbRCysGoA5j7ptZ/EhSlC00eA7ybD -CeYHmh8NrsapKOTGb5u1v3paV8X/mH6vKmsVs7n6LC0opBxzM8eAHEAQ6h8rmz9H -y99FWDYha3lOS4SLkTnuRnNHOMLJajPq3Isu+BgzLWuRGnKZ3rmuUFwPNkCZTvsV -dTdBE4ECgYEAw6jBEil0e8Pc9sGqnz93e8qrYE9wSPso4q3BNJgTbN48kon6mqh7 -gQVgEP/75Th5YrJUrY9Pd/8H9uoMOxbDXgOXG/xNnhC0L+7aM8nhKlxCLndY1e56 -/YymYYH4+D9ZD2u526mK/nmCg2QGOkCVYYp7NXe/mA0g34drKjefmj8CgYEAwIhq -rZhlfAvQThSOqQA9zA7NXPDh4KzIjr8htVu5YvVcv5W2uhsni9DXFaloPnhuLdJ7 -MnPF2WqzQ9YqFrGn/9/OTqeE23f60ed04qLGM4BApb45y5Kw6sCPnWu7dMYfny9i -XeZA2A+ODmqVkrU+ZNVzqzS1krYyUP3exd1voyUCgYEAqPRARH6np3gqhqoVvA4C -D1OjSTdPrrWzSIriG5h2rbv6ck/Tp1l1zKPnoMZrrjRmHWQA2x61cNk4926DwUKW -0cgn5HKqU6P49Ks8oRvi48FnJNjKTXHxoqChy/GAHF4Xecl8ZMKy06v5l5v4BLVg -SSpb2n/dYl9z05IMaBhAKeECgYBKB2n1S6ah1q0GiLL92mDoiDyAYwKG8AjBkk40 -vIsAuNUruTYkQvKmuOsqohO6CXZb2hWSpZ9KZNN+3ucaCL9PDE/4QEM+W9iuQu/X -gLzy6npxAD6avtGVweq2ncjbMp7QB1ksP69pJDn74xGV8miGPuiVyNOUEMgyChtR -Oz6EnQKBgEth0w80CBg6b3NKuASoc/vC08njZQvWpe5xrzY2DL8epVKb1qf6+8SE -eX34cIcSaonEZ2g67MAeIG6jtmPwxWk4EYAsO1u4XiyziABkoNyLKVH4hZg61BsV -jL7R5UrUvBbhKLFOwkcB4Kwdwu7COB/UKa5XJBTMbuw1UTyxlUeI +MIIEpQIBAAKCAQEAqAygFPG5ILLb3G51D0OIN4Kpm5t3Oh1nByTnvi1kMz+sCBBd +CSugt4NnKkB6kiGtMEsrEm1/xg8Bkfbpet3v3+jAidRpjvCISqy3Z9D1cgCFM46h +iob/AvLZpqITiAgsU4fJ4auuIKhFplIGrIKMv2gK8haoBGBoRUD1RM+irwjEr6TN +XTQt2Ap+Ouxs53NLPhAOgumpfzzRR8/Umbhen+G5MhH+XTzzreiClz2V6A79ePJj +y1uQ8NJ79feOOWBDRizRDWwxsnNd24GjkpvcaTwafiK6Vdqeub+XTtiB5RPal2on +Cj0TQDcnaacecl/zmUWsIFNkNJWDcd3/vEdyOQIDAQABAoIBAQCW93icOCdim6tu +FIDu7HEjxSsPUpPCToWu4lWaAHcinxGx0NlzkpD4K4DzcSdrvfszBmQ0UtBVokd7 +1IAdU+HZmePWLk+CDM2zoAPHrO3Cs3r2PS0cIHhZMsearcG0E/uWMseHB08PoXuo +lcnPEhzVGueyYe4guGcTx+5PGeUBLf+fJcEc3rIQnT2LYulM2aqBZSQM3jRUaPYs +F0awDpCNwajW/Bt2VB14Pr+H5MJ+WSznFCqW7SolBkqDGfKckXPSHgX6xZ0y7VCI +MM8vwlVI4mPkaHvSQMSI8vS4Qh+SGQCSs/AuuNLjjPoz1YotV3Ih4YbLj6BjFP2g +CrqzT6VNAoGBANOHmsqE0nRkLzonTDrMdla5b0TjTxwtNM5DjLgJa6UBBqPe+1Lv +JFoBP9bIfYDRWZOZrxXItfMmM43nK/ST6Xqgx1IpHUCLKVr2pA9RXrP+m4oawfgn +frW212fHibeOYiLy+DaQXQ0VRFxsc/VbwKVyVlMEcNg3N93x2E67M7vjAoGBAMtg +7wDa+5gjwuyNr7LKkp5VDTmtKQhoDtg4sw6MSQSMF6fJT9Z4kGTZ23+G85/LsM/k +iXbceabGJ0CQJvGn6oW4dI2Ut2c2nCNVbQCxJ6Nyn/yW7bRLShMnwXvbGAVxVUax +5ohJPZGJ8ar2CP76A0bkvm2Nwylq2gp6Y8h7+iwzAoGBAKizwfQ6sk45iKDsrpNG +dir8gY2DbJigRTksDpLIkJ1skAspz295YpiV3oBCLjYKwVJCg6zwAo0FrqBB+oB5 +ZwByMgWI3NeZJUZy5q2Ay/Lp4MroRELR3PC3/lu6fE90szgEZ4m84TmJ+Jdtt527 +q41H/yj+pbELePb95vIDw2LZAoGBAJBZ+MmupCzUFSI5Xp+UUIS48W4ijaE92mt1 +swF8aMcleBTLOjOL11D9oGHfs0OUG6czGq6WxnGs62dT6ZBUEo1e4rsq9xH3HNOn +anq3Qt8sGIn7xjPVzHnUGeyDEYWrb0+CLZJGCcEnG7SwdKolYfYLnW281Oysvp35 +SKGf/W0pAoGAa2+sZmhb1mpGAf6Bi4z+uym/6qOJmG6CnrBSM9e/r8nujwFVkCYF +3iz48qx3GbuliO6za8aM1drX2u8KWp1uP5KzwYvtW5SfpQ1eusFblHEYQQNRcKLT +j/wZBXnU961eMKkkTe2XsPirO8rVhVmxuFLqT/aEPffcragQFFIGOEQ= -----END RSA PRIVATE KEY----- diff --git a/tests/auto/widgets/certificateerror/BLACKLIST b/tests/auto/widgets/certificateerror/BLACKLIST new file mode 100644 index 00000000000..a8fd16bf3df --- /dev/null +++ b/tests/auto/widgets/certificateerror/BLACKLIST @@ -0,0 +1,2 @@ +[fatalError] +* diff --git a/tests/auto/widgets/certificateerror/tst_certificateerror.cpp b/tests/auto/widgets/certificateerror/tst_certificateerror.cpp index 0bea0415599..7a55e306d92 100644 --- a/tests/auto/widgets/certificateerror/tst_certificateerror.cpp +++ b/tests/auto/widgets/certificateerror/tst_certificateerror.cpp @@ -100,8 +100,8 @@ void tst_CertificateError::handleError() QVERIFY(page.error->isOverridable()); auto chain = page.error->certificateChain(); QCOMPARE(chain.size(), 2); - QCOMPARE(chain[0].serialNumber(), "3b:dd:1a:b7:2f:40:32:3b:c1:bf:37:d4:86:bd:56:c1:d0:6b:2a:43"); - QCOMPARE(chain[1].serialNumber(), "6d:52:fb:b4:57:3b:b2:03:c8:62:7b:7e:44:45:5c:d3:08:87:74:17"); + QCOMPARE(chain[0].serialNumber(), "15:91:08:23:37:91:ee:51:00:d7:4a:db:d7:8c:3b:31:f8:4f:f3:b3"); + QCOMPARE(chain[1].serialNumber(), "3c:16:83:83:59:c4:2a:65:8f:7a:b2:07:10:14:4e:2d:70:9a:3e:23"); if (deferError) { QVERIFY(page.error->deferred()); diff --git a/tests/auto/widgets/origins/tst_origins.cpp b/tests/auto/widgets/origins/tst_origins.cpp index 93a496ac43d..e7d71d7fe77 100644 --- a/tests/auto/widgets/origins/tst_origins.cpp +++ b/tests/auto/widgets/origins/tst_origins.cpp @@ -657,7 +657,7 @@ void tst_Origins::mixedXHR_data() << QVariant(QString("ok")); QTest::newRow("file->cors") << QString("file:" THIS_DIR "resources/mixedXHR.html") << QString("sendXHR('cors:/resources/mixedXHR.txt')") - << QVariant(QString("ok")); + << QVariant(QString("error")); QTest::newRow("qrc->file") << QString("qrc:/resources/mixedXHR.html") << QString("sendXHR('file:" THIS_DIR "resources/mixedXHR.txt')") diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp index 9a3e7b52e45..74082ab8c8a 100644 --- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp +++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp @@ -455,7 +455,7 @@ void tst_QWebEngineDownloadItem::downloadLink() ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadRequested); QCOMPARE(item->isFinished(), false); - QCOMPARE(item->totalBytes(), -1); + QCOMPARE(item->totalBytes(), fileContents.size()); QCOMPARE(item->receivedBytes(), 0); QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); QCOMPARE(item->type(), expectedDownloadType(userAction, fileDisposition)); @@ -568,7 +568,7 @@ void tst_QWebEngineDownloadItem::downloadTwoLinks() ScopedConnection sc2 = connect(m_profile, &QWebEngineProfile::downloadRequested, [&](QWebEngineDownloadItem *item) { QCOMPARE(item->state(), QWebEngineDownloadItem::DownloadRequested); QCOMPARE(item->isFinished(), false); - QCOMPARE(item->totalBytes(), -1); + QCOMPARE(item->totalBytes(), 5); // strlen("fileN") QCOMPARE(item->receivedBytes(), 0); QCOMPARE(item->interruptReason(), QWebEngineDownloadItem::NoReason); QCOMPARE(item->savePageFormat(), QWebEngineDownloadItem::UnknownSaveFormat); diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST index 2498ed7653e..d1425bfd6fc 100644 --- a/tests/auto/widgets/qwebenginepage/BLACKLIST +++ b/tests/auto/widgets/qwebenginepage/BLACKLIST @@ -4,3 +4,4 @@ osx [mouseMovementProperties] windows macos # Can't move cursor (QTBUG-76312) +sles-15.4 # QTBUG-111297 diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp index 5df09357f26..78d0a986235 100644 --- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp +++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp @@ -73,6 +73,13 @@ static void removeRecursive(const QString& dirname) QDir().rmdir(dirname); } +struct TestBasePage : QWebEnginePage +{ + explicit TestBasePage(QWebEngineProfile *profile, QObject *parent = nullptr) : QWebEnginePage(profile, parent) { } + explicit TestBasePage(QObject *parent = nullptr) : QWebEnginePage(parent) { } + QSignalSpy loadSpy { this, &QWebEnginePage::loadFinished }; +}; + class tst_QWebEnginePage : public QObject { Q_OBJECT @@ -3038,25 +3045,42 @@ void tst_QWebEnginePage::toPlainTextLoadFinishedRace() void tst_QWebEnginePage::setZoomFactor() { - QWebEnginePage page; + TestBasePage page, page2; - QVERIFY(qFuzzyCompare(page.zoomFactor(), 1.0)); + QCOMPARE(page.zoomFactor(), 1.0); page.setZoomFactor(2.5); - QVERIFY(qFuzzyCompare(page.zoomFactor(), 2.5)); - - const QUrl urlToLoad("qrc:/resources/test1.html"); - - QSignalSpy finishedSpy(&page, SIGNAL(loadFinished(bool))); - page.load(urlToLoad); - QTRY_COMPARE(finishedSpy.count(), 1); - QVERIFY(finishedSpy.at(0).first().toBool()); - QVERIFY(qFuzzyCompare(page.zoomFactor(), 2.5)); - - page.setZoomFactor(5.5); - QVERIFY(qFuzzyCompare(page.zoomFactor(), 2.5)); + QCOMPARE(page.zoomFactor(), 2.5); + + const QUrl url1("qrc:/resources/test1.html"), url2(QUrl("qrc:/resources/test2.html")); + + page.load(url1); + QTRY_COMPARE(page.loadSpy.count(), 1); + QVERIFY(page.loadSpy.at(0).first().toBool()); + QCOMPARE(page.zoomFactor(), 2.5); + + page.setZoomFactor(5.5); // max accepted zoom: kMaximumPageZoomFactor = 5.0 + QCOMPARE(page.zoomFactor(), 2.5); + + page.setZoomFactor(0.1); // min accepted zoom: kMinimumPageZoomFactor = 0.25 + QCOMPARE(page.zoomFactor(), 2.5); + + // try loading different url and check new values after load + page.loadSpy.clear(); + for (auto &&p : { + qMakePair(&page, 2.5), // navigating away to different url should keep zoom + qMakePair(&page2, 1.0), // same url navigation in diffent page shouldn't be affected + }) { + auto &&page = *p.first; auto zoomFactor = p.second; + page.load(url2); + QTRY_COMPARE(page.loadSpy.count(), 1); + QVERIFY(page.loadSpy.last().first().toBool()); + QCOMPARE(page.zoomFactor(), zoomFactor); + } - page.setZoomFactor(0.1); - QVERIFY(qFuzzyCompare(page.zoomFactor(), 2.5)); + // should have no influence on first page + page2.setZoomFactor(3.5); + for (auto &&p : { qMakePair(&page, 2.5), qMakePair(&page2, 3.5), }) + QCOMPARE(p.first->zoomFactor(), p.second); } void tst_QWebEnginePage::mouseButtonTranslation() diff --git a/tests/auto/widgets/qwebenginesettings/BLACKLIST b/tests/auto/widgets/qwebenginesettings/BLACKLIST new file mode 100644 index 00000000000..d4a35a76a57 --- /dev/null +++ b/tests/auto/widgets/qwebenginesettings/BLACKLIST @@ -0,0 +1,2 @@ +[javascriptClipboard] +ubuntu-20.04 diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST index c1a46e16d6b..592b47c010c 100644 --- a/tests/auto/widgets/qwebengineview/BLACKLIST +++ b/tests/auto/widgets/qwebengineview/BLACKLIST @@ -9,3 +9,6 @@ osx [mixLangLocale:eu_ES] * + +[navigateOnDrop:file] +windows diff --git a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp index 4854b3603e3..b56053fd2f3 100644 --- a/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp +++ b/tests/auto/widgets/qwebengineview/tst_qwebengineview.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -173,6 +174,8 @@ private Q_SLOTS: void setViewPreservesExplicitPage(); void closeDiscardsPage(); void loadAfterRendererCrashed(); + void navigateOnDrop_data(); + void navigateOnDrop(); }; // This will be called before the first test function is executed. @@ -3479,5 +3482,39 @@ void tst_QWebEngineView::loadAfterRendererCrashed() QVERIFY(loadSpy.first().first().toBool()); } +void tst_QWebEngineView::navigateOnDrop_data() +{ + QTest::addColumn("url"); + QTest::newRow("file") << QUrl::fromLocalFile(QDir(TESTS_SOURCE_DIR).absoluteFilePath("qwebengineview/resources/dummy.html")); + QTest::newRow("qrc") << QUrl("qrc:///resources/dummy.html"); +} + +void tst_QWebEngineView::navigateOnDrop() +{ + QFETCH(QUrl, url); + struct WebEngineView : QWebEngineView { + QWebEngineView* createWindow(QWebEnginePage::WebWindowType /* type */) override { return this; } + } view; + view.resize(640, 480); + view.show(); + QVERIFY(QTest::qWaitForWindowExposed(&view)); + + QSignalSpy loadSpy(&view, &QWebEngineView::loadFinished); + QMimeData mimeData; + mimeData.setUrls({ url }); + + auto sendEvents = [&] () { + QDragEnterEvent dee(view.rect().center(), Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier); + QApplication::sendEvent(&view, &dee); + QDropEvent de(view.rect().center(), Qt::CopyAction, &mimeData, Qt::LeftButton, Qt::NoModifier); + QApplication::sendEvent(&view, &de); + }; + + sendEvents(); + QTRY_COMPARE(loadSpy.count(), 1); + QVERIFY(loadSpy.first().first().toBool()); + QCOMPARE(view.url(), url); +} + QTEST_MAIN(tst_QWebEngineView) #include "tst_qwebengineview.moc" diff --git a/tests/auto/widgets/touchinput/BLACKLIST b/tests/auto/widgets/touchinput/BLACKLIST new file mode 100644 index 00000000000..d9e06df8c78 --- /dev/null +++ b/tests/auto/widgets/touchinput/BLACKLIST @@ -0,0 +1,2 @@ +[touchTap] +sles-15.4 # QTBUG-106334 diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro index 2dc1eefcd5a..d35f875c13d 100644 --- a/tests/auto/widgets/widgets.pro +++ b/tests/auto/widgets/widgets.pro @@ -1,3 +1,5 @@ +load(functions) + include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) # workaround for QTBUG-68093 QT_FOR_CONFIG += webenginecore webenginecore-private @@ -37,7 +39,7 @@ qtConfig(ssl) { SUBDIRS += certificateerror } -qtConfig(webengine-spellchecker):!cross_compile { +qtConfig(webengine-spellchecker):!cross_compile:!isUniversal() { !qtConfig(webengine-native-spellchecker) { SUBDIRS += spellchecking } else {