summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--configure.json12
-rw-r--r--configure.pri34
-rw-r--r--dist/changes-5.9.468
-rw-r--r--examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui199
-rw-r--r--mkspecs/features/configure.prf2
-rw-r--r--mkspecs/features/gn_generator.prf11
m---------src/3rdparty0
-rw-r--r--src/core/api/core_api.pro2
-rw-r--r--src/core/api/qwebenginebrowsercontext.cpp73
-rw-r--r--src/core/api/qwebenginebrowsercontext_p.h83
-rw-r--r--src/core/api/qwebenginecookiestore.cpp5
-rw-r--r--src/core/api/qwebengineurlrequestjob.cpp8
-rw-r--r--src/core/browser_context_adapter.cpp14
-rw-r--r--src/core/browser_context_adapter.h2
-rw-r--r--src/core/config/common.pri15
-rw-r--r--src/core/content_browser_client_qt.cpp9
-rw-r--r--src/core/core_module.pro13
-rw-r--r--src/core/delegated_frame_node.cpp2
-rw-r--r--src/core/pdfium_document_wrapper_qt.cpp20
-rw-r--r--src/core/pdfium_document_wrapper_qt.h6
-rw-r--r--src/core/proxy_config_service_qt.cpp14
-rw-r--r--src/core/renderer/user_resource_controller.cpp25
-rw-r--r--src/core/url_request_custom_job.cpp6
-rw-r--r--src/core/web_contents_adapter.cpp12
-rw-r--r--src/core/web_contents_adapter_client.h2
-rw-r--r--src/core/web_contents_delegate_qt.cpp25
-rw-r--r--src/core/web_engine_context.cpp21
-rw-r--r--src/core/web_engine_context.h5
-rw-r--r--src/core/web_event_factory.cpp3
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp20
-rw-r--r--src/webengine/api/qquickwebengineprofile_p.h7
-rw-r--r--src/webengine/api/qquickwebengineview.cpp7
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h5
-rw-r--r--src/webengine/ui_delegates_manager.cpp5
-rw-r--r--src/webengine/webengine.pro2
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem.cpp7
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp49
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h5
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp24
-rw-r--r--src/webenginewidgets/api/qwebengineprofile_p.h16
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp15
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc5
-rw-r--r--src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc5
-rw-r--r--tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp35
-rw-r--r--tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp54
-rw-r--r--tests/auto/quick/qmltests/data/TestWebEngineView.qml18
-rw-r--r--tests/auto/quick/qmltests/data/favicon.html2
-rw-r--r--tests/auto/quick/qmltests/data/tst_contextMenu.qml224
-rw-r--r--tests/auto/quick/qmltests/data/tst_favicon.qml91
-rw-r--r--tests/auto/quick/qmltests/data/tst_mouseClick.qml18
-rw-r--r--tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml57
-rw-r--r--tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml44
-rw-r--r--tests/auto/quick/qmltests/qmltests.pro3
-rw-r--r--tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp21
-rw-r--r--tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp30
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp19
-rw-r--r--tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp20
-rw-r--r--tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp31
-rw-r--r--tests/auto/widgets/qwebengineview/BLACKLIST2
59 files changed, 1119 insertions, 413 deletions
diff --git a/configure.json b/configure.json
index 398df0ce9..7ef1f5003 100644
--- a/configure.json
+++ b/configure.json
@@ -534,7 +534,7 @@
"output": [ "privateFeature" ]
},
"webengine-sanitizer" : {
- "label": "Sanitizer ",
+ "label": "Sanitizer",
"autoDetect": "config.sanitizer && tests.webengine-sanitizer",
"condition": "config.sanitizer",
"output": [ "privateFeature" ]
@@ -561,6 +561,11 @@
"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."
}
],
@@ -588,6 +593,11 @@
"condition": "config.unix"
},
{
+ "type": "feature",
+ "args": "webengine-sanitizer",
+ "condition": "config.sanitizer"
+ },
+ {
"section": "Optional system libraries used",
"condition": "config.unix",
"entries": [
diff --git a/configure.pri b/configure.pri
index e0e482685..497557262 100644
--- a/configure.pri
+++ b/configure.pri
@@ -159,6 +159,7 @@ defineTest(qtConfTest_detectIcuuc) {
defineTest(qtConfTest_isSanitizerSupported) {
sanitizer_combo_supported = true
+
sanitize_address {
asan_supported = false
linux-clang-libc++:isSanitizerSupportedOnLinux() {
@@ -168,7 +169,7 @@ defineTest(qtConfTest_isSanitizerSupported) {
}
!$$asan_supported {
sanitizer_combo_supported = false
- qtLog("An address sanitizer-enabled Qt WebEngine build can only be built on Linux or macOS using Clang and libc++.")
+ qtLog("An address sanitizer-enabled Qt WebEngine build can only be built on Linux or macOS using Clang and libc++.")
}
}
@@ -179,12 +180,16 @@ defineTest(qtConfTest_isSanitizerSupported) {
sanitize_undefined {
ubsan_supported = false
- linux-clang-libc++:isSanitizerSupportedOnLinux():CONFIG(release, debug|release):!debug_and_release {
- ubsan_supported = true
+ CONFIG(release, debug|release):!debug_and_release {
+ linux-clang-libc++:isSanitizerSupportedOnLinux() {
+ ubsan_supported = true
+ } else:macos:isSanitizerSupportedOnMacOS() {
+ ubsan_supported = true
+ }
}
!$$ubsan_supported {
sanitizer_combo_supported = false
- qtLog("An undefined behavior sanitizer-enabled Qt WebEngine build can only be built on Linux using Clang and libc++ in release mode.")
+ qtLog("An undefined behavior sanitizer-enabled Qt WebEngine build can only be built on Linux or macOS using Clang and libc++ in release mode.")
}
}
@@ -209,11 +214,12 @@ defineTest(isSanitizerSupportedOnLinux) {
}
defineTest(isSanitizerSupportedOnMacOS) {
- isEmpty(QT_APPLE_CLANG_MAJOR_VERSION) {
+ isEmpty(QMAKE_APPLE_CLANG_MAJOR_VERSION) {
QTWEBENGINE_CLANG_IS_APPLE = false
} else {
QTWEBENGINE_CLANG_IS_APPLE = true
}
+
$$QTWEBENGINE_CLANG_IS_APPLE:isSanitizerMacOSAppleClangVersionSupported(): return(true)
else:isSanitizerMacOSClangVersionSupported(): return(true)
return(false)
@@ -221,28 +227,28 @@ defineTest(isSanitizerSupportedOnMacOS) {
defineTest(isSanitizerMacOSAppleClangVersionSupported) {
# Clang sanitizer suppression attributes work from Apple Clang version 7.3.0+.
- greaterThan(QT_APPLE_CLANG_MAJOR_VERSION, 7): return(true)
- greaterThan(QT_APPLE_CLANG_MINOR_VERSION, 2): return(true)
+ greaterThan(QMAKE_APPLE_CLANG_MAJOR_VERSION, 7): return(true)
+ greaterThan(QMAKE_APPLE_CLANG_MINOR_VERSION, 2): return(true)
- qtLog("Using Apple Clang version $${QT_APPLE_CLANG_MAJOR_VERSION}.$${QT_APPLE_CLANG_MINOR_VERSION}.$${QT_APPLE_CLANG_PATCH_VERSION}, but at least Apple Clang version 7.3.0 is required to build a sanitizer-enabled Qt WebEngine.")
+ qtLog("Using Apple Clang version $${QMAKE_APPLE_CLANG_MAJOR_VERSION}.$${QMAKE_APPLE_CLANG_MINOR_VERSION}.$${QMAKE_APPLE_CLANG_PATCH_VERSION}, but at least Apple Clang version 7.3.0 is required to build a sanitizer-enabled Qt WebEngine.")
return(false)
}
defineTest(isSanitizerMacOSClangVersionSupported) {
# Clang sanitizer suppression attributes work from non-apple Clang version 3.7+.
- greaterThan(QT_CLANG_MAJOR_VERSION, 3): return(true)
- greaterThan(QT_CLANG_MINOR_VERSION, 6): return(true)
+ greaterThan(QMAKE_CLANG_MAJOR_VERSION, 3): return(true)
+ greaterThan(QMAKE_CLANG_MINOR_VERSION, 6): return(true)
- qtLog("Using Clang version $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}, but at least Clang version 3.7 is required to build a sanitizer-enabled Qt WebEngine.")
+ qtLog("Using Clang version $${QMAKE_CLANG_MAJOR_VERSION}.$${QMAKE_CLANG_MINOR_VERSION}, but at least Clang version 3.7 is required to build a sanitizer-enabled Qt WebEngine.")
return(false)
}
defineTest(isSanitizerLinuxClangVersionSupported) {
# Clang sanitizer suppression attributes work from Clang version 3.7+.
- greaterThan(QT_CLANG_MAJOR_VERSION, 3): return(true)
- greaterThan(QT_CLANG_MINOR_VERSION, 6): return(true)
+ greaterThan(QMAKE_CLANG_MAJOR_VERSION, 3): return(true)
+ greaterThan(QMAKE_CLANG_MINOR_VERSION, 6): return(true)
- qtLog("Using Clang version $${QT_CLANG_MAJOR_VERSION}.$${QT_CLANG_MINOR_VERSION}, but at least Clang version 3.7 is required to build a sanitizer-enabled Qt WebEngine.")
+ qtLog("Using Clang version $${QMAKE_CLANG_MAJOR_VERSION}.$${QMAKE_CLANG_MINOR_VERSION}, but at least Clang version 3.7 is required to build a sanitizer-enabled Qt WebEngine.")
return(false)
}
diff --git a/dist/changes-5.9.4 b/dist/changes-5.9.4
new file mode 100644
index 000000000..e80c7fcb8
--- /dev/null
+++ b/dist/changes-5.9.4
@@ -0,0 +1,68 @@
+Qt 5.9.4 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.9.0.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+http://doc.qt.io/qt-5/index.html
+
+The Qt version 5.9 series is binary compatible with the 5.8.x series.
+Applications compiled for 5.8 will continue to run with 5.9.
+
+Some of the changes listed in this file include issue tracking numbers
+corresponding to tasks in the Qt Bug Tracker:
+
+https://bugreports.qt.io/
+
+Each of these identifiers can be entered in the bug tracker to obtain more
+information about a particular change.
+
+****************************************************************************
+* Qt 5.9.4 changes *
+****************************************************************************
+
+Chromium
+--------
+
+ * Security fixes from Chromium up to version 63.0.3239.132.
+ Including: CVE-2017-15407, CVE-2017-15409, CVE-2017-15410,
+ CVE-2017-15411, CVE-2017-15415, CVE-2017-15416, CVE-2017-15418,
+ CVE-2017-15419, CVE-2017-15422, CVE-2017-15423, CVE-2017-15424,
+ CVE-2017-15425 and CVE-2017-15426
+ * Mitigation of SPECTRE.
+
+General
+-------
+
+ - [QTBUG-64265] JavaScript MouseLeave events are now always raised
+ when mouse is leaving view.
+ - [QTBUG-63266] JavaScript PointerEvent.pointerType property is now
+ properly set.
+ - [QTBUG-64560] Fixed rendering glitches after renderProcessTerminated
+ signal was emitted.
+ - [QTBUG-47206] Fixed incorrect layouting due to bug in HTML5 viewport
+ support.
+ - [QTBUG-57206] Fixed Favicon not updating if URL gets changed from
+ JavaScript.
+ - [QTBUG-58400] Printing does now use less memory, avoiding OOM situations
+ with very large documents.
+ - [QTBUG-65239] Fixed hanging of process if application is closed too
+ fast after startup.
+
+QtWebEngineWidgets
+------------------
+
+ - [QTBUG-64436] Fixed crash when exiting fullscreen mode using the context
+ menu.
+ - [QTBUG-64933] Fixed tooltips that did still show after mouse was moved
+ away.
+
+Platform Specific Changes
+-------------------------
+
+ - Linux:
+ * [QTBUG-65174] Fixed regression from Qt 5.9.2 where the official
+ QtWebEngine binary did not use the installed
+ certificates via libnss.
+ * [QTBUG-57761] Fixed hardcoded lookup of library libGLES2.so.2 in
+ the system.
diff --git a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui
index 3e70ce89a..19db267e8 100644
--- a/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui
+++ b/examples/webenginewidgets/stylesheetbrowser/stylesheetdialog.ui
@@ -5,154 +5,81 @@
<property name="windowModality">
<enum>Qt::ApplicationModal</enum>
</property>
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>547</width>
- <height>431</height>
- </rect>
- </property>
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>547</width>
- <height>431</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>547</width>
- <height>431</height>
- </size>
- </property>
<property name="windowTitle">
<string>Stylesheets</string>
</property>
<property name="modal">
<bool>true</bool>
</property>
- <layout class="QVBoxLayout" name="verticalLayout">
- <item>
- <widget class="QWidget" name="widget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <widget class="QWidget" name="horizontalLayoutWidget">
- <property name="geometry">
- <rect>
- <x>9</x>
- <y>9</y>
- <width>511</width>
- <height>371</height>
- </rect>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="sizeConstraint">
- <enum>QLayout::SetDefaultConstraint</enum>
- </property>
- <item>
- <widget class="QListWidget" name="styleSheetList"/>
- </item>
- <item>
- <layout class="QVBoxLayout" name="verticalLayout_4">
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <item>
- <widget class="QLabel" name="fileNameLabel">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="text">
- <string>Stylesheet name:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QLineEdit" name="fileNameEdit">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item>
- <widget class="QLabel" name="sourceLabel">
- <property name="text">
- <string>Source code:</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPlainTextEdit" name="sourceCodeEdit">
- <property name="font">
- <font>
- <family>Courier New</family>
- <pointsize>10</pointsize>
- </font>
- </property>
- </widget>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout_4">
- <item>
- <widget class="QPushButton" name="addButton">
- <property name="text">
- <string>Add</string>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QPushButton" name="removeButton">
- <property name="text">
- <string>Remove</string>
- </property>
- </widget>
- </item>
- </layout>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </widget>
- </item>
- <item>
+ <layout class="QGridLayout" name="gridLayout_2">
+ <item row="3" column="1">
<widget class="QDialogButtonBox" name="buttonBox">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="standardButtons">
- <set>QDialogButtonBox::Ok</set>
+ <set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="0" rowspan="3">
+ <widget class="QListWidget" name="styleSheetList"/>
+ </item>
+ <item row="0" column="1" rowspan="3">
+ <widget class="QFrame" name="frame">
+ <property name="frameShape">
+ <enum>QFrame::StyledPanel</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>QFrame::Plain</enum>
</property>
+ <layout class="QGridLayout" name="gridLayout">
+ <item row="0" column="0">
+ <widget class="QLabel" name="fileNameLabel">
+ <property name="text">
+ <string>Stylesheet name:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLineEdit" name="fileNameEdit"/>
+ </item>
+ <item row="1" column="0">
+ <widget class="QLabel" name="sourceLabel">
+ <property name="text">
+ <string>Source code:</string>
+ </property>
+ </widget>
+ </item>
+ <item row="2" column="0" colspan="2">
+ <widget class="QPlainTextEdit" name="sourceCodeEdit">
+ <property name="font">
+ <font>
+ <family>Courier New</family>
+ <pointsize>10</pointsize>
+ </font>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0" colspan="2">
+ <layout class="QHBoxLayout" name="horizontalLayout">
+ <item>
+ <widget class="QPushButton" name="addButton">
+ <property name="text">
+ <string>Add</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QPushButton" name="removeButton">
+ <property name="text">
+ <string>Remove</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ </layout>
</widget>
</item>
</layout>
diff --git a/mkspecs/features/configure.prf b/mkspecs/features/configure.prf
index 904e7b1c0..8b8fd3efe 100644
--- a/mkspecs/features/configure.prf
+++ b/mkspecs/features/configure.prf
@@ -48,7 +48,7 @@ defineTest(runConfigure) {
}
sanitizer: !qtConfig(webengine-sanitizer) {
- skipBuild("Chosen sanitizer configuration is not supported. Use --feature-webengine-sanitizer=yes to force build with the chosen sanitizer configuration.")
+ skipBuild("Chosen sanitizer configuration is not supported. Check config.log for details or use -feature-webengine-sanitizer to force build with the chosen sanitizer configuration.")
return(false);
}
diff --git a/mkspecs/features/gn_generator.prf b/mkspecs/features/gn_generator.prf
index a819e146b..efb8a65a1 100644
--- a/mkspecs/features/gn_generator.prf
+++ b/mkspecs/features/gn_generator.prf
@@ -150,17 +150,6 @@ for (define, DEFINES): {
define = $$replace(define,\',)
GN_CONTENTS += " \"$$define\","
}
-!isEmpty(QT_SYSROOT) {
- !isEmpty(QMAKE_LIBDIR_EGL):
- GN_CONTENTS += " \"QT_LIBDIR_EGL=\\\"$${QMAKE_DIR_SEP}$$relative_path($$QMAKE_LIBDIR_EGL, $$[QT_SYSROOT])\\\"\","
- !isEmpty(QMAKE_LIBDIR_OPENGL_ES2)
- GN_CONTENTS += " \"QT_LIBDIR_GLES2=\\\"$${QMAKE_DIR_SEP}$$relative_path($$QMAKE_LIBDIR_OPENGL_ES2, $$[QT_SYSROOT])\\\"\","
-} else {
- !isEmpty(QMAKE_LIBDIR_EGL):
- GN_CONTENTS += " \"QT_LIBDIR_EGL=\\\"$$QMAKE_LIBDIR_EGL\\\"\","
- !isEmpty(QMAKE_LIBDIR_OPENGL_ES2)
- GN_CONTENTS += " \"QT_LIBDIR_GLES2=\\\"$$QMAKE_LIBDIR_OPENGL_ES2\\\"\","
-}
GN_CONTENTS += " ]"
# Source files to compile
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 3af56a2143e4fa3a10f93917ecde4ef46c2c807
+Subproject 17e4aafb6fe894047b46abeb3c3b8290de4094c
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 270595378..93eebbc45 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -33,6 +33,7 @@ HEADERS = \
qwebenginecallback_p.h \
qtwebenginecoreglobal.h \
qtwebenginecoreglobal_p.h \
+ qwebenginebrowsercontext_p.h \
qwebenginecookiestore.h \
qwebenginecookiestore_p.h \
qwebenginehttprequest.h \
@@ -44,6 +45,7 @@ HEADERS = \
SOURCES = \
qtwebenginecoreglobal.cpp \
+ qwebenginebrowsercontext.cpp \
qwebenginecookiestore.cpp \
qwebenginehttprequest.cpp \
qwebengineurlrequestinfo.cpp \
diff --git a/src/core/api/qwebenginebrowsercontext.cpp b/src/core/api/qwebenginebrowsercontext.cpp
new file mode 100644
index 000000000..c3ab16460
--- /dev/null
+++ b/src/core/api/qwebenginebrowsercontext.cpp
@@ -0,0 +1,73 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 "qwebenginebrowsercontext_p.h"
+
+#include "browser_context_adapter.h"
+#include <qtwebenginecoreglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+QWebEngineBrowserContext::QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext,
+ QtWebEngineCore::BrowserContextAdapterClient *profile)
+ : QObject(QtWebEngineCore::BrowserContextAdapter::globalQObjectRoot())
+ , browserContextRef(browserContext)
+ , m_profile(profile)
+{
+ browserContextRef->addClient(m_profile);
+}
+
+QWebEngineBrowserContext::~QWebEngineBrowserContext()
+{
+ if (m_profile)
+ shutdown();
+}
+
+void QWebEngineBrowserContext::shutdown()
+{
+ Q_ASSERT(m_profile);
+ // In the case the user sets this profile as the parent of the interceptor
+ // it can be deleted before the browser-context still referencing it is.
+ browserContextRef->setRequestInterceptor(nullptr);
+ browserContextRef->removeClient(m_profile);
+ m_profile = 0;
+ deleteLater();
+}
+
+QT_END_NAMESPACE
diff --git a/src/core/api/qwebenginebrowsercontext_p.h b/src/core/api/qwebenginebrowsercontext_p.h
new file mode 100644
index 000000000..713ab730e
--- /dev/null
+++ b/src/core/api/qwebenginebrowsercontext_p.h
@@ -0,0 +1,83 @@
+/****************************************************************************
+**
+** Copyright (C) 2018 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 QWEBENGINEBROWSERCONTEXT_P_H
+#define QWEBENGINEBROWSERCONTEXT_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+#include "qtwebenginecoreglobal_p.h"
+
+#include <QObject>
+#include <QSharedPointer>
+
+namespace QtWebEngineCore {
+class BrowserContextAdapter;
+class BrowserContextAdapterClient;
+}
+
+QT_BEGIN_NAMESPACE
+
+// This is a wrapper class for BrowserContextAdapter. BrowserContextAdapter must be destructed before WebEngineContext
+// is destructed. Therefore access it via the QWebEngineBrowserContext which parent is the WebEngineContext::globalQObject.
+// This guarantees the destruction together with the WebEngineContext.
+class QWEBENGINE_PRIVATE_EXPORT QWebEngineBrowserContext : public QObject {
+public:
+ QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QtWebEngineCore::BrowserContextAdapterClient *profile);
+ ~QWebEngineBrowserContext();
+
+ void shutdown();
+
+ QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextRef;
+
+private:
+ QtWebEngineCore::BrowserContextAdapterClient *m_profile;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBENGINEBROWSERCONTEXT_P_H
diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp
index 8adf46bea..031eb8d3d 100644
--- a/src/core/api/qwebenginecookiestore.cpp
+++ b/src/core/api/qwebenginecookiestore.cpp
@@ -230,7 +230,10 @@ QWebEngineCookieStore::~QWebEngineCookieStore()
/*!
Adds \a cookie to the cookie store.
- It is possible to provide an optional \a origin URL argument to limit the scope of the cookie.
+ \note If \a cookie specifies a QNetworkCookie::domain() that does not start with a dot,
+ a dot is automatically prepended. To limit the cookie to the exact server,
+ omit QNetworkCookie::domain() and set \a origin instead.
+
The provided URL should also include the scheme.
\note This operation is asynchronous.
diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp
index a071adbd5..47aab48a0 100644
--- a/src/core/api/qwebengineurlrequestjob.cpp
+++ b/src/core/api/qwebengineurlrequestjob.cpp
@@ -115,12 +115,20 @@ QByteArray QWebEngineUrlRequestJob::requestMethod() const
/*!
Replies to the request with \a device and the MIME type \a contentType.
+
The user has to be aware that \a device will be used on another thread
until the job is deleted. In case simultaneous access from the main thread
is desired, the user is reponsible for making access to \a device thread-safe
for example by using QMutex. Note that the \a device object is not owned by
the web engine. Therefore, the signal QObject::destroyed() of
QWebEngineUrlRequestJob must be monitored.
+
+ The device should remain available at least as long as the job exists.
+ When calling this method with a newly constructed device, one solution is to
+ make the device delete itself when closed, like this:
+ \code
+ connect(device, &QIODevice::aboutToClose, device, &QObject::deleteLater);
+ \endcode
*/
void QWebEngineUrlRequestJob::reply(const QByteArray &contentType, QIODevice *device)
{
diff --git a/src/core/browser_context_adapter.cpp b/src/core/browser_context_adapter.cpp
index 0f392f9f8..3f8397752 100644
--- a/src/core/browser_context_adapter.cpp
+++ b/src/core/browser_context_adapter.cpp
@@ -42,6 +42,7 @@
#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/browsing_data_remover.h"
+#include "content/public/browser/download_manager.h"
#include "browser_context_qt.h"
#include "content_client_qt.h"
@@ -102,9 +103,16 @@ BrowserContextAdapter::BrowserContextAdapter(const QString &storageName)
BrowserContextAdapter::~BrowserContextAdapter()
{
+ Q_ASSERT(!m_downloadManagerDelegate);
+}
+
+void BrowserContextAdapter::shutdown()
+{
m_browserContext->ShutdownStoragePartitions();
- if (m_downloadManagerDelegate)
- content::BrowserThread::DeleteSoon(content::BrowserThread::UI, FROM_HERE, m_downloadManagerDelegate.take());
+ if (m_downloadManagerDelegate) {
+ m_browserContext->GetDownloadManager(m_browserContext.data())->Shutdown();
+ m_downloadManagerDelegate.reset();
+ }
BrowserContextDependencyManager::GetInstance()->DestroyBrowserContextServices(m_browserContext.data());
}
@@ -178,6 +186,8 @@ void BrowserContextAdapter::addClient(BrowserContextAdapterClient *adapterClient
void BrowserContextAdapter::removeClient(BrowserContextAdapterClient *adapterClient)
{
m_clients.removeOne(adapterClient);
+ if (m_clients.isEmpty() && this != WebEngineContext::current()->m_defaultBrowserContext.data())
+ shutdown();
}
void BrowserContextAdapter::cancelDownload(quint32 downloadId)
diff --git a/src/core/browser_context_adapter.h b/src/core/browser_context_adapter.h
index 5960014b9..b647bc30c 100644
--- a/src/core/browser_context_adapter.h
+++ b/src/core/browser_context_adapter.h
@@ -73,6 +73,8 @@ public:
static QSharedPointer<BrowserContextAdapter> defaultContext();
static QObject* globalQObjectRoot();
+ void shutdown();
+
VisitedLinksManagerQt *visitedLinksManager();
DownloadManagerDelegateQt *downloadManagerDelegate();
diff --git a/src/core/config/common.pri b/src/core/config/common.pri
index d8a4fa181..886ebe83d 100644
--- a/src/core/config/common.pri
+++ b/src/core/config/common.pri
@@ -13,7 +13,8 @@ gn_args += \
treat_warnings_as_errors=false \
enable_swiftshader=false \
use_custom_libcxx=false \
- use_jumbo_build=true
+ use_jumbo_build=true \
+ jumbo_file_merge_limit=50
qtConfig(webengine-printing-and-pdf) {
gn_args += enable_basic_printing=true enable_print_preview=true
@@ -62,3 +63,15 @@ CONFIG(debug, debug|release) {
# Compiling with -Os makes a huge difference in binary size
optimize_size: gn_args += optimize_for_size=true
+
+# We don't want to apply sanitizer options to the build tools (GN, dict convert, etc).
+!host_build {
+ sanitizer: gn_args += sanitizer_keep_symbols=true
+ sanitize_address: gn_args += is_asan=true
+ sanitize_thread: gn_args += is_tsan=true
+ sanitize_memory: gn_args += is_msan=true
+ # rtti is required for a specific check of ubsan, -fsanitize=vptr, which uses the runtime
+ # type information to check that correct derived objects are assigned to base pointers. Without
+ # rtti, linking would fail at build time.
+ sanitize_undefined: gn_args += is_ubsan=true use_rtti=true
+}
diff --git a/src/core/content_browser_client_qt.cpp b/src/core/content_browser_client_qt.cpp
index 328dcd38d..d0019e4f3 100644
--- a/src/core/content_browser_client_qt.cpp
+++ b/src/core/content_browser_client_qt.cpp
@@ -105,6 +105,10 @@
#include "web_engine_context.h"
#include "web_engine_library_info.h"
+#if defined(Q_OS_WIN)
+#include "ui/display/win/screen_win.h"
+#endif
+
#if defined(Q_OS_LINUX)
#include "global_descriptors_qt.h"
#include "ui/base/resource/resource_bundle.h"
@@ -295,8 +299,11 @@ public:
{
base::ThreadRestrictions::SetIOAllowed(true);
// Like ChromeBrowserMainExtraPartsViews::PreCreateThreads does.
+#if defined(Q_OS_WIN)
+ display::Screen::SetScreenInstance(new display::win::ScreenWin);
+#else
display::Screen::SetScreenInstance(new DesktopScreenQt);
-
+#endif
return 0;
}
diff --git a/src/core/core_module.pro b/src/core/core_module.pro
index 2409ccb12..d21985e60 100644
--- a/src/core/core_module.pro
+++ b/src/core/core_module.pro
@@ -40,8 +40,17 @@ else: LIBS_PRIVATE += $$NINJA_ARCHIVES
LIBS_PRIVATE += $$NINJA_LIB_DIRS $$NINJA_LIBS
# GN's LFLAGS doesn't always work across all the Linux configurations we support.
# The Windows and macOS ones from GN does provide a few useful flags however
-linux: QMAKE_LFLAGS += -Wl,--gc-sections -Wl,-O1 -Wl,-z,now -Wl,-z,defs
-else: QMAKE_LFLAGS += $$NINJA_LFLAGS
+
+linux {
+ QMAKE_LFLAGS += -Wl,--gc-sections -Wl,-O1 -Wl,-z,now
+ # Embedded address sanitizer symbols are undefined and are picked up by the dynamic link loader
+ # at runtime. Thus we do not to pass the linker flag below, because the linker would complain
+ # about the undefined sanitizer symbols.
+ !sanitizer: QMAKE_LFLAGS += -Wl,-z,defs
+} else {
+ QMAKE_LFLAGS += $$NINJA_LFLAGS
+}
+
POST_TARGETDEPS += $$NINJA_TARGETDEPS
diff --git a/src/core/delegated_frame_node.cpp b/src/core/delegated_frame_node.cpp
index 6f4a4e8db..de39300c9 100644
--- a/src/core/delegated_frame_node.cpp
+++ b/src/core/delegated_frame_node.cpp
@@ -739,6 +739,7 @@ void DelegatedFrameNode::preprocess()
if (!mailboxesToFetch.isEmpty())
fetchAndSyncMailboxes(mailboxesToFetch);
+#endif
// Then render any intermediate RenderPass in order.
typedef QPair<int, QSharedPointer<QSGLayer> > Pair;
@@ -748,7 +749,6 @@ void DelegatedFrameNode::preprocess()
// Proceed with the actual update.
pair.second->updateTexture();
}
-#endif
}
static YUVVideoMaterial::ColorSpace toQt(cc::YUVVideoDrawQuad::ColorSpace color_space)
diff --git a/src/core/pdfium_document_wrapper_qt.cpp b/src/core/pdfium_document_wrapper_qt.cpp
index df829a426..ca1e8cd07 100644
--- a/src/core/pdfium_document_wrapper_qt.cpp
+++ b/src/core/pdfium_document_wrapper_qt.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -129,7 +129,9 @@ private:
};
-PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize& imageSize, const char *password)
+PdfiumDocumentWrapperQt::PdfiumDocumentWrapperQt(const void *pdfData, size_t size,
+ const QSize& imageSize,
+ const char *password)
: m_imageSize(imageSize * 2.0)
{
Q_ASSERT(pdfData);
@@ -153,21 +155,13 @@ QImage PdfiumDocumentWrapperQt::pageAsQImage(size_t index)
return QImage();
}
- PdfiumPageWrapperQt *pageWrapper = nullptr;
- if (!m_cachedPages.contains(index)) {
- pageWrapper = new PdfiumPageWrapperQt(m_documentHandle, index,
- m_imageSize.width(), m_imageSize.height());
- m_cachedPages.insert(index, pageWrapper);
- } else {
- pageWrapper = m_cachedPages.value(index);
- }
-
- return pageWrapper->image();
+ PdfiumPageWrapperQt pageWrapper(m_documentHandle, index,
+ m_imageSize.width(), m_imageSize.height());
+ return pageWrapper.image();
}
PdfiumDocumentWrapperQt::~PdfiumDocumentWrapperQt()
{
- qDeleteAll(m_cachedPages);
FPDF_CloseDocument(m_documentHandle);
if (--m_libraryUsers == 0)
FPDF_DestroyLibrary();
diff --git a/src/core/pdfium_document_wrapper_qt.h b/src/core/pdfium_document_wrapper_qt.h
index 42ac94a28..28c490ae5 100644
--- a/src/core/pdfium_document_wrapper_qt.h
+++ b/src/core/pdfium_document_wrapper_qt.h
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -53,7 +53,8 @@ class PdfiumPageWrapperQt;
class QWEBENGINE_EXPORT PdfiumDocumentWrapperQt
{
public:
- PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize, const char *password = nullptr);
+ PdfiumDocumentWrapperQt(const void *pdfData, size_t size, const QSize &imageSize,
+ const char *password = nullptr);
virtual ~PdfiumDocumentWrapperQt();
QImage pageAsQImage(size_t index);
int pageCount() const { return m_pageCount; }
@@ -63,7 +64,6 @@ private:
int m_pageCount;
void *m_documentHandle;
QSize m_imageSize;
- QHash<int, PdfiumPageWrapperQt*> m_cachedPages;
};
} // namespace QtWebEngineCore
diff --git a/src/core/proxy_config_service_qt.cpp b/src/core/proxy_config_service_qt.cpp
index cd8f4c0fe..7fca18eb6 100644
--- a/src/core/proxy_config_service_qt.cpp
+++ b/src/core/proxy_config_service_qt.cpp
@@ -52,22 +52,20 @@ using content::BrowserThread;
net::ProxyServer ProxyConfigServiceQt::fromQNetworkProxy(const QNetworkProxy &qtProxy)
{
- net::ProxyServer::Scheme proxyScheme = net::ProxyServer::SCHEME_INVALID;
+ net::HostPortPair hostPortPair(qtProxy.hostName().toStdString(), qtProxy.port());
switch (qtProxy.type()) {
case QNetworkProxy::Socks5Proxy:
- proxyScheme = net::ProxyServer::SCHEME_SOCKS5;
- break;
+ return net::ProxyServer(net::ProxyServer::SCHEME_SOCKS5, hostPortPair);
case QNetworkProxy::HttpProxy:
case QNetworkProxy::HttpCachingProxy:
case QNetworkProxy::FtpCachingProxy:
- proxyScheme = net::ProxyServer::SCHEME_HTTP;
- break;
+ return net::ProxyServer(net::ProxyServer::SCHEME_HTTP, hostPortPair);
case QNetworkProxy::NoProxy:
case QNetworkProxy::DefaultProxy:
- proxyScheme = net::ProxyServer::SCHEME_DIRECT;
- break;
+ return net::ProxyServer(net::ProxyServer::SCHEME_DIRECT, net::HostPortPair());
+ default:
+ return net::ProxyServer(net::ProxyServer::SCHEME_INVALID, net::HostPortPair());
}
- return net::ProxyServer(proxyScheme, net::HostPortPair(qtProxy.hostName().toStdString(), qtProxy.port()));
}
ProxyConfigServiceQt::ProxyConfigServiceQt(std::unique_ptr<ProxyConfigService> baseService)
diff --git a/src/core/renderer/user_resource_controller.cpp b/src/core/renderer/user_resource_controller.cpp
index b4375dfdb..f85879053 100644
--- a/src/core/renderer/user_resource_controller.cpp
+++ b/src/core/renderer/user_resource_controller.cpp
@@ -148,9 +148,14 @@ void UserResourceController::RenderFrameObserverHelper::runScripts(UserScriptDat
void UserResourceController::runScripts(UserScriptData::InjectionPoint p, blink::WebLocalFrame *frame)
{
content::RenderFrame *renderFrame = content::RenderFrame::FromWebFrame(frame);
- content::RenderView *renderView = renderFrame->GetRenderView();
+ if (!renderFrame)
+ return;
const bool isMainFrame = renderFrame->IsMainFrame();
+ content::RenderView *renderView = renderFrame->GetRenderView();
+ if (!renderView)
+ return;
+
QList<uint64_t> scriptsToRun = m_viewUserScriptMap.value(0).toList();
scriptsToRun.append(m_viewUserScriptMap.value(renderView).toList());
@@ -233,7 +238,8 @@ void UserResourceController::RenderFrameObserverHelper::OnDestruct()
void UserResourceController::RenderViewObserverHelper::OnDestruct()
{
// Remove all scripts associated with the render view.
- UserResourceController::instance()->renderViewDestroyed(render_view());
+ if (content::RenderView *view = render_view())
+ UserResourceController::instance()->renderViewDestroyed(view);
delete this;
}
@@ -251,20 +257,23 @@ bool UserResourceController::RenderFrameObserverHelper::OnMessageReceived(const
void UserResourceController::RenderFrameObserverHelper::onUserScriptAdded(const UserScriptData &script)
{
- content::RenderView *view = render_frame()->GetRenderView();
- UserResourceController::instance()->addScriptForView(script, view);
+ if (content::RenderFrame *frame = render_frame())
+ if (content::RenderView *view = frame->GetRenderView())
+ UserResourceController::instance()->addScriptForView(script, view);
}
void UserResourceController::RenderFrameObserverHelper::onUserScriptRemoved(const UserScriptData &script)
{
- content::RenderView *view = render_frame()->GetRenderView();
- UserResourceController::instance()->removeScriptForView(script, view);
+ if (content::RenderFrame *frame = render_frame())
+ if (content::RenderView *view = frame->GetRenderView())
+ UserResourceController::instance()->removeScriptForView(script, view);
}
void UserResourceController::RenderFrameObserverHelper::onScriptsCleared()
{
- content::RenderView *view = render_frame()->GetRenderView();
- UserResourceController::instance()->clearScriptsForView(view);
+ if (content::RenderFrame *frame = render_frame())
+ if (content::RenderView *view = frame->GetRenderView())
+ UserResourceController::instance()->clearScriptsForView(view);
}
UserResourceController *UserResourceController::instance()
diff --git a/src/core/url_request_custom_job.cpp b/src/core/url_request_custom_job.cpp
index b49135f79..070414b4b 100644
--- a/src/core/url_request_custom_job.cpp
+++ b/src/core/url_request_custom_job.cpp
@@ -65,12 +65,12 @@ URLRequestCustomJob::URLRequestCustomJob(URLRequest *request,
URLRequestCustomJob::~URLRequestCustomJob()
{
m_proxy->m_job = nullptr;
- content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
- base::Bind(&URLRequestCustomJobProxy::release,
- m_proxy));
if (m_device && m_device->isOpen())
m_device->close();
m_device = nullptr;
+ content::BrowserThread::PostTask(content::BrowserThread::UI, FROM_HERE,
+ base::Bind(&URLRequestCustomJobProxy::release,
+ m_proxy));
}
void URLRequestCustomJob::Start()
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index 0b6a44d8d..668e791c1 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -632,9 +632,11 @@ void WebContentsAdapter::setContent(const QByteArray &data, const QString &mimeT
CHECK_VALID_RENDER_WIDGET_HOST_VIEW(d->webContents->GetRenderViewHost());
QByteArray encodedData = data.toPercentEncoding();
- std::string urlString("data:");
- urlString.append(mimeType.toStdString());
- urlString.append(",");
+ std::string urlString;
+ if (!mimeType.isEmpty())
+ urlString = std::string("data:") + mimeType.toStdString() + std::string(",");
+ else
+ urlString = std::string("data:text/plain;charset=US-ASCII,");
urlString.append(encodedData.constData(), encodedData.length());
GURL dataUrlToLoad(urlString);
@@ -1359,7 +1361,11 @@ bool WebContentsAdapter::handleDropDataFileContents(const content::DropData &dro
const auto maybeFilename = dropData.GetSafeFilenameForImageFileContents();
const QString fileName = maybeFilename ? toQt(maybeFilename->AsUTF16Unsafe()) : QString();
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 9, 0))
const QString &filePath = d->dndTmpDir->filePath(fileName);
+#else
+ const QString &filePath = d->dndTmpDir->path() + QLatin1Char('/') + fileName;
+#endif
QFile file(filePath);
if (!file.open(QIODevice::WriteOnly)) {
qWarning("Cannot write temporary file %s.", qUtf8Printable(filePath));
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index 6416ab6af..d6de9dfe6 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -390,7 +390,7 @@ public:
virtual bool isBeingAdopted() = 0;
virtual void close() = 0;
virtual void windowCloseRejected() = 0;
- virtual bool contextMenuRequested(const WebEngineContextMenuData &) = 0;
+ virtual void contextMenuRequested(const WebEngineContextMenuData &) = 0;
virtual void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) = 0;
virtual void requestFullScreenMode(const QUrl &origin, bool fullscreen) = 0;
virtual bool isFullScreenMode() const = 0;
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 2086bea4b..7b765d99b 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -80,6 +80,16 @@
namespace QtWebEngineCore {
+static gfx::Rect rootViewToScreenRect(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view)
+{
+ RenderWidgetHostViewQt *rwhv = static_cast<RenderWidgetHostViewQt *>(web_contents->GetRenderWidgetHostView());
+ if (!rwhv)
+ return gfx::Rect();
+ content::ScreenInfo screenInfo;
+ rwhv->GetScreenInfo(&screenInfo);
+ return gfx::ScaleToEnclosingRect(anchor_in_root_view, 1 / screenInfo.device_scale_factor);
+}
+
// Maps the LogSeverity defines in base/logging.h to the web engines message levels.
static WebContentsAdapterClient::JavaScriptConsoleMessageLevel mapToJavascriptConsoleMessageLevel(int32_t messageLevel) {
if (messageLevel < 1)
@@ -336,6 +346,9 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::Favic
faviconCandidates.append(toFaviconInfo(candidate));
}
+ // Favicon URL can be changed from JavaScript too. Thus we need to reset
+ // the current candidate icon list to not handle previous icon as a candidate.
+ m_faviconManager->resetCandidates();
m_faviconManager->update(faviconCandidates);
}
@@ -552,8 +565,10 @@ void WebContentsDelegateQt::launchExternalURL(const QUrl &url, ui::PageTransitio
void WebContentsDelegateQt::ShowValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view, const base::string16 &main_text, const base::string16 &sub_text)
{
- Q_UNUSED(web_contents);
- m_viewClient->showValidationMessage(toQt(anchor_in_root_view), toQt(main_text), toQt(sub_text));
+ gfx::Rect anchor = rootViewToScreenRect(web_contents, anchor_in_root_view);
+ if (anchor.IsEmpty())
+ return;
+ m_viewClient->showValidationMessage(toQt(anchor), toQt(main_text), toQt(sub_text));
}
void WebContentsDelegateQt::HideValidationMessage(content::WebContents *web_contents)
@@ -564,8 +579,10 @@ void WebContentsDelegateQt::HideValidationMessage(content::WebContents *web_cont
void WebContentsDelegateQt::MoveValidationMessage(content::WebContents *web_contents, const gfx::Rect &anchor_in_root_view)
{
- Q_UNUSED(web_contents);
- m_viewClient->moveValidationMessage(toQt(anchor_in_root_view));
+ gfx::Rect anchor = rootViewToScreenRect(web_contents, anchor_in_root_view);
+ if (anchor.IsEmpty())
+ return;
+ m_viewClient->moveValidationMessage(toQt(anchor));
}
void WebContentsDelegateQt::BeforeUnloadFired(content::WebContents *tab, bool proceed, bool *proceed_to_fire_unload)
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index e7bbbb9c7..84f6ce738 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -123,7 +123,11 @@ void destroyContext()
// Before destroying MessageLoop via destroying BrowserMainRunner destructor
// WebEngineContext's pointer is used.
sContext->destroy();
- sContext = 0;
+#if !defined(NDEBUG)
+ if (!sContext->HasOneRef())
+ qWarning("WebEngineContext leaked on exit, likely due to leaked WebEngine View or Page");
+#endif
+ sContext = nullptr;
s_destroyed = true;
}
@@ -199,20 +203,27 @@ void WebEngineContext::destroy()
{
if (m_devtoolsServer)
m_devtoolsServer->stop();
- delete m_globalQObject;
- m_globalQObject = 0;
base::MessagePump::Delegate *delegate =
static_cast<base::MessageLoop *>(m_runLoop->delegate_);
// Flush the UI message loop before quitting.
while (delegate->DoWork()) { }
+
+ if (m_defaultBrowserContext)
+ m_defaultBrowserContext->shutdown();
+ // Delete the global object and thus custom profiles
+ delete m_globalQObject;
+ m_globalQObject = nullptr;
+ // Handle any events posted by browser-context shutdown.
+ while (delegate->DoWork()) { }
+
GLContextHelper::destroy();
- m_devtoolsServer.reset(0);
+ m_devtoolsServer.reset();
m_runLoop->AfterRun();
// Force to destroy RenderProcessHostImpl by destroying BrowserMainRunner.
// RenderProcessHostImpl should be destroyed before WebEngineContext since
// default BrowserContext might be used by the RenderprocessHostImpl's destructor.
- m_browserRunner.reset(0);
+ m_browserRunner.reset();
// Drop the false reference.
sContext->Release();
diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h
index 92c45e260..1b4be48b1 100644
--- a/src/core/web_engine_context.h
+++ b/src/core/web_engine_context.h
@@ -80,7 +80,7 @@ class WebEngineContext : public base::RefCounted<WebEngineContext> {
public:
static scoped_refptr<WebEngineContext> current();
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> defaultBrowserContext();
+ QSharedPointer<BrowserContextAdapter> defaultBrowserContext();
QObject *globalQObject();
#if BUILDFLAG(ENABLE_BASIC_PRINTING)
printing::PrintJobManager* getPrintJobManager();
@@ -90,6 +90,7 @@ public:
private:
friend class base::RefCounted<WebEngineContext>;
+ friend class BrowserContextAdapter;
WebEngineContext();
~WebEngineContext();
@@ -98,7 +99,7 @@ private:
std::unique_ptr<content::ContentMainRunner> m_contentRunner;
std::unique_ptr<content::BrowserMainRunner> m_browserRunner;
QObject* m_globalQObject;
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_defaultBrowserContext;
+ QSharedPointer<BrowserContextAdapter> m_defaultBrowserContext;
std::unique_ptr<DevToolsServerQt> m_devtoolsServer;
#if BUILDFLAG(ENABLE_BASIC_PRINTING)
std::unique_ptr<printing::PrintJobManager> m_printJobManager;
diff --git a/src/core/web_event_factory.cpp b/src/core/web_event_factory.cpp
index 4241a11c2..4fb89d4e6 100644
--- a/src/core/web_event_factory.cpp
+++ b/src/core/web_event_factory.cpp
@@ -1024,7 +1024,8 @@ static inline double currentTimeForEvent(const QEvent *event)
{
Q_ASSERT(event);
- if (const QInputEvent *inputEvent = static_cast<const QInputEvent *>(event)) {
+ if (event->type() != QEvent::Leave) {
+ const QInputEvent *inputEvent = static_cast<const QInputEvent *>(event);
if (inputEvent->timestamp())
return static_cast<double>(inputEvent->timestamp()) / 1000;
}
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index f966f2dc6..728f0b4a4 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -142,9 +142,8 @@ ASSERT_ENUMS_MATCH(QQuickWebEngineDownloadItem::MimeHtmlSaveFormat, QtWebEngineC
QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(QSharedPointer<BrowserContextAdapter> browserContext)
: m_settings(new QQuickWebEngineSettings())
- , m_browserContextRef(browserContext)
+ , m_browserContext(new QWebEngineBrowserContext(browserContext, this))
{
- m_browserContextRef->addClient(this);
m_settings->d_ptr->initDefaults();
// Fullscreen API was implemented before the supported setting, so we must
// make it default true to avoid change in default API behavior.
@@ -153,21 +152,26 @@ QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(QSharedPointer<Brow
QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate()
{
- m_browserContextRef->setRequestInterceptor(nullptr);
-
- m_browserContextRef->removeClient(this);
-
- Q_FOREACH (QQuickWebEngineDownloadItem* download, m_ongoingDownloads) {
+ Q_FOREACH (QQuickWebEngineDownloadItem *download, m_ongoingDownloads) {
if (download)
download->cancel();
}
m_ongoingDownloads.clear();
+
+ if (m_browserContext)
+ m_browserContext->shutdown();
+}
+
+QSharedPointer<QtWebEngineCore::BrowserContextAdapter> QQuickWebEngineProfilePrivate::browserContext() const
+{
+ return m_browserContext ? m_browserContext->browserContextRef : nullptr;
}
void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId)
{
- browserContext()->cancelDownload(downloadId);
+ if (m_browserContext)
+ m_browserContext->browserContextRef->cancelDownload(downloadId);
}
void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index 5be82a4f5..61968bf77 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -52,8 +52,9 @@
//
#include "browser_context_adapter_client.h"
-#include "qquickwebengineprofile_p.h"
#include "browser_context_adapter.h"
+#include "qwebenginebrowsercontext_p.h"
+#include "qquickwebengineprofile_p.h"
#include <QExplicitlySharedDataPointer>
#include <QMap>
@@ -71,7 +72,7 @@ public:
QQuickWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext);
~QQuickWebEngineProfilePrivate();
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const { return m_browserContextRef; }
+ QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext() const;
QQuickWebEngineSettings *settings() const { return m_settings.data(); }
void cancelDownload(quint32 downloadId);
@@ -90,7 +91,7 @@ private:
friend class QQuickWebEngineViewPrivate;
QQuickWebEngineProfile *q_ptr;
QScopedPointer<QQuickWebEngineSettings> m_settings;
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> m_browserContextRef;
+ QPointer<QWebEngineBrowserContext> m_browserContext;
QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads;
QList<QQuickWebEngineScript *> m_userScripts;
};
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index 2721039ae..2c30627ad 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -183,7 +183,7 @@ RenderWidgetHostViewQtDelegate *QQuickWebEngineViewPrivate::CreateRenderWidgetHo
return quickDelegate;
}
-bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenuData &data)
+void QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenuData &data)
{
Q_Q(QQuickWebEngineView);
@@ -195,13 +195,13 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
Q_EMIT q->contextMenuRequested(request);
if (request->isAccepted())
- return true;
+ return;
// Assign the WebEngineView as the parent of the menu, so mouse events are properly propagated
// on OSX.
QObject *menu = ui()->addMenu(q, QString(), data.position());
if (!menu)
- return false;
+ return;
// Populate our menu
MenuItemHandler *item = 0;
@@ -329,7 +329,6 @@ bool QQuickWebEngineViewPrivate::contextMenuRequested(const WebEngineContextMenu
// Now fire the popup() method on the top level menu
ui()->showMenu(menu);
- return true;
}
void QQuickWebEngineViewPrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame)
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index a30614b2f..baa89718d 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -114,7 +114,7 @@ public:
void windowCloseRejected() override;
void requestFullScreenMode(const QUrl &origin, bool fullscreen) override;
bool isFullScreenMode() const override;
- bool contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &) override;
+ void contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &) override;
void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) override;
void javascriptDialog(QSharedPointer<QtWebEngineCore::JavaScriptDialogController>) override;
void runFileChooser(QSharedPointer<QtWebEngineCore::FilePickerController>) override;
@@ -138,8 +138,7 @@ public:
void showValidationMessage(const QRect &anchor, const QString &mainText, const QString &subText) override;
void hideValidationMessage() override;
void moveValidationMessage(const QRect &anchor) override;
- virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus,
- int exitCode) override;
+ void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override;
void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override;
void updateScrollPosition(const QPointF &position) override;
void updateContentsSize(const QSizeF &size) override;
diff --git a/src/webengine/ui_delegates_manager.cpp b/src/webengine/ui_delegates_manager.cpp
index fb23f5db7..046affbf4 100644
--- a/src/webengine/ui_delegates_manager.cpp
+++ b/src/webengine/ui_delegates_manager.cpp
@@ -504,7 +504,12 @@ public:
if (pos.isNull() || !item->contains(pos))
return;
const QPoint oldPos = QCursor::pos();
+#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
const QPoint globalPos = item->mapToGlobal(QPointF(pos)).toPoint();
+#else
+ const QPoint posInWindow = item->mapToItem(item->window()->contentItem(), QPointF(pos)).toPoint();
+ const QPoint globalPos = item->window()->mapToGlobal(posInWindow);
+#endif
if (oldPos == globalPos)
return;
m_oldCursorPos = oldPos;
diff --git a/src/webengine/webengine.pro b/src/webengine/webengine.pro
index 58e1263a7..570f41866 100644
--- a/src/webengine/webengine.pro
+++ b/src/webengine/webengine.pro
@@ -59,7 +59,7 @@ HEADERS = \
ui_delegates_manager.h
qtConfig(webengine-testsupport) {
- QT += testlib
+ QT_PRIVATE += testlib
SOURCES += api/qquickwebenginetestsupport.cpp
HEADERS += api/qquickwebenginetestsupport_p.h
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
index ac7a71959..8f097df6c 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
@@ -195,9 +195,10 @@ void QWebEngineDownloadItem::cancel()
// We directly cancel the download request if the user cancels
// before it even started, so no need to notify the profile here.
- if (state == QWebEngineDownloadItem::DownloadInProgress)
- d->profile->browserContext()->cancelDownload(d->downloadId);
- else {
+ if (state == QWebEngineDownloadItem::DownloadInProgress) {
+ if (auto browserContext = d->profile->browserContext())
+ browserContext->cancelDownload(d->downloadId);
+ } else {
d->downloadState = QWebEngineDownloadItem::DownloadCancelled;
Q_EMIT stateChanged(d->downloadState);
}
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index 3bb7f6c83..a8fa98bea 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -139,7 +139,8 @@ static bool printPdfDataOnPrinter(const QByteArray& data, QPrinter& printer)
QPainter painter;
if (!painter.begin(&printer)) {
- qWarning("Failure to print on printer %ls: Could not open printer for painting.", qUtf16Printable(printer.printerName()));
+ qWarning("Failure to print on printer %ls: Could not open printer for painting.",
+ qUtf16Printable(printer.printerName()));
return false;
}
@@ -1475,35 +1476,36 @@ void QWebEnginePagePrivate::wasHidden()
adapter->wasHidden();
}
-bool QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData &data)
+void QWebEnginePagePrivate::contextMenuRequested(const WebEngineContextMenuData &data)
{
if (!view)
- return false;
+ return;
contextData.reset();
- QContextMenuEvent event(QContextMenuEvent::Mouse, data.position(), view->mapToGlobal(data.position()));
switch (view->contextMenuPolicy()) {
- case Qt::PreventContextMenu:
- return false;
case Qt::DefaultContextMenu:
+ {
contextData = data;
+ QContextMenuEvent event(QContextMenuEvent::Mouse, data.position(), view->mapToGlobal(data.position()));
view->contextMenuEvent(&event);
- break;
+ return;
+ }
case Qt::CustomContextMenu:
contextData = data;
Q_EMIT view->customContextMenuRequested(data.position());
- break;
+ return;
case Qt::ActionsContextMenu:
if (view->actions().count()) {
+ QContextMenuEvent event(QContextMenuEvent::Mouse, data.position(), view->mapToGlobal(data.position()));
QMenu::exec(view->actions(), event.globalPos(), 0, view);
- break;
}
- // fallthrough
+ return;
+ case Qt::PreventContextMenu:
case Qt::NoContextMenu:
- event.ignore();
- return false;
+ return;
}
- return true;
+
+ Q_UNREACHABLE();
}
void QWebEnginePagePrivate::navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame)
@@ -1630,12 +1632,21 @@ bool QWebEnginePagePrivate::isEnabled() const
void QWebEnginePagePrivate::setToolTip(const QString &toolTipText)
{
- if (view) {
- QString wrappedTip;
- if (!toolTipText.isEmpty())
- wrappedTip = QLatin1String("<p>") % toolTipText.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("</p>");
- view->setToolTip(wrappedTip);
+ if (!view)
+ return;
+
+ // Hide tooltip if shown.
+ if (toolTipText.isEmpty()) {
+ if (!view->toolTip().isEmpty())
+ view->setToolTip(QString());
+
+ return;
}
+
+ // Update tooltip if text was changed.
+ QString wrappedTip = QLatin1String("<p>") % toolTipText.toHtmlEscaped().left(MaxTooltipLength) % QLatin1String("</p>");
+ if (view->toolTip() != wrappedTip)
+ view->setToolTip(wrappedTip);
}
QMenu *QWebEnginePage::createStandardContextMenu()
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index 66f479717..270849aee 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -109,7 +109,7 @@ public:
bool isBeingAdopted() override;
void close() override;
void windowCloseRejected() override;
- bool contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &data) override;
+ void contextMenuRequested(const QtWebEngineCore::WebEngineContextMenuData &data) override;
void navigationRequested(int navigationType, const QUrl &url, int &navigationRequestAction, bool isMainFrame) override;
void requestFullScreenMode(const QUrl &origin, bool fullscreen) override;
bool isFullScreenMode() const override;
@@ -135,8 +135,7 @@ public:
void showValidationMessage(const QRect &anchor, const QString &mainText, const QString &subText) override;
void hideValidationMessage() override;
void moveValidationMessage(const QRect &anchor) override;
- virtual void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus,
- int exitCode) override;
+ void renderProcessTerminated(RenderProcessTerminationStatus terminationStatus, int exitCode) override;
void requestGeometryChange(const QRect &geometry, const QRect &frameGeometry) override;
void updateScrollPosition(const QPointF &position) override;
void updateContentsSize(const QSizeF &size) override;
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 02fdfa113..737326c24 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -47,8 +47,9 @@
#include "qwebenginesettings.h"
#include "qwebenginescriptcollection_p.h"
+#include "qwebenginebrowsercontext_p.h"
+#include "qtwebenginecoreglobal.h"
#include "browser_context_adapter.h"
-#include <qtwebenginecoreglobal.h>
#include "visited_links_manager_qt.h"
#include "web_engine_settings.h"
@@ -145,23 +146,6 @@ using QtWebEngineCore::BrowserContextAdapter;
\sa QWebEngineDownloadItem, QWebEnginePage::download()
*/
-QWebEngineBrowserContext::QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QWebEngineProfilePrivate *profile)
- : QObject(BrowserContextAdapter::globalQObjectRoot())
- , browserContextRef(browserContext)
- , m_profile(profile)
-{
- browserContextRef->addClient(m_profile);
-}
-
-QWebEngineBrowserContext::~QWebEngineBrowserContext()
-{
- Q_ASSERT(m_profile);
- // In the case the user sets this profile as the parent of the interceptor
- // it can be deleted before the browser-context still referencing it is.
- browserContextRef->setRequestInterceptor(nullptr);
- browserContextRef->removeClient(m_profile);
-}
-
QWebEngineProfilePrivate::QWebEngineProfilePrivate(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext)
: m_settings(new QWebEngineSettings())
, m_scriptCollection(new QWebEngineScriptCollection(new QWebEngineScriptCollectionPrivate(browserContext->userResourceController())))
@@ -181,11 +165,13 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate()
}
m_ongoingDownloads.clear();
+ if (m_browserContext)
+ m_browserContext->shutdown();
}
QSharedPointer<QtWebEngineCore::BrowserContextAdapter> QWebEngineProfilePrivate::browserContext() const
{
- return m_browserContext->browserContextRef;
+ return m_browserContext ? m_browserContext->browserContextRef : nullptr;
}
void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h
index 8cbf241f3..72fa904e4 100644
--- a/src/webenginewidgets/api/qwebengineprofile_p.h
+++ b/src/webenginewidgets/api/qwebengineprofile_p.h
@@ -54,6 +54,7 @@
#include "browser_context_adapter_client.h"
#include "qwebengineprofile.h"
#include "qwebenginescriptcollection.h"
+
#include <QMap>
#include <QPointer>
#include <QScopedPointer>
@@ -65,23 +66,10 @@ class BrowserContextAdapter;
QT_BEGIN_NAMESPACE
+class QWebEngineBrowserContext;
class QWebEngineProfilePrivate;
class QWebEngineSettings;
-// This is a wrapper class for BrowserContextAdapter. BrowserContextAdapter must be destructed before WebEngineContext
-// is destructed. Therefore access it via the QWebEngineBrowserContext which parent is the WebEngineContext::globalQObject.
-// This guarantees the destruction together with the WebEngineContext.
-class QWebEngineBrowserContext : public QObject {
-public:
- QWebEngineBrowserContext(QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContext, QWebEngineProfilePrivate *profile);
- ~QWebEngineBrowserContext();
-
- QSharedPointer<QtWebEngineCore::BrowserContextAdapter> browserContextRef;
-
-private:
- QWebEngineProfilePrivate *m_profile;
-};
-
class QWebEngineProfilePrivate : public QtWebEngineCore::BrowserContextAdapterClient {
public:
Q_DECLARE_PUBLIC(QWebEngineProfile)
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 9b3f62217..7ea451fc5 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -50,8 +50,9 @@
#include <QAction>
#include <QMenu>
#include <QContextMenuEvent>
-#include <QStackedLayout>
#include <QPageLayout>
+#include <QStackedLayout>
+#include <QToolTip>
QT_BEGIN_NAMESPACE
@@ -327,6 +328,18 @@ bool QWebEngineView::event(QEvent *ev)
ev->accept();
return true;
}
+
+ // Override QWidget's default ToolTip handler since it doesn't hide tooltip on empty text.
+ if (ev->type() == QEvent::ToolTip) {
+ if (!toolTip().isEmpty())
+ QToolTip::showText(static_cast<QHelpEvent *>(ev)->globalPos(), toolTip(), this, QRect(), toolTipDuration());
+ else
+ QToolTip::hideText();
+
+ ev->accept();
+ return true;
+ }
+
return QWidget::event(ev);
}
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index eb91d576d..2c161e2df 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -694,9 +694,8 @@
/*!
\fn void QWebEnginePage::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
- Sets the content of this page to \a data. If the \a mimeType argument
- is empty, it is currently assumed that the content is HTML but in future versions we may introduce
- auto-detection.
+ Sets the content of the web page to \a data. If the \a mimeType argument
+ is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}.
External objects referenced in the content are located relative to \a baseUrl.
diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
index 27ee96c5e..18d139c00 100644
--- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
@@ -152,9 +152,8 @@
/*!
\fn void QWebEngineView::setContent(const QByteArray &data, const QString &mimeType, const QUrl &baseUrl)
- Sets the content of the web view to the specified content \a data. If the \a mimeType argument
- is empty, it is currently assumed that the content is HTML but in future versions we may
- introduce auto-detection.
+ Sets the content of the web view to \a data. If the \a mimeType argument
+ is empty, it is assumed that the content is \c{text/plain,charset=US-ASCII}.
External objects referenced in the content are located relative to \a baseUrl.
diff --git a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
index 65d4ec295..930c208ee 100644
--- a/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
+++ b/tests/auto/core/qwebenginecookiestore/tst_qwebenginecookiestore.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -32,7 +32,6 @@
#include <QtWebEngineCore/qwebenginecookiestore.h>
#include <QtWebEngineWidgets/qwebenginepage.h>
#include <QtWebEngineWidgets/qwebengineprofile.h>
-#include <QtWebEngineWidgets/qwebengineview.h>
class tst_QWebEngineCookieStore : public QObject
{
@@ -52,6 +51,9 @@ private Q_SLOTS:
void cookieSignals();
void setAndDeleteCookie();
void batchCookieTasks();
+
+private:
+ QWebEngineProfile m_profile;
};
tst_QWebEngineCookieStore::tst_QWebEngineCookieStore()
@@ -68,6 +70,7 @@ void tst_QWebEngineCookieStore::init()
void tst_QWebEngineCookieStore::cleanup()
{
+ m_profile.cookieStore()->deleteAllCookies();
}
void tst_QWebEngineCookieStore::initTestCase()
@@ -80,15 +83,15 @@ void tst_QWebEngineCookieStore::cleanupTestCase()
void tst_QWebEngineCookieStore::cookieSignals()
{
- QWebEngineView view;
- QWebEngineCookieStore *client = view.page()->profile()->cookieStore();
- client->deleteAllCookies();
+ QWebEnginePage page(&m_profile);
+
+ QWebEngineCookieStore *client = m_profile.cookieStore();
- QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
- view.load(QUrl("qrc:///resources/index.html"));
+ page.load(QUrl("qrc:///resources/index.html"));
QTRY_COMPARE(loadSpy.count(), 1);
QVariant success = loadSpy.takeFirst().takeFirst();
@@ -110,11 +113,10 @@ void tst_QWebEngineCookieStore::cookieSignals()
void tst_QWebEngineCookieStore::setAndDeleteCookie()
{
- QWebEngineView view;
- QWebEngineCookieStore *client = view.page()->profile()->cookieStore();
- client->deleteAllCookies();
+ QWebEnginePage page(&m_profile);
+ QWebEngineCookieStore *client = m_profile.cookieStore();
- QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
@@ -130,7 +132,7 @@ void tst_QWebEngineCookieStore::setAndDeleteCookie()
QTRY_COMPARE(cookieAddedSpy.count(),2);
client->deleteCookie(cookie1);
- view.load(QUrl("qrc:///resources/content.html"));
+ page.load(QUrl("qrc:///resources/content.html"));
QTRY_COMPARE(loadSpy.count(), 1);
QVariant success = loadSpy.takeFirst().takeFirst();
@@ -151,11 +153,10 @@ void tst_QWebEngineCookieStore::setAndDeleteCookie()
void tst_QWebEngineCookieStore::batchCookieTasks()
{
- QWebEngineView view;
- QWebEngineCookieStore *client = view.page()->profile()->cookieStore();
- client->deleteAllCookies();
+ QWebEnginePage page(&m_profile);
+ QWebEngineCookieStore *client = m_profile.cookieStore();
- QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
+ QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
QSignalSpy cookieAddedSpy(client, SIGNAL(cookieAdded(const QNetworkCookie &)));
QSignalSpy cookieRemovedSpy(client, SIGNAL(cookieRemoved(const QNetworkCookie &)));
@@ -167,7 +168,7 @@ void tst_QWebEngineCookieStore::batchCookieTasks()
client->setCookie(cookie2);
QTRY_COMPARE(cookieAddedSpy.count(), 2);
- view.load(QUrl("qrc:///resources/index.html"));
+ page.load(QUrl("qrc:///resources/index.html"));
QTRY_COMPARE(loadSpy.count(), 1);
QVariant success = loadSpy.takeFirst().takeFirst();
diff --git a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
index daf4d811e..926c3e042 100644
--- a/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
+++ b/tests/auto/core/qwebengineurlrequestinterceptor/tst_qwebengineurlrequestinterceptor.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2016 The Qt Company Ltd.
+** Copyright (C) 2017 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtWebEngine module of the Qt Toolkit.
@@ -32,7 +32,6 @@
#include <QtWebEngineWidgets/qwebenginepage.h>
#include <QtWebEngineWidgets/qwebengineprofile.h>
#include <QtWebEngineWidgets/qwebenginesettings.h>
-#include <QtWebEngineWidgets/qwebengineview.h>
class tst_QWebEngineUrlRequestInterceptor : public QObject
{
@@ -104,20 +103,22 @@ public:
void tst_QWebEngineUrlRequestInterceptor::interceptRequest()
{
- QWebEngineView view;
+ QWebEngineProfile profile;
+ profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
TestRequestInterceptor interceptor(/* intercept */ true);
- view.page()->settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+ profile.setRequestInterceptor(&interceptor);
- QSignalSpy loadSpy(&view, SIGNAL(loadFinished(bool)));
- view.page()->profile()->setRequestInterceptor(&interceptor);
- view.load(QUrl("qrc:///resources/index.html"));
+ QWebEnginePage page(&profile);
+ QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+
+ page.load(QUrl("qrc:///resources/index.html"));
QTRY_COMPARE(loadSpy.count(), 1);
QVariant success = loadSpy.takeFirst().takeFirst();
QVERIFY(success.toBool());
loadSpy.clear();
QVariant ok;
- view.page()->runJavaScript("post();", [&ok](const QVariant result){ ok = result; });
+ page.runJavaScript("post();", [&ok](const QVariant result){ ok = result; });
QTRY_VERIFY(ok.toBool());
QTRY_COMPARE(loadSpy.count(), 1);
success = loadSpy.takeFirst().takeFirst();
@@ -125,7 +126,7 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest()
QVERIFY(!success.toBool());
loadSpy.clear();
- view.load(QUrl("qrc:///resources/__placeholder__"));
+ page.load(QUrl("qrc:///resources/__placeholder__"));
QTRY_COMPARE(loadSpy.count(), 1);
success = loadSpy.takeFirst().takeFirst();
// The redirection for __placeholder__ should succeed.
@@ -135,8 +136,8 @@ void tst_QWebEngineUrlRequestInterceptor::interceptRequest()
// Make sure that registering an observer does not modify the request.
TestRequestInterceptor observer(/* intercept */ false);
- view.page()->profile()->setRequestInterceptor(&observer);
- view.load(QUrl("qrc:///resources/__placeholder__"));
+ profile.setRequestInterceptor(&observer);
+ page.load(QUrl("qrc:///resources/__placeholder__"));
QTRY_COMPARE(loadSpy.count(), 1);
success = loadSpy.takeFirst().takeFirst();
// Since we do not intercept, loading an invalid path should not succeed.
@@ -163,18 +164,18 @@ public:
void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding()
{
- QWebEngineView view;
- QWebEnginePage *page = view.page();
+ QWebEngineProfile profile;
LocalhostContentProvider contentProvider;
- QSignalSpy spyLoadFinished(page, SIGNAL(loadFinished(bool)));
+ profile.setRequestInterceptor(&contentProvider);
- page->profile()->setRequestInterceptor(&contentProvider);
+ QWebEnginePage page(&profile);
+ QSignalSpy spyLoadFinished(&page, SIGNAL(loadFinished(bool)));
- page->setHtml("<p>Hi", QUrl::fromEncoded("http://[::1]/index.html"));
+ page.setHtml("<p>Hi", QUrl::fromEncoded("http://[::1]/index.html"));
QTRY_COMPARE(spyLoadFinished.count(), 1);
QCOMPARE(contentProvider.requestedUrls.count(), 0);
- evaluateJavaScriptSync(page, "var r = new XMLHttpRequest();"
+ evaluateJavaScriptSync(&page, "var r = new XMLHttpRequest();"
"r.open('GET', 'http://[::1]/test.xml', false);"
"r.send(null);"
);
@@ -185,12 +186,13 @@ void tst_QWebEngineUrlRequestInterceptor::ipv6HostEncoding()
void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
{
- QWebEnginePage page;
- page.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+ QWebEngineProfile profile;
+ profile.settings()->setAttribute(QWebEngineSettings::ErrorPageEnabled, false);
+ TestRequestInterceptor interceptor(/* intercept */ true);
+ profile.setRequestInterceptor(&interceptor);
+ QWebEnginePage page(&profile);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
- TestRequestInterceptor interceptor(/* intercept */ true);
- page.profile()->setRequestInterceptor(&interceptor);
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
QVERIFY(spy.wait());
@@ -214,10 +216,11 @@ void tst_QWebEngineUrlRequestInterceptor::requestedUrl()
void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl()
{
- QWebEnginePage page;
+ QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ true);
- page.profile()->setRequestInterceptor(&interceptor);
+ profile.setRequestInterceptor(&interceptor);
+ QWebEnginePage page(&profile);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/__placeholder__"));
@@ -244,10 +247,11 @@ void tst_QWebEngineUrlRequestInterceptor::setUrlSameUrl()
void tst_QWebEngineUrlRequestInterceptor::firstPartyUrl()
{
- QWebEnginePage page;
+ QWebEngineProfile profile;
TestRequestInterceptor interceptor(/* intercept */ false);
- page.profile()->setRequestInterceptor(&interceptor);
+ profile.setRequestInterceptor(&interceptor);
+ QWebEnginePage page(&profile);
QSignalSpy spy(&page, SIGNAL(loadFinished(bool)));
page.setUrl(QUrl("qrc:///resources/firstparty.html"));
diff --git a/tests/auto/quick/qmltests/data/TestWebEngineView.qml b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
index 9fb8c4bfe..cadad4e27 100644
--- a/tests/auto/quick/qmltests/data/TestWebEngineView.qml
+++ b/tests/auto/quick/qmltests/data/TestWebEngineView.qml
@@ -82,6 +82,24 @@ WebEngineView {
verifyElementHasFocus(element);
}
+ function getElementCenter(element) {
+ var center;
+ runJavaScript("(function() {" +
+ " var elem = document.getElementById('" + element + "');" +
+ " var rect = elem.getBoundingClientRect();" +
+ " return { 'x': (rect.left + rect.right) / 2, 'y': (rect.top + rect.bottom) / 2 };" +
+ "})();", function(result) { center = result } );
+ testCase.tryVerify(function() { return center !== undefined; });
+ return center;
+ }
+
+ function getTextSelection() {
+ var textSelection;
+ runJavaScript("window.getSelection().toString()", function(result) { textSelection = result });
+ testCase.tryVerify(function() { return textSelection !== undefined; });
+ return textSelection;
+ }
+
TestResult { id: testResult }
TestCase { id: testCase }
diff --git a/tests/auto/quick/qmltests/data/favicon.html b/tests/auto/quick/qmltests/data/favicon.html
index 9823fa323..7a81194e4 100644
--- a/tests/auto/quick/qmltests/data/favicon.html
+++ b/tests/auto/quick/qmltests/data/favicon.html
@@ -5,6 +5,6 @@
<body>
<p>It's expected that you see a favicon displayed for this page when you open it as a local file.</p>
<p>The favicon looks like this:</p>
-<img src="icons/favicon.png"/>
+<img id='image' src="icons/favicon.png"/>
</body>
</html>
diff --git a/tests/auto/quick/qmltests/data/tst_contextMenu.qml b/tests/auto/quick/qmltests/data/tst_contextMenu.qml
new file mode 100644
index 000000000..58947beaf
--- /dev/null
+++ b/tests/auto/quick/qmltests/data/tst_contextMenu.qml
@@ -0,0 +1,224 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 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:GPL-EXCEPT$
+** 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 General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** 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-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+import QtQuick 2.0
+import QtQuick.Controls 1.4
+import QtTest 1.0
+import QtWebEngine 1.6
+
+TestWebEngineView {
+ id: webEngineView
+ width: 400
+ height: 400
+
+ property string linkText: ""
+ property var mediaType: null
+ property string selectedText: ""
+
+ onContextMenuRequested: {
+ linkText = request.linkText;
+ mediaType = request.mediaType;
+ selectedText = request.selectedText;
+ }
+
+ SignalSpy {
+ id: contextMenuRequestedSpy
+ target: webEngineView
+ signalName: "contextMenuRequested"
+ }
+
+ function getContextMenus() {
+ var data = webEngineView.data;
+ var contextMenus = [];
+
+ for (var i = 0; i < data.length; i++) {
+ if (data[i].type == MenuItemType.Menu) {
+ contextMenus.push(data[i]);
+ }
+ }
+ return contextMenus;
+ }
+
+ function destroyContextMenu() {
+ contextMenuTest.keyPress(Qt.Key_Escape);
+ return getContextMenus().length == 0;
+ }
+
+ TestCase {
+ id: contextMenuTest
+ name: "WebEngineViewContextMenu"
+ when: windowShown
+
+ function init() {
+ var contextMenus = getContextMenus();
+ compare(contextMenus.length, 0);
+ }
+
+ function cleanup() {
+ contextMenuRequestedSpy.clear();
+ }
+
+ function test_contextMenu_data() {
+ return [
+ { tag: "defaultContextMenu", userHandled: false, accepted: false },
+ { tag: "defaultContextMenuWithConnect", userHandled: true, accepted: false },
+ { tag: "dontShowDefaultContextMenu", userHandled: true, accepted: true },
+ ];
+ }
+
+ function test_contextMenu(row) {
+ if (Qt.platform.os == "osx") {
+ skip("When the menu pops up on macOS, it does not return and the test fails after time out.");
+ }
+
+ function contextMenuHandler(request) {
+ request.accepted = row.accepted;
+ }
+
+ if (row.userHandled) {
+ webEngineView.contextMenuRequested.connect(contextMenuHandler);
+ }
+
+ mouseClick(webEngineView, 20, 20, Qt.RightButton);
+ contextMenuRequestedSpy.wait();
+ compare(contextMenuRequestedSpy.count, 1);
+
+ // There should be maximum one ContextMenu present at a time
+ var contextMenus = getContextMenus();
+ verify(contextMenus.length <= 1);
+ compare(contextMenus[0] != null, !row.accepted);
+
+ // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying
+ tryVerify(destroyContextMenu);
+ webEngineView.contextMenuRequested.disconnect(contextMenuHandler);
+ }
+
+ function test_contextMenuLinkAndSelectedText() {
+ if (Qt.platform.os == "osx") {
+ skip("When the menu pops up on macOS, it does not return and the test fails after time out.");
+ }
+
+ webEngineView.loadHtml("<html><body>" +
+ "<span id='text'>Text </span>" +
+ "<a id='link' href='test1.html'>Link</a>" +
+ "</body></html>");
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // 1. Nothing is selected, right click on the link
+ var linkCenter = getElementCenter("link");
+ mouseClick(webEngineView, linkCenter.x, linkCenter.y, Qt.RightButton);
+ contextMenuRequestedSpy.wait();
+ compare(contextMenuRequestedSpy.count, 1);
+
+ var contextMenus = getContextMenus();
+ compare(contextMenus.length, 1);
+ verify(contextMenus[0]);
+ compare(linkText, "Link");
+ compare(mediaType, ContextMenuRequest.MediaTypeNone);
+ compare(selectedText, "");
+
+ contextMenuRequestedSpy.clear();
+ // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying
+ tryVerify(destroyContextMenu);
+
+ // 2. Everything is selected, right click on the link
+ webEngineView.triggerWebAction(WebEngineView.SelectAll);
+ tryVerify(function() { return getTextSelection() == "Text Link" });
+
+ mouseClick(webEngineView, linkCenter.x, linkCenter.y, Qt.RightButton);
+ contextMenuRequestedSpy.wait();
+ compare(contextMenuRequestedSpy.count, 1);
+
+ contextMenus = getContextMenus();
+ compare(contextMenus.length, 1);
+ verify(contextMenus[0]);
+ compare(linkText, "Link");
+ compare(mediaType, ContextMenuRequest.MediaTypeNone);
+ compare(selectedText, "Text Link");
+
+ contextMenuRequestedSpy.clear();
+ // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying
+ tryVerify(destroyContextMenu);
+
+ // 3. Everything is selected, right click on the text
+ var textCenter = getElementCenter("text");
+ mouseClick(webEngineView, textCenter.x, textCenter.y, Qt.RightButton);
+ contextMenuRequestedSpy.wait();
+ compare(contextMenuRequestedSpy.count, 1);
+
+ contextMenus = getContextMenus();
+ compare(contextMenus.length, 1);
+ verify(contextMenus[0]);
+ compare(linkText, "");
+ compare(mediaType, ContextMenuRequest.MediaTypeNone);
+ compare(selectedText, "Text Link");
+
+ // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying
+ tryVerify(destroyContextMenu);
+ }
+
+ function test_contextMenuMediaType() {
+ if (Qt.platform.os == "osx") {
+ skip("When the menu pops up on macOS, it does not return and the test fails after time out.");
+ }
+
+ webEngineView.url = Qt.resolvedUrl("favicon.html");
+ verify(webEngineView.waitForLoadSucceeded());
+ // 1. Right click on the image
+ var center = getElementCenter("image");
+ mouseClick(webEngineView, center.x, center.y, Qt.RightButton);
+ contextMenuRequestedSpy.wait();
+ compare(contextMenuRequestedSpy.count, 1);
+
+ var contextMenus = getContextMenus();
+ compare(contextMenus.length, 1);
+ verify(contextMenus[0]);
+ compare(linkText, "");
+ compare(mediaType, ContextMenuRequest.MediaTypeImage);
+ compare(selectedText, "");
+ contextMenuRequestedSpy.clear();
+ // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying
+ tryVerify(destroyContextMenu);
+
+ // 2. Right click out of the image
+ mouseClick(webEngineView, center.x + 30, center.y, Qt.RightButton);
+ contextMenuRequestedSpy.wait();
+ compare(contextMenuRequestedSpy.count, 1);
+
+ contextMenus = getContextMenus();
+ compare(contextMenus.length, 1);
+ verify(contextMenus[0]);
+ compare(linkText, "");
+ compare(mediaType, ContextMenuRequest.MediaTypeNone);
+ compare(selectedText, "");
+
+ // FIXME: Sometimes the keyPress(Qt.Key_Escape) event isn't caught so we keep trying
+ tryVerify(destroyContextMenu);
+ }
+ }
+}
diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml
index ea474e0dc..1159f3194 100644
--- a/tests/auto/quick/qmltests/data/tst_favicon.qml
+++ b/tests/auto/quick/qmltests/data/tst_favicon.qml
@@ -54,6 +54,35 @@ TestWebEngineView {
return url.toString().substring(16)
}
+ function getFaviconPixel(faviconImage) {
+ var grabImage = Qt.createQmlObject("
+ import QtQuick 2.5\n
+ Image { }", test)
+ var faviconCanvas = Qt.createQmlObject("
+ import QtQuick 2.5\n
+ Canvas { }", test)
+
+ test.tryVerify(function() { return faviconImage.status == Image.Ready });
+ faviconImage.grabToImage(function(result) {
+ grabImage.source = result.url
+ });
+ test.tryVerify(function() { return grabImage.status == Image.Ready });
+
+ faviconCanvas.width = faviconImage.width;
+ faviconCanvas.height = faviconImage.height;
+ var ctx = faviconCanvas.getContext("2d");
+ ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height);
+ var imageData = ctx.getImageData(Math.round(faviconCanvas.width/2),
+ Math.round(faviconCanvas.height/2),
+ faviconCanvas.width,
+ faviconCanvas.height);
+
+ grabImage.destroy();
+ faviconCanvas.destroy();
+
+ return imageData.data;
+ }
+
SignalSpy {
id: iconChangedSpy
target: webEngineView
@@ -285,12 +314,6 @@ TestWebEngineView {
var faviconImage = Qt.createQmlObject("
import QtQuick 2.5\n
Image { sourceSize: Qt.size(width, height) }", test)
- var grabImage = Qt.createQmlObject("
- import QtQuick 2.5\n
- Image { }", test)
- var faviconCanvas = Qt.createQmlObject("
- import QtQuick 2.5\n
- Canvas { }", test)
compare(iconChangedSpy.count, 0)
@@ -303,27 +326,53 @@ TestWebEngineView {
faviconImage.width = row.size
faviconImage.height = row.size
faviconImage.source = webEngineView.icon
- verify(_waitFor(function() { return faviconImage.status == Image.Ready } ))
- faviconImage.grabToImage(function(result) {
- grabImage.source = result.url
- })
- verify(_waitFor(function() { return grabImage.status == Image.Ready } ))
+ var pixel = getFaviconPixel(faviconImage);
+ compare(pixel[0], row.value)
- faviconCanvas.width = faviconImage.width
- faviconCanvas.height = faviconImage.height
- var ctx = faviconCanvas.getContext("2d")
- ctx.drawImage(grabImage, 0, 0, grabImage.width, grabImage.height)
+ faviconImage.destroy()
+ }
- var center = Math.round(row.size/2)
- var imageData = ctx.getImageData(center, center, center, center)
- var pixel = imageData.data
+ function test_dynamicFavicon() {
+ var faviconImage = Qt.createQmlObject("
+ import QtQuick 2.5\n
+ Image { width: 16; height: 16; sourceSize: Qt.size(width, height); }", test)
+ faviconImage.source = Qt.binding(function() { return webEngineView.icon; });
- compare(pixel[0], row.value)
+ var colors = [
+ {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg==", "r": 255, "g": 0, "b": 0},
+ {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg==", "r": 0, "g": 255, "b": 0},
+ {"url": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg==", "r": 0, "g": 0, "b": 255},
+ ];
+ var pixel;
+
+ compare(iconChangedSpy.count, 0);
+ webEngineView.loadHtml(
+ "<html>" +
+ "<link rel='icon' type='image/png' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='/>" +
+ "</html>"
+ );
+ verify(webEngineView.waitForLoadSucceeded());
+ tryCompare(iconChangedSpy, "count", 1);
+
+ pixel = getFaviconPixel(faviconImage);
+ compare(pixel[0], 0);
+ compare(pixel[1], 0);
+ compare(pixel[2], 0);
+
+ for (var i = 0; i < colors.length; ++i) {
+ iconChangedSpy.clear();
+ runJavaScript("document.getElementsByTagName('link')[0].href = 'data:image/png;base64," + colors[i]["url"] + "';");
+ tryCompare(faviconImage, "source", "image://favicon/data:image/png;base64," + colors[i]["url"]);
+ compare(iconChangedSpy.count, 1);
+
+ pixel = getFaviconPixel(faviconImage);
+ compare(pixel[0], colors[i]["r"]);
+ compare(pixel[1], colors[i]["g"]);
+ compare(pixel[2], colors[i]["b"]);
+ }
faviconImage.destroy()
- grabImage.destroy()
- faviconCanvas.destroy()
}
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_mouseClick.qml b/tests/auto/quick/qmltests/data/tst_mouseClick.qml
index 527102f59..bd6625a90 100644
--- a/tests/auto/quick/qmltests/data/tst_mouseClick.qml
+++ b/tests/auto/quick/qmltests/data/tst_mouseClick.qml
@@ -64,24 +64,6 @@ TestWebEngineView {
name: "WebEngineViewMouseClick"
when: windowShown
- function getElementCenter(element) {
- var center;
- runJavaScript("(function() {" +
- " var elem = document.getElementById('" + element + "');" +
- " var rect = elem.getBoundingClientRect();" +
- " return { 'x': (rect.left + rect.right) / 2, 'y': (rect.top + rect.bottom) / 2 };" +
- "})();", function(result) { center = result } );
- tryVerify(function() { return center != undefined; });
- return center;
- }
-
- function getTextSelection() {
- var textSelection;
- runJavaScript("window.getSelection().toString()", function(result) { textSelection = result });
- tryVerify(function() { return textSelection != undefined; });
- return textSelection;
- }
-
function test_singleClick() {
webEngineView.settings.focusOnNavigationEnabled = false;
webEngineView.loadHtml("<html><body>" +
diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml
new file mode 100644
index 000000000..36efa7680
--- /dev/null
+++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml
@@ -0,0 +1,57 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 1.4 as Controls
+
+Controls.Menu {
+ id: menu
+ signal done()
+
+ // Use private API for now
+ onAboutToHide: doneTimer.start()
+
+ // WORKAROUND On Mac the Menu may be destroyed before the MenuItem
+ // is actually triggered (see qtbase commit 08cc9b9991ae9ab51)
+ Timer {
+ id: doneTimer
+ interval: 100
+ onTriggered: menu.done()
+ }
+}
diff --git a/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml
new file mode 100644
index 000000000..e61f4c230
--- /dev/null
+++ b/tests/auto/quick/qmltests/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml
@@ -0,0 +1,44 @@
+/****************************************************************************
+**
+** Copyright (C) 2016 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$
+**
+****************************************************************************/
+
+import QtQuick 2.5
+import QtQuick.Controls 1.4 as Controls
+
+Controls.MenuItem { }
+
diff --git a/tests/auto/quick/qmltests/qmltests.pro b/tests/auto/quick/qmltests/qmltests.pro
index 5014fd6e3..16ecbc1bc 100644
--- a/tests/auto/quick/qmltests/qmltests.pro
+++ b/tests/auto/quick/qmltests/qmltests.pro
@@ -43,6 +43,7 @@ OTHER_FILES += \
$$PWD/data/keyboardEvents.html \
$$PWD/data/titleupdate.js \
$$PWD/data/tst_activeFocusOnPress.qml \
+ $$PWD/data/tst_contextMenu.qml \
$$PWD/data/tst_desktopBehaviorLoadHtml.qml \
$$PWD/data/tst_download.qml \
$$PWD/data/tst_favicon.qml \
@@ -92,6 +93,8 @@ OTHER_FILES += \
$$PWD/mock-delegates/QtWebEngine/Controls1Delegates/AlertDialog.qml \
$$PWD/mock-delegates/QtWebEngine/Controls1Delegates/ConfirmDialog.qml \
$$PWD/mock-delegates/QtWebEngine/Controls1Delegates/FilePicker.qml \
+ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/Menu.qml \
+ $$PWD/mock-delegates/QtWebEngine/Controls1Delegates/MenuItem.qml \
$$PWD/mock-delegates/QtWebEngine/Controls1Delegates/PromptDialog.qml \
$$PWD/mock-delegates/QtWebEngine/Controls1Delegates/qmldir \
$$PWD/mock-delegates/TestParams/FilePickerParams.qml \
diff --git a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp
index 6bba8a6df..3ce697faf 100644
--- a/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp
+++ b/tests/auto/widgets/qwebenginedownloads/tst_qwebenginedownloads.cpp
@@ -418,6 +418,13 @@ void tst_QWebEngineDownloads::downloadLink()
void tst_QWebEngineDownloads::downloadTwoLinks()
{
HttpServer server;
+ QSignalSpy requestSpy(&server, &HttpServer::newRequest);
+ QList<HttpReqRep*> results;
+ connect(&server, &HttpServer::newRequest, [&](HttpReqRep *rr) {
+ rr->setParent(nullptr);
+ results.append(rr);
+ });
+
QWebEngineProfile profile;
QWebEnginePage page(&profile);
QWebEngineView view;
@@ -425,7 +432,8 @@ void tst_QWebEngineDownloads::downloadTwoLinks()
view.load(server.url());
view.show();
- auto indexRR = waitForRequest(&server);
+ QTRY_COMPARE(requestSpy.count(), 1);
+ std::unique_ptr<HttpReqRep> indexRR(results.takeFirst());
QVERIFY(indexRR);
QCOMPARE(indexRR->requestMethod(), QByteArrayLiteral("GET"));
QCOMPARE(indexRR->requestPath(), QByteArrayLiteral("/"));
@@ -436,19 +444,24 @@ void tst_QWebEngineDownloads::downloadTwoLinks()
QVERIFY(waitForSignal(&page, &QWebEnginePage::loadFinished, [&](bool ok){ loadOk = ok; }));
QVERIFY(loadOk);
- auto favIconRR = waitForFaviconRequest(&server);
+ QTRY_COMPARE(requestSpy.count(), 2);
+ std::unique_ptr<HttpReqRep> favIconRR(results.takeFirst());
QVERIFY(favIconRR);
+ favIconRR->setResponseStatus(404);
+ favIconRR->sendResponse();
QTRY_VERIFY(view.focusWidget());
QWidget *renderWidget = view.focusWidget();
QTest::mouseClick(renderWidget, Qt::LeftButton, {}, QPoint(10, 10));
QTest::mouseClick(renderWidget, Qt::LeftButton, {}, QPoint(10, 30));
- auto file1RR = waitForRequest(&server);
+ QTRY_VERIFY(requestSpy.count() >= 3);
+ std::unique_ptr<HttpReqRep> file1RR(results.takeFirst());
QVERIFY(file1RR);
QCOMPARE(file1RR->requestMethod(), QByteArrayLiteral("GET"));
QCOMPARE(file1RR->requestPath(), QByteArrayLiteral("/file1"));
- auto file2RR = waitForRequest(&server);
+ QTRY_COMPARE(requestSpy.count(), 4);
+ std::unique_ptr<HttpReqRep> file2RR(results.takeFirst());
QVERIFY(file2RR);
QCOMPARE(file2RR->requestMethod(), QByteArrayLiteral("GET"));
QCOMPARE(file2RR->requestPath(), QByteArrayLiteral("/file2"));
diff --git a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp
index 710561cce..6ae4c41e6 100644
--- a/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp
+++ b/tests/auto/widgets/qwebenginefaviconmanager/tst_qwebenginefaviconmanager.cpp
@@ -60,6 +60,7 @@ private Q_SLOTS:
void downloadIconsDisabled();
void downloadTouchIconsEnabled_data();
void downloadTouchIconsEnabled();
+ void dynamicFavicon();
private:
QWebEngineView *m_view;
@@ -473,6 +474,35 @@ void tst_QWebEngineFaviconManager::downloadTouchIconsEnabled()
QVERIFY(icon.availableSizes().contains(expectedIconSize));
}
+void tst_QWebEngineFaviconManager::dynamicFavicon()
+{
+ QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool)));
+ QSignalSpy iconUrlChangedSpy(m_page, SIGNAL(iconUrlChanged(QUrl)));
+ QSignalSpy iconChangedSpy(m_page, SIGNAL(iconChanged(QIcon)));
+
+ QMap<Qt::GlobalColor, QString> colors;
+ colors.insert(Qt::red, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8DwHwAFBQIAX8jx0gAAAABJRU5ErkJggg=="));
+ colors.insert(Qt::green, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNk+M/wHwAEBgIApD5fRAAAAABJRU5ErkJggg=="));
+ colors.insert(Qt::blue, QString("iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mNkYPj/HwADBwIAMCbHYQAAAABJRU5ErkJggg=="));
+
+ m_page->setHtml("<html>"
+ "<link rel='icon' type='image/png' href='data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII='/>"
+ "</html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+ QTRY_COMPARE(iconUrlChangedSpy.count(), 1);
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+
+ QCOMPARE(m_page->icon().pixmap(1, 1).toImage().pixelColor(0, 0), QColor(Qt::black));
+
+ for (Qt::GlobalColor color : colors.keys()) {
+ iconChangedSpy.clear();
+ evaluateJavaScriptSync(m_page, "document.getElementsByTagName('link')[0].href = 'data:image/png;base64," + colors[color] + "';");
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+ QTRY_COMPARE(m_page->iconUrl().toString(), QString("data:image/png;base64," + colors[color]));
+ QCOMPARE(m_page->icon().pixmap(1, 1).toImage().pixelColor(0, 0), QColor(color));
+ }
+}
+
QTEST_MAIN(tst_QWebEngineFaviconManager)
#include "tst_qwebenginefaviconmanager.moc"
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index f0ab74d6c..a6f09e4fc 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -29,6 +29,7 @@
#include <QMainWindow>
#include <QMenu>
#include <QMimeDatabase>
+#include <QNetworkProxy>
#include <QOpenGLWidget>
#include <QPaintEngine>
#include <QPushButton>
@@ -217,6 +218,7 @@ private Q_SLOTS:
void viewSource();
void viewSourceURL_data();
void viewSourceURL();
+ void proxyConfigWithUnexpectedHostPortPair();
private:
static QPoint elementCenter(QWebEnginePage *page, const QString &id);
@@ -4570,6 +4572,23 @@ void tst_QWebEnginePage::viewSourceURL()
QVERIFY(!page.action(QWebEnginePage::ViewSource)->isEnabled());
}
+Q_DECLARE_METATYPE(QNetworkProxy::ProxyType);
+
+void tst_QWebEnginePage::proxyConfigWithUnexpectedHostPortPair()
+{
+ // Chromium expects a proxy of type NoProxy to not have a host or port set.
+
+ QNetworkProxy proxy;
+ proxy.setType(QNetworkProxy::NoProxy);
+ proxy.setHostName(QStringLiteral("127.0.0.1"));
+ proxy.setPort(244);
+ QNetworkProxy::setApplicationProxy(proxy);
+
+ QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool)));
+ m_page->load(QStringLiteral("http://127.0.0.1:245/"));
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+}
+
static QByteArrayList params = {QByteArrayLiteral("--use-fake-device-for-media-stream")};
W_QTEST_MAIN(tst_QWebEnginePage, params)
diff --git a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
index 294cc52b1..6961f3b6d 100644
--- a/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
+++ b/tests/auto/widgets/qwebengineprofile/tst_qwebengineprofile.cpp
@@ -163,20 +163,25 @@ public:
class ReplyingUrlSchemeHandler : public QWebEngineUrlSchemeHandler
{
- QBuffer m_buffer;
- QByteArray m_bufferData;
public:
ReplyingUrlSchemeHandler(QObject *parent = nullptr)
: QWebEngineUrlSchemeHandler(parent)
{
- m_buffer.setBuffer(&m_bufferData);
+ }
+ ~ReplyingUrlSchemeHandler()
+ {
}
void requestStarted(QWebEngineUrlRequestJob *job)
{
- m_bufferData = job->requestUrl().toString().toUtf8();
- job->reply("text/plain;charset=utf-8", &m_buffer);
+ QBuffer *buffer = new QBuffer;
+ buffer->setData(job->requestUrl().toString().toUtf8());
+ connect(buffer, &QIODevice::aboutToClose, buffer, &QObject::deleteLater);
+ m_buffers.append(buffer);
+ job->reply("text/plain;charset=utf-8", buffer);
}
+
+ QList<QPointer<QBuffer>> m_buffers;
};
class StreamingIODevice : public QIODevice {
@@ -309,6 +314,11 @@ void tst_QWebEngineProfile::urlSchemeHandlers()
url = QUrl(QStringLiteral("aviancarrier:inspector.mortensen@politistyrke.dk"));
QVERIFY(loadSync(&view, url));
QCOMPARE(toPlainTextSync(view.page()), url.toString());
+
+ // Check that all buffers got deleted
+ QCOMPARE(gopherHandler.m_buffers.count(), 2);
+ for (int i = 0; i < gopherHandler.m_buffers.count(); ++i)
+ QVERIFY(gopherHandler.m_buffers.at(i).isNull());
}
class FailingUrlSchemeHandler : public QWebEngineUrlSchemeHandler
diff --git a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
index e614c74d8..d852ca902 100644
--- a/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
+++ b/tests/auto/widgets/qwebenginescript/tst_qwebenginescript.cpp
@@ -81,15 +81,12 @@ void tst_QWebEngineScript::injectionPoint()
s.setInjectionPoint(static_cast<QWebEngineScript::InjectionPoint>(injectionPoint));
s.setWorldId(QWebEngineScript::MainWorld);
QWebEnginePage page;
- page.scripts().insert(s);
- page.setHtml(QStringLiteral("<html><head><script> var contents;") + testScript
- + QStringLiteral("document.addEventListener(\"load\", setTimeout(function(event) {\
- document.body.innerText = contents;\
- }, 550));\
- </script></head><body></body></html>"));
QSignalSpy spyFinished(&page, &QWebEnginePage::loadFinished);
+ page.scripts().insert(s);
+ page.setHtml(QStringLiteral("<html><head><script>") + testScript + QStringLiteral("</script></head><body></body></html>"));
QVERIFY(spyFinished.wait());
- QTRY_COMPARE(evaluateJavaScriptSync(&page, "document.body.innerText"), QVariant::fromValue(QStringLiteral("SUCCESS")));
+ const QVariant expected(QVariant::fromValue(QStringLiteral("SUCCESS")));
+ QTRY_COMPARE(evaluateJavaScriptSync(&page, "document.myContents"), expected);
}
void tst_QWebEngineScript::injectionPoint_data()
@@ -97,17 +94,21 @@ void tst_QWebEngineScript::injectionPoint_data()
QTest::addColumn<int>("injectionPoint");
QTest::addColumn<QString>("testScript");
QTest::newRow("DocumentCreation") << static_cast<int>(QWebEngineScript::DocumentCreation)
- << QStringLiteral("var contents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";");
+ << QStringLiteral("document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";");
QTest::newRow("DocumentReady") << static_cast<int>(QWebEngineScript::DocumentReady)
// use a zero timeout to make sure the user script got a chance to run as the order is undefined.
<< QStringLiteral("document.addEventListener(\"DOMContentLoaded\", function() {\
- setTimeout(function() {\
- contents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\
- }, 0)});");
- QTest::newRow("Deferred") << static_cast<int>(QWebEngineScript::Deferred)
- << QStringLiteral("document.addEventListener(\"load\", setTimeout(function(event) {\
- contents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\
- }, 500));");
+ setTimeout(function() {\
+ document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\
+ }, 0)});");
+ QTest::newRow("Deferred") << static_cast<int>(QWebEngineScript::DocumentReady)
+ << QStringLiteral("document.onreadystatechange = function() { \
+ if (document.readyState == \"complete\") { \
+ setTimeout(function() {\
+ document.myContents = (typeof(foo) == \"undefined\")? \"FAILURE\" : \"SUCCESS\";\
+ }, 0);\
+ } \
+ };");
}
void tst_QWebEngineScript::scriptWorld()
diff --git a/tests/auto/widgets/qwebengineview/BLACKLIST b/tests/auto/widgets/qwebengineview/BLACKLIST
index 0da1000a8..bf7292c86 100644
--- a/tests/auto/widgets/qwebengineview/BLACKLIST
+++ b/tests/auto/widgets/qwebengineview/BLACKLIST
@@ -5,4 +5,4 @@ windows
*
[textSelectionOutOfInputField]
-windows
+*