diff options
author | Liang Qi <liang.qi@qt.io> | 2019-09-12 10:00:03 +0200 |
---|---|---|
committer | Liang Qi <liang.qi@qt.io> | 2019-09-12 20:19:28 +0200 |
commit | 2f71cdff2cda7903fd0b5ff0033d790877e40181 (patch) | |
tree | 0255e40f5366123bedefcbc9ad7d482f2e8198a2 /src | |
parent | d91b839d67bcfa1cfeb3d095b6885c97c53b9812 (diff) | |
parent | 5b0bbd7345b698faab0116b821802fb4a30c0fa4 (diff) | |
download | qtwebengine-wip/qt6.tar.gz |
Merge "Merge remote-tracking branch 'origin/5.14' into wip/qt6"wip/qt6
Diffstat (limited to 'src')
71 files changed, 3289 insertions, 813 deletions
diff --git a/src/3rdparty b/src/3rdparty -Subproject f5613a4bc321972b8f72654d4c4bc9ba0c36ffb +Subproject feccbb4ea7fa685dcd013f5a3f6c14ea768636c diff --git a/src/core/config/common.pri b/src/buildtools/config/common.pri index edebdb33c..1a54f1559 100644 --- a/src/core/config/common.pri +++ b/src/buildtools/config/common.pri @@ -1,6 +1,7 @@ # Shared configuration for all our supported platforms +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) -QT_FOR_CONFIG += webenginecore +QT_FOR_CONFIG += buildtools-private webenginecore webenginecore-private gn_args += \ use_qt=true \ @@ -28,10 +29,15 @@ gn_args += \ safe_browsing_mode=0 \ optimize_webui=false -!win32: gn_args += \ - use_jumbo_build=true \ - jumbo_file_merge_limit=8 \ - jumbo_build_excluded="[\"browser\"]" +greaterThan(QMAKE_JUMBO_MERGE_LIMIT,0) { + gn_args += \ + use_jumbo_build=true \ + jumbo_file_merge_limit=$$QMAKE_JUMBO_MERGE_LIMIT +} + +!greaterThan(QMAKE_JUMBO_MERGE_LIMIT,8) { + gn_args += jumbo_build_excluded="[\"browser\"]" +} qtConfig(webengine-printing-and-pdf) { gn_args += enable_basic_printing=true enable_print_preview=true @@ -73,11 +79,11 @@ precompile_header { gn_args += enable_precompiled_headers=false } -CONFIG(release, debug|release):!isDeveloperBuild() { +CONFIG(release, debug|release):!qtConfig(webengine-developer-build) { gn_args += is_official_build=true } else { gn_args += is_official_build=false - !isDeveloperBuild(): gn_args += is_unsafe_developer_build=false + !qtConfig(webengine-developer-build): gn_args += is_unsafe_developer_build=false } CONFIG(release, debug|release) { @@ -116,7 +122,7 @@ optimize_size: gn_args += optimize_for_size=true sanitize_undefined: gn_args += is_ubsan=true is_ubsan_vptr=true } -qtConfig(webengine-v8-snapshot) { +qtConfig(webengine-v8-snapshot):qtConfig(webengine-v8-snapshot-support) { gn_args += v8_use_snapshot=true } else { gn_args += v8_use_snapshot=false diff --git a/src/core/config/functions.pri b/src/buildtools/config/functions.pri index 8c11faa16..8c11faa16 100644 --- a/src/core/config/functions.pri +++ b/src/buildtools/config/functions.pri diff --git a/src/core/config/linux.pri b/src/buildtools/config/linux.pri index 998aedc40..998aedc40 100644 --- a/src/core/config/linux.pri +++ b/src/buildtools/config/linux.pri diff --git a/src/core/config/mac_osx.pri b/src/buildtools/config/mac_osx.pri index 3f2fe9c0a..3f2fe9c0a 100644 --- a/src/core/config/mac_osx.pri +++ b/src/buildtools/config/mac_osx.pri diff --git a/src/core/config/windows.pri b/src/buildtools/config/windows.pri index 385faeed0..dfa40e9dc 100644 --- a/src/core/config/windows.pri +++ b/src/buildtools/config/windows.pri @@ -22,7 +22,7 @@ clang_cl { gn_args += is_clang=false use_lld=false } -isDeveloperBuild() { +qtConfig(webengine-developer-build) { gn_args += \ is_win_fastlink=true diff --git a/src/buildtools/configure.json b/src/buildtools/configure.json new file mode 100644 index 000000000..3fc342992 --- /dev/null +++ b/src/buildtools/configure.json @@ -0,0 +1,716 @@ +{ + "module": "buildtools", + "depends": [ + "core-private", + "gui-private", + "printsupport" + ], + "commandline": { + "options": { + "webengine-core": "boolean", + "webengine-jumbo-build": { "type": "optionalString", "name": "merge_limit"} + } + }, + "libraries": { + "webengine-dbus": { + "label": "d-bus", + "sources": [ + { "type": "pkgConfig", "args": "dbus-1" } + ] + }, + "webengine-fontconfig": { + "label": "fontconfig", + "sources": [ + { "type": "pkgConfig", "args": "fontconfig" } + ] + }, + "webengine-libdrm": { + "label": "libdrm", + "sources": [ + { "type": "pkgConfig", "args": "libdrm" } + ] + }, + "webengine-xcomposite": { + "label": "xcomposite", + "sources": [ + { "type": "pkgConfig", "args": "xcomposite" } + ] + }, + "webengine-xcursor": { + "label": "xcursor", + "sources": [ + { "type": "pkgConfig", "args": "xcursor" } + ] + }, + "webengine-xi": { + "label": "xi", + "sources": [ + { "type": "pkgConfig", "args": "xi" } + ] + }, + "webengine-xtst": { + "label": "xtst", + "sources": [ + { "type": "pkgConfig", "args": "xtst" } + ] + }, + "webengine-nss": { + "label": "nss >= 3.26", + "sources": [ + { "type": "pkgConfig", "args": "nss >= 3.26" } + ] + }, + "webengine-x11" : { + "label" : "x11", + "sources": [ + { "type": "pkgConfig", "args": "x11" } + ] + }, + "webengine-glib": { + "label": "glib-2.0 >= 2.32.0", + "sources": [ + { "type": "pkgConfig", "args": "glib-2.0 >= 2.32.0" } + ] + }, + "webengine-harfbuzz": { + "label": "harfbuzz >= 2.2.0", + "sources": [ + { "type": "pkgConfig", "args": "harfbuzz >= 2.2.0" } + ] + }, + "webengine-jpeglib": { + "label": "compatible jpeglib", + "type": "compile", + "test": { + "head": [ + "#include <cstdio>", + "#include <cstring>", + "extern \"C\" {", + " #include <jpeglib.h>", + "}" + ], + "main": [ + "JDIMENSION dummy;", + "jpeg_crop_scanline(nullptr, &dummy, &dummy);", + "jpeg_skip_scanlines(nullptr, dummy);" + ] + }, + "sources": [ + { "type": "pkgConfig", "args": "libjpeg" }, + "-ljpeg" + ] + }, + "webengine-jsoncpp": { + "label": "jsoncpp", + "sources": [ + { "type": "pkgConfig", "args": "jsoncpp" } + ] + }, + "webengine-libevent": { + "label": "libevent", + "sources": [ + { "type": "pkgConfig", "args": "libevent" } + ] + }, + "webengine-minizip": { + "label": "minizip", + "sources": [ + { "type": "pkgConfig", "args": "minizip" } + ] + }, + "webengine-png": { + "label": "libpng >= 1.6.0", + "sources": [ + { "type": "pkgConfig", "args": "libpng >= 1.6.0" } + ] + }, + "webengine-protobuf": { + "label": "protobuf", + "sources": [ + { "type": "pkgConfig", "args": "protobuf" } + ] + }, + "webengine-zlib": { + "label": "zlib", + "sources": [ + { "type": "pkgConfig", "args": "zlib" } + ] + }, + "webengine-re2": { + "label": "re2", + "test" : { + "main": [ + "std::string s;", + "RE2 re2(s);" + ] + }, + "headers": "re2/re2.h", + "sources": [ + { "type": "pkgConfig", "args": "re2" } + ] + }, + "webengine-icu": { + "label": "icu >= 63", + "sources": [ + { "type": "pkgConfig", "args": "icu-uc >= 63 icu-i18n >= 63" } + ] + }, + "webengine-webp": { + "label": "libwebp, libwebpmux and libwebpdemux", + "sources": [ + { "type": "pkgConfig", "args": "libwebp libwebpmux libwebpdemux" } + ] + }, + "webengine-lcms2": { + "label": "lcms2", + "sources": [ + { "type": "pkgConfig", "args": "lcms2" } + ] + }, + "webengine-freetype": { + "label": "freetype >= 2.4.2", + "test": { + "head": [ + "#include <ft2build.h>", + "#include FT_FREETYPE_H", + "#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20402)", + "# error This version of freetype is too old.", + "#endif" + ], + "main": [ + "FT_Face ft_face = 0;", + "FT_Reference_Face(ft_face);" + ] + }, + "sources": [ + { "type": "pkgConfig", "args": "freetype2" } + ] + }, + "webengine-libxml2": { + "label": "compatible libxml2 and libxslt", + "type": "compile", + "test": { + "tail": [ + "#if !defined(LIBXML_ICU_ENABLED)", + "#error libxml icu not enabled", + "#endif" + ] + }, + "headers": "libxml/xmlversion.h", + "sources": [ + { "type": "pkgConfig", "args": "libxml-2.0 libxslt" } + ] + }, + "webengine-libdrm": { + "label": "libdrm", + "sources": [ + { "type": "pkgConfig", "args": "libdrm" } + ] + }, + "webengine-xcomposite": { + "label": "xcomposite", + "sources": [ + { "type": "pkgConfig", "args": "xcomposite" } + ] + }, + "webengine-xcursor": { + "label": "xcursor", + "sources": [ + { "type": "pkgConfig", "args": "xcursor" } + ] + }, + "webengine-xi": { + "label": "xi", + "sources": [ + { "type": "pkgConfig", "args": "xi" } + ] + }, + "webengine-xtst": { + "label": "xtst", + "sources": [ + { "type": "pkgConfig", "args": "xtst" } + ] + }, + "webengine-ffmpeg": { + "label": "libavcodec libavformat libavutil", + "sources": [ + { "type": "pkgConfig", "args": "libavcodec libavformat libavutil" } + ] + }, + "webengine-opus": { + "label": "opus", + "sources": [ + { "type": "pkgConfig", "args": "opus" } + ] + }, + "webengine-snappy": { + "label": "snappy", + "test": { + "main": [ + "snappy::Source *src = 0;", + "snappy::Sink *sink = 0;" + ] + }, + "headers": "snappy.h", + "sources": [ + "-lsnappy" + ] + }, + "webengine-libvpx": { + "label": "libvpx", + "test": { + "main": [ + "vpx_codec_cx_pkt pkt;", + "pkt.data.frame.width[0] = 0u;", + "pkt.data.frame.height[0] = 0u;" + ] + }, + "headers": "vpx/vpx_encoder.h", + "sources": [ + { "type": "pkgConfig", "args": "vpx" }, + "-lvpx" + ] + } + }, + + "testDir": "config.tests", + "tests" : { + "webengine-bison": { + "label": "bison", + "type": "detectBison" + }, + "webengine-flex": { + "label": "flex", + "type": "detectFlex" + }, + "webengine-gn": { + "label": "system gn", + "type": "detectGn" + }, + "webengine-glibc": { + "label": "glibc > 2.16", + "type": "compile", + "test": { + "include": "features.h", + "tail": [ + "#if __GLIBC__ < 2 || __GLIBC_MINOR__ < 17", + "#error glibc versions below 2.17 are not supported", + "#endif" + ] + } + }, + "webengine-gperf": { + "label": "gperf", + "type": "detectGperf" + }, + "webengine-khr": { + "label": "khr", + "type": "compile", + "test": { + "include": "KHR/khrplatform.h", + "qmake" : [ + "!isEmpty(QMAKE_INCDIR_EGL): INCLUDEPATH += $$QMAKE_INCDIR_EGL", + "!isEmpty(QMAKE_INCDIR_OPENGL): INCLUDEPATH += $$QMAKE_INCDIR_OPENGL" + ] + } + }, + "webengine-ninja": { + "label": "system ninja", + "type": "detectNinja" + }, + "webengine-python2": { + "label": "python2", + "type": "detectPython2", + "log": "location" + }, + "webengine-winversion": { + "label": "winversion", + "type": "compile", + "test": { + "head" : [ + "#if !defined(__clang__) && _MSC_FULL_VER < 191426428", + "#error unsupported Visual Studio version", + "#endif" + ] + } + }, + "webengine-host-pkg-config": { + "label": "host pkg-config", + "type": "detectHostPkgConfig", + "log": "path" + }, + "webengine-jumbo-build": { + "label": "jumbo build merge limit", + "type": "detectJumboBuild", + "log": "merge_limit" + }, + "webengine-protoc": { + "label": "protoc", + "type": "detectProtoc" + }, + "webengine-win-compiler64": { + "label": "64bit compiler", + "type": "isWindowsHostCompiler64" + } + }, + "features": { + "webengine-core": { + "label": "Support Qt WebEngine Core", + "purpose": "Provides WebEngine Core support.", + "condition": "module.gui + && features.webengine-python2 + && features.webengine-gperf + && features.webengine-bison + && features.webengine-flex + && (!features.xcb || features.webengine-ozone-x11)", + "output": [ "privateFeature" ] + }, + "webengine-python2": { + "label": "python2", + "condition": "tests.webengine-python2", + "output": [ + "privateFeature", + { "type": "varAssign", "name": "QMAKE_PYTHON2", "value": "tests.webengine-python2.location" } + ] + }, + "webengine-gperf": { + "label": "gperf", + "condition": "tests.webengine-gperf", + "output": [ "privateFeature" ] + }, + "webengine-bison": { + "label": "bison", + "condition": "tests.webengine-bison", + "output": [ "privateFeature" ] + }, + "webengine-flex": { + "label": "flex", + "condition": "tests.webengine-flex", + "output": [ "privateFeature" ] + }, + "webengine-system-ninja": { + "label": "Use System Ninja", + "condition": "tests.webengine-ninja", + "output": [ "privateFeature" ] + }, + "webengine-system-fontconfig": { + "label": "fontconfig", + "condition": "libs.webengine-fontconfig", + "output": [ "privateFeature" ] + }, + "webengine-system-dbus": { + "label": "dbus", + "condition": "libs.webengine-dbus", + "output": [ "privateFeature" ] + }, + "webengine-system-libdrm": { + "label": "libdrm", + "condition": "libs.webengine-libdrm", + "output": [ "privateFeature" ] + }, + "webengine-system-xcomposite": { + "label": "xcomposite", + "condition": "libs.webengine-xcomposite", + "output": [ "privateFeature" ] + }, + "webengine-system-xcursor": { + "label": "xcursor", + "condition": "libs.webengine-xcursor", + "output": [ "privateFeature" ] + }, + "webengine-system-xi": { + "label": "xi", + "condition": "libs.webengine-xi", + "output": [ "privateFeature" ] + }, + "webengine-system-xtst": { + "label": "xtst", + "condition": "libs.webengine-xtst", + "output": [ "privateFeature" ] + }, + "webengine-system-gn": { + "label": "Use System Gn", + "autoDetect": "false", + "condition": "tests.webengine-gn", + "output": [ "privateFeature" ] + }, + "webengine-system-khr" : { + "label": "khr", + "condition": "config.unix && tests.webengine-khr", + "output": [ "privateFeature" ] + }, + "webengine-system-nss": { + "label": "nss", + "condition": "config.unix && !config.darwin && libs.webengine-nss", + "output": [ "privateFeature" ] + }, + "webengine-system-glibc": { + "label": "glibc", + "condition": "config.linux && tests.webengine-glibc", + "output": [ "privateFeature" ] + }, + "webengine-system-x11" : { + "label": "x11", + "condition": "config.unix && libs.webengine-x11", + "output": [ "privateFeature" ] + }, + "webengine-host-pkg-config": { + "label": "host-pkg-config", + "condition": "config.unix && tests.webengine-host-pkg-config", + "output": [ + "privateFeature", + { "type": "varAssign", "name": "QMAKE_PKG_CONFIG_HOST", "value": "tests.webengine-host-pkg-config.path" } + ] + }, + "webengine-ozone-x11" : { + "label": "Support qpa-xcb", + "condition": "config.unix + && features.xcb + && features.webengine-system-x11 + && features.webengine-system-libdrm + && features.webengine-system-xcomposite + && features.webengine-system-xcursor + && features.webengine-system-xi + && features.webengine-system-xtst", + "output": [ "privateFeature" ] + }, + "webengine-jumbo-build": { + "label": "jumbo build merge batch", + "condition": "tests.webengine-jumbo-build", + "output": [ + "privateFeature", + { "type": "varAssign", "name": "QMAKE_JUMBO_MERGE_LIMIT", "value": "tests.webengine-jumbo-build.merge_limit" } + ] + }, + "webengine-system-libdrm": { + "label": "libdrm", + "condition": "libs.webengine-libdrm", + "output": [ "privateFeature" ] + }, + "webengine-system-xcomposite": { + "label": "xcomposite", + "condition": "libs.webengine-xcomposite", + "output": [ "privateFeature" ] + }, + "webengine-system-xcursor": { + "label": "xcursor", + "condition": "libs.webengine-xcursor", + "output": [ "privateFeature" ] + }, + "webengine-system-xi": { + "label": "xi", + "condition": "libs.webengine-xi", + "output": [ "privateFeature" ] + }, + "webengine-system-xtst": { + "label": "xtst", + "condition": "libs.webengine-xtst", + "output": [ "privateFeature" ] + }, + "webengine-system-harfbuzz": { + "label": "harfbuzz", + "condition": "config.unix && features.system-harfbuzz && libs.webengine-harfbuzz", + "output": [ "privateFeature" ] + }, + "webengine-system-glib" : { + "label": "glib", + "condition": "config.unix && libs.webengine-glib", + "output": [ "privateFeature" ] + }, + "webengine-system-minizip" : { + "label": "minizip", + "condition": "config.unix && libs.webengine-minizip", + "output": [ "privateFeature" ] + }, + "webengine-system-zlib" : { + "label": "zlib", + "condition": "config.unix && features.system-zlib && libs.webengine-zlib", + "output": [ "privateFeature" ] + }, + "webengine-system-libevent" : { + "label": "libevent", + "condition": "config.unix && libs.webengine-libevent", + "output": [ "privateFeature" ] + }, + "webengine-system-jsoncpp" : { + "label": "jsoncpp", + "condition": "config.unix && libs.webengine-jsoncpp", + "output": [ "privateFeature" ] + }, + "webengine-system-protobuf" : { + "label": "protobuf", + "condition": "config.unix && libs.webengine-protobuf && tests.webengine-protoc", + "output": [ "privateFeature" ] + }, + "webengine-system-png" : { + "label": "png", + "condition": "config.unix && features.system-png && libs.webengine-png", + "output": [ "privateFeature" ] + }, + "webengine-system-jpeg" : { + "label": "JPEG", + "condition": "config.unix && features.system-jpeg && libs.webengine-jpeglib", + "output": [ "privateFeature" ] + }, + "webengine-system-re2": { + "label": "re2", + "condition": "config.unix && libs.webengine-re2", + "output": [ "privateFeature" ] + }, + "webengine-system-icu": { + "label": "icu", + "autoDetect": "false", + "condition": "libs.webengine-icu", + "output": [ "privateFeature" ] + }, + "webengine-system-libwebp": { + "label": "libwebp, libwebpmux and libwebpdemux", + "condition": "config.unix && libs.webengine-webp", + "output": [ "privateFeature" ] + }, + "webengine-system-opus": { + "label": "opus", + "condition": "config.unix && libs.webengine-opus", + "output": [ "privateFeature" ] + }, + "webengine-system-ffmpeg": { + "label": "ffmpeg", + "autoDetect": "false", + "condition": "libs.webengine-ffmpeg && features.webengine-system-opus && features.webengine-system-libwebp", + "output": [ "privateFeature" ] + }, + "webengine-system-libxml2": { + "label": "libxml2 and libxslt", + "condition": "config.unix && libs.webengine-libxml2", + "output": [ "privateFeature" ] + }, + "webengine-system-lcms2" : { + "label": "lcms2", + "condition": "config.unix && libs.webengine-lcms2", + "output": [ "privateFeature" ] + }, + "webengine-system-freetype" : { + "label": "freetype", + "condition": "config.unix && features.system-freetype && libs.webengine-freetype", + "output": [ "privateFeature" ] + }, + "webengine-system-libvpx" : { + "label": "libvpx", + "condition": "config.unix && libs.webengine-libvpx", + "output": [ "privateFeature" ] + }, + "webengine-system-snappy" : { + "label": "snappy", + "condition": "config.unix && libs.webengine-snappy", + "output": [ "privateFeature" ] + }, + "webengine-winversion" : { + "label": "winversion", + "condition": "config.win32 && tests.webengine-winversion", + "output": [ "privateFeature" ] + }, + "webengine-win-compiler64": { + "label": "64bit compiler", + "condition": "config.win32 && tests.webengine-win-compiler64", + "output": [ "privateFeature" ] + } + }, + "report": [ + { + "type": "warning", + "condition": "!module.gui", + "message": "QtWebEngine requires QtGui." + }, + { + "type": "warning", + "condition": "!features.webengine-python2", + "message": "Python version 2 (2.7.5 or later) is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.webengine-gperf", + "message": "gperf is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.webengine-bison", + "message": "bison is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "!features.webengine-flex", + "message": "flex is required to build QtWebEngine." + }, + { + "type": "warning", + "condition": "config.linux && !features.webengine-ozone-x11 && features.xcb", + "message": "Could not find all necessary libraries for qpa-xcb support." + }, + { + "type": "warning", + "condition": "config.win32 && !features.webengine-win-compiler64", + "message": "64-bit cross-building or native toolchain is required to build QtWebEngine." + } + ], + "summary": [ + { + "section": "Qt WebEngine Build Tools", + "entries": [ + "webengine-system-ninja", + "webengine-system-gn", + { + "message": "Jumbo Build Merge Limit", + "type": "jumboBuild" + }, + { + "section": "Required system libraries", + "condition": "config.unix && !config.macos && features.webengine-core", + "entries": [ + "webengine-system-fontconfig", + "webengine-system-dbus", + "webengine-system-nss", + "webengine-system-khr", + "webengine-system-glibc" + ] + }, + { + "section": "Required system libraries for qpa-xcb", + "condition": "config.unix && !config.macos && features.webengine-core", + "entries": [ + "webengine-system-x11", + "webengine-system-libdrm", + "webengine-system-xcomposite", + "webengine-system-xcursor", + "webengine-system-xi", + "webengine-system-xtst" + ] + }, + { + "section": "Optional system libraries used", + "condition": "config.unix", + "entries": [ + "webengine-system-re2", + "webengine-system-icu", + "webengine-system-libwebp", + "webengine-system-opus", + "webengine-system-ffmpeg", + "webengine-system-libvpx", + "webengine-system-snappy", + "webengine-system-glib", + "webengine-system-zlib", + "webengine-system-minizip", + "webengine-system-libevent", + "webengine-system-jsoncpp", + "webengine-system-protobuf", + "webengine-system-libxml2", + "webengine-system-lcms2", + "webengine-system-png", + "webengine-system-jpeg", + "webengine-system-harfbuzz", + "webengine-system-freetype" + ] + } + ] + } + ] +} diff --git a/src/buildtools/gn.pro b/src/buildtools/gn.pro index b6bf9cfc4..033202e6e 100644 --- a/src/buildtools/gn.pro +++ b/src/buildtools/gn.pro @@ -3,8 +3,8 @@ option(host_build) !debug_and_release: CONFIG += release -include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) -QT_FOR_CONFIG += webenginecore-private +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) +QT_FOR_CONFIG += buildtools-private build_pass|!debug_and_release { !qtConfig(webengine-system-gn): CONFIG(release, debug|release) { diff --git a/src/buildtools/ninja.pro b/src/buildtools/ninja.pro index 6382d6cfb..66a6d5aa6 100644 --- a/src/buildtools/ninja.pro +++ b/src/buildtools/ninja.pro @@ -2,8 +2,8 @@ TEMPLATE = aux !debug_and_release: CONFIG += release -include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) -QT_FOR_CONFIG += webenginecore-private +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) +QT_FOR_CONFIG += buildtools-private build_pass|!debug_and_release { !qtConfig(webengine-system-ninja): CONFIG(release, debug|release) { diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro index 1c5f140e0..f14b4b01d 100644 --- a/src/core/api/core_api.pro +++ b/src/core/api/core_api.pro @@ -37,6 +37,7 @@ HEADERS = \ qtwebenginecoreglobal_p.h \ qwebenginecookiestore.h \ qwebenginecookiestore_p.h \ + qwebenginefindtextresult.h \ qwebenginehttprequest.h \ qwebenginemessagepumpscheduler_p.h \ qwebenginenotification.h \ @@ -53,6 +54,7 @@ SOURCES = \ qtwebenginecoreglobal.cpp \ qwebengineclientcertificatestore.cpp \ qwebenginecookiestore.cpp \ + qwebenginefindtextresult.cpp \ qwebenginehttprequest.cpp \ qwebenginemessagepumpscheduler.cpp \ qwebenginenotification.cpp \ diff --git a/src/core/api/qwebenginefindtextresult.cpp b/src/core/api/qwebenginefindtextresult.cpp new file mode 100644 index 000000000..ce1be359e --- /dev/null +++ b/src/core/api/qwebenginefindtextresult.cpp @@ -0,0 +1,116 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qwebenginefindtextresult.h" + +QT_BEGIN_NAMESPACE + +class QWebEngineFindTextResultPrivate : public QSharedData { +public: + int numberOfMatches = 0; + int activeMatchOrdinal = 0; +}; + +/*! + \class QWebEngineFindTextResult + \brief The QWebEngineFindTextResult class encapsulates the result of a string search on a page. + \since 5.14 + + \inmodule QtWebEngineCore + + Results are passed to the user in the + \l QWebEnginePage::findTextFinished() and + \l{WebEngineView::findTextFinished()}{WebEngineView.findTextFinished()} signals. +*/ + +/*! \internal +*/ +QWebEngineFindTextResult::QWebEngineFindTextResult() + : d(new QWebEngineFindTextResultPrivate) +{} + +/*! \internal +*/ +QWebEngineFindTextResult::QWebEngineFindTextResult(int numberOfMatches, int activeMatchOrdinal) + : d(new QWebEngineFindTextResultPrivate) +{ + d->numberOfMatches = numberOfMatches; + d->activeMatchOrdinal = activeMatchOrdinal; +} + +/*! \internal +*/ +QWebEngineFindTextResult::QWebEngineFindTextResult(const QWebEngineFindTextResult &other) + : d(other.d) +{} + +/*! \internal +*/ +QWebEngineFindTextResult &QWebEngineFindTextResult::operator=(const QWebEngineFindTextResult &other) +{ + d = other.d; + return *this; +} + +/*! \internal +*/ +QWebEngineFindTextResult::~QWebEngineFindTextResult() +{} + +/*! + \property QWebEngineFindTextResult::numberOfMatches + \brief The number of matches found. +*/ +int QWebEngineFindTextResult::numberOfMatches() const +{ + return d->numberOfMatches; +} + +/*! + \property QWebEngineFindTextResult::activeMatchOrdinal + \brief The index of the currently highlighted match. +*/ +int QWebEngineFindTextResult::activeMatchOrdinal() const +{ + return d->activeMatchOrdinal; +} + +QT_END_NAMESPACE + +#include "moc_qwebenginefindtextresult.cpp" diff --git a/src/core/api/qwebenginefindtextresult.h b/src/core/api/qwebenginefindtextresult.h new file mode 100644 index 000000000..073a8135f --- /dev/null +++ b/src/core/api/qwebenginefindtextresult.h @@ -0,0 +1,81 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QWEBENGINEFINDTEXTRESULT_H +#define QWEBENGINEFINDTEXTRESULT_H + +#include <QtWebEngineCore/qtwebenginecoreglobal.h> +#include <QtCore/QObject> +#include <QtCore/QSharedData> + +namespace QtWebEngineCore { +class FindTextHelper; +} + +QT_BEGIN_NAMESPACE + +class QWebEngineFindTextResultPrivate; + +class Q_WEBENGINECORE_EXPORT QWebEngineFindTextResult { + Q_GADGET + Q_PROPERTY(int numberOfMatches READ numberOfMatches CONSTANT FINAL) + Q_PROPERTY(int activeMatchOrdinal READ activeMatchOrdinal CONSTANT FINAL) + +public: + int numberOfMatches() const; + int activeMatchOrdinal() const; + + QWebEngineFindTextResult(); + QWebEngineFindTextResult(const QWebEngineFindTextResult &other); + QWebEngineFindTextResult &operator=(const QWebEngineFindTextResult &other); + ~QWebEngineFindTextResult(); + +private: + QWebEngineFindTextResult(int numberOfMatches, int activeMatchOrdinal); + + QSharedDataPointer<QWebEngineFindTextResultPrivate> d; + + friend class QtWebEngineCore::FindTextHelper; +}; + +QT_END_NAMESPACE + +Q_DECLARE_METATYPE(QWebEngineFindTextResult) + +#endif // QWEBENGINEFINDTEXTRESULT_H diff --git a/src/core/api/qwebengineurlrequestinfo.cpp b/src/core/api/qwebengineurlrequestinfo.cpp index e2101fd02..2aa43a318 100644 --- a/src/core/api/qwebengineurlrequestinfo.cpp +++ b/src/core/api/qwebengineurlrequestinfo.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -185,7 +185,9 @@ QWebEngineUrlRequestInfo::QWebEngineUrlRequestInfo(QWebEngineUrlRequestInfoPriva \value ResourceTypeCspReport A report of Content Security Policy (CSP) violations. CSP reports are in JSON format and they are delivered by HTTP POST requests to specified servers. (Added in Qt 5.7) - \value ResourceTypePluginResource A resource requested by a plugin. (Added in Qt 5.7) + \value ResourceTypePluginResource A resource requested by a plugin. (Added in Qt 5.7) + \value ResourceTypeNavigationPreload A service worker navigation preload + request. (Added in Qt 5.14) \value ResourceTypeUnknown Unknown request type. \note For forward compatibility all values not matched should be treated as unknown, @@ -248,8 +250,10 @@ QUrl QWebEngineUrlRequestInfo::firstPartyUrl() const } /*! - Returns the origin url of the document which initiated - the navigation when a frame navigates another frame. + Returns the origin URL of the document that initiated + the navigation of a frame to another frame. + + \since 5.14 */ QUrl QWebEngineUrlRequestInfo::initiator() const diff --git a/src/core/certificate_error_controller.cpp b/src/core/certificate_error_controller.cpp index a747451df..71465a1af 100644 --- a/src/core/certificate_error_controller.cpp +++ b/src/core/certificate_error_controller.cpp @@ -90,9 +90,10 @@ CertificateErrorControllerPrivate::CertificateErrorControllerPrivate(int cert_er , strictEnforcement(strict_enforcement) , callback(cb) { - if (ssl_info.cert.get()) { - validStart = toQt(ssl_info.cert->valid_start()); - validExpiry = toQt(ssl_info.cert->valid_expiry()); + if (auto cert = ssl_info.cert.get()) { + validStart = toQt(cert->valid_start()); + validExpiry = toQt(cert->valid_expiry()); + chain = toCertificateChain(cert); } } @@ -186,4 +187,9 @@ QString CertificateErrorController::errorString() const return getQStringForMessageId(IDS_CERT_ERROR_UNKNOWN_ERROR_DESCRIPTION); } +QList<QSslCertificate> CertificateErrorController::chain() const +{ + return d->chain; +} + QT_END_NAMESPACE diff --git a/src/core/certificate_error_controller.h b/src/core/certificate_error_controller.h index 5bea61c9b..7f5300dc8 100644 --- a/src/core/certificate_error_controller.h +++ b/src/core/certificate_error_controller.h @@ -55,6 +55,7 @@ #include <QtCore/QDateTime> #include <QtCore/QUrl> +#include <QtNetwork/QSslCertificate> QT_BEGIN_NAMESPACE @@ -95,6 +96,7 @@ public: QString errorString() const; QDateTime validStart() const; QDateTime validExpiry() const; + QList<QSslCertificate> chain() const; void accept(bool); diff --git a/src/core/certificate_error_controller_p.h b/src/core/certificate_error_controller_p.h index abde9a7d5..f3b0c23fa 100644 --- a/src/core/certificate_error_controller_p.h +++ b/src/core/certificate_error_controller_p.h @@ -71,6 +71,7 @@ public: bool overridable; bool strictEnforcement; const base::Callback<void(content::CertificateRequestResultType)> callback; + QList<QSslCertificate> chain; }; QT_END_NAMESPACE diff --git a/src/core/compositor/compositor_resource_fence.cpp b/src/core/compositor/compositor_resource_fence.cpp index 7fc5fbfb2..4179395d6 100644 --- a/src/core/compositor/compositor_resource_fence.cpp +++ b/src/core/compositor/compositor_resource_fence.cpp @@ -146,12 +146,12 @@ void CompositorResourceFence::release() } // static -scoped_refptr<CompositorResourceFence> CompositorResourceFence::create() +scoped_refptr<CompositorResourceFence> CompositorResourceFence::create(std::unique_ptr<gl::GLFence> glFence) { - if (gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) { - std::unique_ptr<gl::GLFence> glFence{gl::GLFence::Create()}; + if (!glFence && gl::GLContext::GetCurrent() && gl::GLFence::IsSupported()) + glFence = gl::GLFence::Create(); + if (glFence) return base::MakeRefCounted<CompositorResourceFence>(glFence->Transfer()); - } return nullptr; } diff --git a/src/core/compositor/compositor_resource_fence.h b/src/core/compositor/compositor_resource_fence.h index 1c2ea3695..196297f78 100644 --- a/src/core/compositor/compositor_resource_fence.h +++ b/src/core/compositor/compositor_resource_fence.h @@ -60,7 +60,7 @@ public: void release(); // May be used only by GPU thread. - static scoped_refptr<CompositorResourceFence> create(); + static scoped_refptr<CompositorResourceFence> create(std::unique_ptr<gl::GLFence> glFence = nullptr); private: gl::TransferableFence m_sync; diff --git a/src/core/compositor/display_consumer.h b/src/core/compositor/display_consumer.h new file mode 100644 index 000000000..d220088ad --- /dev/null +++ b/src/core/compositor/display_consumer.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_CONSUMER_H +#define DISPLAY_CONSUMER_H + +#include "qtwebenginecoreglobal_p.h" + +namespace QtWebEngineCore { + +// Receives composited frames for display. +class DisplayConsumer +{ +public: + // Schedule a call to updatePaintNode soon. + // + // Called on the consumer thread. + virtual void scheduleUpdate() = 0; + +protected: + ~DisplayConsumer() {} +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_CONSUMER_H diff --git a/src/core/compositor/display_frame_sink.cpp b/src/core/compositor/display_frame_sink.cpp new file mode 100644 index 000000000..945600299 --- /dev/null +++ b/src/core/compositor/display_frame_sink.cpp @@ -0,0 +1,140 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_frame_sink.h" + +#include <QMap> + +namespace QtWebEngineCore { + +namespace { + +class DisplayFrameSinkMap +{ +public: + static DisplayFrameSinkMap *instance() + { + static DisplayFrameSinkMap map; + return ↦ + } + + scoped_refptr<DisplayFrameSink> findOrCreate(viz::FrameSinkId frameSinkId) + { + QMutexLocker locker(&m_mutex); + auto it = m_map.find(frameSinkId); + if (it == m_map.end()) + it = m_map.insert(frameSinkId, new DisplayFrameSink(frameSinkId)); + return *it; + } + + void remove(viz::FrameSinkId frameSinkId) + { + QMutexLocker locker(&m_mutex); + m_map.remove(frameSinkId); + } + +private: + mutable QMutex m_mutex; + QMap<viz::FrameSinkId, DisplayFrameSink *> m_map; +}; + +} // namespace + +// static +scoped_refptr<DisplayFrameSink> DisplayFrameSink::findOrCreate(viz::FrameSinkId frameSinkId) +{ + return DisplayFrameSinkMap::instance()->findOrCreate(frameSinkId); +} + +DisplayFrameSink::DisplayFrameSink(viz::FrameSinkId frameSinkId) + : m_frameSinkId(frameSinkId) +{ + DCHECK(m_frameSinkId.is_valid()); +} + +DisplayFrameSink::~DisplayFrameSink() +{ + DisplayFrameSinkMap::instance()->remove(m_frameSinkId); +} + +void DisplayFrameSink::connect(DisplayConsumer *consumer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_consumer == nullptr); + m_consumer = consumer; +} + +void DisplayFrameSink::connect(DisplayProducer *producer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_producer == nullptr); + m_producer = producer; +} + +void DisplayFrameSink::disconnect(DisplayConsumer *consumer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_consumer == consumer); + m_consumer = nullptr; +} + +void DisplayFrameSink::disconnect(DisplayProducer *producer) +{ + QMutexLocker locker(&m_mutex); + DCHECK(m_producer == producer); + m_producer = nullptr; +} + +void DisplayFrameSink::scheduleUpdate() +{ + QMutexLocker locker(&m_mutex); + if (m_consumer) + m_consumer->scheduleUpdate(); +} + +QSGNode *DisplayFrameSink::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +{ + QMutexLocker locker(&m_mutex); + QSGNode *newNode = oldNode; + if (m_producer) + newNode = m_producer->updatePaintNode(oldNode, delegate); + return newNode; +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_frame_sink.h b/src/core/compositor/display_frame_sink.h new file mode 100644 index 000000000..f620dc4f2 --- /dev/null +++ b/src/core/compositor/display_frame_sink.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_FRAME_SINK_H +#define DISPLAY_FRAME_SINK_H + +#include "display_consumer.h" +#include "display_producer.h" + +#include "base/memory/ref_counted.h" +#include "base/memory/scoped_refptr.h" +#include "components/viz/common/surfaces/frame_sink_id.h" + +#include <QMutex> + +namespace QtWebEngineCore { + +// Connects a DisplayConsumer with a DisplayProducer. +class DisplayFrameSink final : public base::RefCountedThreadSafe<DisplayFrameSink> +{ +public: + static scoped_refptr<DisplayFrameSink> findOrCreate(viz::FrameSinkId frameSinkId); + DisplayFrameSink(viz::FrameSinkId frameSinkId); + ~DisplayFrameSink(); + void connect(DisplayConsumer *consumer); + void connect(DisplayProducer *producer); + void disconnect(DisplayConsumer *consumer); + void disconnect(DisplayProducer *producer); + void scheduleUpdate(); + QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate); + +private: + const viz::FrameSinkId m_frameSinkId; + mutable QMutex m_mutex; + DisplayProducer *m_producer = nullptr; + DisplayConsumer *m_consumer = nullptr; +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_FRAME_SINK_H diff --git a/src/core/compositor/display_gl_output_surface.cpp b/src/core/compositor/display_gl_output_surface.cpp new file mode 100644 index 000000000..5a78b8322 --- /dev/null +++ b/src/core/compositor/display_gl_output_surface.cpp @@ -0,0 +1,292 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_gl_output_surface.h" + +#include "chromium_gpu_helper.h" + +#include "base/threading/thread_task_runner_handle.h" +#include "components/viz/service/display/display.h" +#include "components/viz/service/display/output_surface_frame.h" +#include "gpu/command_buffer/client/gles2_implementation.h" +#include "gpu/command_buffer/client/gles2_interface.h" +#include "gpu/command_buffer/service/mailbox_manager.h" +#include "gpu/command_buffer/service/texture_base.h" +#include "gpu/ipc/in_process_command_buffer.h" +#include "ui/gl/color_space_utils.h" + +namespace QtWebEngineCore { + +DisplayGLOutputSurface::DisplayGLOutputSurface( + scoped_refptr<viz::VizProcessContextProvider> contextProvider, + viz::UpdateVSyncParametersCallback callback) + : OutputSurface(contextProvider) + , m_commandBuffer(contextProvider->command_buffer()) + , m_gl(contextProvider->ContextGL()) +{ + capabilities_.uses_default_gl_framebuffer = false; + m_gl->GenFramebuffers(1, &m_fboId); + contextProvider->SetUpdateVSyncParametersCallback(std::move(callback)); +} + +DisplayGLOutputSurface::~DisplayGLOutputSurface() +{ + m_gl->DeleteFramebuffers(1, &m_fboId); + if (m_sink) + m_sink->disconnect(this); +} + +// Called from viz::Display::Initialize. +void DisplayGLOutputSurface::BindToClient(viz::OutputSurfaceClient *client) +{ + m_display = static_cast<viz::Display *>(client); + m_sink = DisplayFrameSink::findOrCreate(m_display->frame_sink_id()); + m_sink->connect(this); +} + +// Triggered by ui::Compositor::SetVisible(true). +void DisplayGLOutputSurface::EnsureBackbuffer() +{ +} + +// Triggered by ui::Compositor::SetVisible(false). Framebuffer must be cleared. +void DisplayGLOutputSurface::DiscardBackbuffer() +{ + NOTIMPLEMENTED(); + // m_gl->DiscardBackbufferCHROMIUM(); +} + +// Called from viz::DirectRenderer::DrawFrame before rendering starts, but only +// if the parameters differ from the previous Reshape call. +// +// Parameters: +// +// - sizeInPixels comes from ui::Compositor::SetScaleAndSize via +// viz::HostContextFactoryPrivate::ResizeDisplay. +// +// - devicePixelRatio comes from viz::CompositorFrame::device_scale_factor() +// via viz::RootCompositorFrameSinkImpl::SubmitCompositorFrame and +// viz::Display::SetLocalSurfaceId. +// +// - colorSpace and hasAlpha correspond to the color_space and +// has_transparent_background properties of the root viz::RenderPass. +// +// - useStencil should create a stencil buffer, but this is only needed for +// overdraw feedback (--show-overdraw-feedback), so it's safe to ignore. +// Accordingly, capabilities_.supports_stencil should be set to false. +// +void DisplayGLOutputSurface::Reshape(const gfx::Size &sizeInPixels, + float devicePixelRatio, + const gfx::ColorSpace &colorSpace, + bool hasAlpha, + bool /*useStencil*/) +{ + m_currentShape = Shape{sizeInPixels, devicePixelRatio, colorSpace, hasAlpha}; + m_gl->ResizeCHROMIUM(sizeInPixels.width(), sizeInPixels.height(), devicePixelRatio, + gl::ColorSpaceUtils::GetGLColorSpace(colorSpace), hasAlpha); +} + +std::unique_ptr<DisplayGLOutputSurface::Buffer> DisplayGLOutputSurface::makeBuffer(const Shape &shape) +{ + std::unique_ptr<Buffer> buffer = std::make_unique<Buffer>(this); + buffer->shape = shape; + m_gl->GenTextures(1, &buffer->clientId); + m_gl->BindTexture(GL_TEXTURE_2D, buffer->clientId); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + m_gl->TexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + uint32_t width = shape.sizeInPixels.width(); + uint32_t height = shape.sizeInPixels.height(); + uint32_t format = shape.hasAlpha ? GL_RGBA : GL_RGB; + m_gl->TexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, nullptr); + return buffer; +} + +void DisplayGLOutputSurface::deleteBufferResources(Buffer *buffer) +{ + m_gl->DeleteTextures(1, &buffer->clientId); +} + +// Called by viz::GLRenderer during rendering whenever it switches to the root +// render pass. +void DisplayGLOutputSurface::BindFramebuffer() +{ + if (!m_backBuffer || m_backBuffer->shape != m_currentShape) + m_backBuffer = makeBuffer(m_currentShape); + + m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fboId); + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, m_backBuffer->clientId, 0); +} + +// Called from viz::Display::DrawAndSwap after rendering. +// +// Parameters: +// +// - frame.size is the same as the size given to Reshape. +// +// - frame.sub_buffer_rect and frame.content_bounds are never used since these +// are only enabled if gl::GLSurface::SupportsPostSubBuffer() or +// gl::GLSurface::SupportsSwapBuffersWithBounds() are true, respectively, +// but this not the case for any offscreen gl::GLSurface. +// +// - frame.latency_info is viz::CompositorFrame::metadata.latency_info. +void DisplayGLOutputSurface::SwapBuffers(viz::OutputSurfaceFrame frame) +{ + DCHECK(frame.size == m_currentShape.sizeInPixels); + DCHECK(!frame.sub_buffer_rect.has_value()); + DCHECK(frame.content_bounds.empty()); + DCHECK(m_backBuffer); + + m_gl->BindFramebuffer(GL_FRAMEBUFFER, m_fboId); + m_gl->FramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0); + gpu::SyncToken syncToken; + m_gl->GenSyncTokenCHROMIUM(syncToken.GetData()); + + unsigned int clientId = m_backBuffer->clientId; + + // Now some thread-hopping: + // + // - We start here on the viz thread (client side of command buffer). + // + // - Then we'll jump to the gpu thread (service side of command buffer) to + // get the real OpenGL texture id. + // + // - Then we'll get a call from the Qt Quick Scene Graph thread (could be + // a separate thread or the main thread). + // + // - Finally we'll return to the viz thread to acknowledge the swap. + + { + QMutexLocker locker(&m_mutex); + m_taskRunner = base::ThreadTaskRunnerHandle::Get(); + m_middleBuffer = std::move(m_backBuffer); + m_middleBuffer->serviceId = 0; + } + + m_commandBuffer->GetTextureQt( + clientId, + base::BindOnce(&DisplayGLOutputSurface::swapBuffersOnGpuThread, base::Unretained(this)), + std::vector<gpu::SyncToken>{syncToken}); +} + +void DisplayGLOutputSurface::swapBuffersOnGpuThread(unsigned int id, std::unique_ptr<gl::GLFence> fence) +{ + { + QMutexLocker locker(&m_mutex); + m_middleBuffer->serviceId = id; + m_middleBuffer->fence = CompositorResourceFence::create(std::move(fence)); + } + + m_sink->scheduleUpdate(); +} + +void DisplayGLOutputSurface::swapBuffersOnVizThread() +{ + { + QMutexLocker locker(&m_mutex); + m_backBuffer = std::move(m_middleBuffer); + } + + m_display->DidReceiveSwapBuffersAck(); + m_display->DidReceivePresentationFeedback( + gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(), + gfx::PresentationFeedback::Flags::kVSync)); +} + +void DisplayGLOutputSurface::SetDrawRectangle(const gfx::Rect &) +{ +} + +// Returning nullptr here effectively disables viz::OverlayProcessor. +viz::OverlayCandidateValidator *DisplayGLOutputSurface::GetOverlayCandidateValidator() const +{ + return nullptr; +} + +// Returning true here will cause viz::GLRenderer to try to render the output +// surface as an overlay plane (see viz::DirectRenderer::DrawFrame and +// viz::GLRenderer::ScheduleOverlays). +bool DisplayGLOutputSurface::IsDisplayedAsOverlayPlane() const +{ + return false; +} + +// Only used if IsDisplayedAsOverlayPlane was true (called from +// viz::GLRenderer::ScheduleOverlays). +unsigned DisplayGLOutputSurface::GetOverlayTextureId() const +{ + return 0; +} + +// Only used if IsDisplayedAsOverlayPlane was true (called from +// viz::DirectRender::DrawFrame). +gfx::BufferFormat DisplayGLOutputSurface::GetOverlayBufferFormat() const +{ + return gfx::BufferFormat(); +} + +// Called by viz::GLRenderer but always false in all implementations except for +// android_webview::ParentOutputSurface. +bool DisplayGLOutputSurface::HasExternalStencilTest() const +{ + return false; +} + +// Only called if HasExternalStencilTest was true. Dead code? +void DisplayGLOutputSurface::ApplyExternalStencil() +{ + NOTREACHED(); +} + +// Called from GLRenderer::GetFramebufferCopyTextureFormat when using +// glCopyTexSubImage2D on our framebuffer. +uint32_t DisplayGLOutputSurface::GetFramebufferCopyTextureFormat() +{ + return GL_RGBA; +} + +// Called from viz::DirectRenderer::DrawFrame, only used for overlays. +unsigned DisplayGLOutputSurface::UpdateGpuFence() +{ + NOTREACHED(); + return 0; +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_gl_output_surface.h b/src/core/compositor/display_gl_output_surface.h new file mode 100644 index 000000000..c42a6630a --- /dev/null +++ b/src/core/compositor/display_gl_output_surface.h @@ -0,0 +1,148 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_GL_OUTPUT_SURFACE_H +#define DISPLAY_GL_OUTPUT_SURFACE_H + +#include "compositor_resource_fence.h" +#include "display_frame_sink.h" + +#include "components/viz/common/display/update_vsync_parameters_callback.h" +#include "components/viz/service/display/output_surface.h" +#include "components/viz/service/display_embedder/viz_process_context_provider.h" +#include "gpu/command_buffer/common/mailbox.h" +#include "gpu/command_buffer/common/sync_token.h" + +namespace viz { +class Display; +class SyntheticBeginFrameSource; +} // namespace viz + +namespace QtWebEngineCore { + +// NOTE: Some methods are defined in display_gl_output_surface_qsg.cpp due +// to conflicts between Qt & Chromium OpenGL APIs. +class DisplayGLOutputSurface final : public viz::OutputSurface, public DisplayProducer +{ +public: + DisplayGLOutputSurface( + scoped_refptr<viz::VizProcessContextProvider> contextProvider, + viz::UpdateVSyncParametersCallback callback); + ~DisplayGLOutputSurface() override; + + // Overridden from viz::OutputSurface. + void BindToClient(viz::OutputSurfaceClient *client) override; + void EnsureBackbuffer() override; + void DiscardBackbuffer() override; + void BindFramebuffer() override; + void SetDrawRectangle(const gfx::Rect &drawRect) override; + viz::OverlayCandidateValidator *GetOverlayCandidateValidator() const override; + bool IsDisplayedAsOverlayPlane() const override; + unsigned GetOverlayTextureId() const override; + gfx::BufferFormat GetOverlayBufferFormat() const override; + void Reshape(const gfx::Size &size, + float devicePixelRatio, + const gfx::ColorSpace &colorSpace, + bool hasAlpha, + bool useStencil) override; + bool HasExternalStencilTest() const override; + void ApplyExternalStencil() override; + uint32_t GetFramebufferCopyTextureFormat() override; + void SwapBuffers(viz::OutputSurfaceFrame frame) override; + unsigned UpdateGpuFence() override; + + // Overridden from DisplayProducer. + QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; + +private: + struct Shape + { + gfx::Size sizeInPixels; + float devicePixelRatio; + gfx::ColorSpace colorSpace; + bool hasAlpha; + + bool operator==(const Shape &that) const + { + return (sizeInPixels == that.sizeInPixels && + devicePixelRatio == that.devicePixelRatio && + colorSpace == that.colorSpace && + hasAlpha == that.hasAlpha); + } + bool operator!=(const Shape &that) const { return !(*this == that); } + }; + + struct Buffer + { + DisplayGLOutputSurface *parent; + Shape shape; + uint32_t clientId = 0; + uint32_t serviceId = 0; + scoped_refptr<CompositorResourceFence> fence; + + Buffer(DisplayGLOutputSurface *parent) : parent(parent) {} + ~Buffer() { parent->deleteBufferResources(this); } + }; + + class Texture; + + void swapBuffersOnGpuThread(unsigned int id, std::unique_ptr<gl::GLFence> fence); + void swapBuffersOnVizThread(); + + std::unique_ptr<Buffer> makeBuffer(const Shape &shape); + void deleteBufferResources(Buffer *buffer); + void attachBuffer(); + void detachBuffer(); + + gpu::InProcessCommandBuffer *const m_commandBuffer; + gpu::gles2::GLES2Interface *const m_gl; + mutable QMutex m_mutex; + uint32_t m_fboId = 0; + viz::Display *m_display = nullptr; + scoped_refptr<DisplayFrameSink> m_sink; + Shape m_currentShape; + std::unique_ptr<Buffer> m_backBuffer; + std::unique_ptr<Buffer> m_middleBuffer; + std::unique_ptr<Buffer> m_frontBuffer; + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_GL_OUTPUT_SURFACE_H diff --git a/src/core/compositor/display_gl_output_surface_qsg.cpp b/src/core/compositor/display_gl_output_surface_qsg.cpp new file mode 100644 index 000000000..2f7b3de84 --- /dev/null +++ b/src/core/compositor/display_gl_output_surface_qsg.cpp @@ -0,0 +1,121 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_gl_output_surface.h" + +#include "compositor_resource_fence.h" +#include "render_widget_host_view_qt_delegate.h" +#include "type_conversion.h" + +#include <QOpenGLFunctions> +#include <QSGImageNode> +#include <QSGTexture> + +namespace QtWebEngineCore { + +class DisplayGLOutputSurface::Texture final : public QSGTexture +{ +public: + Texture(uint32_t id, QSize sizeInPixels, bool hasAlphaChannel, scoped_refptr<CompositorResourceFence> fence) + : m_id(id) + , m_sizeInPixels(sizeInPixels) + , m_hasAlphaChannel(hasAlphaChannel) + , m_fence(std::move(fence)) + { + } + + // QSGTexture: + int textureId() const override { return m_id; } + QSize textureSize() const override { return m_sizeInPixels; } + bool hasAlphaChannel() const override { return m_hasAlphaChannel; } + bool hasMipmaps() const override { return false; } + void bind() override + { + if (m_fence) { + m_fence->wait(); + m_fence.reset(); + } + + QOpenGLContext *context = QOpenGLContext::currentContext(); + QOpenGLFunctions *funcs = context->functions(); + funcs->glBindTexture(GL_TEXTURE_2D, m_id); + } + +private: + uint32_t m_id; + QSize m_sizeInPixels; + bool m_hasAlphaChannel; + scoped_refptr<CompositorResourceFence> m_fence; +}; + +QSGNode *DisplayGLOutputSurface::updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +{ + { + QMutexLocker locker(&m_mutex); + if (m_middleBuffer && m_middleBuffer->serviceId) { + std::swap(m_middleBuffer, m_frontBuffer); + m_taskRunner->PostTask( + FROM_HERE, + base::BindOnce(&DisplayGLOutputSurface::swapBuffersOnVizThread, base::Unretained(this))); + m_taskRunner.reset(); + } + } + + if (!m_frontBuffer) + return oldNode; + + auto node = static_cast<QSGImageNode *>(oldNode); + if (!node) + node = delegate->createImageNode(); + + QSize sizeInPixels = toQt(m_frontBuffer->shape.sizeInPixels); + QSizeF sizeInDips = QSizeF(sizeInPixels) / m_frontBuffer->shape.devicePixelRatio; + QRectF rectInDips(QPointF(0, 0), sizeInDips); + node->setRect(rectInDips); + node->setOwnsTexture(true); + node->setTexture(new Texture(m_frontBuffer->serviceId, + sizeInPixels, + m_frontBuffer->shape.hasAlpha, + m_frontBuffer->fence)); + node->setTextureCoordinatesTransform(QSGImageNode::MirrorVertically); + + return node; +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_overrides.cpp b/src/core/compositor/display_overrides.cpp new file mode 100644 index 000000000..4547bb04b --- /dev/null +++ b/src/core/compositor/display_overrides.cpp @@ -0,0 +1,80 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_gl_output_surface.h" +#include "display_software_output_surface.h" + +#include "components/viz/service/display_embedder/gpu_display_provider.h" +#include "gpu/ipc/in_process_command_buffer.h" + +std::unique_ptr<viz::OutputSurface> +viz::GpuDisplayProvider::CreateGLOutputSurface( + scoped_refptr<VizProcessContextProvider> context_provider, + UpdateVSyncParametersCallback update_vsync_callback) +{ + return std::make_unique<QtWebEngineCore::DisplayGLOutputSurface>( + std::move(context_provider), std::move(update_vsync_callback)); +} + +std::unique_ptr<viz::OutputSurface> +viz::GpuDisplayProvider::CreateSoftwareOutputSurface( + UpdateVSyncParametersCallback update_vsync_callback) +{ + return std::make_unique<QtWebEngineCore::DisplaySoftwareOutputSurface>(std::move(update_vsync_callback)); +} + +void gpu::InProcessCommandBuffer::GetTextureQt( + unsigned int client_id, + GetTextureCallback callback, + const std::vector<SyncToken>& sync_token_fences) +{ + ScheduleGpuTask(base::BindOnce(&InProcessCommandBuffer::GetTextureQtOnGpuThread, + gpu_thread_weak_ptr_factory_.GetWeakPtr(), + client_id, + std::move(callback)), + sync_token_fences); +} + +void gpu::InProcessCommandBuffer::GetTextureQtOnGpuThread( + unsigned int client_id, GetTextureCallback callback) +{ + MakeCurrent(); + gpu::TextureBase *texture = decoder_->GetTextureBase(client_id); + std::move(callback).Run(texture ? texture->service_id() : 0, gl::GLFence::Create()); +} diff --git a/src/core/compositor/display_producer.h b/src/core/compositor/display_producer.h new file mode 100644 index 000000000..5de09d2d2 --- /dev/null +++ b/src/core/compositor/display_producer.h @@ -0,0 +1,69 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_PRODUCER_H +#define DISPLAY_PRODUCER_H + +#include "qtwebenginecoreglobal_p.h" + +QT_BEGIN_NAMESPACE +class QSGNode; +QT_END_NAMESPACE + +namespace QtWebEngineCore { +class RenderWidgetHostViewQtDelegate; + +// Produces composited frames for display. +class DisplayProducer +{ +public: + // Generate scene graph nodes for the current frame. + // + // If this is a scheduled update (that is, scheduleUpdate was called + // earlier), then updatePaintNode will generate nodes for a new frame. + // Otherwise, it will just regenerate nodes for the old frame. + virtual QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) = 0; + +protected: + ~DisplayProducer() {} +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_PRODUCER_H diff --git a/src/core/compositor/display_software_output_surface.cpp b/src/core/compositor/display_software_output_surface.cpp new file mode 100644 index 000000000..13f8e8f38 --- /dev/null +++ b/src/core/compositor/display_software_output_surface.cpp @@ -0,0 +1,173 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "display_software_output_surface.h" + +#include "display_frame_sink.h" +#include "render_widget_host_view_qt_delegate.h" +#include "type_conversion.h" + +#include "base/threading/thread_task_runner_handle.h" +#include "components/viz/service/display/display.h" +#include "components/viz/service/display/output_surface_frame.h" + +#include <QMutex> +#include <QPainter> +#include <QSGImageNode> + +namespace QtWebEngineCore { + +class DisplaySoftwareOutputSurface::Device final : public viz::SoftwareOutputDevice, public DisplayProducer +{ +public: + ~Device(); + + // Called from DisplaySoftwareOutputSurface. + void bind(viz::FrameSinkId frameSinkId); + + // Overridden from viz::SoftwareOutputDevice. + void Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) override; + void OnSwapBuffers(base::OnceClosure swapCompletionCallback) override; + + // Overridden from DisplayProducer. + QSGNode *updatePaintNode(QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) override; + +private: + mutable QMutex m_mutex; + scoped_refptr<DisplayFrameSink> m_sink; + float m_devicePixelRatio = 1.0; + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; + base::OnceClosure m_swapCompletionCallback; + QImage m_image; + float m_imageDevicePixelRatio = 1.0; +}; + +DisplaySoftwareOutputSurface::Device::~Device() +{ + if (m_sink) + m_sink->disconnect(this); +} + +void DisplaySoftwareOutputSurface::Device::bind(viz::FrameSinkId frameSinkId) +{ + m_sink = DisplayFrameSink::findOrCreate(frameSinkId); + m_sink->connect(this); +} + +void DisplaySoftwareOutputSurface::Device::Resize(const gfx::Size &sizeInPixels, float devicePixelRatio) +{ + if (viewport_pixel_size_ == sizeInPixels && m_devicePixelRatio == devicePixelRatio) + return; + m_devicePixelRatio = devicePixelRatio; + viewport_pixel_size_ = sizeInPixels; + surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(sizeInPixels.width(), sizeInPixels.height())); +} + +void DisplaySoftwareOutputSurface::Device::OnSwapBuffers(base::OnceClosure swapCompletionCallback) +{ + QMutexLocker locker(&m_mutex); + m_taskRunner = base::ThreadTaskRunnerHandle::Get(); + m_swapCompletionCallback = std::move(swapCompletionCallback); + m_sink->scheduleUpdate(); +} + +inline QImage::Format imageFormat(SkColorType colorType) +{ + switch (colorType) { + case kBGRA_8888_SkColorType: + return QImage::Format_ARGB32_Premultiplied; + case kRGBA_8888_SkColorType: + return QImage::Format_RGBA8888_Premultiplied; + default: + Q_UNREACHABLE(); + return QImage::Format_ARGB32_Premultiplied; + } +} + +QSGNode *DisplaySoftwareOutputSurface::Device::updatePaintNode( + QSGNode *oldNode, RenderWidgetHostViewQtDelegate *delegate) +{ + QMutexLocker locker(&m_mutex); + + // Delete old node to make sure refcount of m_image is at most 1. + delete oldNode; + QSGImageNode *node = delegate->createImageNode(); + + if (m_swapCompletionCallback) { + SkPixmap skPixmap; + surface_->peekPixels(&skPixmap); + QImage image(reinterpret_cast<const uchar *>(skPixmap.addr()), + viewport_pixel_size_.width(), viewport_pixel_size_.height(), + skPixmap.rowBytes(), imageFormat(skPixmap.colorType())); + if (m_image.size() == image.size()) { + QRect damageRect = toQt(damage_rect_); + QPainter(&m_image).drawImage(damageRect, image, damageRect); + } else { + m_image = image; + m_image.detach(); + } + m_imageDevicePixelRatio = m_devicePixelRatio; + m_taskRunner->PostTask(FROM_HERE, std::move(m_swapCompletionCallback)); + m_taskRunner.reset(); + } + + QSizeF sizeInDips = QSizeF(m_image.size()) / m_imageDevicePixelRatio; + node->setRect(QRectF(QPointF(0, 0), sizeInDips)); + node->setOwnsTexture(true); + node->setTexture(delegate->createTextureFromImage(m_image)); + + return node; +} + +DisplaySoftwareOutputSurface::DisplaySoftwareOutputSurface(viz::UpdateVSyncParametersCallback callback) + : SoftwareOutputSurface(std::make_unique<Device>(), std::move(callback)) +{} + +DisplaySoftwareOutputSurface::~DisplaySoftwareOutputSurface() {} + +// Called from viz::Display::Initialize. +void DisplaySoftwareOutputSurface::BindToClient(viz::OutputSurfaceClient *client) +{ + auto display = static_cast<viz::Display *>(client); + auto device = static_cast<Device *>(software_device()); + device->bind(display->frame_sink_id()); + SoftwareOutputSurface::BindToClient(client); +} + +} // namespace QtWebEngineCore diff --git a/src/core/compositor/display_software_output_surface.h b/src/core/compositor/display_software_output_surface.h new file mode 100644 index 000000000..6707c74dc --- /dev/null +++ b/src/core/compositor/display_software_output_surface.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DISPLAY_SOFTWARE_OUTPUT_SURFACE_H +#define DISPLAY_SOFTWARE_OUTPUT_SURFACE_H + +#include "components/viz/service/display_embedder/software_output_surface.h" + +namespace QtWebEngineCore { + +class DisplaySoftwareOutputSurface final : public viz::SoftwareOutputSurface +{ +public: + DisplaySoftwareOutputSurface(viz::UpdateVSyncParametersCallback callback); + ~DisplaySoftwareOutputSurface() override; + + // Overridden from viz::SoftwareOutputSurface. + void BindToClient(viz::OutputSurfaceClient *client) override; + +private: + class Device; +}; + +} // namespace QtWebEngineCore + +#endif // !DISPLAY_SOFTWARE_OUTPUT_SURFACE_H diff --git a/src/core/configure.json b/src/core/configure.json index 66e39ddc2..cf01b9914 100644 --- a/src/core/configure.json +++ b/src/core/configure.json @@ -1,11 +1,12 @@ { "module": "webenginecore", "depends": [ + "buildtools-private", "core-private", "gui-private", "printsupport" ], - "condition": "module.gui", + "condition": "features.webengine-core", "testDir": "../../config.tests", "commandline": { "options": { @@ -28,8 +29,6 @@ "webengine-v8-snapshot": "boolean", "webengine-webchannel": "boolean", "webengine-kerberos": "boolean", - "webengine-widgets": "boolean", - "webengine-qml": "boolean", "alsa": { "type": "boolean", "name": "webengine-alsa" }, "pulseaudio": { "type": "boolean", "name": "webengine-pulseaudio" }, "ffmpeg": { "type": "enum", "name": "webengine-system-ffmpeg", "values": { "system": "yes", "qt": "no" } }, @@ -45,94 +44,17 @@ }, "libraries": { - "webengine-dbus": { - "label": "d-bus", - "sources": [ - { "type": "pkgConfig", "args": "dbus-1" } - ] - }, - "webengine-fontconfig": { - "label": "fontconfig", - "sources": [ - { "type": "pkgConfig", "args": "fontconfig" } - ] - }, - "webengine-libdrm": { - "label": "libdrm", - "sources": [ - { "type": "pkgConfig", "args": "libdrm" } - ] - }, - "webengine-xcomposite": { - "label": "xcomposite", - "sources": [ - { "type": "pkgConfig", "args": "xcomposite" } - ] - }, - "webengine-xcursor": { - "label": "xcursor", - "sources": [ - { "type": "pkgConfig", "args": "xcursor" } - ] - }, - "webengine-xi": { - "label": "xi", - "sources": [ - { "type": "pkgConfig", "args": "xi" } - ] - }, - "webengine-xtst": { - "label": "xtst", - "sources": [ - { "type": "pkgConfig", "args": "xtst" } - ] - }, - "webengine-harfbuzz": { - "label": "harfbuzz >= 2.2.0", - "sources": [ - { "type": "pkgConfig", "args": "harfbuzz >= 2.2.0" } - ] - }, - "webengine-glib": { - "label": "glib-2.0 >= 2.32.0", - "sources": [ - { "type": "pkgConfig", "args": "glib-2.0 >= 2.32.0" } - ] - }, - "webengine-zlib": { - "label": "zlib", - "sources": [ - { "type": "pkgConfig", "args": "zlib" } - ] - }, - "webengine-minizip": { - "label": "minizip", - "sources": [ - { "type": "pkgConfig", "args": "minizip" } - ] - }, - "webengine-libevent": { - "label": "libevent", - "sources": [ - { "type": "pkgConfig", "args": "libevent" } - ] - }, - "webengine-libxml2": { - "label": "libxml2 and libxslt", - "sources": [ - { "type": "pkgConfig", "args": "libxml-2.0 libxslt" } - ] - }, - "webengine-jsoncpp": { - "label": "jsoncpp", - "sources": [ - { "type": "pkgConfig", "args": "jsoncpp" } - ] - }, - "webengine-protobuf": { - "label": "protobuf", - "sources": [ - { "type": "pkgConfig", "args": "protobuf" } + "webengine-alsa": { + "label": "alsa", + "test": { + "tail": [ + "#if SND_LIB_VERSION < 0x1000a // 1.0.10", + "#error Alsa version found too old, require >= 1.0.10", + "#endif" + ] + }, + "headers" : ["alsa/asoundlib.h"], + "sources" : [{ "type": "pkgConfig", "args": "alsa" } ] }, "webengine-poppler-cpp": { @@ -141,195 +63,33 @@ { "type": "pkgConfig", "args": "poppler-cpp" } ] }, - "pulseaudio": { + "webengine-pulseaudio": { "label": "pulseaudio >= 0.9.10", "sources": [ { "type": "pkgConfig", "args": "libpulse >= 0.9.10 libpulse-mainloop-glib" } ] - }, - "webengine-icu": { - "label": "icu >= 63", - "sources": [ - { "type": "pkgConfig", "args": "icu-uc >= 63 icu-i18n >= 63" } - ] - }, - "webengine-ffmpeg": { - "label": "libavcodec libavformat libavutil", - "sources": [ - { "type": "pkgConfig", "args": "libavcodec libavformat libavutil" } - ] - }, - "webengine-opus": { - "label": "opus", - "sources": [ - { "type": "pkgConfig", "args": "opus" } - ] - }, - "webengine-webp": { - "label": "libwebp, libwebpmux and libwebpdemux", - "sources": [ - { "type": "pkgConfig", "args": "libwebp libwebpmux libwebpdemux" } - ] - }, - "webengine-nss": { - "label": "nss >= 3.26", - "sources": [ - { "type": "pkgConfig", "args": "nss >= 3.26" } - ] - }, - "webengine-png": { - "label": "libpng >= 1.6.0", - "sources": [ - { "type": "pkgConfig", "args": "libpng >= 1.6.0" } - ] - }, - "webengine-jpeglib": { - "label": "compatible jpeglib", - "type": "compile", - "test": { - "head": [ - "#include <cstdio>", - "#include <cstring>", - "extern \"C\" {", - " #include <jpeglib.h>", - "}" - ], - "main": [ - "JDIMENSION dummy;", - "jpeg_crop_scanline(nullptr, &dummy, &dummy);", - "jpeg_skip_scanlines(nullptr, dummy);" - ] - }, - "sources": [ - { "type": "pkgConfig", "args": "libjpeg" }, - "-ljpeg" - ] - }, - "webengine-lcms2": { - "label": "lcms2", - "sources": [ - { "type": "pkgConfig", "args": "lcms2" } - ] - }, - "webengine-freetype": { - "label": "freetype >= 2.4.2", - "test": { - "head": [ - "#include <ft2build.h>", - "#include FT_FREETYPE_H", - "#if ((FREETYPE_MAJOR*10000 + FREETYPE_MINOR*100 + FREETYPE_PATCH) < 20402)", - "# error This version of freetype is too old.", - "#endif" - ], - "main": [ - "FT_Face ft_face = 0;", - "FT_Reference_Face(ft_face);" - ] - }, - "sources": [ - { "type": "pkgConfig", "args": "freetype2" } - ] - }, - "webengine-x11" : { - "label" : "x11", - "sources": [ - { "type": "pkgConfig", "args": "x11" } - ] } }, "tests" : { - "webengine-alsa": { - "label": "alsa", - "test": "alsa", - "type": "compile" - }, "webengine-host-compiler": { "label": "host compiler", "test": "hostcompiler", "host": "true", "type": "compile" }, - "webengine-khr": { - "label": "khr", - "test": "khr", - "type": "compile" - }, - "webengine-libvpx": { - "label": "libvpx", - "test": "libvpx", - "type": "compile" - }, - "webengine-snappy": { - "label": "snappy", - "test": "snappy", - "type": "compile" - }, - "webengine-winversion": { - "label": "winversion", - "test": "winversion", - "type": "compile" - }, - "webengine-protoc": { - "label": "protoc", - "type": "detectProtoc" - }, - "webengine-python2": { - "label": "python2", - "type": "detectPython2", - "log": "location" - }, "webengine-host-pkg-config": { "label": "host pkg-config", "type": "detectHostPkgConfig", "log": "path" }, - "webengine-gperf": { - "label": "gperf", - "type": "detectGperf" - }, - "webengine-bison": { - "label": "bison", - "type": "detectBison" - }, - "webengine-flex": { - "label": "flex", - "type": "detectFlex" - }, - "webengine-ninja": { - "label": "system ninja", - "type": "detectNinja" - }, - "webengine-gn": { - "label": "system gn", - "type": "detectGn" - }, "webengine-embedded-build": { - "label": "embedded", - "type": "embedded" - }, - "webengine-re2": { - "label": "re2", - "test": "re2", - "type": "compile" - }, - "webengine-glibc": { - "label": "glibc > 2.26", - "type": "compile", - "test": "glibc" - }, - "webengine-libxml2-compatible": { - "label" : "compatible system libxml2", - "test" : "xml2", - "type": "compile" + "label": "embedded build", + "type": "detectEmbedded" }, "webengine-sanitizer": { "label" : "sanitizer support", "type": "isSanitizerSupported" }, - "webengine-win-compiler64": { - "label": "64bit compiler", - "type": "isWindowsHostCompiler64" - }, "webengine-arm-thumb" : { "label": "thumb instruction set", "type": "hasThumbFlag" @@ -344,119 +104,7 @@ "flag": "-z,noexecstack" } }, - "features": { - "webengine-system-fontconfig": { - "label": "fontconfig", - "condition": "libs.webengine-fontconfig", - "output": [ "privateFeature" ] - }, - "webengine-system-dbus": { - "label": "dbus", - "condition": "libs.webengine-dbus", - "output": [ "privateFeature" ] - }, - "webengine-system-libdrm": { - "label": "libdrm", - "condition": "libs.webengine-libdrm", - "output": [ "privateFeature" ] - }, - "webengine-system-xcomposite": { - "label": "xcomposite", - "condition": "libs.webengine-xcomposite", - "output": [ "privateFeature" ] - }, - "webengine-system-xcursor": { - "label": "xcursor", - "condition": "libs.webengine-xcursor", - "output": [ "privateFeature" ] - }, - "webengine-system-xi": { - "label": "xi", - "condition": "libs.webengine-xi", - "output": [ "privateFeature" ] - }, - "webengine-system-xtst": { - "label": "xtst", - "condition": "libs.webengine-xtst", - "output": [ "privateFeature" ] - }, - "webengine-system-harfbuzz": { - "label": "harfbuzz", - "condition": "config.unix && features.system-harfbuzz && libs.webengine-harfbuzz", - "output": [ "privateFeature" ] - }, - "webengine-system-glib" : { - "label": "glib", - "condition": "config.unix && libs.webengine-glib", - "output": [ "privateFeature" ] - }, - "webengine-system-minizip" : { - "label": "minizip", - "condition": "config.unix && libs.webengine-minizip", - "output": [ "privateFeature" ] - }, - "webengine-system-zlib" : { - "label": "zlib", - "condition": "config.unix && features.system-zlib && libs.webengine-zlib", - "output": [ "privateFeature" ] - }, - "webengine-system-libevent" : { - "label": "libevent", - "condition": "config.unix && libs.webengine-libevent", - "output": [ "privateFeature" ] - }, - "webengine-system-jsoncpp" : { - "label": "jsoncpp", - "condition": "config.unix && libs.webengine-jsoncpp", - "output": [ "privateFeature" ] - }, - "webengine-system-protobuf" : { - "label": "protobuf", - "condition": "config.unix && libs.webengine-protobuf && tests.webengine-protoc", - "output": [ "privateFeature" ] - }, - "webengine-system-png" : { - "label": "png", - "condition": "config.unix && features.system-png && libs.webengine-png", - "output": [ "privateFeature" ] - }, - "webengine-system-jpeg" : { - "label": "JPEG", - "condition": "config.unix && features.system-jpeg && libs.webengine-jpeglib", - "output": [ "privateFeature" ] - }, - "webengine-python2": { - "label": "python2", - "condition": "tests.webengine-python2", - "output": [ - "privateFeature", - { "type": "varAssign", "name": "QMAKE_PYTHON2", "value": "tests.webengine-python2.location" } - ] - }, - "webengine-host-pkg-config": { - "label": "host-pkg-config", - "condition": "config.unix && tests.webengine-host-pkg-config", - "output": [ - "privateFeature", - { "type": "varAssign", "name": "QMAKE_PKG_CONFIG_HOST", "value": "tests.webengine-host-pkg-config.path" } - ] - }, - "webengine-gperf": { - "label": "gperf", - "condition": "tests.webengine-gperf", - "output": [ "privateFeature" ] - }, - "webengine-bison": { - "label": "bison", - "condition": "tests.webengine-bison", - "output": [ "privateFeature" ] - }, - "webengine-flex": { - "label": "flex", - "condition": "tests.webengine-flex", - "output": [ "privateFeature" ] - }, "webengine-embedded-build": { "label": "Embedded build", "purpose": "Enables the embedded build configuration.", @@ -465,9 +113,15 @@ "autoDetect": "tests.webengine-embedded-build", "output": [ "privateFeature" ] }, + "webengine-developer-build": { + "label": "Developer build", + "purpose": "Enables the developer build configuration.", + "autoDetect": "features.private_tests", + "output": [ "privateFeature" ] + }, "webengine-alsa": { "label": "Use ALSA", - "condition": "config.unix && tests.webengine-alsa", + "condition": "config.unix && libs.webengine-alsa", "output": [ "privateFeature" ] }, "webengine-v8-snapshot": { @@ -481,26 +135,6 @@ "condition": "!config.unix || !features.cross_compile || arch.arm64 || tests.webengine-host-compiler", "output": [ "privateFeature" ] }, - "webengine-system-khr" : { - "label": "khr", - "condition": "config.unix && tests.webengine-khr", - "output": [ "privateFeature" ] - }, - "webengine-system-libvpx" : { - "label": "libvpx", - "condition": "config.unix && tests.webengine-libvpx", - "output": [ "privateFeature" ] - }, - "webengine-system-snappy" : { - "label": "snappy", - "condition": "config.unix && tests.webengine-snappy", - "output": [ "privateFeature" ] - }, - "webengine-winversion" : { - "label": "winversion", - "condition": "config.win32 && tests.webengine-winversion", - "output": [ "privateFeature" ] - }, "webengine-geolocation": { "label": "Geolocation", "condition": "module.positioning", @@ -509,7 +143,7 @@ "webengine-pulseaudio": { "label": "Use PulseAudio", "autoDetect": "config.unix", - "condition": "libs.pulseaudio", + "condition": "libs.webengine-pulseaudio", "output": [ "privateFeature" ] }, "webengine-pepper-plugins": { @@ -577,80 +211,6 @@ "autoDetect": "!features.webengine-embedded-build", "output": [ "privateFeature" ] }, - "webengine-system-nss": { - "label": "nss", - "condition": "config.unix && !config.darwin && libs.webengine-nss", - "output": [ "privateFeature" ] - }, - "webengine-system-libwebp": { - "label": "libwebp, libwebpmux and libwebpdemux", - "autoDetect": "config.unix", - "condition": "libs.webengine-webp", - "output": [ "privateFeature" ] - }, - "webengine-system-opus": { - "label": "opus", - "autoDetect": "config.unix", - "condition": "libs.webengine-opus", - "output": [ "privateFeature" ] - }, - "webengine-system-ffmpeg": { - "label": "ffmpeg", - "autoDetect": false, - "condition": "libs.webengine-ffmpeg && features.webengine-system-opus && features.webengine-system-libwebp", - "output": [ "privateFeature" ] - }, - "webengine-system-icu": { - "label": "icu", - "autoDetect": false, - "condition": "libs.webengine-icu", - "output": [ "privateFeature" ] - }, - "webengine-system-re2": { - "label": "re2", - "autoDetect": "config.unix", - "condition": "tests.webengine-re2", - "output": [ "privateFeature" ] - }, - "webengine-system-ninja": { - "label": "Use System Ninja", - "condition": "tests.webengine-ninja", - "output": [ "privateFeature" ] - }, - "webengine-system-gn": { - "label": "Use System Gn", - "autoDetect": false, - "condition": "tests.webengine-gn", - "output": [ "privateFeature" ] - }, - "webengine-system-glibc": { - "label": "glibc", - "condition": "config.linux && tests.webengine-glibc", - "output": [ "privateFeature" ] - }, - "webengine-system-libxml2": { - "label": "libxml2 and libxslt", - "condition": "config.unix - && libs.webengine-libxml2 - && tests.webengine-libxml2-compatible", - "output": [ "privateFeature" ] - }, - "webengine-system-lcms2" : { - "label": "lcms2", - "autoDetect": "features.webengine-printing-and-pdf", - "condition": "config.unix && libs.webengine-lcms2", - "output": [ "privateFeature" ] - }, - "webengine-system-freetype" : { - "label": "freetype", - "condition": "config.unix && features.system-freetype && libs.webengine-freetype", - "output": [ "privateFeature" ] - }, - "webengine-system-x11" : { - "label": "x11", - "condition": "config.unix && libs.webengine-x11", - "output": [ "privateFeature" ] - }, "webengine-ozone-x11" : { "label": "Support qpa-xcb", "condition": "config.unix @@ -674,29 +234,11 @@ "condition": "libs.webengine-poppler-cpp", "output": [ "privateFeature" ] }, - "webengine-win-compiler64": { - "label": "64bit compiler", - "condition": "config.win32 && tests.webengine-win-compiler64", - "output": [ "privateFeature" ] - }, "webengine-arm-thumb": { "label": "Thumb instruction set", "condition": "config.linux && features.webengine-embedded-build && arch.arm && tests.webengine-arm-thumb", "output": [ "privateFeature" ] }, - "webengine-widgets": { - "label": "Qt WebEngine Widgets", - "purpose": "Provides WebEngine Widgets support.", - "section": "WebEngine", - "condition": "module.widgets", - "output": [ "privateFeature" ] - }, - "webengine-qml": { - "label": "Qt WebEngine Qml", - "purpose": "Provides WebEngine Qml support.", - "section": "WebEngine", - "output": [ "privateFeature" ] - }, "webengine-full-debug-info": { "label": "Full debug information", "purpose": "Enables debug information for Blink and V8.", @@ -717,26 +259,6 @@ "report": [ { "type": "warning", - "condition": "!features.webengine-python2", - "message": "Python version 2 (2.7.5 or later) is required to build QtWebEngine." - }, - { - "type": "warning", - "condition": "!features.webengine-gperf", - "message": "gperf is required to build QtWebEngine." - }, - { - "type": "warning", - "condition": "!features.webengine-bison", - "message": "bison is required to build QtWebEngine." - }, - { - "type": "warning", - "condition": "!features.webengine-flex", - "message": "flex is required to build QtWebEngine." - }, - { - "type": "warning", "condition": "config.sanitizer && !tests.webengine-sanitizer && !features.webengine-sanitizer", "message": "Qt WebEngine cannot be built with the chosen sanitizer configuration. Check config.log for details or use -feature-webengine-sanitizer to force the build." }, @@ -747,23 +269,23 @@ }, { "type": "warning", - "condition": "config.win32 && !features.webengine-win-compiler64", - "message": "64-bit cross-building or native toolchain is required to build QtWebEngine." + "condition": "config.linux && features.webengine-embedded-build && !features.webengine-system-ffmpeg && arch.arm && !features.webengine-arm-thumb", + "message": "Thumb instruction set is required to build ffmpeg for QtWebEngine." }, { "type": "warning", - "condition": "config.linux && features.webengine-embedded-build && !features.webengine-system-ffmpeg && arch.arm && !features.webengine-arm-thumb", - "message": "Thumb instruction set is required to build ffmpeg for QtWebEngine." + "condition": "config.linux && features.webengine-v8-snapshot && !features.webengine-v8-snapshot-support", + "message": "V8 snapshot cannot be built. Most likely, the 32-bit host compiler does not work. Please make sure you have 32-bit devel environment installed." } ], "summary": [ { "section": "Qt WebEngineCore", + "condition": "features.webengine-core", "entries": [ - "webengine-widgets", - "webengine-qml", "webengine-embedded-build", + "webengine-developer-build", "webengine-full-debug-info", "webengine-pepper-plugins", "webengine-printing-and-pdf", @@ -771,7 +293,6 @@ "webengine-spellchecker", "webengine-native-spellchecker", "webengine-webrtc", - "webengine-system-ninja", "webengine-geolocation", "webengine-webchannel", "webengine-v8-snapshot", @@ -831,54 +352,6 @@ "type": "macosToolchainVersion", "args": "deploymentTarget", "condition": "config.macos" - }, - { - "section": "Optional system libraries used", - "condition": "config.unix", - "entries": [ - "webengine-system-re2", - "webengine-system-icu", - "webengine-system-libwebp", - "webengine-system-opus", - "webengine-system-ffmpeg", - "webengine-system-libvpx", - "webengine-system-snappy", - "webengine-system-glib", - "webengine-system-zlib", - "webengine-system-minizip", - "webengine-system-libevent", - "webengine-system-jsoncpp", - "webengine-system-protobuf", - "webengine-system-libxml2", - "webengine-system-lcms2", - "webengine-system-png", - "webengine-system-jpeg", - "webengine-system-harfbuzz", - "webengine-system-freetype" - ] - }, - { - "section": "Required system libraries", - "condition": "config.unix && !config.macos", - "entries": [ - "webengine-system-fontconfig", - "webengine-system-dbus", - "webengine-system-nss", - "webengine-system-khr", - "webengine-system-glibc" - ] - }, - { - "section": "Required system libraries for qpa-xcb", - "condition": "config.unix && !config.macos", - "entries": [ - "webengine-system-x11", - "webengine-system-libdrm", - "webengine-system-xcomposite", - "webengine-system-xcursor", - "webengine-system-xi", - "webengine-system-xtst" - ] } ] } diff --git a/src/core/core_chromium.pri b/src/core/core_chromium.pri index 908387788..810ec9a0f 100644 --- a/src/core/core_chromium.pri +++ b/src/core/core_chromium.pri @@ -59,16 +59,21 @@ SOURCES = \ compositor/compositor_resource_tracker.cpp \ compositor/content_gpu_client_qt.cpp \ compositor/delegated_frame_node.cpp \ + compositor/display_frame_sink.cpp \ + compositor/display_overrides.cpp \ + compositor/display_software_output_surface.cpp \ content_client_qt.cpp \ content_browser_client_qt.cpp \ content_main_delegate_qt.cpp \ content_utility_client_qt.cpp \ + delegated_frame_host_client_qt.cpp \ desktop_screen_qt.cpp \ devtools_frontend_qt.cpp \ devtools_manager_delegate_qt.cpp \ download_manager_delegate_qt.cpp \ favicon_manager.cpp \ file_picker_controller.cpp \ + find_text_helper.cpp \ javascript_dialog_controller.cpp \ javascript_dialog_manager_qt.cpp \ login_delegate_qt.cpp \ @@ -163,16 +168,20 @@ HEADERS = \ compositor/compositor_resource_tracker.h \ compositor/content_gpu_client_qt.h \ compositor/delegated_frame_node.h \ + compositor/display_frame_sink.h \ + compositor/display_software_output_surface.h \ content_client_qt.h \ content_browser_client_qt.h \ content_main_delegate_qt.h \ content_utility_client_qt.h \ + delegated_frame_host_client_qt.h \ desktop_screen_qt.h \ devtools_frontend_qt.h \ devtools_manager_delegate_qt.h \ download_manager_delegate_qt.h \ favicon_manager.h \ file_picker_controller.h \ + find_text_helper.h \ global_descriptors_qt.h \ javascript_dialog_controller_p.h \ javascript_dialog_controller.h \ @@ -292,11 +301,13 @@ qtConfig(webengine-printing-and-pdf) { contains(QT_CONFIG, opengl) { SOURCES += \ compositor/compositor_resource_fence.cpp \ + compositor/display_gl_output_surface.cpp \ + compositor/display_gl_output_surface_qsg.cpp \ compositor/stream_video_node.cpp \ compositor/yuv_video_node.cpp - HEADERS += \ compositor/compositor_resource_fence.h \ + compositor/display_gl_output_surface.h \ compositor/stream_video_node.h \ compositor/yuv_video_node.h } diff --git a/src/core/core_common.pri b/src/core/core_common.pri index c92278657..2a9dc90c0 100644 --- a/src/core/core_common.pri +++ b/src/core/core_common.pri @@ -1,5 +1,6 @@ +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) -QT_FOR_CONFIG += webenginecore webenginecore-private +QT_FOR_CONFIG += buildtools-private webenginecore webenginecore-private # NOTE: The TARGET, QT, QT_PRIVATE variables are used in both core_module.pro and core_gyp_generator.pro # gyp/ninja will take care of the compilation, qmake/make will finish with linking and install. diff --git a/src/core/core_module.pro b/src/core/core_module.pro index b220af4a5..4b9268e1a 100644 --- a/src/core/core_module.pro +++ b/src/core/core_module.pro @@ -63,7 +63,7 @@ CONFIG *= no_smart_library_merge osx { LIBS_PRIVATE += -Wl,-force_load,$${api_library_path}$${QMAKE_DIR_SEP}lib$${api_library_name}.a } else: win32 { - !isDeveloperBuild() { + !qtConfig(webengine-developer-build) { # Remove unused functions and data in debug non-developer builds, because the binaries will # be smaller in the shipped packages. QMAKE_LFLAGS += /OPT:REF diff --git a/src/core/delegated_frame_host_client_qt.cpp b/src/core/delegated_frame_host_client_qt.cpp new file mode 100644 index 000000000..d3f5a4ade --- /dev/null +++ b/src/core/delegated_frame_host_client_qt.cpp @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "delegated_frame_host_client_qt.h" + +#include "render_widget_host_view_qt.h" + +namespace QtWebEngineCore { + +ui::Layer *DelegatedFrameHostClientQt::DelegatedFrameHostGetLayer() const +{ + return p->m_rootLayer.get(); +} + +bool DelegatedFrameHostClientQt::DelegatedFrameHostIsVisible() const +{ + return !p->host()->is_hidden(); +} + +SkColor DelegatedFrameHostClientQt::DelegatedFrameHostGetGutterColor() const +{ + return p->GetBackgroundColor().value_or(SK_ColorWHITE); +} + +void DelegatedFrameHostClientQt::OnBeginFrame(base::TimeTicks frame_time) +{ + p->host()->ProgressFlingIfNeeded(frame_time); +} + +void DelegatedFrameHostClientQt::OnFrameTokenChanged(uint32_t frame_token) +{ + p->OnFrameTokenChangedForView(frame_token); +} + +float DelegatedFrameHostClientQt::GetDeviceScaleFactor() const +{ + return p->m_screenInfo.device_scale_factor; +} + +void DelegatedFrameHostClientQt::InvalidateLocalSurfaceIdOnEviction() +{ + p->m_dfhLocalSurfaceIdAllocator.Invalidate(); +} + +std::vector<viz::SurfaceId> DelegatedFrameHostClientQt::CollectSurfaceIdsForEviction() +{ + return p->host()->CollectSurfaceIdsForEviction(); +} + +bool DelegatedFrameHostClientQt::ShouldShowStaleContentOnEviction() +{ + return p->host()->ShouldShowStaleContentOnEviction(); +} + +} // namespace QtWebEngineCore diff --git a/src/core/delegated_frame_host_client_qt.h b/src/core/delegated_frame_host_client_qt.h new file mode 100644 index 000000000..b5dc6eb59 --- /dev/null +++ b/src/core/delegated_frame_host_client_qt.h @@ -0,0 +1,73 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef DELEGATED_FRAME_HOST_CLIENT_QT_H +#define DELEGATED_FRAME_HOST_CLIENT_QT_H + +#include "qtwebenginecoreglobal_p.h" + +#include "content/browser/renderer_host/delegated_frame_host.h" +#include "content/browser/renderer_host/render_widget_host_impl.h" + +namespace QtWebEngineCore { + +class RenderWidgetHostViewQt; +class DelegatedFrameHostClientQt : public content::DelegatedFrameHostClient +{ +public: + explicit DelegatedFrameHostClientQt(RenderWidgetHostViewQt *p) : p(p) {} + + // Overridden from content::DelegatedFrameHostClient + ui::Layer *DelegatedFrameHostGetLayer() const override; + bool DelegatedFrameHostIsVisible() const override; + SkColor DelegatedFrameHostGetGutterColor() const override; + void OnBeginFrame(base::TimeTicks frame_time) override; + void OnFrameTokenChanged(uint32_t frame_token) override; + float GetDeviceScaleFactor() const override; + void InvalidateLocalSurfaceIdOnEviction() override; + std::vector<viz::SurfaceId> CollectSurfaceIdsForEviction() override; + bool ShouldShowStaleContentOnEviction() override; + +private: + RenderWidgetHostViewQt *p; +}; + +} // namespace QtWebEngineCore + +#endif // !DELEGATED_FRAME_HOST_CLIENT_QT_H diff --git a/src/core/favicon_manager.h b/src/core/favicon_manager.h index df74f6303..a8247d15f 100644 --- a/src/core/favicon_manager.h +++ b/src/core/favicon_manager.h @@ -90,7 +90,7 @@ public: TouchIcon = 1 << 1, TouchPrecomposedIcon = 1 << 2 }; - Q_DECLARE_FLAGS(FaviconTypeFlags, FaviconTypeFlag); + Q_DECLARE_FLAGS(FaviconTypeFlags, FaviconTypeFlag) FaviconInfo(); FaviconInfo(const FaviconInfo &); diff --git a/src/core/find_text_helper.cpp b/src/core/find_text_helper.cpp new file mode 100644 index 000000000..effda529f --- /dev/null +++ b/src/core/find_text_helper.cpp @@ -0,0 +1,171 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "find_text_helper.h" +#include "qwebenginefindtextresult.h" +#include "type_conversion.h" +#include "web_contents_adapter_client.h" + +#include "content/public/browser/web_contents.h" +#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" + +namespace QtWebEngineCore { + +// static +int FindTextHelper::m_findRequestIdCounter = -1; + +FindTextHelper::FindTextHelper(content::WebContents *webContents, WebContentsAdapterClient *viewClient) + : m_webContents(webContents) + , m_viewClient(viewClient) + , m_currentFindRequestId(m_findRequestIdCounter++) + , m_lastCompletedFindRequestId(m_currentFindRequestId) +{ +} + +FindTextHelper::~FindTextHelper() +{ + if (isFindTextInProgress()) + stopFinding(); +} + +void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, bool findBackward, const QWebEngineCallback<bool> resultCallback) +{ + if (findText.isEmpty()) { + stopFinding(); + m_viewClient->findTextFinished(QWebEngineFindTextResult()); + m_widgetCallbacks.invokeEmpty(resultCallback); + return; + } + + startFinding(findText, caseSensitively, findBackward); + m_widgetCallbacks.registerCallback(m_currentFindRequestId, resultCallback); +} + +void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, bool findBackward, const QJSValue &resultCallback) +{ + if (findText.isEmpty()) { + stopFinding(); + m_viewClient->findTextFinished(QWebEngineFindTextResult()); + if (!resultCallback.isUndefined()) { + QJSValueList args; + args.append(QJSValue(0)); + const_cast<QJSValue&>(resultCallback).call(args); + } + return; + } + + startFinding(findText, caseSensitively, findBackward); + if (!resultCallback.isUndefined()) + m_quickCallbacks.insert(m_currentFindRequestId, resultCallback); +} + +void FindTextHelper::startFinding(const QString &findText, bool caseSensitively, bool findBackward) +{ + if (findText.isEmpty()) { + stopFinding(); + return; + } + + if (m_currentFindRequestId > m_lastCompletedFindRequestId) { + // There are cases where the render process will overwrite a previous request + // with the new search and we'll have a dangling callback, leaving the application + // waiting for it forever. + // Assume that any unfinished find has been unsuccessful when a new one is started + // to cover that case. + m_viewClient->findTextFinished(QWebEngineFindTextResult()); + invokeResultCallback(m_currentFindRequestId, 0); + } + + blink::mojom::FindOptionsPtr options = blink::mojom::FindOptions::New(); + options->forward = !findBackward; + options->match_case = caseSensitively; + options->find_next = findText == m_previousFindText; + m_previousFindText = findText; + + m_currentFindRequestId = m_findRequestIdCounter++; + m_webContents->Find(m_currentFindRequestId, toString16(findText), std::move(options)); +} + +void FindTextHelper::stopFinding() +{ + m_lastCompletedFindRequestId = m_currentFindRequestId; + m_previousFindText = QString(); + m_webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); +} + +bool FindTextHelper::isFindTextInProgress() const +{ + return m_currentFindRequestId != m_lastCompletedFindRequestId; +} + +void FindTextHelper::handleFindReply(content::WebContents *source, int requestId, int numberOfMatches, + const gfx::Rect &selectionRect, int activeMatchOrdinal, bool finalUpdate) +{ + Q_UNUSED(selectionRect); + + Q_ASSERT(source == m_webContents); + + if (!finalUpdate || requestId <= m_lastCompletedFindRequestId) + return; + + Q_ASSERT(m_currentFindRequestId == requestId); + m_lastCompletedFindRequestId = requestId; + m_viewClient->findTextFinished(QWebEngineFindTextResult(numberOfMatches, activeMatchOrdinal)); + invokeResultCallback(requestId, numberOfMatches); +} + +void FindTextHelper::handleLoadCommitted() +{ + // Make sure that we don't set the findNext WebFindOptions on a new frame. + m_previousFindText = QString(); +} + +void FindTextHelper::invokeResultCallback(int requestId, int numberOfMatches) +{ + if (m_quickCallbacks.contains(requestId)) { + QJSValue resultCallback = m_quickCallbacks.take(requestId); + QJSValueList args; + args.append(QJSValue(numberOfMatches)); + resultCallback.call(args); + } else { + m_widgetCallbacks.invoke(requestId, numberOfMatches > 0); + } +} + +} // namespace QtWebEngineCore diff --git a/src/core/find_text_helper.h b/src/core/find_text_helper.h new file mode 100644 index 000000000..e8f186272 --- /dev/null +++ b/src/core/find_text_helper.h @@ -0,0 +1,102 @@ +/**************************************************************************** +** +** Copyright (C) 2019 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtWebEngine module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef FIND_TEXT_HELPER_H +#define FIND_TEXT_HELPER_H + +#include "qtwebenginecoreglobal_p.h" + +#include "qwebenginecallback_p.h" +#include <QJSValue> + +namespace content { +class WebContents; +} + +namespace gfx { +class Rect; +} + +namespace QtWebEngineCore { + +class WebContentsAdapterClient; + +class Q_WEBENGINECORE_PRIVATE_EXPORT FindTextHelper { +public: + FindTextHelper(content::WebContents *webContents, WebContentsAdapterClient *viewClient); + ~FindTextHelper(); + + void startFinding(const QString &findText, bool caseSensitively, bool findBackward, const QWebEngineCallback<bool> resultCallback); + void startFinding(const QString &findText, bool caseSensitively, bool findBackward, const QJSValue &resultCallback); + void startFinding(const QString &findText, bool caseSensitively, bool findBackward); + void stopFinding(); + bool isFindTextInProgress() const; + void handleFindReply(content::WebContents *source, int requestId, int numberOfMatches, const gfx::Rect &selectionRect, int activeMatchOrdinal, bool finalUpdate); + void handleLoadCommitted(); + +private: + void invokeResultCallback(int requestId, int numberOfMatches); + + content::WebContents *m_webContents; + WebContentsAdapterClient *m_viewClient; + + static int m_findRequestIdCounter; + int m_currentFindRequestId; + int m_lastCompletedFindRequestId; + + QString m_previousFindText; + + QMap<int, QJSValue> m_quickCallbacks; + CallbackDirectory m_widgetCallbacks; +}; + +} // namespace QtWebEngineCore + +#endif // FIND_TEXT_HELPER_H diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro index 0219a2be9..377d8363c 100644 --- a/src/core/gn_run.pro +++ b/src/core/gn_run.pro @@ -1,5 +1,6 @@ +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) -QT_FOR_CONFIG += webenginecore-private +QT_FOR_CONFIG += buildtools-private webenginecore-private core-private gui-private TEMPLATE = aux diff --git a/src/core/pref_service_adapter.h b/src/core/pref_service_adapter.h index 83f6a322e..1c7c44a96 100644 --- a/src/core/pref_service_adapter.h +++ b/src/core/pref_service_adapter.h @@ -38,8 +38,8 @@ ** ****************************************************************************/ -#ifndef PREF_SRVICE_ADAPTER_H -#define PREF_SERIVE_ADAPTER_H +#ifndef PREF_SERVICE_ADAPTER_H +#define PREF_SERVICE_ADAPTER_H #include "components/prefs/pref_service.h" #include "qtwebenginecoreglobal_p.h" @@ -82,4 +82,4 @@ private: } -#endif // PREF_SERIVE_ADAPTER_H +#endif // PREF_SERVICE_ADAPTER_H diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp index 9a5058a5a..38fe56f7d 100644 --- a/src/core/profile_io_data_qt.cpp +++ b/src/core/profile_io_data_qt.cpp @@ -100,6 +100,8 @@ #include "net/cert_net/cert_net_fetcher_impl.h" #endif +#include <mutex> + namespace QtWebEngineCore { static bool doNetworkSessionParamsMatch(const net::HttpNetworkSession::Params &first, @@ -164,7 +166,6 @@ ProfileIODataQt::ProfileIODataQt(ProfileQt *profile) #if QT_CONFIG(ssl) m_clientCertificateStoreData(new ClientCertificateStoreData), #endif - m_mutex(QMutex::Recursive), m_removerObserver(this), m_weakPtrFactory(this) { @@ -243,7 +244,7 @@ void ProfileIODataQt::initializeOnIOThread() m_urlRequestContext->set_enable_brotli(base::FeatureList::IsEnabled(features::kBrotliEncoding)); // this binds factory to io thread m_weakPtr = m_weakPtrFactory.GetWeakPtr(); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); generateAllStorage(); generateJobFactory(); setGlobalCertificateVerification(); @@ -283,7 +284,7 @@ void ProfileIODataQt::cancelAllUrlRequests() void ProfileIODataQt::generateAllStorage() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); generateStorage(); generateCookieStore(); generateUserAgent(); @@ -390,7 +391,7 @@ void ProfileIODataQt::generateCookieStore() Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); Q_ASSERT(m_urlRequestContext); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); // FIXME: Add code to remove the old database. m_storage->set_channel_id_service( @@ -443,7 +444,7 @@ void ProfileIODataQt::generateUserAgent() Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_storage->set_http_user_agent_settings(std::unique_ptr<net::HttpUserAgentSettings>( new net::StaticHttpUserAgentSettings(m_httpAcceptLanguage.toStdString(), m_httpUserAgent.toStdString()))); @@ -455,7 +456,7 @@ void ProfileIODataQt::generateHttpCache() Q_ASSERT(m_urlRequestContext); Q_ASSERT(m_storage); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); net::HttpCache::DefaultBackend* main_backend = 0; switch (m_httpCacheType) { @@ -508,7 +509,7 @@ void ProfileIODataQt::generateJobFactory() Q_ASSERT(m_urlRequestContext); Q_ASSERT(!m_jobFactory); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_updateJobFactory = false; std::unique_ptr<net::URLRequestJobFactoryImpl> jobFactory(new net::URLRequestJobFactoryImpl()); @@ -563,7 +564,7 @@ void ProfileIODataQt::regenerateJobFactory() Q_ASSERT(m_jobFactory); Q_ASSERT(m_baseJobFactory); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_updateJobFactory = false; if (m_customUrlSchemes == m_installedCustomSchemes) @@ -584,7 +585,7 @@ void ProfileIODataQt::regenerateJobFactory() void ProfileIODataQt::setGlobalCertificateVerification() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); if (m_useForGlobalCertificateVerification) { #if defined(USE_NSS_CERTS) // Set request context used by NSS for OCSP requests. @@ -623,7 +624,7 @@ void ProfileIODataQt::setFullConfiguration() void ProfileIODataQt::requestStorageGeneration() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); if (m_initialized && !m_updateAllStorage) { m_updateAllStorage = true; createProxyConfig(); @@ -636,7 +637,7 @@ void ProfileIODataQt::requestStorageGeneration() { void ProfileIODataQt::createProxyConfig() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); // We must create the proxy config service on the UI loop on Linux because it // must synchronously run on the glib message loop. This will be passed to // the URLRequestContextStorage on the IO thread in GetURLRequestContext(). @@ -657,7 +658,7 @@ void ProfileIODataQt::updateStorageSettings() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); setFullConfiguration(); base::Token groupId = content::BrowserContext::GetServiceInstanceGroupFor(m_profile); @@ -672,7 +673,7 @@ void ProfileIODataQt::updateStorageSettings() void ProfileIODataQt::updateCookieStore() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_persistentCookiesPolicy = m_profileAdapter->persistentCookiesPolicy(); m_cookiesPath = m_profileAdapter->cookiesPath(); if (!m_pendingStorageRequestGeneration) @@ -682,7 +683,7 @@ void ProfileIODataQt::updateCookieStore() void ProfileIODataQt::updateUserAgent() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_httpAcceptLanguage = m_profileAdapter->httpAcceptLanguage(); m_httpUserAgent = m_profileAdapter->httpUserAgent(); if (!m_pendingStorageRequestGeneration) @@ -692,7 +693,7 @@ void ProfileIODataQt::updateUserAgent() void ProfileIODataQt::updateHttpCache() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_httpCacheType = m_profileAdapter->httpCacheType(); m_httpCachePath = m_profileAdapter->httpCachePath(); m_httpCacheMaxSize = m_profileAdapter->httpCacheMaxSize(); @@ -716,7 +717,7 @@ void ProfileIODataQt::updateHttpCache() void ProfileIODataQt::updateJobFactory() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_customUrlSchemes = m_profileAdapter->customUrlSchemes(); @@ -730,7 +731,7 @@ void ProfileIODataQt::updateJobFactory() void ProfileIODataQt::updateRequestInterceptor() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_requestInterceptor = m_profileAdapter->requestInterceptor(); m_hasPageInterceptors = m_profileAdapter->hasPageRequestInterceptor(); // We in this case do not need to regenerate any Chromium classes. @@ -772,7 +773,7 @@ bool ProfileIODataQt::canGetCookies(const QUrl &firstPartyUrl, const QUrl &url) void ProfileIODataQt::updateUsedForGlobalCertificateVerification() { Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI)); - QMutexLocker lock(&m_mutex); + const std::lock_guard<QRecursiveMutex> lock(m_mutex); m_useForGlobalCertificateVerification = m_profileAdapter->isUsedForGlobalCertificateVerification(); if (m_useForGlobalCertificateVerification) diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h index f2dc67f44..4a5b9f77d 100644 --- a/src/core/profile_io_data_qt.h +++ b/src/core/profile_io_data_qt.h @@ -177,7 +177,12 @@ private: QList<QByteArray> m_customUrlSchemes; QList<QByteArray> m_installedCustomSchemes; QWebEngineUrlRequestInterceptor* m_requestInterceptor = nullptr; - QMutex m_mutex; +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) + QMutex m_mutex{QMutex::Recursive}; + using QRecursiveMutex = QMutex; +#else + QRecursiveMutex m_mutex; +#endif int m_httpCacheMaxSize = 0; bool m_initialized = false; bool m_updateAllStorage = false; diff --git a/src/core/render_widget_host_view_qt.cpp b/src/core/render_widget_host_view_qt.cpp index 0242506ee..2918fd8bc 100644 --- a/src/core/render_widget_host_view_qt.cpp +++ b/src/core/render_widget_host_view_qt.cpp @@ -51,6 +51,9 @@ #include "web_contents_adapter_client.h" #include "web_event_factory.h" +#include "base/threading/thread_task_runner_handle.h" +#include "components/viz/common/features.h" +#include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/surfaces/frame_sink_id_allocator.h" #include "components/viz/host/host_frame_sink_manager.h" #include "content/browser/compositor/surface_utils.h" @@ -271,10 +274,12 @@ static content::ScreenInfo screenInfoFromQScreen(QScreen *screen) RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget) : content::RenderWidgetHostViewBase::RenderWidgetHostViewBase(widget) + , m_taskRunner(base::ThreadTaskRunnerHandle::Get()) , m_gestureProvider(QtGestureProviderConfig(), this) , m_sendMotionActionDown(false) , m_touchMotionStarted(false) - , m_compositor(new Compositor(widget)) + , m_enableViz(features::IsVizDisplayCompositorEnabled()) + , m_visible(false) , m_loadVisuallyCommittedState(NotCommitted) , m_adapterClient(0) , m_imeInProgress(false) @@ -288,14 +293,39 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget , m_mouseWheelPhaseHandler(this) , m_frameSinkId(host()->GetFrameSinkId()) { - host()->SetView(this); - if (GetTextInputManager()) GetTextInputManager()->AddObserver(this); const QPlatformInputContext *context = QGuiApplicationPrivate::platformIntegration()->inputContext(); m_imeHasHiddenTextCapability = context && context->hasCapability(QPlatformInputContext::HiddenTextCapability); + if (m_enableViz) { + m_rootLayer.reset(new ui::Layer(ui::LAYER_SOLID_COLOR)); + m_rootLayer->SetColor(SK_ColorTRANSPARENT); + + m_delegatedFrameHost.reset(new content::DelegatedFrameHost( + host()->GetFrameSinkId(), + &m_delegatedFrameHostClient, + true /* should_register_frame_sink_id */)); + + content::ImageTransportFactory *imageTransportFactory = content::ImageTransportFactory::GetInstance(); + ui::ContextFactory *contextFactory = imageTransportFactory->GetContextFactory(); + ui::ContextFactoryPrivate *contextFactoryPrivate = imageTransportFactory->GetContextFactoryPrivate(); + m_uiCompositor.reset(new ui::Compositor( + contextFactoryPrivate->AllocateFrameSinkId(), + contextFactory, + contextFactoryPrivate, + m_taskRunner, + false /* enable_pixel_canvas */)); + m_uiCompositor->SetAcceleratedWidget(gfx::kNullAcceleratedWidget); // null means offscreen + m_uiCompositor->SetRootLayer(m_rootLayer.get()); + + m_displayFrameSink = DisplayFrameSink::findOrCreate(m_uiCompositor->frame_sink_id()); + m_displayFrameSink->connect(this); + } else { + m_compositor.reset(new Compositor(widget)); + } + if (host()->delegate() && host()->delegate()->GetInputEventRouter()) host()->delegate()->GetInputEventRouter()->AddFrameSinkIdOwner(GetFrameSinkId(), this); @@ -305,12 +335,22 @@ RenderWidgetHostViewQt::RenderWidgetHostViewQt(content::RenderWidgetHost *widget config.tap_slop = ui::GestureConfiguration::GetInstance()->max_touch_move_in_pixels_for_click(); config.enable_longpress_drag_selection = false; m_touchSelectionController.reset(new ui::TouchSelectionController(m_touchSelectionControllerClient.get(), config)); + + host()->render_frame_metadata_provider()->ReportAllFrameSubmissionsForTesting(true); + + // May call SetNeedsBeginFrames + host()->SetView(this); } RenderWidgetHostViewQt::~RenderWidgetHostViewQt() { + m_delegate.reset(); + QObject::disconnect(m_adapterClientDestroyedConnection); + if (m_enableViz) + m_displayFrameSink->disconnect(this); + if (text_input_manager_) text_input_manager_->RemoveObserver(this); @@ -404,6 +444,8 @@ bool RenderWidgetHostViewQt::HasFocus() bool RenderWidgetHostViewQt::IsSurfaceAvailableForCopy() { + if (m_enableViz) + return m_delegatedFrameHost->CanCopyFromCompositingSurface(); return true; } @@ -411,6 +453,11 @@ void RenderWidgetHostViewQt::CopyFromSurface(const gfx::Rect &src_rect, const gfx::Size &output_size, base::OnceCallback<void(const SkBitmap &)> callback) { + if (m_enableViz) { + m_delegatedFrameHost->CopyFromCompositingSurface(src_rect, output_size, std::move(callback)); + return; + } + QImage image; if (m_delegate->copySurface(toQt(src_rect), toQt(output_size), image)) std::move(callback).Run(toSkBitmap(image)); @@ -441,6 +488,18 @@ gfx::Rect RenderWidgetHostViewQt::GetViewBounds() void RenderWidgetHostViewQt::UpdateBackgroundColor() { + if (m_enableViz) { + DCHECK(GetBackgroundColor()); + SkColor color = *GetBackgroundColor(); + bool opaque = SkColorGetA(color) == SK_AlphaOPAQUE; + m_rootLayer->SetFillsBoundsOpaquely(opaque); + m_rootLayer->SetColor(color); + m_uiCompositor->SetBackgroundColor(color); + m_delegate->setClearColor(toQt(color)); + host()->Send(new RenderViewObserverQt_SetBackgroundColor(host()->GetRoutingID(), color)); + return; + } + auto color = GetBackgroundColor(); if (color) { m_delegate->setClearColor(toQt(*color)); @@ -662,17 +721,15 @@ void RenderWidgetHostViewQt::DisplayTooltipText(const base::string16 &tooltip_te m_adapterClient->setToolTip(toQt(tooltip_text)); } -void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient *frameSink) +void RenderWidgetHostViewQt::DidCreateNewRendererCompositorFrameSink(viz::mojom::CompositorFrameSinkClient *frameSinkClient) { - m_compositor->setFrameSinkClient(frameSink); + DCHECK(!m_enableViz); + m_compositor->setFrameSinkClient(frameSinkClient); } -void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList>) +void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &local_surface_id, viz::CompositorFrame frame, base::Optional<viz::HitTestRegionList> hit_test_region_list) { - bool scrollOffsetChanged = (m_lastScrollOffset != frame.metadata.root_scroll_offset); - bool contentsSizeChanged = (m_lastContentsSize != frame.metadata.root_layer_size); - m_lastScrollOffset = frame.metadata.root_scroll_offset; - m_lastContentsSize = frame.metadata.root_layer_size; + DCHECK(!m_enableViz); // Force to process swap messages uint32_t frame_token = frame.metadata.frame_token; @@ -681,19 +738,7 @@ void RenderWidgetHostViewQt::SubmitCompositorFrame(const viz::LocalSurfaceId &lo m_compositor->submitFrame( std::move(frame), - base::BindOnce(&RenderWidgetHostViewQtDelegate::update, base::Unretained(m_delegate.get()))); - - if (m_loadVisuallyCommittedState == NotCommitted) { - m_loadVisuallyCommittedState = DidFirstCompositorFrameSwap; - } else if (m_loadVisuallyCommittedState == DidFirstVisuallyNonEmptyPaint) { - m_adapterClient->loadVisuallyCommitted(); - m_loadVisuallyCommittedState = NotCommitted; - } - - if (scrollOffsetChanged) - m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset)); - if (contentsSizeChanged) - m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); + base::BindOnce(&RenderWidgetHostViewQt::callUpdate, base::Unretained(this))); } void RenderWidgetHostViewQt::GetScreenInfo(content::ScreenInfo *results) @@ -906,7 +951,7 @@ viz::ScopedSurfaceIdAllocator RenderWidgetHostViewQt::DidUpdateVisualProperties( base::OnceCallback<void()> allocation_task = base::BindOnce(&RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete, base::Unretained(this), metadata); - return viz::ScopedSurfaceIdAllocator(std::move(allocation_task)); + return viz::ScopedSurfaceIdAllocator(&m_dfhLocalSurfaceIdAllocator, std::move(allocation_task)); } void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::RenderFrameMetadata &metadata) @@ -914,19 +959,71 @@ void RenderWidgetHostViewQt::OnDidUpdateVisualPropertiesComplete(const cc::Rende synchronizeVisualProperties(metadata.local_surface_id_allocation); } +void RenderWidgetHostViewQt::OnDidFirstVisuallyNonEmptyPaint() +{ + if (m_loadVisuallyCommittedState == NotCommitted) { + m_loadVisuallyCommittedState = DidFirstVisuallyNonEmptyPaint; + } else if (m_loadVisuallyCommittedState == DidFirstCompositorFrameSwap) { + m_adapterClient->loadVisuallyCommitted(); + m_loadVisuallyCommittedState = NotCommitted; + } +} + +void RenderWidgetHostViewQt::scheduleUpdate() +{ + DCHECK(m_enableViz); + m_taskRunner->PostTask( + FROM_HERE, + base::BindOnce(&RenderWidgetHostViewQt::callUpdate, m_weakPtrFactory.GetWeakPtr())); +} + +void RenderWidgetHostViewQt::callUpdate() +{ + m_delegate->update(); + + if (m_loadVisuallyCommittedState == NotCommitted) { + m_loadVisuallyCommittedState = DidFirstCompositorFrameSwap; + } else if (m_loadVisuallyCommittedState == DidFirstVisuallyNonEmptyPaint) { + m_adapterClient->loadVisuallyCommitted(); + m_loadVisuallyCommittedState = NotCommitted; + } +} + QSGNode *RenderWidgetHostViewQt::updatePaintNode(QSGNode *oldNode) { + if (m_enableViz) + return m_displayFrameSink->updatePaintNode(oldNode, m_delegate.get()); return m_compositor->updatePaintNode(oldNode, m_delegate.get()); } void RenderWidgetHostViewQt::notifyShown() { - host()->WasShown(false); + if (m_enableViz) { + if (m_visible) + return; + m_visible = true; + m_delegatedFrameHost->AttachToCompositor(m_uiCompositor.get()); + m_delegatedFrameHost->WasShown(GetLocalSurfaceIdAllocation().local_surface_id(), + m_viewRectInDips.size(), + false /* record_presentation_time */); + host()->WasShown(false); + } else { + host()->WasShown(false); + } } void RenderWidgetHostViewQt::notifyHidden() { - host()->WasHidden(); + if (m_enableViz) { + if (!m_visible) + return; + m_visible = false; + host()->WasHidden(); + m_delegatedFrameHost->WasHidden(); + m_delegatedFrameHost->DetachFromCompositor(); + } else { + host()->WasHidden(); + } } void RenderWidgetHostViewQt::visualPropertiesChanged() @@ -1644,6 +1741,7 @@ void RenderWidgetHostViewQt::handleFocusEvent(QFocusEvent *ev) void RenderWidgetHostViewQt::SetNeedsBeginFrames(bool needs_begin_frames) { + DCHECK(!m_enableViz); m_compositor->setNeedsBeginFrames(needs_begin_frames); } @@ -1683,26 +1781,35 @@ void RenderWidgetHostViewQt::SetWantsAnimateOnlyBeginFrames() viz::SurfaceId RenderWidgetHostViewQt::GetCurrentSurfaceId() const { + if (m_enableViz) + return m_delegatedFrameHost->GetCurrentSurfaceId(); return viz::SurfaceId(); } const viz::FrameSinkId &RenderWidgetHostViewQt::GetFrameSinkId() const { + if (m_enableViz) + return m_delegatedFrameHost->frame_sink_id(); return m_frameSinkId; } const viz::LocalSurfaceIdAllocation &RenderWidgetHostViewQt::GetLocalSurfaceIdAllocation() const { - return m_localSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation(); + return m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation(); } void RenderWidgetHostViewQt::TakeFallbackContentFrom(content::RenderWidgetHostView *view) { DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewChildFrame()); DCHECK(!static_cast<RenderWidgetHostViewBase*>(view)->IsRenderWidgetHostViewGuest()); - base::Optional<SkColor> color = view->GetBackgroundColor(); + RenderWidgetHostViewQt *viewQt = static_cast<RenderWidgetHostViewQt *>(view); + base::Optional<SkColor> color = viewQt->GetBackgroundColor(); if (color) SetBackgroundColor(*color); + if (m_enableViz) { + m_delegatedFrameHost->TakeFallbackContentFrom(viewQt->m_delegatedFrameHost.get()); + host()->GetContentRenderingTimeoutFrom(viewQt->host()); + } } void RenderWidgetHostViewQt::EnsureSurfaceSynchronizedForWebTest() @@ -1729,14 +1836,38 @@ void RenderWidgetHostViewQt::OnRenderFrameMetadataChangedAfterActivation() m_selectionEnd = metadata.selection.end; m_touchSelectionControllerClient->UpdateClientSelectionBounds(m_selectionStart, m_selectionEnd); } + + gfx::Vector2dF scrollOffset = metadata.root_scroll_offset.value_or(gfx::Vector2dF()); + gfx::SizeF contentsSize = metadata.root_layer_size; + std::swap(m_lastScrollOffset, scrollOffset); + std::swap(m_lastContentsSize, contentsSize); + if (scrollOffset != m_lastScrollOffset) + m_adapterClient->updateScrollPosition(toQt(m_lastScrollOffset)); + if (contentsSize != m_lastContentsSize) + m_adapterClient->updateContentsSize(toQt(m_lastContentsSize)); } void RenderWidgetHostViewQt::synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceIdAllocation> &childSurfaceId) { if (childSurfaceId) - m_localSurfaceIdAllocator.UpdateFromChild(*childSurfaceId); + m_dfhLocalSurfaceIdAllocator.UpdateFromChild(*childSurfaceId); else - m_localSurfaceIdAllocator.GenerateId(); + m_dfhLocalSurfaceIdAllocator.GenerateId(); + + if (m_enableViz) { + gfx::Size viewSizeInDips = GetRequestedRendererSize(); + gfx::Size viewSizeInPixels = GetCompositorViewportPixelSize(); + m_rootLayer->SetBounds(gfx::Rect(gfx::Point(), viewSizeInPixels)); + m_uiCompositorLocalSurfaceIdAllocator.GenerateId(); + m_uiCompositor->SetScaleAndSize( + m_screenInfo.device_scale_factor, + viewSizeInPixels, + m_uiCompositorLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation()); + m_delegatedFrameHost->EmbedSurface( + m_dfhLocalSurfaceIdAllocator.GetCurrentLocalSurfaceIdAllocation().local_surface_id(), + viewSizeInDips, + cc::DeadlinePolicy::UseDefaultDeadline()); + } host()->SynchronizeVisualProperties(); } diff --git a/src/core/render_widget_host_view_qt.h b/src/core/render_widget_host_view_qt.h index 91d5b8610..5935f477a 100644 --- a/src/core/render_widget_host_view_qt.h +++ b/src/core/render_widget_host_view_qt.h @@ -40,10 +40,11 @@ #ifndef RENDER_WIDGET_HOST_VIEW_QT_H #define RENDER_WIDGET_HOST_VIEW_QT_H +#include "compositor/display_frame_sink.h" +#include "delegated_frame_host_client_qt.h" #include "render_widget_host_view_qt_delegate.h" #include "base/memory/weak_ptr.h" -#include "components/viz/common/frame_sinks/begin_frame_source.h" #include "components/viz/common/resources/transferable_resource.h" #include "components/viz/common/surfaces/parent_local_surface_id_allocator.h" #include "components/viz/host/host_frame_sink_client.h" @@ -53,7 +54,7 @@ #include "content/browser/renderer_host/text_input_manager.h" #include "gpu/ipc/common/gpu_messages.h" #include "ui/events/gesture_detection/filtered_gesture_provider.h" -#include "qtwebenginecoreglobal_p.h" + #include <QMap> #include <QPoint> #include <QtGlobal> @@ -104,6 +105,7 @@ class RenderWidgetHostViewQt , public RenderWidgetHostViewQtDelegateClient , public base::SupportsWeakPtr<RenderWidgetHostViewQt> , public content::TextInputManager::Observer + , public DisplayConsumer { public: enum LoadVisuallyCommittedState { @@ -215,12 +217,16 @@ public: // Overridden from content::BrowserAccessibilityDelegate content::BrowserAccessibilityManager* CreateBrowserAccessibilityManager(content::BrowserAccessibilityDelegate* delegate, bool for_root_frame) override; - LoadVisuallyCommittedState getLoadVisuallyCommittedState() const { return m_loadVisuallyCommittedState; } - void setLoadVisuallyCommittedState(LoadVisuallyCommittedState state) { m_loadVisuallyCommittedState = state; } + + // Called from WebContentsDelegateQt + void OnDidFirstVisuallyNonEmptyPaint(); // Overridden from content::RenderFrameMetadataProvider::Observer void OnRenderFrameMetadataChangedAfterActivation() override; + // Overridden from DisplayConsumer + void scheduleUpdate() override; + gfx::SizeF lastContentsSize() const { return m_lastContentsSize; } gfx::Vector2dF lastScrollOffset() const { return m_lastScrollOffset; } @@ -230,6 +236,8 @@ public: ui::TextInputType getTextInputType() const; private: + friend class DelegatedFrameHostClientQt; + void processMotionEvent(const ui::MotionEvent &motionEvent); void clearPreviousTouchMotionState(); QList<QTouchEvent::TouchPoint> mapTouchPointIds(const QList<QTouchEvent::TouchPoint> &inputPoints); @@ -241,12 +249,16 @@ private: void synchronizeVisualProperties(const base::Optional<viz::LocalSurfaceIdAllocation> &childSurfaceId); + void callUpdate(); + // Geometry of the view in screen DIPs. gfx::Rect m_viewRectInDips; // Geometry of the window, including frame, in screen DIPs. gfx::Rect m_windowRectInDips; content::ScreenInfo m_screenInfo; + scoped_refptr<base::SingleThreadTaskRunner> m_taskRunner; + ui::FilteredGestureProvider m_gestureProvider; base::TimeDelta m_eventsToNowDelta; bool m_sendMotionActionDown; @@ -255,6 +267,13 @@ private: QList<QTouchEvent::TouchPoint> m_previousTouchPoints; std::unique_ptr<RenderWidgetHostViewQtDelegate> m_delegate; + const bool m_enableViz; + bool m_visible; + DelegatedFrameHostClientQt m_delegatedFrameHostClient{this}; + std::unique_ptr<content::DelegatedFrameHost> m_delegatedFrameHost; + std::unique_ptr<ui::Layer> m_rootLayer; + std::unique_ptr<ui::Compositor> m_uiCompositor; + scoped_refptr<DisplayFrameSink> m_displayFrameSink; std::unique_ptr<Compositor> m_compositor; LoadVisuallyCommittedState m_loadVisuallyCommittedState; @@ -268,7 +287,8 @@ private: gfx::Vector2dF m_lastScrollOffset; gfx::SizeF m_lastContentsSize; - viz::ParentLocalSurfaceIdAllocator m_localSurfaceIdAllocator; + viz::ParentLocalSurfaceIdAllocator m_dfhLocalSurfaceIdAllocator; + viz::ParentLocalSurfaceIdAllocator m_uiCompositorLocalSurfaceIdAllocator; uint m_imState; int m_anchorPositionWithinSelection; @@ -290,6 +310,8 @@ private: std::unique_ptr<ui::TouchSelectionController> m_touchSelectionController; gfx::SelectionBound m_selectionStart; gfx::SelectionBound m_selectionEnd; + + base::WeakPtrFactory<RenderWidgetHostViewQt> m_weakPtrFactory{this}; }; } // namespace QtWebEngineCore diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp index 02d2db448..ddadeb9f2 100644 --- a/src/core/type_conversion.cpp +++ b/src/core/type_conversion.cpp @@ -40,11 +40,14 @@ #include "type_conversion.h" #include <content/public/common/favicon_url.h> +#include <net/cert/x509_certificate.h> +#include <net/cert/x509_util.h> #include <ui/events/event_constants.h> #include <ui/gfx/image/image_skia.h> #include <QtCore/qcoreapplication.h> #include <QtGui/qmatrix4x4.h> +#include <QtNetwork/qsslcertificate.h> namespace QtWebEngineCore { @@ -256,4 +259,20 @@ void convertToQt(const SkMatrix44 &m, QMatrix4x4 &c) c = qtMatrix; } +static QSslCertificate toCertificate(CRYPTO_BUFFER *buffer) +{ + auto derCert = net::x509_util::CryptoBufferAsStringPiece(buffer); + return QSslCertificate(QByteArray::fromRawData(derCert.data(), derCert.size()), QSsl::Der); +} + +QList<QSslCertificate> toCertificateChain(net::X509Certificate *certificate) +{ + // from leaf to root as in QtNetwork + QList<QSslCertificate> chain; + chain.append(toCertificate(certificate->cert_buffer())); + for (auto &&buffer : certificate->intermediate_buffers()) + chain.append(toCertificate(buffer.get())); + return chain; +} + } // namespace QtWebEngineCore diff --git a/src/core/type_conversion.h b/src/core/type_conversion.h index 7b1f1b4d6..dfd8e8fef 100644 --- a/src/core/type_conversion.h +++ b/src/core/type_conversion.h @@ -64,6 +64,7 @@ #include "url/gurl.h" QT_FORWARD_DECLARE_CLASS(QMatrix4x4) +QT_FORWARD_DECLARE_CLASS(QSslCertificate) namespace content { struct FaviconURL; @@ -73,6 +74,10 @@ namespace gfx { class ImageSkiaRep; } +namespace net { +class X509Certificate; +} + namespace QtWebEngineCore { inline QString toQt(const base::string16 &string) @@ -291,6 +296,8 @@ inline QStringList fromVector(const std::vector<base::string16> &vector) FaviconInfo toFaviconInfo(const content::FaviconURL &); +QList<QSslCertificate> toCertificateChain(net::X509Certificate *certificate); + } // namespace QtWebEngineCore #endif // TYPE_CONVERSION_H diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp index ee0b8cc39..85e63c5a4 100644 --- a/src/core/web_contents_adapter.cpp +++ b/src/core/web_contents_adapter.cpp @@ -86,7 +86,6 @@ #include "content/public/common/web_preferences.h" #include "content/public/common/webrtc_ip_handling_policy.h" #include "extensions/buildflags/buildflags.h" -#include "third_party/blink/public/mojom/frame/find_in_page.mojom.h" #include "third_party/blink/public/web/web_media_player_action.h" #include "printing/buildflags/buildflags.h" #include "ui/base/clipboard/clipboard.h" @@ -416,7 +415,6 @@ WebContentsAdapter::WebContentsAdapter() #endif , m_adapterClient(nullptr) , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) - , m_lastFindRequestId(0) , m_currentDropAction(blink::kWebDragOperationNone) , m_devToolsFrontend(nullptr) { @@ -433,7 +431,6 @@ WebContentsAdapter::WebContentsAdapter(std::unique_ptr<content::WebContents> web #endif , m_adapterClient(nullptr) , m_nextRequestId(CallbackDirectory::ReservedCallbackIdsEnd) - , m_lastFindRequestId(0) , m_currentDropAction(blink::kWebDragOperationNone) , m_devToolsFrontend(nullptr) { @@ -694,7 +691,7 @@ void WebContentsAdapter::load(const QWebEngineHttpRequest &request) } auto navigate = [](QWeakPointer<WebContentsAdapter> weakAdapter, const content::NavigationController::LoadURLParams ¶ms) { - WebContentsAdapter *adapter = weakAdapter.data(); + const auto adapter = weakAdapter.toStrongRef(); if (!adapter) return; adapter->webContents()->GetController().LoadURLWithParams(params); @@ -1046,41 +1043,6 @@ quint64 WebContentsAdapter::fetchDocumentInnerText() return m_nextRequestId++; } -quint64 WebContentsAdapter::findText(const QString &subString, bool caseSensitively, bool findBackward) -{ - CHECK_INITIALIZED(0); - if (m_lastFindRequestId > m_webContentsDelegate->lastReceivedFindReply()) { - // There are cases where the render process will overwrite a previous request - // with the new search and we'll have a dangling callback, leaving the application - // waiting for it forever. - // Assume that any unfinished find has been unsuccessful when a new one is started - // to cover that case. - m_webContentsDelegate->setLastReceivedFindReply(m_lastFindRequestId); - m_adapterClient->didFindText(m_lastFindRequestId, 0); - } - - blink::mojom::FindOptionsPtr options = blink::mojom::FindOptions::New(); - options->forward = !findBackward; - options->match_case = caseSensitively; - options->find_next = subString == m_webContentsDelegate->lastSearchedString(); - m_webContentsDelegate->setLastSearchedString(subString); - - // Find already allows a request ID as input, but only as an int. - // Use the same counter but mod it to MAX_INT, this keeps the same likeliness of request ID clashing. - int shrunkRequestId = m_nextRequestId++ & 0x7fffffff; - m_webContents->Find(shrunkRequestId, toString16(subString), std::move(options)); - m_lastFindRequestId = shrunkRequestId; - return shrunkRequestId; -} - -void WebContentsAdapter::stopFinding() -{ - CHECK_INITIALIZED(); - m_webContentsDelegate->setLastReceivedFindReply(m_lastFindRequestId); - m_webContentsDelegate->setLastSearchedString(QString()); - m_webContents->StopFinding(content::STOP_FIND_ACTION_KEEP_SELECTION); -} - void WebContentsAdapter::updateWebPreferences(const content::WebPreferences & webPreferences) { CHECK_INITIALIZED(); @@ -1696,12 +1658,6 @@ void WebContentsAdapter::focusIfNecessary() m_webContents->Focus(); } -bool WebContentsAdapter::isFindTextInProgress() const -{ - CHECK_INITIALIZED(false); - return m_lastFindRequestId != m_webContentsDelegate->lastReceivedFindReply(); -} - bool WebContentsAdapter::hasFocusedFrame() const { CHECK_INITIALIZED(false); @@ -1745,6 +1701,12 @@ FaviconManager *WebContentsAdapter::faviconManager() return m_webContentsDelegate->faviconManager(); } +FindTextHelper *WebContentsAdapter::findTextHelper() +{ + CHECK_INITIALIZED(nullptr); + return m_webContentsDelegate->findTextHelper(); +} + void WebContentsAdapter::viewSource() { CHECK_INITIALIZED(); diff --git a/src/core/web_contents_adapter.h b/src/core/web_contents_adapter.h index baf9d241c..11f8f9cb1 100644 --- a/src/core/web_contents_adapter.h +++ b/src/core/web_contents_adapter.h @@ -85,6 +85,7 @@ namespace QtWebEngineCore { class DevToolsFrontendQt; class FaviconManager; +class FindTextHelper; class MessagePassingInterface; class ProfileQt; class RenderViewObserverHostQt; @@ -158,8 +159,6 @@ public: quint64 runJavaScriptCallbackResult(const QString &javaScript, quint32 worldId); quint64 fetchDocumentMarkup(); quint64 fetchDocumentInnerText(); - quint64 findText(const QString &subString, bool caseSensitively, bool findBackward); - void stopFinding(); void updateWebPreferences(const content::WebPreferences &webPreferences); void download(const QUrl &url, const QString &suggestedFileName, const QUrl &referrerUrl = QUrl(), @@ -205,6 +204,7 @@ public: void setWebChannel(QWebChannel *, uint worldId); #endif FaviconManager *faviconManager(); + FindTextHelper *findTextHelper(); QPointF lastScrollOffset() const; QSizeF lastContentsSize() const; @@ -263,7 +263,6 @@ private: #endif WebContentsAdapterClient *m_adapterClient; quint64 m_nextRequestId; - int m_lastFindRequestId; std::unique_ptr<content::DropData> m_currentDropData; uint m_currentDropAction; bool m_updateDragActionCalled; diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h index d53568215..4bdb55b4c 100644 --- a/src/core/web_contents_adapter_client.h +++ b/src/core/web_contents_adapter_client.h @@ -64,6 +64,7 @@ QT_FORWARD_DECLARE_CLASS(CertificateErrorController) QT_FORWARD_DECLARE_CLASS(ClientCertSelectController) QT_FORWARD_DECLARE_CLASS(QKeyEvent) QT_FORWARD_DECLARE_CLASS(QVariant) +QT_FORWARD_DECLARE_CLASS(QWebEngineFindTextResult) QT_FORWARD_DECLARE_CLASS(QWebEngineQuotaRequest) QT_FORWARD_DECLARE_CLASS(QWebEngineRegisterProtocolHandlerRequest) QT_FORWARD_DECLARE_CLASS(QWebEngineUrlRequestInfo) @@ -461,7 +462,6 @@ public: virtual void didRunJavaScript(quint64 requestId, const QVariant& result) = 0; virtual void didFetchDocumentMarkup(quint64 requestId, const QString& result) = 0; virtual void didFetchDocumentInnerText(quint64 requestId, const QString& result) = 0; - virtual void didFindText(quint64 requestId, int matchCount) = 0; virtual void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) = 0; virtual void didPrintPageToPdf(const QString &filePath, bool success) = 0; virtual bool passOnFocus(bool reverse) = 0; @@ -499,6 +499,7 @@ public: virtual TouchHandleDrawableClient *createTouchHandle(const QMap<int, QImage> &images) = 0; virtual void showTouchSelectionMenu(TouchSelectionMenuController *menuController, const QRect &bounds, const QSize &handleSize) = 0; virtual void hideTouchSelectionMenu() = 0; + virtual void findTextFinished(const QWebEngineFindTextResult &result) = 0; virtual ProfileAdapter *profileAdapter() = 0; virtual WebContentsAdapter* webContentsAdapter() = 0; diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp index f18617f8e..9855e3859 100644 --- a/src/core/web_contents_delegate_qt.cpp +++ b/src/core/web_contents_delegate_qt.cpp @@ -102,8 +102,8 @@ static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptCo WebContentsDelegateQt::WebContentsDelegateQt(content::WebContents *webContents, WebContentsAdapterClient *adapterClient) : m_viewClient(adapterClient) - , m_lastReceivedFindReply(0) , m_faviconManager(new FaviconManager(webContents, adapterClient)) + , m_findTextHelper(new FindTextHelper(webContents, adapterClient)) , m_lastLoadProgress(-1) , m_loadingState(determineLoadingState(webContents)) , m_didStartLoadingSeen(m_loadingState == LoadingState::Loading) @@ -350,9 +350,7 @@ void WebContentsDelegateQt::EmitLoadFinished(bool success, const QUrl &url, bool void WebContentsDelegateQt::EmitLoadCommitted() { - // Make sure that we don't set the findNext WebFindOptions on a new frame. - m_lastSearchedString = QString(); - + m_findTextHelper->handleLoadCommitted(); m_viewClient->loadCommitted(); m_viewClient->updateNavigationActions(); } @@ -577,13 +575,7 @@ bool WebContentsDelegateQt::DidAddMessageToConsole(content::WebContents *source, void WebContentsDelegateQt::FindReply(content::WebContents *source, int request_id, int number_of_matches, const gfx::Rect& selection_rect, int active_match_ordinal, bool final_update) { - Q_UNUSED(source) - Q_UNUSED(selection_rect) - Q_UNUSED(active_match_ordinal) - if (final_update && request_id > m_lastReceivedFindReply) { - m_lastReceivedFindReply = request_id; - m_viewClient->didFindText(request_id, number_of_matches); - } + m_findTextHelper->handleFindReply(source, request_id, number_of_matches, selection_rect, active_match_ordinal, final_update); } void WebContentsDelegateQt::RequestMediaAccessPermission(content::WebContents *web_contents, const content::MediaStreamRequest &request, content::MediaResponseCallback callback) @@ -623,13 +615,7 @@ void WebContentsDelegateQt::DidFirstVisuallyNonEmptyPaint() if (!rwhv) return; - RenderWidgetHostViewQt::LoadVisuallyCommittedState loadVisuallyCommittedState = rwhv->getLoadVisuallyCommittedState(); - if (loadVisuallyCommittedState == RenderWidgetHostViewQt::NotCommitted) { - rwhv->setLoadVisuallyCommittedState(RenderWidgetHostViewQt::DidFirstVisuallyNonEmptyPaint); - } else if (loadVisuallyCommittedState == RenderWidgetHostViewQt::DidFirstCompositorFrameSwap) { - m_viewClient->loadVisuallyCommitted(); - rwhv->setLoadVisuallyCommittedState(RenderWidgetHostViewQt::NotCommitted); - } + rwhv->OnDidFirstVisuallyNonEmptyPaint(); } void WebContentsDelegateQt::ActivateContents(content::WebContents* contents) @@ -798,6 +784,11 @@ FaviconManager *WebContentsDelegateQt::faviconManager() return m_faviconManager.data(); } +FindTextHelper *WebContentsDelegateQt::findTextHelper() +{ + return m_findTextHelper.data(); +} + WebEngineSettings *WebContentsDelegateQt::webEngineSettings() const { return m_viewClient->webEngineSettings(); } diff --git a/src/core/web_contents_delegate_qt.h b/src/core/web_contents_delegate_qt.h index 00b715c30..f1d5ed76c 100644 --- a/src/core/web_contents_delegate_qt.h +++ b/src/core/web_contents_delegate_qt.h @@ -50,6 +50,7 @@ #include "color_chooser_controller.h" #include "favicon_manager.h" +#include "find_text_helper.h" #include "javascript_dialog_manager_qt.h" #include <QtCore/qvector.h> @@ -112,10 +113,6 @@ class WebContentsDelegateQt : public content::WebContentsDelegate public: WebContentsDelegateQt(content::WebContents*, WebContentsAdapterClient *adapterClient); ~WebContentsDelegateQt(); - QString lastSearchedString() const { return m_lastSearchedString; } - void setLastSearchedString(const QString &s) { m_lastSearchedString = s; } - int lastReceivedFindReply() const { return m_lastReceivedFindReply; } - void setLastReceivedFindReply(int id) { m_lastReceivedFindReply = id; } QUrl url() const { return m_url; } QString title() const { return m_title; } @@ -178,6 +175,7 @@ public: void requestUserNotificationPermission(const QUrl &requestingOrigin); void launchExternalURL(const QUrl &url, ui::PageTransition page_transition, bool is_main_frame, bool has_user_gesture); FaviconManager *faviconManager(); + FindTextHelper *findTextHelper(); void setSavePageInfo(const SavePageInfo &spi) { m_savePageInfo = spi; } const SavePageInfo &savePageInfo() { return m_savePageInfo; } @@ -213,10 +211,9 @@ private: int &streamCount(blink::MediaStreamType type); WebContentsAdapterClient *m_viewClient; - QString m_lastSearchedString; - int m_lastReceivedFindReply; QVector<int64_t> m_loadingErrorFrameList; QScopedPointer<FaviconManager> m_faviconManager; + QScopedPointer<FindTextHelper> m_findTextHelper; SavePageInfo m_savePageInfo; QSharedPointer<FilePickerController> m_filePickerController; QUrl m_initialTargetUrl; diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp index a988040ee..a42565c2b 100644 --- a/src/core/web_engine_context.cpp +++ b/src/core/web_engine_context.cpp @@ -488,6 +488,16 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableES3GLContext); #endif + bool threadedGpu = true; +#ifndef QT_NO_OPENGL + threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); +#endif + + bool enableViz = ((threadedGpu && !parsedCommandLine->HasSwitch("disable-viz-display-compositor")) + || parsedCommandLine->HasSwitch("enable-viz-display-compositor")); + parsedCommandLine->RemoveSwitch("disable-viz-display-compositor"); + parsedCommandLine->RemoveSwitch("enable-viz-display-compositor"); + std::string disableFeatures; std::string enableFeatures; // Needed to allow navigations within pages that were set using setHtml(). One example is @@ -495,10 +505,6 @@ WebEngineContext::WebEngineContext() // This is deprecated behavior, and will be removed in a future Chromium version, as per // upstream Chromium commit ba52f56207a4b9d70b34880fbff2352e71a06422. appendToFeatureList(enableFeatures, features::kAllowContentInitiatedDataUrlNavigations.name); - // Surface synchronization breaks our current graphics integration (since 65) - appendToFeatureList(disableFeatures, features::kEnableSurfaceSynchronization.name); - // Viz Display Compositor is enabled by default since 73. Doesn't work for us (also implies SurfaceSynchronization) - appendToFeatureList(disableFeatures, features::kVizDisplayCompositor.name); // The video-capture service is not functioning at this moment (since 69) appendToFeatureList(disableFeatures, features::kMojoVideoCapture.name); // Breaks WebEngineNewViewRequest.userInitiated API (since 73) @@ -506,8 +512,6 @@ WebEngineContext::WebEngineContext() // We do not yet support the network-service, but it is enabled by default since 75. appendToFeatureList(disableFeatures, network::features::kNetworkService.name); - // VideoSurfaceLayer is enabled by default since 75. We don't support it. - appendToFeatureList(disableFeatures, media::kUseSurfaceLayerForVideo.name); // BlinkGenPropertyTrees is enabled by default in 75, but causes regressions. appendToFeatureList(disableFeatures, blink::features::kBlinkGenPropertyTrees.name); @@ -531,6 +535,15 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(cc::switches::kDisableCompositedAntialiasing); } + if (!enableViz) { + // Surface synchronization breaks our current graphics integration (since 65) + appendToFeatureList(disableFeatures, features::kEnableSurfaceSynchronization.name); + // Viz Display Compositor is enabled by default since 73. Doesn't work for us (also implies SurfaceSynchronization) + appendToFeatureList(disableFeatures, features::kVizDisplayCompositor.name); + // VideoSurfaceLayer is enabled by default since 75. We don't support it. + appendToFeatureList(disableFeatures, media::kUseSurfaceLayerForVideo.name); + } + appendToFeatureSwitch(parsedCommandLine, switches::kDisableFeatures, disableFeatures); appendToFeatureSwitch(parsedCommandLine, switches::kEnableFeatures, enableFeatures); base::FeatureList::InitializeInstance( @@ -619,10 +632,6 @@ WebEngineContext::WebEngineContext() parsedCommandLine->AppendSwitch(switches::kDisableGpu); } - bool threadedGpu = true; -#ifndef QT_NO_OPENGL - threadedGpu = QOpenGLContext::supportsThreadedOpenGL(); -#endif registerMainThreadFactories(threadedGpu); SetContentClient(new ContentClientQt); diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp index 1b0723cb5..7f5306e67 100644 --- a/src/core/web_event_factory.cpp +++ b/src/core/web_event_factory.cpp @@ -1490,8 +1490,15 @@ blink::WebMouseWheelEvent WebEventFactory::toWebWheelEvent(QWheelEvent *ev) webEvent.SetType(webEventTypeForEvent(ev)); webEvent.SetModifiers(modifiersForEvent(ev)); webEvent.SetTimeStamp(base::TimeTicks::Now()); +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) webEvent.SetPositionInWidget(ev->x(), ev->y()); webEvent.SetPositionInScreen(ev->globalX(), ev->globalY()); +#else + webEvent.SetPositionInWidget(static_cast<float>(ev->position().x()), + static_cast<float>(ev->position().y())); + webEvent.SetPositionInScreen(static_cast<float>(ev->globalPosition().x()), + static_cast<float>(ev->globalPosition().y())); +#endif webEvent.wheel_ticks_x = static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; webEvent.wheel_ticks_y = static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; @@ -1520,8 +1527,15 @@ bool WebEventFactory::coalesceWebWheelEvent(blink::WebMouseWheelEvent &webEvent, #endif webEvent.SetTimeStamp(base::TimeTicks::Now()); +#if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) webEvent.SetPositionInWidget(ev->x(), ev->y()); webEvent.SetPositionInScreen(ev->globalX(), ev->globalY()); +#else + webEvent.SetPositionInWidget(static_cast<float>(ev->position().x()), + static_cast<float>(ev->position().y())); + webEvent.SetPositionInScreen(static_cast<float>(ev->globalPosition().x()), + static_cast<float>(ev->globalPosition().y())); +#endif webEvent.wheel_ticks_x += static_cast<float>(ev->angleDelta().x()) / QWheelEvent::DefaultDeltasPerStep; webEvent.wheel_ticks_y += static_cast<float>(ev->angleDelta().y()) / QWheelEvent::DefaultDeltasPerStep; diff --git a/src/process/support_win.cpp b/src/process/support_win.cpp index 21481ce08..3d0ef37bf 100644 --- a/src/process/support_win.cpp +++ b/src/process/support_win.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include <qlibrary.h> +#include <qoperatingsystemversion.h> #include <qsysinfo.h> #include <qt_windows.h> #include <Tlhelp32.h> @@ -80,7 +81,7 @@ public: ShcoreDLL() : getProcessDpiAwareness(0), setProcessDpiAwareness(0) { - if (QSysInfo::windowsVersion() < QSysInfo::WV_WINDOWS8_1) + if (QOperatingSystemVersion::current() < QOperatingSystemVersion::Windows8_1) return; library.setFileName(QStringLiteral("SHCore")); if (!library.load()) diff --git a/src/src.pro b/src/src.pro index 30562686a..99967fd82 100644 --- a/src/src.pro +++ b/src/src.pro @@ -1,32 +1,50 @@ -include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) -QT_FOR_CONFIG += webenginecore webenginecore-private +load(platform) + +include($$QTWEBENGINE_OUT_ROOT/src/buildtools/qtbuildtools-config.pri) +QT_FOR_CONFIG += buildtools-private TEMPLATE = subdirs -process.depends = core -webengine.depends = core -webenginewidgets.depends = core webengine -webengine_plugin.subdir = webengine/plugin -webengine_plugin.target = sub-webengine-plugin -webengine_plugin.depends = webengine +isWebEngineCoreBuild():qtConfig(webengine-core) { + include($$QTWEBENGINE_OUT_ROOT/src/core/qtwebenginecore-config.pri) + include($$QTWEBENGINE_OUT_ROOT/src/webengine/qtwebengine-config.pri) + include($$QTWEBENGINE_OUT_ROOT/src/webenginewidgets/qtwebenginewidgets-config.pri) + QT_FOR_CONFIG += webenginecore webenginecore-private webengine-private webenginewidgets-private + + process.depends = core + webengine.depends = core + webenginewidgets.depends = core webengine + webengine_plugin.subdir = webengine/plugin + webengine_plugin.target = sub-webengine-plugin + webengine_plugin.depends = webengine -core.depends = buildtools + core.depends = buildtools -SUBDIRS += buildtools \ - core \ - process + SUBDIRS += buildtools \ + core \ + process -qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile { + qtConfig(webengine-spellchecker):!qtConfig(webengine-native-spellchecker):!cross_compile { SUBDIRS += qwebengine_convert_dict qwebengine_convert_dict.subdir = tools/qwebengine_convert_dict qwebengine_convert_dict.depends = core -} + } -qtConfig(webengine-qml) { - SUBDIRS += webengine -} + qtConfig(webengine-qml) { + SUBDIRS += webengine + } -qtConfig(webengine-widgets) { - SUBDIRS += plugins webenginewidgets - plugins.depends = webenginewidgets + qtConfig(webengine-widgets) { + SUBDIRS += plugins webenginewidgets + plugins.depends = webenginewidgets + } +} else { + !isEmpty(skipBuildReason):!build_pass { + log(QtWebEngine will not be built. $${skipBuildReason} $${EOL}) + errorbuild.commands = @echo QtWebEngine will not be built. $${skipBuildReason} + errorbuild.CONFIG = phony + QMAKE_EXTRA_TARGETS += errorbuild + first.depends += errorbuild + QMAKE_EXTRA_TARGETS += first + } } diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp index 30283dc03..58d950cd9 100644 --- a/src/webengine/api/qquickwebengineview.cpp +++ b/src/webengine/api/qquickwebengineview.cpp @@ -43,6 +43,7 @@ #include "profile_adapter.h" #include "certificate_error_controller.h" #include "file_picker_controller.h" +#include "find_text_helper.h" #include "javascript_dialog_controller.h" #include "touch_selection_menu_controller.h" @@ -61,6 +62,7 @@ #include "qquickwebenginesettings_p.h" #include "qquickwebenginescript_p.h" #include "qquickwebenginetouchhandleprovider_p_p.h" +#include "qwebenginefindtextresult.h" #include "qwebenginequotarequest.h" #include "qwebengineregisterprotocolhandlerrequest.h" @@ -164,7 +166,6 @@ QQuickWebEngineViewPrivate::~QQuickWebEngineViewPrivate() { Q_ASSERT(m_profileInitialized); m_profile->d_ptr->removeWebContentsAdapterClient(this); - adapter->stopFinding(); if (faviconProvider) faviconProvider->detach(q_ptr); // q_ptr->d_ptr might be null due to destroy() @@ -273,8 +274,8 @@ void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const Q Q_EMIT q->navigationRequested(&navigationRequest); navigationRequestAction = navigationRequest.action(); - if ((navigationRequestAction == WebContentsAdapterClient::AcceptRequest) && adapter->isFindTextInProgress()) - adapter->stopFinding(); + if ((navigationRequestAction == WebContentsAdapterClient::AcceptRequest) && adapter->findTextHelper()->isFindTextInProgress()) + adapter->findTextHelper()->stopFinding(); } void QQuickWebEngineViewPrivate::javascriptDialog(QSharedPointer<JavaScriptDialogController> dialog) @@ -699,6 +700,12 @@ void QQuickWebEngineViewPrivate::widgetChanged(RenderWidgetHostViewQtDelegate *n bindViewAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateQuick *>(newWidgetBase)); } +void QQuickWebEngineViewPrivate::findTextFinished(const QWebEngineFindTextResult &result) +{ + Q_Q(QQuickWebEngineView); + Q_EMIT q->findTextFinished(result); +} + WebEngineSettings *QQuickWebEngineViewPrivate::webEngineSettings() const { return m_settings->d_ptr.data(); @@ -1185,14 +1192,6 @@ void QQuickWebEngineViewPrivate::didRunJavaScript(quint64 requestId, const QVari callback.call(args); } -void QQuickWebEngineViewPrivate::didFindText(quint64 requestId, int matchCount) -{ - QJSValue callback = m_callbacks.take(requestId); - QJSValueList args; - args.append(QJSValue(matchCount)); - callback.call(args); -} - void QQuickWebEngineViewPrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) { Q_Q(QQuickWebEngineView); @@ -1464,18 +1463,8 @@ void QQuickWebEngineView::findText(const QString &subString, FindFlags options, Q_D(QQuickWebEngineView); if (!d->adapter->isInitialized()) return; - if (subString.isEmpty()) { - d->adapter->stopFinding(); - if (!callback.isUndefined()) { - QJSValueList args; - args.append(QJSValue(0)); - const_cast<QJSValue&>(callback).call(args); - } - } else { - quint64 requestId = d->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward); - if (!callback.isUndefined()) - d->m_callbacks.insert(requestId, callback); - } + + d->adapter->findTextHelper()->startFinding(subString, options & FindCaseSensitively, options & FindBackward, callback); } QQuickWebEngineHistory *QQuickWebEngineView::navigationHistory() const diff --git a/src/webengine/api/qquickwebengineview_p.h b/src/webengine/api/qquickwebengineview_p.h index 3c8e1d9ec..4a88e3c28 100644 --- a/src/webengine/api/qquickwebengineview_p.h +++ b/src/webengine/api/qquickwebengineview_p.h @@ -79,6 +79,7 @@ class QQuickWebEngineSettings; class QQuickWebEngineTooltipRequest; class QQuickWebEngineFormValidationMessageRequest; class QQuickWebEngineViewPrivate; +class QWebEngineFindTextResult; class QWebEngineQuotaRequest; class QWebEngineRegisterProtocolHandlerRequest; @@ -574,6 +575,7 @@ Q_SIGNALS: Q_REVISION(10) void tooltipRequested(QQuickWebEngineTooltipRequest *request); Q_REVISION(11) void lifecycleStateChanged(LifecycleState state); Q_REVISION(11) void recommendedStateChanged(LifecycleState state); + Q_REVISION(11) void findTextFinished(const QWebEngineFindTextResult &result); #if QT_CONFIG(webengine_testsupport) void testSupportChanged(); diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h index e0f2595ec..df6843ac3 100644 --- a/src/webengine/api/qquickwebengineview_p_p.h +++ b/src/webengine/api/qquickwebengineview_p_p.h @@ -80,6 +80,7 @@ class QQuickWebEngineSettings; class QQuickWebEngineFaviconProvider; class QQuickWebEngineProfilePrivate; class QQuickWebEngineTouchHandleProvider; +class QWebEngineFindTextResult; QQuickWebEngineView::WebAction editorActionForKeyEvent(QKeyEvent* event); @@ -133,7 +134,6 @@ public: void didRunJavaScript(quint64, const QVariant&) override; void didFetchDocumentMarkup(quint64, const QString&) override { } void didFetchDocumentInnerText(quint64, const QString&) override { } - void didFindText(quint64, int) override; void didPrintPage(quint64 requestId, QSharedPointer<QByteArray>) override; void didPrintPageToPdf(const QString &filePath, bool success) override; bool passOnFocus(bool reverse) override; @@ -170,6 +170,7 @@ public: QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; void printRequested() override; void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidgetBase) override; + void findTextFinished(const QWebEngineFindTextResult &result) override; void updateAction(QQuickWebEngineView::WebAction) const; void adoptWebContents(QtWebEngineCore::WebContentsAdapter *webContents); diff --git a/src/webengine/configure.json b/src/webengine/configure.json index ec5ad34d9..ebe1ddb2b 100644 --- a/src/webengine/configure.json +++ b/src/webengine/configure.json @@ -1,9 +1,20 @@ { "module": "webengine", + "condition": "module.webenginecore && features.webengine-qml", "depends": [ "webenginecore-private" ], + "commandline": { + "options": { + "webengine-qml": "boolean" + } + }, "features": { + "webengine-qml": { + "label": "Support Qt WebEngine Qml", + "purpose": "Provides WebEngine Qml support.", + "output": [ "privateFeature" ] + }, "webengine-ui-delegates": { "label": "UI Delegates", "section": "WebEngine", @@ -18,8 +29,8 @@ "summary": [ { "section": "Qt WebEngineQml", - "condition": "features.webengine-qml", "entries": [ + "webengine-qml", "webengine-ui-delegates", "webengine-testsupport" ] diff --git a/src/webengine/doc/src/webengineview_lgpl.qdoc b/src/webengine/doc/src/webengineview_lgpl.qdoc index 1c4328d01..8f03774c8 100644 --- a/src/webengine/doc/src/webengineview_lgpl.qdoc +++ b/src/webengine/doc/src/webengineview_lgpl.qdoc @@ -414,26 +414,33 @@ \qmlmethod void WebEngineView::findText(string subString) \since QtWebEngine 1.1 Finds the specified string, \a subString, in the page. + The findTextFinished() signal is emitted when a string search is completed. To clear the search highlight, just pass an empty string. + + \sa findTextFinished() */ /*! \qmlmethod void WebEngineView::findText(string subString, FindFlags options) \since QtWebEngine 1.1 Finds the specified string, \a subString, in the page, using the given \a options. + The findTextFinished() signal is emitted when a string search is completed. To clear the search highlight, just pass an empty string. \code findText("Qt", WebEngineView.FindBackward | WebEngineView.FindCaseSensitively); \endcode + + \sa findTextFinished() */ /*! \qmlmethod void WebEngineView::findText(string subString, FindFlags options, variant resultCallback) \since QtWebEngine 1.1 Finds the specified string, \a subString, in the page, using the given \a options. + The findTextFinished() signal is emitted when a string search is completed. To clear the search highlight, just pass an empty string. @@ -447,6 +454,8 @@ console.log("Qt was found!"); }); \endcode + + \sa findTextFinished() */ /*! @@ -1569,5 +1578,39 @@ resource state is however completely safe. \sa lifecycleState, {WebEngine Lifecycle Example} +*/ + +/*! + \qmltype FindTextResult + \instantiates QWebEngineFindTextResult + \inqmlmodule QtWebEngine + \since QtWebEngine 1.11 + + \brief A utility type for encapsulating the result of a string search on a page. + + \sa WebEngineView::findTextFinished() +*/ + +/*! + \qmlproperty int FindTextResult::numberOfMatches + \readonly + + \brief The number of matches found. +*/ + +/*! + \qmlproperty int FindTextResult::activeMatchOrdinal + \readonly + + \brief The index of the currently highlighted match. +*/ + +/*! + \qmlsignal WebEngineView::findTextFinished(FindTextResult result) + \since QtWebEngine 1.11 + + This signal is emitted when a string search on a page is completed. \a result is + the result of the string search. + \sa findText(), FindTextResult */ diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp index ad49d6543..e47a46a95 100644 --- a/src/webengine/plugin/plugin.cpp +++ b/src/webengine/plugin/plugin.cpp @@ -55,6 +55,7 @@ #include <QtWebEngine/private/qquickwebenginetouchhandleprovider_p_p.h> #include <QtWebEngine/private/qquickwebengineview_p.h> #include <QtWebEngine/private/qquickwebengineaction_p.h> +#include <QtWebEngineCore/qwebenginefindtextresult.h> #include <QtWebEngineCore/qwebenginenotification.h> #include <QtWebEngineCore/qwebenginequotarequest.h> #include <QtWebEngineCore/qwebengineregisterprotocolhandlerrequest.h> @@ -170,6 +171,8 @@ public: qmlRegisterUncreatableType<QWebEngineNotification>(uri, 1, 9, "WebEngineNotification", msgUncreatableType("WebEngineNotification")); qmlRegisterUncreatableType<QQuickWebEngineTooltipRequest>(uri, 1, 10, "TooltipRequest", msgUncreatableType("TooltipRequest")); + qRegisterMetaType<QWebEngineFindTextResult>(); + qmlRegisterUncreatableType<QWebEngineFindTextResult>(uri, 1, 11, "FindTextResult", msgUncreatableType("FindTextResult")); } private: diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.cpp b/src/webenginewidgets/api/qwebenginecertificateerror.cpp index f04b73615..a61d98f94 100644 --- a/src/webenginewidgets/api/qwebenginecertificateerror.cpp +++ b/src/webenginewidgets/api/qwebenginecertificateerror.cpp @@ -39,6 +39,8 @@ #include "qwebenginecertificateerror.h" +#include "certificate_error_controller.h" + QT_BEGIN_NAMESPACE /*! @@ -51,14 +53,38 @@ QT_BEGIN_NAMESPACE QWebEnginePage::certificateError(). */ -class QWebEngineCertificateErrorPrivate { +class QWebEngineCertificateErrorPrivate : public QSharedData { public: QWebEngineCertificateErrorPrivate(int error, QUrl url, bool overridable, QString errorDescription); + ~QWebEngineCertificateErrorPrivate() { + if (deferred && !answered) + rejectCertificate(); + } + + void resolveError(bool accept) { + if (answered) + return; + answered = true; + if (overridable) { + if (auto ctl = controller.lock()) + ctl->accept(accept); + } + } + + void ignoreCertificateError() { resolveError(true); } + void rejectCertificate() { resolveError(false); } + QWebEngineCertificateError::Error error; QUrl url; bool overridable; QString errorDescription; + QList<QSslCertificate> chain; + + bool answered = false, deferred = false; + QWeakPointer<CertificateErrorController> controller; + + Q_DISABLE_COPY(QWebEngineCertificateErrorPrivate) }; QWebEngineCertificateErrorPrivate::QWebEngineCertificateErrorPrivate(int error, QUrl url, bool overridable, QString errorDescription) @@ -68,17 +94,31 @@ QWebEngineCertificateErrorPrivate::QWebEngineCertificateErrorPrivate(int error, , errorDescription(errorDescription) { } - /*! \internal */ QWebEngineCertificateError::QWebEngineCertificateError(int error, QUrl url, bool overridable, QString errorDescription) - : d_ptr(new QWebEngineCertificateErrorPrivate(error, url, overridable, errorDescription)) + : d(new QWebEngineCertificateErrorPrivate(error, url, overridable, errorDescription)) { } /*! \internal */ +QWebEngineCertificateError::QWebEngineCertificateError(const QSharedPointer<CertificateErrorController> &controller) + : d(new QWebEngineCertificateErrorPrivate(controller->error(), controller->url(), + controller->overridable(), controller->errorString())) +{ + d->controller = controller; + d->chain = controller->chain(); +} + +QWebEngineCertificateError::QWebEngineCertificateError(const QWebEngineCertificateError &other) = default; + +QWebEngineCertificateError& QWebEngineCertificateError::operator=(const QWebEngineCertificateError &other) = default; + +/*! \internal +*/ QWebEngineCertificateError::~QWebEngineCertificateError() { + } /*! @@ -116,7 +156,6 @@ QWebEngineCertificateError::~QWebEngineCertificateError() */ bool QWebEngineCertificateError::isOverridable() const { - const Q_D(QWebEngineCertificateError); return d->overridable; } @@ -127,7 +166,6 @@ bool QWebEngineCertificateError::isOverridable() const */ QUrl QWebEngineCertificateError::url() const { - const Q_D(QWebEngineCertificateError); return d->url; } @@ -138,7 +176,6 @@ QUrl QWebEngineCertificateError::url() const */ QWebEngineCertificateError::Error QWebEngineCertificateError::error() const { - const Q_D(QWebEngineCertificateError); return d->error; } @@ -149,8 +186,66 @@ QWebEngineCertificateError::Error QWebEngineCertificateError::error() const */ QString QWebEngineCertificateError::errorDescription() const { - const Q_D(QWebEngineCertificateError); return d->errorDescription; } +/*! + Marks the certificate error for delayed handling. + + This function should be called when there is a need to postpone the decision whether to ignore a + certificate error, for example, while waiting for user input. When called, the function pauses the + URL request until ignoreCertificateError() or rejectCertificate() is called. + + \note It is only possible to defer overridable certificate errors. + + \sa isOverridable(), deferred() +*/ +void QWebEngineCertificateError::defer() +{ + if (isOverridable()) + d->deferred = true; +} + +/*! + Returns whether the decision for error handling was delayed and the URL load was halted. +*/ +bool QWebEngineCertificateError::deferred() const +{ + return d->deferred; +} + +/*! + Ignores the certificate error and continues the loading of the requested URL. +*/ +void QWebEngineCertificateError::ignoreCertificateError() +{ + d->ignoreCertificateError(); +} + +/*! + Rejects the certificate and aborts the loading of the requested URL. +*/ +void QWebEngineCertificateError::rejectCertificate() +{ + d->rejectCertificate(); +} + +/*! + Returns \c true if the error was explicitly rejected or accepted. +*/ +bool QWebEngineCertificateError::answered() const +{ + return d->answered; +} + +/*! + Returns the peer's chain of digital certificates + + Chain starts with the peer's immediate certificate and ending with the CA's certificate. +*/ +QList<QSslCertificate> QWebEngineCertificateError::chain() const +{ + return d->chain; +} + QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginecertificateerror.h b/src/webenginewidgets/api/qwebenginecertificateerror.h index 82ac281be..b2dd65a9f 100644 --- a/src/webenginewidgets/api/qwebenginecertificateerror.h +++ b/src/webenginewidgets/api/qwebenginecertificateerror.h @@ -42,11 +42,13 @@ #include <QtWebEngineWidgets/qtwebenginewidgetsglobal.h> -#include <QtCore/qscopedpointer.h> +#include <QtCore/qsharedpointer.h> #include <QtCore/qurl.h> +#include <QtNetwork/QSslCertificate> QT_BEGIN_NAMESPACE +class CertificateErrorController; class QWebEngineCertificateErrorPrivate; class QWEBENGINEWIDGETS_EXPORT QWebEngineCertificateError { @@ -78,10 +80,22 @@ public: bool isOverridable() const; QString errorDescription() const; + QWebEngineCertificateError(const QWebEngineCertificateError &other); + QWebEngineCertificateError& operator=(const QWebEngineCertificateError &other); + + void defer(); + bool deferred() const; + + void rejectCertificate(); + void ignoreCertificateError(); + bool answered() const; + + QList<QSslCertificate> chain() const; + private: - Q_DISABLE_COPY(QWebEngineCertificateError) - Q_DECLARE_PRIVATE(QWebEngineCertificateError) - QScopedPointer<QWebEngineCertificateErrorPrivate> d_ptr; + friend class QWebEnginePagePrivate; + QWebEngineCertificateError(const QSharedPointer<CertificateErrorController> &controller); + QExplicitlySharedDataPointer<QWebEngineCertificateErrorPrivate> d; }; QT_END_NAMESPACE diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp index 7ce572e2f..7b0cfe074 100644 --- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp +++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2016 The Qt Company Ltd. +** Copyright (C) 2019 The Qt Company Ltd. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtWebEngine module of the Qt Toolkit. @@ -124,8 +124,9 @@ static inline QWebEngineDownloadItem::DownloadInterruptReason toDownloadInterrup then the download request will be automatically rejected and nothing will be written to disk. - \note Some properties, like the \l path under which the file will be saved, - can only be changed before calling accept(). + \note Some properties, such as setting the path and file name where the file + will be saved (see \l downloadDirectory() and \l downloadFileName()), can + only be changed before calling accept(). \section2 Object Life Cycle @@ -510,6 +511,10 @@ QString QWebEngineDownloadItem::mimeType() const /*! \obsolete + + Use \l suggestedFileName(), \l downloadDirectory(), and + \l downloadFileName() instead. + Returns the full target path where data is being downloaded to. The path includes the file name. The default suggested path is the standard download location @@ -523,6 +528,10 @@ QString QWebEngineDownloadItem::path() const } /*! + \obsolete + + Use \l setDownloadDirectory() and \l setDownloadFileName() instead. + Sets the full target path to download the file to. The \a path should also include the file name. The download path can only be set in response @@ -572,7 +581,7 @@ QString QWebEngineDownloadItem::downloadDirectory() const /*! \since 5.14 - Sets the directory path to download the file to. + Sets \a directory as the directory path to download the file to. The download directory path can only be set in response to the QWebEngineProfile::downloadRequested() signal before the download is accepted. Past that point, this function has no effect on the @@ -598,7 +607,7 @@ void QWebEngineDownloadItem::setDownloadDirectory(QString directory) /*! \since 5.14 - Returns the suggested file name. + Returns the file name to download the file to. */ QString QWebEngineDownloadItem::downloadFileName() const @@ -610,7 +619,7 @@ QString QWebEngineDownloadItem::downloadFileName() const /*! \since 5.14 - Sets the file name to download the file to. + Sets \a fileName as the file name to download the file to. The download file name can only be set in response to the QWebEngineProfile::downloadRequested() signal before the download is accepted. Past that point, this function has no effect on the diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp index e990170eb..b22d47916 100644 --- a/src/webenginewidgets/api/qwebenginepage.cpp +++ b/src/webenginewidgets/api/qwebenginepage.cpp @@ -45,12 +45,14 @@ #include "certificate_error_controller.h" #include "color_chooser_controller.h" #include "favicon_manager.h" +#include "find_text_helper.h" #include "file_picker_controller.h" #include "javascript_dialog_controller.h" #if QT_CONFIG(webengine_printing_and_pdf) #include "printer_worker.h" #endif #include "qwebenginecertificateerror.h" +#include "qwebenginefindtextresult.h" #include "qwebenginefullscreenrequest.h" #include "qwebenginehistory.h" #include "qwebenginehistory_p.h" @@ -170,6 +172,7 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile) qRegisterMetaType<QWebEngineQuotaRequest>(); qRegisterMetaType<QWebEngineRegisterProtocolHandlerRequest>(); + qRegisterMetaType<QWebEngineFindTextResult>(); // See setVisible(). wasShownTimer.setSingleShot(true); @@ -291,6 +294,7 @@ void QWebEnginePagePrivate::loadStarted(const QUrl &provisionalUrl, bool isError return; isLoading = true; + m_certificateErrorControllers.clear(); QTimer::singleShot(0, q, &QWebEnginePage::loadStarted); } @@ -420,11 +424,6 @@ void QWebEnginePagePrivate::didFetchDocumentInnerText(quint64 requestId, const Q m_callbacks.invoke(requestId, result); } -void QWebEnginePagePrivate::didFindText(quint64 requestId, int matchCount) -{ - m_callbacks.invoke(requestId, matchCount > 0); -} - void QWebEnginePagePrivate::didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) { #if QT_CONFIG(webengine_printing_and_pdf) @@ -702,6 +701,12 @@ void QWebEnginePagePrivate::widgetChanged(RenderWidgetHostViewQtDelegate *newWid bindPageAndWidget(q, static_cast<RenderWidgetHostViewQtDelegateWidget *>(newWidgetBase)); } +void QWebEnginePagePrivate::findTextFinished(const QWebEngineFindTextResult &result) +{ + Q_Q(QWebEnginePage); + Q_EMIT q->findTextFinished(result); +} + void QWebEnginePagePrivate::ensureInitialized() const { if (!adapter->isInitialized()) @@ -802,6 +807,16 @@ QWebEnginePage::QWebEnginePage(QObject* parent) } /*! + \fn void QWebEnginePage::findTextFinished(const QWebEngineFindTextResult &result) + \since 5.14 + + This signal is emitted when a search string search on a page is completed. \a result is + the result of the string search. + + \sa findText() +*/ + +/*! \fn void QWebEnginePage::printRequested() \since 5.12 @@ -963,7 +978,6 @@ QWebEnginePage::~QWebEnginePage() if (d_ptr) { // d_ptr might be exceptionally null if profile adapter got deleted first setDevToolsPage(nullptr); - d_ptr->adapter->stopFinding(); QWebEnginePagePrivate::bindPageAndView(this, nullptr); QWebEnginePagePrivate::bindPageAndWidget(this, nullptr); } @@ -1592,16 +1606,11 @@ void QWebEnginePage::findText(const QString &subString, FindFlags options, const { Q_D(QWebEnginePage); if (!d->adapter->isInitialized()) { - d->m_callbacks.invokeEmpty(resultCallback); + QtWebEngineCore::CallbackDirectory().invokeEmpty(resultCallback); return; } - if (subString.isEmpty()) { - d->adapter->stopFinding(); - d->m_callbacks.invokeEmpty(resultCallback); - } else { - quint64 requestId = d->adapter->findText(subString, options & FindCaseSensitively, options & FindBackward); - d->m_callbacks.registerCallback(requestId, resultCallback); - } + + d->adapter->findTextHelper()->startFinding(subString, options & FindCaseSensitively, options & FindBackward, resultCallback); } /*! @@ -1652,8 +1661,8 @@ void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl & { Q_Q(QWebEnginePage); bool accepted = q->acceptNavigationRequest(url, static_cast<QWebEnginePage::NavigationType>(navigationType), isMainFrame); - if (accepted && adapter->isFindTextInProgress()) - adapter->stopFinding(); + if (accepted && adapter->findTextHelper()->isFindTextInProgress()) + adapter->findTextHelper()->stopFinding(); navigationRequestAction = accepted ? WebContentsAdapterClient::AcceptRequest : WebContentsAdapterClient::IgnoreRequest; } @@ -1707,10 +1716,11 @@ void QWebEnginePagePrivate::allowCertificateError(const QSharedPointer<Certifica Q_Q(QWebEnginePage); bool accepted = false; - QWebEngineCertificateError error(controller->error(), controller->url(), controller->overridable() && !controller->strictEnforcement(), controller->errorString()); + QWebEngineCertificateError error(controller); accepted = q->certificateError(error); - - if (error.isOverridable()) + if (error.deferred() && !error.answered()) + m_certificateErrorControllers.append(controller); + else if (!error.answered() && error.isOverridable()) controller->accept(accepted); } diff --git a/src/webenginewidgets/api/qwebenginepage.h b/src/webenginewidgets/api/qwebenginepage.h index 736d7ed69..cd012ea70 100644 --- a/src/webenginewidgets/api/qwebenginepage.h +++ b/src/webenginewidgets/api/qwebenginepage.h @@ -62,6 +62,7 @@ class QWebChannel; class QWebEngineCertificateError; class QWebEngineClientCertificateSelection; class QWebEngineContextMenuData; +class QWebEngineFindTextResult; class QWebEngineFullScreenRequest; class QWebEngineHistory; class QWebEnginePage; @@ -369,6 +370,8 @@ Q_SIGNALS: void lifecycleStateChanged(LifecycleState state); void recommendedStateChanged(LifecycleState state); + void findTextFinished(const QWebEngineFindTextResult &result); + protected: virtual QWebEnginePage *createWindow(WebWindowType type); virtual QStringList chooseFiles(FileSelectionMode mode, const QStringList &oldFiles, const QStringList &acceptedMimeTypes); diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h index acf95a265..2843f69c4 100644 --- a/src/webenginewidgets/api/qwebenginepage_p.h +++ b/src/webenginewidgets/api/qwebenginepage_p.h @@ -72,6 +72,7 @@ class WebContentsAdapter; } QT_BEGIN_NAMESPACE +class QWebEngineFindTextResult; class QWebEngineHistory; class QWebEnginePage; class QWebEngineProfile; @@ -127,7 +128,6 @@ public: void didRunJavaScript(quint64 requestId, const QVariant& result) override; void didFetchDocumentMarkup(quint64 requestId, const QString& result) override; void didFetchDocumentInnerText(quint64 requestId, const QString& result) override; - void didFindText(quint64 requestId, int matchCount) override; void didPrintPage(quint64 requestId, QSharedPointer<QByteArray> result) override; void didPrintPageToPdf(const QString &filePath, bool success) override; bool passOnFocus(bool reverse) override; @@ -163,6 +163,7 @@ public: ClientType clientType() override { return QtWebEngineCore::WebContentsAdapterClient::WidgetsClient; } void interceptRequest(QWebEngineUrlRequestInfo &) override; void widgetChanged(QtWebEngineCore::RenderWidgetHostViewQtDelegate *newWidget) override; + void findTextFinished(const QWebEngineFindTextResult &result) override; QtWebEngineCore::ProfileAdapter *profileAdapter() override; QtWebEngineCore::WebContentsAdapter *webContentsAdapter() override; @@ -209,6 +210,8 @@ public: #if QT_CONFIG(webengine_printing_and_pdf) QPrinter *currentPrinter; #endif + + QList<QSharedPointer<CertificateErrorController>> m_certificateErrorControllers; }; class QContextMenuBuilder : public QtWebEngineCore::RenderViewContextMenuQt diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp index 6e2db533e..4a77eb8cf 100644 --- a/src/webenginewidgets/api/qwebengineprofile.cpp +++ b/src/webenginewidgets/api/qwebengineprofile.cpp @@ -101,7 +101,7 @@ using QtWebEngineCore::ProfileAdapter; web pages not specifically created with another profile belong to. Implementing the QWebEngineUrlRequestInterceptor interface and registering the interceptor on a - profile by setRequestInterceptor() enables intercepting, blocking, and modifying URL + profile by setUrlRequestInterceptor() enables intercepting, blocking, and modifying URL requests (QWebEngineUrlRequestInfo) before they reach the networking stack of Chromium. A QWebEngineUrlSchemeHandler can be registered for a profile by installUrlSchemeHandler() diff --git a/src/webenginewidgets/configure.json b/src/webenginewidgets/configure.json new file mode 100644 index 000000000..a27faf78d --- /dev/null +++ b/src/webenginewidgets/configure.json @@ -0,0 +1,28 @@ +{ + "module": "webenginewidgets", + "condition": "module.webenginecore && features.webengine-widgets", + "depends": [ + "webenginecore-private" + ], + "commandline": { + "options": { + "webengine-widgets": "boolean" + } + }, + "features": { + "webengine-widgets": { + "label": "Support Qt WebEngine Widgets", + "purpose": "Provides WebEngine Widgets support.", + "condition": "module.widgets", + "output": [ "privateFeature" ] + } + }, + "summary": [ + { + "section": "Qt WebEngineWidgets", + "entries": [ + "webengine-widgets" + ] + } + ] +} diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc index 99bbc5162..699d7f181 100644 --- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc @@ -489,6 +489,7 @@ /*! \fn void QWebEnginePage::findText(const QString &subString, QWebEnginePage::FindFlags options = FindFlags(), const QWebEngineCallback<bool> &resultCallback = QWebEngineCallback<bool>()) Finds the specified string, \a subString, in the page, using the given \a options. + The findTextFinished() signal is emitted when a string search is completed. To clear the search highlight, just pass an empty string. @@ -501,13 +502,15 @@ For example: \snippet qtwebengine_qwebenginepage_snippet.cpp 0 + + \sa findTextFinished() */ /*! \fn QWebEngineSettings *QWebEnginePage::settings() const Returns a pointer to the page's settings object. - \sa QWebEngineSettings::globalSettings() + \sa QWebEngineSettings::defaultSettings() */ /*! @@ -519,6 +522,8 @@ Return \c true to ignore the error and complete the request. Return \c false to stop loading the request. + \note If the error was successfully deferred then the returned value will be ignored. + \sa QWebEngineCertificateError */ diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc index ce75a4203..0706598ef 100644 --- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc @@ -22,12 +22,14 @@ // by its LGPL license. Documentation written from scratch for new methods should be // placed inline in the code as usual. +#if QT_DEPRECATED_SINCE(5, 5) /*! \fn static QWebEngineSettings *QWebEngineSettings::globalSettings() \obsolete Use defaultSettings() instead. */ +#endif /*! \class QWebEngineSettings diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc index 1b7812dff..3f1b6e509 100644 --- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc +++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc @@ -393,5 +393,5 @@ \snippet qtwebengine_qwebengineview_snippet.cpp 6 - \sa QWebEngineSettings::globalSettings() + \sa QWebEngineSettings::defaultSettings() */ |