summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-21 14:35:01 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-03-21 14:35:01 +0100
commit432af50e930b7f11455fc1daec17d9c215ea88ee (patch)
tree75f8e9cc04069de32c25660298c4fce046f88b4e
parent809afc26fe0c47b249cf11376c8ea484a2bfaaf1 (diff)
parentd5a479a720ee76fae9fa7b0f7b6b3d0a61718ff0 (diff)
Merge remote-tracking branch 'origin/5.13' into dev
-rw-r--r--configure.pri2
-rw-r--r--dist/changes-5.12.274
-rw-r--r--examples/webengine/quicknanobrowser/BrowserWindow.qml23
m---------src/3rdparty0
-rw-r--r--src/buildtools/gn.pro8
-rw-r--r--src/core/api/core_api.pro2
-rw-r--r--src/core/api/qwebengineclientcertificatestore.cpp53
-rw-r--r--src/core/api/qwebengineclientcertificatestore.h22
-rw-r--r--src/core/api/qwebenginecookiestore.cpp2
-rw-r--r--src/core/api/qwebenginemessagepumpscheduler.cpp72
-rw-r--r--src/core/api/qwebenginemessagepumpscheduler_p.h80
-rw-r--r--src/core/api/qwebenginenotification.cpp15
-rw-r--r--src/core/api/qwebenginenotification.h21
-rw-r--r--src/core/api/qwebengineurlrequestjob.cpp2
-rw-r--r--src/core/api/qwebengineurlrequestjob.h2
-rw-r--r--src/core/api/qwebengineurlschemehandler.cpp2
-rw-r--r--src/core/browser_accessibility_manager_qt.cpp6
-rw-r--r--src/core/browser_accessibility_manager_qt.h3
-rw-r--r--src/core/browser_accessibility_qt.cpp3
-rw-r--r--src/core/browser_main_parts_qt.cpp48
-rw-r--r--src/core/config/common.pri1
-rw-r--r--src/core/content_client_qt.cpp5
-rw-r--r--src/core/core_project.pro8
-rw-r--r--src/core/favicon_manager.cpp20
-rw-r--r--src/core/favicon_manager.h15
-rw-r--r--src/core/gn_run.pro2
-rw-r--r--src/core/login_delegate_qt.cpp19
-rw-r--r--src/core/login_delegate_qt.h1
-rw-r--r--src/core/net/client_cert_override.cpp58
-rw-r--r--src/core/net/client_cert_override.h8
-rw-r--r--src/core/net/client_cert_store_data.cpp21
-rw-r--r--src/core/net/client_cert_store_data.h8
-rw-r--r--src/core/net/network_delegate_qt.cpp3
-rw-r--r--src/core/net/url_request_custom_job_delegate.cpp2
-rw-r--r--src/core/net/url_request_custom_job_delegate.h2
-rw-r--r--src/core/ozone/gl_surface_glx_qt.cpp2
-rw-r--r--src/core/platform_notification_service_qt.cpp2
-rw-r--r--src/core/printing/pdfium_document_wrapper_qt.cpp5
-rw-r--r--src/core/profile_adapter.cpp29
-rw-r--r--src/core/profile_adapter.h13
-rw-r--r--src/core/profile_adapter_client.h2
-rw-r--r--src/core/profile_io_data_qt.cpp21
-rw-r--r--src/core/profile_io_data_qt.h7
-rw-r--r--src/core/renderer/content_renderer_client_qt.cpp27
-rw-r--r--src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp27
-rw-r--r--src/core/type_conversion.cpp2
-rw-r--r--src/core/web_contents_adapter.cpp11
-rw-r--r--src/core/web_contents_adapter_client.h1
-rw-r--r--src/core/web_contents_delegate_qt.cpp6
-rw-r--r--src/core/web_contents_view_qt.cpp29
-rw-r--r--src/core/web_contents_view_qt.h7
-rw-r--r--src/core/web_engine_context.cpp50
-rw-r--r--src/core/web_engine_context.h3
-rw-r--r--src/core/web_engine_settings.cpp39
-rw-r--r--src/core/web_engine_settings.h6
-rw-r--r--src/webengine/api/qquickwebengineclientcertificateselection.cpp19
-rw-r--r--src/webengine/api/qquickwebengineclientcertificateselection_p.h6
-rw-r--r--src/webengine/api/qquickwebenginedialogrequests.cpp6
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem.cpp26
-rw-r--r--src/webengine/api/qquickwebenginedownloaditem_p_p.h1
-rw-r--r--src/webengine/api/qquickwebengineprofile.cpp65
-rw-r--r--src/webengine/api/qquickwebengineprofile.h5
-rw-r--r--src/webengine/api/qquickwebengineprofile_p.h9
-rw-r--r--src/webengine/api/qquickwebenginesettings.cpp22
-rw-r--r--src/webengine/api/qquickwebenginesettings_p.h4
-rw-r--r--src/webengine/api/qquickwebengineview.cpp4
-rw-r--r--src/webengine/api/qquickwebengineview_p_p.h2
-rw-r--r--src/webengine/doc/src/external-resources.qdoc5
-rw-r--r--src/webengine/doc/src/qtwebengine-examples.qdoc2
-rw-r--r--src/webengine/doc/src/qtwebengine-features.qdoc6
-rw-r--r--src/webengine/doc/src/qtwebengine-overview.qdoc30
-rw-r--r--src/webengine/doc/src/qtwebengine-qmlmodule.qdoc6
-rw-r--r--src/webengine/plugin/plugin.cpp6
-rw-r--r--src/webengine/plugin/plugin.pro1
-rw-r--r--src/webengine/plugin/plugins.qmltypes87
-rw-r--r--src/webengine/testsupport/plugins.qmltypes73
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem.cpp23
-rw-r--r--src/webenginewidgets/api/qwebenginedownloaditem_p.h4
-rw-r--r--src/webenginewidgets/api/qwebenginenotificationpresenter.cpp10
-rw-r--r--src/webenginewidgets/api/qwebenginepage.cpp36
-rw-r--r--src/webenginewidgets/api/qwebenginepage_p.h1
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.cpp83
-rw-r--r--src/webenginewidgets/api/qwebengineprofile.h8
-rw-r--r--src/webenginewidgets/api/qwebengineprofile_p.h5
-rw-r--r--src/webenginewidgets/api/qwebenginesettings.cpp3
-rw-r--r--src/webenginewidgets/api/qwebenginesettings.h1
-rw-r--r--src/webenginewidgets/api/qwebengineview.cpp2
-rw-r--r--src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc2
-rw-r--r--src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc20
-rw-r--r--src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc4
-rw-r--r--src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc14
-rw-r--r--tests/auto/core/core.pro7
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/qwebengineclientcertificatestore.pro1
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/resources/certificate.crt23
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/resources/certificate1.crt23
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/resources/privatekey.key28
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/resources/privatekey1.key28
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp98
-rw-r--r--tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.qrc8
-rw-r--r--tests/auto/quick/publicapi/tst_publicapi.cpp70
-rw-r--r--tests/auto/quick/qmltests/data/tst_favicon.qml33
-rw-r--r--tests/auto/quick/qmltests/data/tst_notification.qml8
-rw-r--r--tests/auto/quick/quick.pro2
-rw-r--r--tests/auto/shared/data/notification.html2
-rw-r--r--tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp38
-rw-r--r--tests/auto/widgets/offscreen/offscreen.pro6
-rw-r--r--tests/auto/widgets/offscreen/tst_offscreen.cpp60
-rw-r--r--tests/auto/widgets/proxy/proxy.pro9
-rw-r--r--tests/auto/widgets/proxy/proxy_server.cpp90
-rw-r--r--tests/auto/widgets/proxy/proxy_server.h59
-rw-r--r--tests/auto/widgets/proxy/tst_proxy.cpp69
-rw-r--r--tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp32
-rw-r--r--tests/auto/widgets/qwebenginepage/BLACKLIST6
-rw-r--r--tests/auto/widgets/qwebenginepage/resources/reload.html8
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp68
-rw-r--r--tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc1
-rw-r--r--tests/auto/widgets/widgets.pro11
117 files changed, 1847 insertions, 444 deletions
diff --git a/configure.pri b/configure.pri
index 46fec536a..8db31ddd3 100644
--- a/configure.pri
+++ b/configure.pri
@@ -314,6 +314,6 @@ defineTest(qtConfTest_hasThumbFlag) {
}
defineTest(qtConfTest_hasGcc6OrNewer) {
- greaterThan(QT_GCC_MAJOR_VERSION, 5):return(true)
+ greaterThan(QMAKE_GCC_MAJOR_VERSION, 5):return(true)
return(false)
}
diff --git a/dist/changes-5.12.2 b/dist/changes-5.12.2
new file mode 100644
index 000000000..0f5087e55
--- /dev/null
+++ b/dist/changes-5.12.2
@@ -0,0 +1,74 @@
+Qt 5.12.2 is a bug-fix release. It maintains both forward and backward
+compatibility (source and binary) with Qt 5.12.0 through 5.12.1.
+
+For more details, refer to the online documentation included in this
+distribution. The documentation is also available online:
+
+https://doc.qt.io/qt-5/index.html
+
+The Qt version 5.12 series is binary compatible with the 5.11.x series.
+Applications compiled for 5.11 will continue to run with 5.12.
+
+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.12.2 Changes *
+****************************************************************************
+
+Behavior Changes
+----------------
+
+ - Deleting a download item will now also cancel the download if it is
+ still in progress.
+
+
+Chromium
+--------
+
+ - Security fixes from Chromium up to version 72.0.3626.121, including:
+ * CVE-2019-5754
+ * CVE-2019-5755
+ * CVE-2019-5756
+ * CVE-2019-5757
+ * CVE-2019-5758
+ * CVE-2019-5759
+ * CVE-2019-5760
+ * CVE-2019-5762
+ * CVE-2019-5763
+ * CVE-2019-5764
+ * CVE-2019-5769
+ * CVE-2019-5770
+ * CVE-2019-5775
+ * CVE-2019-5776
+ * CVE-2019-5777
+ * CVE-2019-5779
+ * CVE-2019-5781
+ * CVE-2019-5782
+ * CVE-2019-5783
+ * CVE-2019-5784
+ * CVE-2019-5786
+ * Security issue 895117
+ * Security issue 895970
+ * Security issue 899689
+ * Security issue 901677
+ * Security issue 903500
+ * Security issue 907047
+ * Security issue 908358
+ * Security issue 911253
+ * Security issue 912508
+ * Security issue 912520
+ * Security issue 922677
+
+General
+-------
+
+ - [QTBUG-72021] Improved tooltip wrapping to match other browsers.
+ - [QTBUG-72714] Fixed clipboard API not being permitted when settings allowed it.
+ - [QTBUG-73839] Fixed minor memory leak per download.
+ - Fixed regression in certificate transparency checking.
diff --git a/examples/webengine/quicknanobrowser/BrowserWindow.qml b/examples/webengine/quicknanobrowser/BrowserWindow.qml
index d8216acaf..29e1a9da7 100644
--- a/examples/webengine/quicknanobrowser/BrowserWindow.qml
+++ b/examples/webengine/quicknanobrowser/BrowserWindow.qml
@@ -89,6 +89,7 @@ ApplicationWindow {
property alias touchIconsEnabled: touchIconsEnabled.checked
property alias webRTCPublicInterfacesOnly : webRTCPublicInterfacesOnly.checked
property alias devToolsEnabled: devToolsEnabled.checked
+ property alias pdfViewerEnabled: pdfViewerEnabled.checked
}
Action {
@@ -333,6 +334,12 @@ ApplicationWindow {
checkable: true
checked: false
}
+ MenuItem {
+ id: pdfViewerEnabled
+ text: "PDF viewer enabled"
+ checkable: true
+ checked: WebEngine.settings.pdfViewerEnabled
+ }
}
}
}
@@ -380,11 +387,12 @@ ApplicationWindow {
focus: true
onLinkHovered: function(hoveredUrl) {
- if (hoveredUrl === "")
- resetStatusText.start();
+ if (hoveredUrl == "")
+ hideStatusText.start();
else {
- resetStatusText.stop();
statusText.text = hoveredUrl;
+ statusBubble.visible = true;
+ hideStatusText.stop();
}
}
@@ -410,6 +418,7 @@ ApplicationWindow {
settings.autoLoadIconsForPage: appSettings.autoLoadIconsForPage
settings.touchIconsEnabled: appSettings.touchIconsEnabled
settings.webRTCPublicInterfacesOnly: appSettings.webRTCPublicInterfacesOnly
+ settings.pdfViewerEnabled: appSettings.pdfViewerEnabled
onCertificateError: function(error) {
error.defer();
@@ -570,6 +579,7 @@ ApplicationWindow {
id: statusBubble
color: "oldlace"
property int padding: 8
+ visible: false
anchors.left: parent.left
anchors.bottom: parent.bottom
@@ -582,9 +592,12 @@ ApplicationWindow {
elide: Qt.ElideMiddle
Timer {
- id: resetStatusText
+ id: hideStatusText
interval: 750
- onTriggered: statusText.text = ""
+ onTriggered: {
+ statusText.text = "";
+ statusBubble.visible = false;
+ }
}
}
}
diff --git a/src/3rdparty b/src/3rdparty
-Subproject 8d510183ca27142801b56bb50d63cbb2a92d433
+Subproject 0aae24c2876d19946ce0d28adc38c3dbed2c654
diff --git a/src/buildtools/gn.pro b/src/buildtools/gn.pro
index 559cdf183..30ada9357 100644
--- a/src/buildtools/gn.pro
+++ b/src/buildtools/gn.pro
@@ -18,7 +18,13 @@ build_pass|!debug_and_release {
src_3rd_party_dir = $$absolute_path("$${getChromiumSrcDir()}/../", "$$QTWEBENGINE_ROOT")
gn_bootstrap = $$system_path($$absolute_path(gn/build/gen.py, $$src_3rd_party_dir))
- gn_configure = $$system_quote($$gn_bootstrap) --no-last-commit-position --out-path $$out_path
+ gn_configure = $$system_quote($$gn_bootstrap) --no-last-commit-position --out-path $$out_path \
+ --cc \"$$which($$QMAKE_CC)\" --cxx \"$$which($$QMAKE_CXX)\" \
+ --ld \"$$which($$QMAKE_LINK)\"
+ macos {
+ gn_configure += --isysroot \"$$QMAKE_MAC_SDK_PATH\"
+ }
+ message($$gn_configure)
!system("$$pythonPathForSystem() $$gn_configure") {
error("GN generation error!")
}
diff --git a/src/core/api/core_api.pro b/src/core/api/core_api.pro
index 4d3ddcc8e..326d4481f 100644
--- a/src/core/api/core_api.pro
+++ b/src/core/api/core_api.pro
@@ -38,6 +38,7 @@ HEADERS = \
qwebenginecookiestore.h \
qwebenginecookiestore_p.h \
qwebenginehttprequest.h \
+ qwebenginemessagepumpscheduler_p.h \
qwebenginenotification.h \
qwebenginequotarequest.h \
qwebengineregisterprotocolhandlerrequest.h \
@@ -53,6 +54,7 @@ SOURCES = \
qwebengineclientcertificatestore.cpp \
qwebenginecookiestore.cpp \
qwebenginehttprequest.cpp \
+ qwebenginemessagepumpscheduler.cpp \
qwebenginenotification.cpp \
qwebenginequotarequest.cpp \
qwebengineregisterprotocolhandlerrequest.cpp \
diff --git a/src/core/api/qwebengineclientcertificatestore.cpp b/src/core/api/qwebengineclientcertificatestore.cpp
index 850dd16d7..854628b29 100644
--- a/src/core/api/qwebengineclientcertificatestore.cpp
+++ b/src/core/api/qwebengineclientcertificatestore.cpp
@@ -48,8 +48,6 @@ QT_BEGIN_NAMESPACE
#if QT_CONFIG(ssl)
-QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance = nullptr;
-
/*!
\class QWebEngineClientCertificateStore::Entry
\inmodule QtWebEngineCore
@@ -69,8 +67,8 @@ QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::m_instance =
The getInstance() method can be used to access the single instance of the class.
*/
-QWebEngineClientCertificateStore::QWebEngineClientCertificateStore()
- : d_ptr(new QtWebEngineCore::ClientCertificateStoreData)
+QWebEngineClientCertificateStore::QWebEngineClientCertificateStore(QtWebEngineCore::ClientCertificateStoreData *storeData)
+ : m_storeData(storeData)
{
}
@@ -85,59 +83,35 @@ QWebEngineClientCertificateStore::~QWebEngineClientCertificateStore()
}
/*!
- Returns an in-memory client certificate store.
-*/
-
-QWebEngineClientCertificateStore *QWebEngineClientCertificateStore::getInstance()
-{
- if (!m_instance)
- m_instance = new QWebEngineClientCertificateStore;
- return m_instance;
-}
-
-/*!
Adds a \a certificate with the \a privateKey to the in-memory client certificate store.
*/
void QWebEngineClientCertificateStore::add(const QSslCertificate &certificate, const QSslKey &privateKey)
{
- d_ptr->add(certificate, privateKey);
+ m_storeData->add(certificate, privateKey);
}
/*!
- Returns a list of private and public keys of client certificates in the in-memory store.
- Returns an empty list if the in-memory store does not contain certificates.
+ Returns a list of the client certificates in the in-memory store.
+ Returns an empty list if the store does not contain any certificates.
*/
-QList<QWebEngineClientCertificateStore::Entry> QWebEngineClientCertificateStore::toList() const
+QVector<QSslCertificate> QWebEngineClientCertificateStore::certificates() const
{
- QList<Entry> certificateList;
- for (auto data : qAsConst(d_ptr->addedCerts)) {
- Entry entry;
- entry.certificate = data->certificate;
- entry.privateKey = data->key;
- certificateList.append(entry);
- }
+ QVector<QSslCertificate> certificateList;
+ for (auto data : qAsConst(m_storeData->extraCerts))
+ certificateList.append(data->certificate);
return certificateList;
}
/*!
Deletes all the instances of the client certificate in the in-memory client certificate store
- that matches the certificate in the \a entry.
+ that matches the certificate \a certificate.
*/
-void QWebEngineClientCertificateStore::remove(Entry entry)
+void QWebEngineClientCertificateStore::remove(const QSslCertificate &certificate)
{
- auto it = d_ptr->addedCerts.begin();
- while (it != d_ptr->addedCerts.end()) {
- auto *overrideData = *it;
- if (entry.certificate.toDer() == overrideData->certificate.toDer()) {
- d_ptr->deletedCerts.append(overrideData);
- it = d_ptr->addedCerts.erase(it);
- continue;
- }
- ++it;
- }
+ m_storeData->remove(certificate);
}
/*!
@@ -146,8 +120,7 @@ void QWebEngineClientCertificateStore::remove(Entry entry)
void QWebEngineClientCertificateStore::clear()
{
- d_ptr->deletedCerts.append(d_ptr->addedCerts);
- d_ptr->addedCerts.clear();
+ m_storeData->clear();
}
#endif // QT_CONFIG(ssl)
diff --git a/src/core/api/qwebengineclientcertificatestore.h b/src/core/api/qwebengineclientcertificatestore.h
index c0bd66e2b..d9a1a0545 100644
--- a/src/core/api/qwebengineclientcertificatestore.h
+++ b/src/core/api/qwebengineclientcertificatestore.h
@@ -42,42 +42,34 @@
#include <QtWebEngineCore/qtwebenginecoreglobal.h>
-#include <QtCore/qscopedpointer.h>
+#include <QtCore/qvector.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslkey.h>
namespace QtWebEngineCore {
-class ClientCertOverrideStore;
struct ClientCertificateStoreData;
+class ProfileAdapter;
}
QT_BEGIN_NAMESPACE
#if QT_CONFIG(ssl)
-
class QWEBENGINECORE_EXPORT QWebEngineClientCertificateStore {
public:
- struct Entry {
- QSslKey privateKey;
- QSslCertificate certificate;
- };
-
- static QWebEngineClientCertificateStore *getInstance();
void add(const QSslCertificate &certificate, const QSslKey &privateKey);
- QList<Entry> toList() const;
- void remove(Entry entry);
+ QVector<QSslCertificate> certificates() const;
+ void remove(const QSslCertificate &certificate);
void clear();
private:
- friend class QtWebEngineCore::ClientCertOverrideStore;
- static QWebEngineClientCertificateStore *m_instance;
+ friend class QtWebEngineCore::ProfileAdapter;
Q_DISABLE_COPY(QWebEngineClientCertificateStore)
- QWebEngineClientCertificateStore();
+ QWebEngineClientCertificateStore(QtWebEngineCore::ClientCertificateStoreData *storeData);
~QWebEngineClientCertificateStore();
- QScopedPointer<QtWebEngineCore::ClientCertificateStoreData> d_ptr;
+ QtWebEngineCore::ClientCertificateStoreData *m_storeData;
};
#endif // QT_CONFIG(ssl)
diff --git a/src/core/api/qwebenginecookiestore.cpp b/src/core/api/qwebenginecookiestore.cpp
index 035c98342..3897fb128 100644
--- a/src/core/api/qwebenginecookiestore.cpp
+++ b/src/core/api/qwebenginecookiestore.cpp
@@ -382,7 +382,7 @@ void QWebEngineCookieStore::setCookieFilter(std::function<bool(const FilterReque
\inmodule QtWebEngineCore
\since 5.11
- \brief This struct is used in conjunction with QWebEngineCookieStore::setCookieFilter() and is
+ \brief The QWebEngineCookieStore::FilterRequest struct is used in conjunction with QWebEngineCookieStore::setCookieFilter() and is
the type \a filterCallback operates on.
\sa QWebEngineCookieStore::setCookieFilter()
diff --git a/src/core/api/qwebenginemessagepumpscheduler.cpp b/src/core/api/qwebenginemessagepumpscheduler.cpp
new file mode 100644
index 000000000..34cbc49bf
--- /dev/null
+++ b/src/core/api/qwebenginemessagepumpscheduler.cpp
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qwebenginemessagepumpscheduler_p.h"
+
+#include <QAbstractEventDispatcher>
+#include <QCoreApplication>
+#include <QTimerEvent>
+
+QWebEngineMessagePumpScheduler::QWebEngineMessagePumpScheduler(std::function<void()> callback)
+ : m_callback(std::move(callback))
+{}
+
+void QWebEngineMessagePumpScheduler::scheduleWork()
+{
+ QCoreApplication::postEvent(this, new QTimerEvent(0));
+}
+
+void QWebEngineMessagePumpScheduler::scheduleDelayedWork(int delay)
+{
+ if (delay < 0) {
+ killTimer(m_timerId);
+ m_timerId = 0;
+ } else if (!m_timerId || delay < QAbstractEventDispatcher::instance()->remainingTime(m_timerId)) {
+ killTimer(m_timerId);
+ m_timerId = startTimer(delay);
+ }
+}
+
+void QWebEngineMessagePumpScheduler::timerEvent(QTimerEvent *ev)
+{
+ Q_ASSERT(!ev->timerId() || m_timerId == ev->timerId());
+ killTimer(m_timerId);
+ m_timerId = 0;
+ m_callback();
+}
diff --git a/src/core/api/qwebenginemessagepumpscheduler_p.h b/src/core/api/qwebenginemessagepumpscheduler_p.h
new file mode 100644
index 000000000..4c9e4d600
--- /dev/null
+++ b/src/core/api/qwebenginemessagepumpscheduler_p.h
@@ -0,0 +1,80 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 3 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL3 included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 3 requirements
+** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 2.0 or (at your option) the GNU General
+** Public license version 3 or any later version approved by the KDE Free
+** Qt Foundation. The licenses are as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-2.0.html and
+** https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QWEBENGINEMESSAGEPUMPSCHEDULER_P_H
+#define QWEBENGINEMESSAGEPUMPSCHEDULER_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 <QtCore/qobject.h>
+
+#include <functional>
+
+QT_BEGIN_NAMESPACE
+
+class QWEBENGINECORE_PRIVATE_EXPORT QWebEngineMessagePumpScheduler : public QObject
+{
+ Q_OBJECT
+public:
+ QWebEngineMessagePumpScheduler(std::function<void()> callback);
+ void scheduleWork();
+ void scheduleDelayedWork(int delay);
+
+protected:
+ void timerEvent(QTimerEvent *ev) override;
+
+private:
+ int m_timerId = 0;
+ std::function<void()> m_callback;
+};
+
+QT_END_NAMESPACE
+
+#endif // !QWEBENGINEMESSAGEPUMPSCHEDULER_P_H
diff --git a/src/core/api/qwebenginenotification.cpp b/src/core/api/qwebenginenotification.cpp
index 0b91cf273..89fd1eff9 100644
--- a/src/core/api/qwebenginenotification.cpp
+++ b/src/core/api/qwebenginenotification.cpp
@@ -55,6 +55,11 @@ using QtWebEngineCore::UserNotificationController;
\inmodule QtWebEngineCore
This class contains the information and API for HTML5 desktop and push notifications.
+
+ Web engine notifications are passed to the user in the
+ \l QWebEngineProfile::setNotificationPresenter() and
+ \l QQuickWebEngineProfile::userNotification() calls and the
+ \l WebEngineProfile::userNotification() signal.
*/
class QWebEngineNotificationPrivate : public UserNotificationController::Client {
@@ -212,18 +217,18 @@ QString QWebEngineNotification::language() const
\brief The text direction for the notification's title and body.
\sa title(), message()
*/
-QWebEngineNotification::Direction QWebEngineNotification::direction() const
+Qt::LayoutDirection QWebEngineNotification::direction() const
{
Q_D(const QWebEngineNotification);
- return d ? static_cast<Direction>(d->controller->direction()) : DirectionAuto;
+ return d ? d->controller->direction() : Qt::LayoutDirectionAuto;
}
/*!
- Returns \c true if the notification is a default constructed null notification.
+ Returns \c true if the notification is not a default constructed null notification.
*/
-bool QWebEngineNotification::isNull() const
+bool QWebEngineNotification::isValid() const
{
- return d_ptr.isNull();
+ return !d_ptr.isNull();
}
/*!
diff --git a/src/core/api/qwebenginenotification.h b/src/core/api/qwebenginenotification.h
index b6b7414f9..0012e5d78 100644
--- a/src/core/api/qwebenginenotification.h
+++ b/src/core/api/qwebenginenotification.h
@@ -64,22 +64,15 @@ class QWEBENGINECORE_EXPORT QWebEngineNotification : public QObject {
Q_PROPERTY(QString message READ message CONSTANT FINAL)
Q_PROPERTY(QString tag READ tag CONSTANT FINAL)
Q_PROPERTY(QString language READ language CONSTANT FINAL)
- Q_PROPERTY(Direction direction READ direction CONSTANT FINAL)
+ Q_PROPERTY(Qt::LayoutDirection direction READ direction CONSTANT FINAL)
public:
QWebEngineNotification();
- QWebEngineNotification(const QWebEngineNotification &);
+ QWebEngineNotification(const QWebEngineNotification &other);
virtual ~QWebEngineNotification();
- const QWebEngineNotification &operator=(const QWebEngineNotification &);
+ const QWebEngineNotification &operator=(const QWebEngineNotification &other);
- enum Direction {
- LeftToRight = Qt::LeftToRight,
- RightToLeft = Qt::RightToLeft,
- DirectionAuto = Qt::LayoutDirectionAuto
- };
- Q_ENUM(Direction)
-
- bool matches(const QWebEngineNotification &) const;
+ bool matches(const QWebEngineNotification &other) const;
QUrl origin() const;
QIcon icon() const;
@@ -87,9 +80,9 @@ public:
QString message() const;
QString tag() const;
QString language() const;
- Direction direction() const;
+ Qt::LayoutDirection direction() const;
- bool isNull() const;
+ bool isValid() const;
public Q_SLOTS:
void show() const;
@@ -100,7 +93,7 @@ Q_SIGNALS:
void closed();
private:
- QWebEngineNotification(const QSharedPointer<QtWebEngineCore::UserNotificationController> &);
+ QWebEngineNotification(const QSharedPointer<QtWebEngineCore::UserNotificationController> &controller);
Q_DECLARE_PRIVATE(QWebEngineNotification)
QScopedPointer<QWebEngineNotificationPrivate> d_ptr;
friend class QQuickWebEngineProfilePrivate;
diff --git a/src/core/api/qwebengineurlrequestjob.cpp b/src/core/api/qwebengineurlrequestjob.cpp
index 41b43d42c..bc860b3b3 100644
--- a/src/core/api/qwebengineurlrequestjob.cpp
+++ b/src/core/api/qwebengineurlrequestjob.cpp
@@ -143,7 +143,7 @@ QUrl QWebEngineUrlRequestJob::initiator() const
\since 5.13
Returns any HTTP headers added to the request.
*/
-const QMap<QByteArray, QByteArray> &QWebEngineUrlRequestJob::requestHeaders() const
+QMap<QByteArray, QByteArray> QWebEngineUrlRequestJob::requestHeaders() const
{
return d_ptr->requestHeaders();
}
diff --git a/src/core/api/qwebengineurlrequestjob.h b/src/core/api/qwebengineurlrequestjob.h
index 55ec7c6d2..b2dd8baa3 100644
--- a/src/core/api/qwebengineurlrequestjob.h
+++ b/src/core/api/qwebengineurlrequestjob.h
@@ -73,7 +73,7 @@ public:
QUrl requestUrl() const;
QByteArray requestMethod() const;
QUrl initiator() const;
- const QMap<QByteArray, QByteArray> &requestHeaders() const;
+ QMap<QByteArray, QByteArray> requestHeaders() const;
void reply(const QByteArray &contentType, QIODevice *device);
void fail(Error error);
diff --git a/src/core/api/qwebengineurlschemehandler.cpp b/src/core/api/qwebengineurlschemehandler.cpp
index 2e93f4b73..aecee5044 100644
--- a/src/core/api/qwebengineurlschemehandler.cpp
+++ b/src/core/api/qwebengineurlschemehandler.cpp
@@ -45,7 +45,7 @@ QT_BEGIN_NAMESPACE
/*!
\class QWebEngineUrlSchemeHandler
- \brief The QWebEngineUrlSchemeHandler is a base class for handling custom URL schemes.
+ \brief The QWebEngineUrlSchemeHandler class is a base class for handling custom URL schemes.
\since 5.6
To implement a custom URL scheme for QtWebEngine, you first have to create an instance of
diff --git a/src/core/browser_accessibility_manager_qt.cpp b/src/core/browser_accessibility_manager_qt.cpp
index 644a0a9f0..7fb1386c5 100644
--- a/src/core/browser_accessibility_manager_qt.cpp
+++ b/src/core/browser_accessibility_manager_qt.cpp
@@ -76,6 +76,12 @@ BrowserAccessibilityManagerQt::BrowserAccessibilityManagerQt(
, m_parentObject(parentObject)
{
Initialize(initialTree);
+ m_valid = true; // BrowserAccessibilityQt can start using the AXTree
+}
+
+BrowserAccessibilityManagerQt::~BrowserAccessibilityManagerQt()
+{
+ m_valid = false; // BrowserAccessibilityQt should stop using the AXTree
}
QAccessibleInterface *BrowserAccessibilityManagerQt::rootParentAccessible()
diff --git a/src/core/browser_accessibility_manager_qt.h b/src/core/browser_accessibility_manager_qt.h
index a2d6db458..87c8875ba 100644
--- a/src/core/browser_accessibility_manager_qt.h
+++ b/src/core/browser_accessibility_manager_qt.h
@@ -57,14 +57,17 @@ public:
const ui::AXTreeUpdate& initialTree,
BrowserAccessibilityDelegate* delegate,
BrowserAccessibilityFactory* factory = new BrowserAccessibilityFactory());
+ ~BrowserAccessibilityManagerQt() override;
void FireBlinkEvent(ax::mojom::Event event_type,
BrowserAccessibility* node) override;
QAccessibleInterface *rootParentAccessible();
+ bool isValid() const { return m_valid; }
private:
Q_DISABLE_COPY(BrowserAccessibilityManagerQt)
QObject *m_parentObject;
+ bool m_valid = false;
};
}
diff --git a/src/core/browser_accessibility_qt.cpp b/src/core/browser_accessibility_qt.cpp
index c906071f2..75527ea95 100644
--- a/src/core/browser_accessibility_qt.cpp
+++ b/src/core/browser_accessibility_qt.cpp
@@ -73,7 +73,8 @@ BrowserAccessibilityQt::BrowserAccessibilityQt()
bool BrowserAccessibilityQt::isValid() const
{
- return true;
+ auto managerQt = static_cast<BrowserAccessibilityManagerQt *>(manager_);
+ return managerQt && managerQt->isValid();
}
QObject *BrowserAccessibilityQt::object() const
diff --git a/src/core/browser_main_parts_qt.cpp b/src/core/browser_main_parts_qt.cpp
index e6c76fb4f..4dbff086b 100644
--- a/src/core/browser_main_parts_qt.cpp
+++ b/src/core/browser_main_parts_qt.cpp
@@ -39,6 +39,8 @@
#include "browser_main_parts_qt.h"
+#include "api/qwebenginemessagepumpscheduler_p.h"
+
#include "base/message_loop/message_loop.h"
#include "base/process/process.h"
#include "base/threading/thread_restrictions.h"
@@ -63,11 +65,7 @@
#include "service/service_qt.h"
#include "web_engine_context.h"
-#include <QCoreApplication>
-#include <QEvent>
#include <QEventLoop>
-#include <QObject>
-#include <QTimerEvent>
#include <QtGui/qtgui-config.h>
#if QT_CONFIG(opengl)
@@ -106,16 +104,12 @@ int GetTimeIntervalMilliseconds(const base::TimeTicks &from)
return delay < 0 ? 0 : delay;
}
-class MessagePumpForUIQt : public QObject,
- public base::MessagePump
+class MessagePumpForUIQt : public base::MessagePump
{
public:
MessagePumpForUIQt()
- : m_delegate(nullptr)
- , m_explicitLoop(nullptr)
- , m_timerId(0)
- {
- }
+ : m_scheduler([this]() { handleScheduledWork(); })
+ {}
void Run(Delegate *delegate) override
{
@@ -138,36 +132,17 @@ public:
void ScheduleWork() override
{
+ // NOTE: This method may called from any thread at any time.
if (!m_delegate)
m_delegate = base::MessageLoopForUI::current();
- QCoreApplication::postEvent(this, new QTimerEvent(0));
- m_timerScheduledTime = base::TimeTicks::Now();
+ m_scheduler.scheduleWork();
}
void ScheduleDelayedWork(const base::TimeTicks &delayed_work_time) override
{
if (!m_delegate)
m_delegate = base::MessageLoopForUI::current();
- if (delayed_work_time.is_null()) {
- killTimer(m_timerId);
- m_timerId = 0;
- m_timerScheduledTime = base::TimeTicks();
- } else if (!m_timerId || delayed_work_time < m_timerScheduledTime) {
- killTimer(m_timerId);
- m_timerId = startTimer(GetTimeIntervalMilliseconds(delayed_work_time));
- m_timerScheduledTime = delayed_work_time;
- }
- }
-
-protected:
- void timerEvent(QTimerEvent *ev) override
- {
- Q_ASSERT(!ev->timerId() || m_timerId == ev->timerId());
- killTimer(m_timerId);
- m_timerId = 0;
- m_timerScheduledTime = base::TimeTicks();
-
- handleScheduledWork();
+ m_scheduler.scheduleDelayedWork(GetTimeIntervalMilliseconds(delayed_work_time));
}
private:
@@ -235,10 +210,9 @@ private:
ScheduleDelayedWork(delayed_work_time);
}
- Delegate *m_delegate;
- QEventLoop *m_explicitLoop;
- int m_timerId;
- base::TimeTicks m_timerScheduledTime;
+ Delegate *m_delegate = nullptr;
+ QEventLoop *m_explicitLoop = nullptr;
+ QWebEngineMessagePumpScheduler m_scheduler;
};
} // anonymous namespace
diff --git a/src/core/config/common.pri b/src/core/config/common.pri
index 57913423a..85940977a 100644
--- a/src/core/config/common.pri
+++ b/src/core/config/common.pri
@@ -96,7 +96,6 @@ 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
diff --git a/src/core/content_client_qt.cpp b/src/core/content_client_qt.cpp
index 9bfc8eede..3217bc899 100644
--- a/src/core/content_client_qt.cpp
+++ b/src/core/content_client_qt.cpp
@@ -65,10 +65,9 @@
#if BUILDFLAG(ENABLE_LIBRARY_CDMS)
#include "media/cdm/cdm_paths.h" // nogncheck
+#include "third_party/widevine/cdm/buildflags.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h"
-#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
-#define WIDEVINE_CDM_AVAILABLE
-#if defined(WIDEVINE_CDM_AVAILABLE) && !defined(WIDEVINE_CDM_IS_COMPONENT)
+#if BUILDFLAG(ENABLE_WIDEVINE) && !BUILDFLAG(ENABLE_WIDEVINE_CDM_COMPONENT)
#define WIDEVINE_CDM_AVAILABLE_NOT_COMPONENT
namespace switches {
const char kCdmWidevinePath[] = "widevine-path";
diff --git a/src/core/core_project.pro b/src/core/core_project.pro
index 5980072ea..ecb4a3ab5 100644
--- a/src/core/core_project.pro
+++ b/src/core/core_project.pro
@@ -17,3 +17,11 @@ INCLUDEPATH += $$CHROMIUM_SRC_DIR \
SOURCES += $$NINJA_SOURCES
HEADERS += $$NINJA_HEADERS
DEFINES += $$NINJA_DEFINES
+
+lupdate_run {
+ SOURCES += clipboard_qt.cpp \
+ profile_adapter_client.cpp \
+ profile_adapter.cpp \
+ render_view_context_menu_qt.cpp \
+ web_contents_adapter.cpp
+}
diff --git a/src/core/favicon_manager.cpp b/src/core/favicon_manager.cpp
index de6a0f183..f7ba858c1 100644
--- a/src/core/favicon_manager.cpp
+++ b/src/core/favicon_manager.cpp
@@ -253,7 +253,7 @@ void FaviconManager::update(const QList<FaviconInfo> &candidates)
const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
continue;
if (it->isValid())
@@ -272,6 +272,14 @@ void FaviconManager::update(const QList<FaviconInfo> &candidates)
void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
{
+ // Invalidate types of the already stored candidate icons because it might differ
+ // among pages.
+ for (FaviconInfo candidateFaviconInfo : candidates) {
+ const QUrl &candidateUrl = candidateFaviconInfo.url;
+ if (m_faviconInfoMap.contains(candidateUrl))
+ m_faviconInfoMap[candidateUrl].type = FaviconInfo::InvalidIcon;
+ }
+
m_candidateCount = candidates.count();
for (FaviconInfo candidateFaviconInfo : candidates) {
const QUrl &candidateUrl = candidateFaviconInfo.url;
@@ -279,8 +287,8 @@ void FaviconManager::updateCandidates(const QList<FaviconInfo> &candidates)
if (!m_faviconInfoMap.contains(candidateUrl))
m_faviconInfoMap.insert(candidateUrl, candidateFaviconInfo);
else {
- // The same icon can be used for more than one page with different types.
- m_faviconInfoMap[candidateUrl].type = candidateFaviconInfo.type;
+ // The same icon URL can be used for different types.
+ m_faviconInfoMap[candidateUrl].type |= candidateFaviconInfo.type;
}
m_faviconInfoMap[candidateUrl].candidate = true;
@@ -311,7 +319,7 @@ QUrl FaviconManager::candidateIconUrl(bool touchIconsEnabled) const
unsigned bestArea = 0;
for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
continue;
if (it->isValid() && bestArea < area(it->size)) {
@@ -331,7 +339,7 @@ void FaviconManager::generateCandidateIcon(bool touchIconsEnabled)
const QList<FaviconInfo> &faviconInfoList = getFaviconInfoList(true /* candidates only */);
for (auto it = faviconInfoList.cbegin(), end = faviconInfoList.cend(); it != end; ++it) {
- if (!touchIconsEnabled && it->type != FaviconInfo::Favicon)
+ if (!touchIconsEnabled && !(it->type & FaviconInfo::Favicon))
continue;
if (!it->isValid() || !it->isDownloaded())
@@ -373,7 +381,7 @@ FaviconInfo::FaviconInfo(const FaviconInfo &other)
{
}
-FaviconInfo::FaviconInfo(const QUrl &url, FaviconInfo::FaviconType type)
+FaviconInfo::FaviconInfo(const QUrl &url, FaviconInfo::FaviconTypeFlags type)
: url(url)
, type(type)
, size(QSize(0, 0))
diff --git a/src/core/favicon_manager.h b/src/core/favicon_manager.h
index f9758d0f0..60d194c4b 100644
--- a/src/core/favicon_manager.h
+++ b/src/core/favicon_manager.h
@@ -84,23 +84,24 @@ class WebContentsAdapterClient;
// Based on src/3rdparty/chromium/content/public/common/favicon_url.h
class QWEBENGINECORE_PRIVATE_EXPORT FaviconInfo {
public:
- enum FaviconType {
- InvalidIcon,
- Favicon,
- TouchIcon,
- TouchPrecomposedIcon
+ enum FaviconTypeFlag {
+ InvalidIcon = 0,
+ Favicon = 1 << 0,
+ TouchIcon = 1 << 1,
+ TouchPrecomposedIcon = 1 << 2
};
+ Q_DECLARE_FLAGS(FaviconTypeFlags, FaviconTypeFlag);
FaviconInfo();
FaviconInfo(const FaviconInfo &);
- FaviconInfo(const QUrl &, FaviconInfo::FaviconType);
+ FaviconInfo(const QUrl &, FaviconInfo::FaviconTypeFlags);
~FaviconInfo();
bool isValid() const;
bool isDownloaded() const;
QUrl url;
- FaviconType type;
+ FaviconTypeFlags type;
// Stores the largest size in case of multi-size icon
QSize size;
bool candidate;
diff --git a/src/core/gn_run.pro b/src/core/gn_run.pro
index 9860c4541..0219a2be9 100644
--- a/src/core/gn_run.pro
+++ b/src/core/gn_run.pro
@@ -49,7 +49,7 @@ build_pass|!debug_and_release {
ninjaflags = $$(NINJAFLAGS)
isEmpty(ninjaflags):!silent: ninjaflags = "-v"
- runninja.commands = $$NINJA $$ninjaflags -C $$gn_build_root QtWebEngineCore
+ runninja.commands = $$NINJA $$ninjaflags \$\(NINJAJOBS\) -C $$gn_build_root QtWebEngineCore
QMAKE_EXTRA_TARGETS += runninja
build_pass:build_all: default_target.target = all
diff --git a/src/core/login_delegate_qt.cpp b/src/core/login_delegate_qt.cpp
index 5b407c094..0050f87c7 100644
--- a/src/core/login_delegate_qt.cpp
+++ b/src/core/login_delegate_qt.cpp
@@ -68,6 +68,7 @@
#include "resource_context_qt.h"
#include "type_conversion.h"
#include "web_contents_view_qt.h"
+#include "web_engine_context.h"
namespace QtWebEngineCore {
@@ -118,6 +119,11 @@ QString LoginDelegateQt::host() const
return QString::fromStdString(m_authInfo->challenger.host());
}
+int LoginDelegateQt::port() const
+{
+ return m_authInfo->challenger.port();
+}
+
bool LoginDelegateQt::isProxy() const
{
return m_authInfo->is_proxy;
@@ -126,6 +132,19 @@ bool LoginDelegateQt::isProxy() const
void LoginDelegateQt::triggerDialogOnUI()
{
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+
+ if (isProxy()) {
+ // workaround for 'ws' redefined symbols when including QNetworkProxy
+ auto authentication = WebEngineContext::qProxyNetworkAuthentication(host(), port());
+ if (std::get<0>(authentication)) {
+ base::PostTaskWithTraits(
+ FROM_HERE, { content::BrowserThread::IO },
+ base::BindOnce(&LoginDelegateQt::sendAuthToRequester, this, true,
+ std::get<1>(authentication), std::get<2>(authentication)));
+
+ return;
+ }
+ }
content::WebContentsImpl *webContents =
static_cast<content::WebContentsImpl *>(m_webContentsGetter.Run());
if (!webContents)
diff --git a/src/core/login_delegate_qt.h b/src/core/login_delegate_qt.h
index ccd1f7322..3a9c073cd 100644
--- a/src/core/login_delegate_qt.h
+++ b/src/core/login_delegate_qt.h
@@ -74,6 +74,7 @@ public:
QUrl url() const;
QString realm() const;
QString host() const;
+ int port() const;
bool isProxy() const;
void sendAuthToRequester(bool success, const QString &user, const QString &password);
diff --git a/src/core/net/client_cert_override.cpp b/src/core/net/client_cert_override.cpp
index caf6adad7..305f0cef0 100644
--- a/src/core/net/client_cert_override.cpp
+++ b/src/core/net/client_cert_override.cpp
@@ -37,12 +37,13 @@
**
****************************************************************************/
-#include "net/client_cert_override.h"
+#include "client_cert_override.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/task/post_task.h"
#include "base/callback_forward.h"
+#include "content/public/browser/browser_task_traits.h"
#include "net/ssl/client_cert_store.h"
#include "net/ssl/ssl_cert_request_info.h"
#include "net/ssl/ssl_private_key.h"
@@ -51,8 +52,7 @@
#include "third_party/boringssl/src/include/openssl/err.h"
#include "third_party/boringssl/src/include/openssl/evp.h"
-#include "api/qwebengineclientcertificatestore.h"
-#include "net/client_cert_store_data.h"
+#include "client_cert_store_data.h"
#include "profile_io_data_qt.h"
#include <QtNetwork/qtnetworkglobal.h>
@@ -98,40 +98,66 @@ private:
namespace QtWebEngineCore {
-ClientCertOverrideStore::ClientCertOverrideStore()
+ClientCertOverrideStore::ClientCertOverrideStore(ClientCertificateStoreData *storeData)
: ClientCertStore()
+ , m_storeData(storeData)
, m_nativeStore(createNativeStore())
{
}
ClientCertOverrideStore::~ClientCertOverrideStore() = default;
-void ClientCertOverrideStore::GetClientCerts(const net::SSLCertRequestInfo &cert_request_info,
- const ClientCertListCallback &callback)
-{
#if QT_CONFIG(ssl)
- QWebEngineClientCertificateStore *clientCertificateStore = QWebEngineClientCertificateStore::getInstance();
- const auto &clientCertOverrideData = clientCertificateStore->d_ptr->addedCerts;
+net::ClientCertIdentityList ClientCertOverrideStore::GetClientCertsOnUIThread(const net::SSLCertRequestInfo &cert_request_info)
+{
+ DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+ const auto &clientCertOverrideData = m_storeData->extraCerts;
// Look for certificates in memory store
for (int i = 0; i < clientCertOverrideData.length(); i++) {
scoped_refptr<net::X509Certificate> cert = clientCertOverrideData[i]->certPtr;
if (cert != NULL && cert->IsIssuedByEncoded(cert_request_info.cert_authorities)) {
net::ClientCertIdentityList selected_identities;
selected_identities.push_back(std::make_unique<ClientCertIdentityOverride>(cert, clientCertOverrideData[i]->keyPtr));
- callback.Run(std::move(selected_identities));
- return;
+ return selected_identities;
}
}
-#endif // QT_CONFIG(ssl)
+ return net::ClientCertIdentityList();
+}
- // Continue with native cert store if matching certificate is not found in memory
- if (m_nativeStore) {
+void ClientCertOverrideStore::GetClientCertsReturn(const net::SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback,
+ net::ClientCertIdentityList &&result)
+{
+ // Continue with native cert store if matching certificatse were not found in memory
+ if (result.empty() && m_nativeStore)
m_nativeStore->GetClientCerts(cert_request_info, callback);
+ else
+ callback.Run(std::move(result));
+}
+
+#endif // QT_CONFIG(ssl)
+
+void ClientCertOverrideStore::GetClientCerts(const net::SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback)
+{
+#if QT_CONFIG(ssl)
+ // Access the user-provided data from the UI thread, but return on whatever thread this is.
+ if (base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, { content::BrowserThread::UI },
+ base::BindOnce(&ClientCertOverrideStore::GetClientCertsOnUIThread,
+ base::Unretained(this), base::ConstRef(cert_request_info)),
+ base::BindOnce(&ClientCertOverrideStore::GetClientCertsReturn,
+ base::Unretained(this), base::ConstRef(cert_request_info), callback))
+ ) {
return;
}
+#endif // QT_CONFIG(ssl)
- callback.Run(net::ClientCertIdentityList());
- return;
+ // Continue with native cert store if we failed to post task
+ if (m_nativeStore)
+ m_nativeStore->GetClientCerts(cert_request_info, callback);
+ else
+ callback.Run(net::ClientCertIdentityList());
}
// static
diff --git a/src/core/net/client_cert_override.h b/src/core/net/client_cert_override.h
index 4f13c3116..35c1f96af 100644
--- a/src/core/net/client_cert_override.h
+++ b/src/core/net/client_cert_override.h
@@ -49,16 +49,22 @@ class SSLCertRequestInfo;
} // namespace net
namespace QtWebEngineCore {
+struct ClientCertificateStoreData;
class ClientCertOverrideStore : public net::ClientCertStore
{
public:
- ClientCertOverrideStore();
+ ClientCertOverrideStore(ClientCertificateStoreData *storeData);
virtual ~ClientCertOverrideStore() override;
void GetClientCerts(const net::SSLCertRequestInfo &cert_request_info,
const ClientCertListCallback &callback) override;
private:
static std::unique_ptr<net::ClientCertStore> createNativeStore();
+ net::ClientCertIdentityList GetClientCertsOnUIThread(const net::SSLCertRequestInfo &request);
+ void GetClientCertsReturn(const net::SSLCertRequestInfo &cert_request_info,
+ const ClientCertListCallback &callback,
+ net::ClientCertIdentityList &&result);
+ ClientCertificateStoreData *m_storeData;
std::unique_ptr<net::ClientCertStore> m_nativeStore;
};
diff --git a/src/core/net/client_cert_store_data.cpp b/src/core/net/client_cert_store_data.cpp
index ae4deed1c..d1018a063 100644
--- a/src/core/net/client_cert_store_data.cpp
+++ b/src/core/net/client_cert_store_data.cpp
@@ -138,12 +138,27 @@ void ClientCertificateStoreData::add(const QSslCertificate &certificate, const Q
data->certPtr = net::X509Certificate::CreateFromBytes(certInBytes.data(), certInBytes.length());
data->key = privateKey;
data->certificate = certificate;
- addedCerts.append(data);
+ extraCerts.append(data);
}
-ClientCertificateStoreData::~ClientCertificateStoreData()
+void ClientCertificateStoreData::remove(const QSslCertificate &certificate)
{
- qDeleteAll(deletedCerts);
+ auto it = extraCerts.begin();
+ while (it != extraCerts.end()) {
+ const QtWebEngineCore::ClientCertificateStoreData::Entry *overrideData = *it;
+ if (certificate.toDer() == overrideData->certificate.toDer()) {
+ it = extraCerts.erase(it);
+ delete overrideData;
+ continue;
+ }
+ ++it;
+ }
+}
+
+void ClientCertificateStoreData::clear()
+{
+ qDeleteAll(extraCerts);
+ extraCerts.clear();
}
} // namespace QtWebEngineCore
diff --git a/src/core/net/client_cert_store_data.h b/src/core/net/client_cert_store_data.h
index 41dc1f8ec..7f83f4b60 100644
--- a/src/core/net/client_cert_store_data.h
+++ b/src/core/net/client_cert_store_data.h
@@ -46,7 +46,7 @@
#if QT_CONFIG(ssl)
#include "base/memory/ref_counted.h"
-#include <QtCore/qlist.h>
+#include <QtCore/qvector.h>
#include <QtNetwork/qsslcertificate.h>
#include <QtNetwork/qsslkey.h>
@@ -65,11 +65,11 @@ struct ClientCertificateStoreData {
scoped_refptr<net::SSLPrivateKey> keyPtr;
};
- ~ClientCertificateStoreData();
void add(const QSslCertificate &certificate, const QSslKey &privateKey);
+ void remove(const QSslCertificate &certificate);
+ void clear();
- QList<Entry*> addedCerts;
- QList<Entry*> deletedCerts;
+ QVector<Entry*> extraCerts;
};
} // namespace QtWebEngineCore
diff --git a/src/core/net/network_delegate_qt.cpp b/src/core/net/network_delegate_qt.cpp
index 3641cb845..60478d3ef 100644
--- a/src/core/net/network_delegate_qt.cpp
+++ b/src/core/net/network_delegate_qt.cpp
@@ -68,6 +68,9 @@ WebContentsAdapterClient::NavigationType pageTransitionToNavigationType(ui::Page
if (qualifier & ui::PAGE_TRANSITION_FORWARD_BACK)
return WebContentsAdapterClient::BackForwardNavigation;
+ // FIXME: Make redirects a separate type:
+ if (qualifier & ui::PAGE_TRANSITION_CLIENT_REDIRECT)
+ return WebContentsAdapterClient::OtherNavigation;
ui::PageTransition strippedTransition = ui::PageTransitionStripQualifier(transition);
diff --git a/src/core/net/url_request_custom_job_delegate.cpp b/src/core/net/url_request_custom_job_delegate.cpp
index 83d47e291..b5a7a55a7 100644
--- a/src/core/net/url_request_custom_job_delegate.cpp
+++ b/src/core/net/url_request_custom_job_delegate.cpp
@@ -83,7 +83,7 @@ QUrl URLRequestCustomJobDelegate::initiator() const
return m_initiatorOrigin;
}
-const QMap<QByteArray, QByteArray> &URLRequestCustomJobDelegate::requestHeaders() const
+QMap<QByteArray, QByteArray> URLRequestCustomJobDelegate::requestHeaders() const
{
return m_requestHeaders;
}
diff --git a/src/core/net/url_request_custom_job_delegate.h b/src/core/net/url_request_custom_job_delegate.h
index 9de0224f9..1bf3ade1f 100644
--- a/src/core/net/url_request_custom_job_delegate.h
+++ b/src/core/net/url_request_custom_job_delegate.h
@@ -81,7 +81,7 @@ public:
QUrl url() const;
QByteArray method() const;
QUrl initiator() const;
- const QMap<QByteArray, QByteArray> &requestHeaders() const;
+ QMap<QByteArray, QByteArray> requestHeaders() const;
void reply(const QByteArray &contentType, QIODevice *device);
void redirect(const QUrl& url);
diff --git a/src/core/ozone/gl_surface_glx_qt.cpp b/src/core/ozone/gl_surface_glx_qt.cpp
index 4faa08091..24772889f 100644
--- a/src/core/ozone/gl_surface_glx_qt.cpp
+++ b/src/core/ozone/gl_surface_glx_qt.cpp
@@ -173,7 +173,7 @@ bool GLSurfaceGLXQt::Initialize(GLSurfaceFormat format)
GLX_PBUFFER_HEIGHT, m_size.height(),
GLX_LARGEST_PBUFFER, x11::False,
GLX_PRESERVED_CONTENTS, x11::False,
- NULL
+ x11::None // MEMO doc: ...must be terminated with None or NULL
};
m_surfaceBuffer = glXCreatePbuffer(display, static_cast<GLXFBConfig>(g_config), pbuffer_attributes);
diff --git a/src/core/platform_notification_service_qt.cpp b/src/core/platform_notification_service_qt.cpp
index dff3aed61..f3457c7aa 100644
--- a/src/core/platform_notification_service_qt.cpp
+++ b/src/core/platform_notification_service_qt.cpp
@@ -201,7 +201,7 @@ int64_t PlatformNotificationServiceQt::ReadNextPersistentNotificationId(content:
Q_ASSERT(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
auto prefs = static_cast<ProfileQt *>(browser_context)->GetPrefs();
int64_t nextId = prefs->GetInteger(prefs::kNotificationNextPersistentId) + 1;
- prefs->SetInt64(prefs::kNotificationNextPersistentId, nextId);
+ prefs->SetInteger(prefs::kNotificationNextPersistentId, nextId);
return nextId;
}
diff --git a/src/core/printing/pdfium_document_wrapper_qt.cpp b/src/core/printing/pdfium_document_wrapper_qt.cpp
index a18258d0e..6dbdf64ef 100644
--- a/src/core/printing/pdfium_document_wrapper_qt.cpp
+++ b/src/core/printing/pdfium_document_wrapper_qt.cpp
@@ -54,7 +54,6 @@ public:
: m_pageData(FPDF_LoadPage(data, pageIndex))
, m_width(FPDF_GetPageWidth(m_pageData))
, m_height(FPDF_GetPageHeight(m_pageData))
- , m_index(pageIndex)
, m_image(createImage(targetWidth, targetHeight))
{
}
@@ -63,7 +62,6 @@ public:
: m_pageData(nullptr)
, m_width(-1)
, m_height(-1)
- , m_index(-1)
, m_image(QImage())
{
}
@@ -102,14 +100,13 @@ private:
0, 0);
FPDFBitmap_Destroy(bitmap);
bitmap = nullptr;
- return std::move(image);
+ return image;
}
private:
FPDF_PAGE m_pageData;
int m_width;
int m_height;
- int m_index;
QImage m_image;
};
diff --git a/src/core/profile_adapter.cpp b/src/core/profile_adapter.cpp
index 8ddeb5b8f..6f05c4c3f 100644
--- a/src/core/profile_adapter.cpp
+++ b/src/core/profile_adapter.cpp
@@ -55,6 +55,7 @@
#include "type_conversion.h"
#include "visited_links_manager_qt.h"
#include "web_engine_context.h"
+#include "web_contents_adapter_client.h"
#include "components/keyed_service/content/browser_context_dependency_manager.h"
@@ -105,11 +106,17 @@ ProfileAdapter::ProfileAdapter(const QString &storageName):
ProfileAdapter::~ProfileAdapter()
{
+ while (!m_webContentsAdapterClients.isEmpty()) {
+ m_webContentsAdapterClients.first()->releaseProfile();
+ }
WebEngineContext::current()->removeProfileAdapter(this);
if (m_downloadManagerDelegate) {
m_profile->GetDownloadManager(m_profile.data())->Shutdown();
m_downloadManagerDelegate.reset();
}
+#if QT_CONFIG(ssl)
+ delete m_clientCertificateStore;
+#endif
Q_ASSERT(m_pageRequestInterceptors == 0);
}
@@ -230,7 +237,8 @@ ProfileAdapter *ProfileAdapter::createDefaultProfileAdapter()
ProfileAdapter *ProfileAdapter::defaultProfileAdapter()
{
- return WebEngineContext::current()->defaultProfileAdapter();
+ WebEngineContext *context = WebEngineContext::current();
+ return context ? context->defaultProfileAdapter() : nullptr;
}
QObject* ProfileAdapter::globalQObjectRoot()
@@ -617,6 +625,16 @@ bool ProfileAdapter::isSpellCheckEnabled() const
#endif
}
+void ProfileAdapter::addWebContentsAdapterClient(WebContentsAdapterClient *client)
+{
+ m_webContentsAdapterClients.append(client);
+}
+
+void ProfileAdapter::removeWebContentsAdapterClient(WebContentsAdapterClient *client)
+{
+ m_webContentsAdapterClients.removeAll(client);
+}
+
void ProfileAdapter::resetVisitedLinksManager()
{
m_visitedLinksManager.reset(new VisitedLinksManagerQt(m_profile.data(), persistVisitedLinks()));
@@ -652,4 +670,13 @@ bool ProfileAdapter::isUsedForGlobalCertificateVerification() const
return m_usedForGlobalCertificateVerification;
}
+#if QT_CONFIG(ssl)
+QWebEngineClientCertificateStore *ProfileAdapter::clientCertificateStore()
+{
+ if (!m_clientCertificateStore)
+ m_clientCertificateStore = new QWebEngineClientCertificateStore(m_profile->m_profileIOData->clientCertificateStoreData());
+ return m_clientCertificateStore;
+}
+#endif
+
} // namespace QtWebEngineCore
diff --git a/src/core/profile_adapter.h b/src/core/profile_adapter.h
index 482835010..48094a3d8 100644
--- a/src/core/profile_adapter.h
+++ b/src/core/profile_adapter.h
@@ -60,6 +60,7 @@
#include <QString>
#include <QVector>
+#include "api/qwebengineclientcertificatestore.h"
#include "api/qwebenginecookiestore.h"
#include "api/qwebengineurlrequestinterceptor.h"
#include "api/qwebengineurlschemehandler.h"
@@ -75,6 +76,7 @@ class ProfileAdapterClient;
class ProfileQt;
class UserResourceControllerHost;
class VisitedLinksManagerQt;
+class WebContentsAdapterClient;
class QWEBENGINECORE_PRIVATE_EXPORT ProfileAdapter : public QObject
{
@@ -132,6 +134,9 @@ public:
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
+ void addWebContentsAdapterClient(WebContentsAdapterClient *client);
+ void removeWebContentsAdapterClient(WebContentsAdapterClient *client);
+
// KEEP IN SYNC with API or add mapping layer
enum HttpCacheType {
MemoryHttpCache = 0,
@@ -200,6 +205,10 @@ public:
void removePageRequestInterceptor();
bool hasPageRequestInterceptor() const { return m_pageRequestInterceptors > 0; }
+#if QT_CONFIG(ssl)
+ QWebEngineClientCertificateStore *clientCertificateStore();
+#endif
+
QHash<QByteArray, QWeakPointer<UserNotificationController>> &ephemeralNotifications()
{ return m_ephemeralNotifications; }
QHash<QByteArray, QSharedPointer<UserNotificationController>> &persistentNotifications()
@@ -218,6 +227,9 @@ private:
QScopedPointer<DownloadManagerDelegateQt> m_downloadManagerDelegate;
QScopedPointer<UserResourceControllerHost> m_userResourceController;
QScopedPointer<QWebEngineCookieStore> m_cookieStore;
+#if QT_CONFIG(ssl)
+ QWebEngineClientCertificateStore *m_clientCertificateStore = nullptr;
+#endif
QPointer<QWebEngineUrlRequestInterceptor> m_requestInterceptor;
QString m_dataPath;
@@ -233,6 +245,7 @@ private:
QHash<QByteArray, QSharedPointer<UserNotificationController>> m_persistentNotifications;
QList<ProfileAdapterClient*> m_clients;
+ QVector<WebContentsAdapterClient *> m_webContentsAdapterClients;
int m_httpCacheMaxSize;
int m_pageRequestInterceptors;
QrcUrlSchemeHandler m_qrcHandler;
diff --git a/src/core/profile_adapter_client.h b/src/core/profile_adapter_client.h
index 0309200b4..8ee9d240e 100644
--- a/src/core/profile_adapter_client.h
+++ b/src/core/profile_adapter_client.h
@@ -147,6 +147,8 @@ public:
virtual void useForGlobalCertificateVerificationChanged() {}
virtual void showNotification(QSharedPointer<UserNotificationController> &) { }
+ virtual void addWebContentsAdapterClient(WebContentsAdapterClient *adapter) = 0;
+ virtual void removeWebContentsAdapterClient(WebContentsAdapterClient *adapter) = 0;
static QString downloadInterruptReasonToString(DownloadInterruptReason reason);
};
diff --git a/src/core/profile_io_data_qt.cpp b/src/core/profile_io_data_qt.cpp
index 01a4e98aa..a73a7c21d 100644
--- a/src/core/profile_io_data_qt.cpp
+++ b/src/core/profile_io_data_qt.cpp
@@ -79,6 +79,7 @@
#include "services/network/proxy_service_mojo.h"
#include "net/client_cert_override.h"
+#include "net/client_cert_store_data.h"
#include "net/cookie_monster_delegate_qt.h"
#include "net/custom_protocol_handler.h"
#include "net/network_delegate_qt.h"
@@ -168,6 +169,9 @@ static net::HttpNetworkSession::Params generateNetworkSessionParams(bool ignoreC
ProfileIODataQt::ProfileIODataQt(ProfileQt *profile)
: m_profile(profile),
+#if QT_CONFIG(ssl)
+ m_clientCertificateStoreData(new ClientCertificateStoreData),
+#endif
m_mutex(QMutex::Recursive),
m_weakPtrFactory(this)
{
@@ -207,6 +211,10 @@ QPointer<ProfileAdapter> ProfileIODataQt::profileAdapter()
void ProfileIODataQt::shutdownOnUIThread()
{
DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
+#if QT_CONFIG(ssl)
+ delete m_clientCertificateStoreData;
+ m_clientCertificateStoreData = nullptr;
+#endif
bool posted = content::BrowserThread::DeleteSoon(content::BrowserThread::IO, FROM_HERE, this);
if (!posted) {
qWarning() << "Could not delete ProfileIODataQt on io thread !";
@@ -771,9 +779,20 @@ void ProfileIODataQt::updateUsedForGlobalCertificateVerification()
base::BindOnce(&ProfileIODataQt::setGlobalCertificateVerification, m_weakPtr));
}
+#if QT_CONFIG(ssl)
+ClientCertificateStoreData *ProfileIODataQt::clientCertificateStoreData()
+{
+ return m_clientCertificateStoreData;
+}
+#endif
+
std::unique_ptr<net::ClientCertStore> ProfileIODataQt::CreateClientCertStore()
{
- return std::unique_ptr<net::ClientCertStore>(new ClientCertOverrideStore());
+#if QT_CONFIG(ssl)
+ return std::unique_ptr<net::ClientCertStore>(new ClientCertOverrideStore(m_clientCertificateStoreData));
+#else
+ return nullptr;
+#endif
}
// static
diff --git a/src/core/profile_io_data_qt.h b/src/core/profile_io_data_qt.h
index b983b3a99..57ddb6fd3 100644
--- a/src/core/profile_io_data_qt.h
+++ b/src/core/profile_io_data_qt.h
@@ -69,6 +69,7 @@ class ExtensionSystemQt;
namespace QtWebEngineCore {
+class ClientCertificateStoreData;
class ProfileQt;
// ProfileIOData contains data that lives on the IOthread
@@ -123,6 +124,9 @@ public:
void updateUsedForGlobalCertificateVerification(); // runs on ui thread
bool hasPageInterceptors();
+#if QT_CONFIG(ssl)
+ ClientCertificateStoreData *clientCertificateStoreData();
+#endif
std::unique_ptr<net::ClientCertStore> CreateClientCertStore();
static ProfileIODataQt *FromResourceContext(content::ResourceContext *resource_context);
private:
@@ -146,6 +150,9 @@ private:
QAtomicPointer<net::ProxyConfigService> m_proxyConfigService;
QPointer<ProfileAdapter> m_profileAdapter; // never dereferenced in IO thread and it is passed by qpointer
ProfileAdapter::PersistentCookiesPolicy m_persistentCookiesPolicy;
+#if QT_CONFIG(ssl)
+ ClientCertificateStoreData *m_clientCertificateStoreData;
+#endif
QString m_cookiesPath;
QString m_channelIdPath;
QString m_httpAcceptLanguage;
diff --git a/src/core/renderer/content_renderer_client_qt.cpp b/src/core/renderer/content_renderer_client_qt.cpp
index 296e78b07..f68370a24 100644
--- a/src/core/renderer/content_renderer_client_qt.cpp
+++ b/src/core/renderer/content_renderer_client_qt.cpp
@@ -103,9 +103,8 @@
#include "content/public/renderer/key_system_support.h"
#include "media/base/media_switches.h"
#include "media/base/video_codecs.h"
+#include "third_party/widevine/cdm/buildflags.h"
#include "third_party/widevine/cdm/widevine_cdm_common.h"
-
-#include "widevine_cdm_version.h" // In SHARED_INTERMEDIATE_DIR.
#endif
namespace QtWebEngineCore {
@@ -438,7 +437,7 @@ static void AddExternalClearKey(std::vector<std::unique_ptr<media::KeySystemProp
kExternalClearKeyCdmProxyTestKeySystem));
}
-#if defined(WIDEVINE_CDM_AVAILABLE)
+#if BUILDFLAG(ENABLE_WIDEVINE)
static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoCodec> &supported_video_codecs, bool is_secure)
{
media::SupportedCodecs supported_codecs = media::EME_CODEC_NONE;
@@ -450,11 +449,11 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC
// TODO(sandersd): Distinguish these from those that are directly supported,
// as those may offer a higher level of protection.
if (!supported_video_codecs.empty() || !is_secure) {
- supported_codecs |= media::EME_CODEC_WEBM_OPUS;
- supported_codecs |= media::EME_CODEC_WEBM_VORBIS;
- supported_codecs |= media::EME_CODEC_MP4_FLAC;
+ supported_codecs |= media::EME_CODEC_OPUS;
+ supported_codecs |= media::EME_CODEC_VORBIS;
+ supported_codecs |= media::EME_CODEC_FLAC;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
- supported_codecs |= media::EME_CODEC_MP4_AAC;
+ supported_codecs |= media::EME_CODEC_AAC;
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
}
@@ -462,15 +461,15 @@ static media::SupportedCodecs GetSupportedCodecs(const std::vector<media::VideoC
for (const auto &codec : supported_video_codecs) {
switch (codec) {
case media::VideoCodec::kCodecVP8:
- supported_codecs |= media::EME_CODEC_WEBM_VP8;
+ supported_codecs |= media::EME_CODEC_VP8;
break;
case media::VideoCodec::kCodecVP9:
- supported_codecs |= media::EME_CODEC_WEBM_VP9;
- supported_codecs |= media::EME_CODEC_COMMON_VP9;
+ supported_codecs |= media::EME_CODEC_LEGACY_VP9;
+ supported_codecs |= media::EME_CODEC_VP9;
break;
#if BUILDFLAG(USE_PROPRIETARY_CODECS)
case media::VideoCodec::kCodecH264:
- supported_codecs |= media::EME_CODEC_MP4_AVC1;
+ supported_codecs |= media::EME_CODEC_AVC1;
break;
#endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
default:
@@ -529,7 +528,7 @@ static void AddWidevine(std::vector<std::unique_ptr<media::KeySystemProperties>>
persistent_license_support, persistent_usage_record_support,
persistent_state_support, distinctive_identifier_support));
}
-#endif // defined(WIDEVINE_CDM_AVAILABLE)
+#endif // BUILDFLAG(ENABLE_WIDEVINE)
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr<media::KeySystemProperties>> *key_systems)
@@ -538,9 +537,9 @@ void ContentRendererClientQt::AddSupportedKeySystems(std::vector<std::unique_ptr
if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting))
AddExternalClearKey(key_systems);
-#if defined(WIDEVINE_CDM_AVAILABLE)
+#if BUILDFLAG(ENABLE_WIDEVINE)
AddWidevine(key_systems);
-#endif // defined(WIDEVINE_CDM_AVAILABLE)
+#endif // BUILDFLAG(ENABLE_WIDEVINE)
#endif // BUILDFLAG(ENABLE_LIBRARY_CDMS)
}
diff --git a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp
index 0583060c6..007aa9b63 100644
--- a/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp
+++ b/src/core/renderer_host/resource_dispatcher_host_delegate_qt.cpp
@@ -47,8 +47,11 @@
#include "base/guid.h"
#include "base/strings/stringprintf.h"
#include "base/task/post_task.h"
+#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_task_traits.h"
#include "content/public/browser/browser_thread.h"
+#include "content/public/browser/download_manager.h"
+#include "content/public/browser/download_request_utils.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/render_frame_host.h"
@@ -69,6 +72,8 @@
#include "resource_context_qt.h"
#include "type_conversion.h"
+#include "web_contents_delegate_qt.h"
+#include "web_engine_settings.h"
namespace QtWebEngineCore {
@@ -82,6 +87,23 @@ void OnPdfStreamIntercepted(
if (!web_contents)
return;
+ WebContentsDelegateQt *contentsDelegate = static_cast<WebContentsDelegateQt*>(web_contents->GetDelegate());
+ if (!contentsDelegate)
+ return;
+
+ WebEngineSettings *settings = contentsDelegate->webEngineSettings();
+ if (!settings->testAttribute(WebEngineSettings::PdfViewerEnabled)
+ || !settings->testAttribute(WebEngineSettings::PluginsEnabled)) {
+ // If the applications has been set up to always download PDF files to open them in an
+ // external viewer, trigger the download.
+ std::unique_ptr<download::DownloadUrlParameters> params(
+ content::DownloadRequestUtils::CreateDownloadForWebContentsMainFrame(
+ web_contents, original_url, NO_TRAFFIC_ANNOTATION_YET));
+ content::BrowserContext::GetDownloadManager(web_contents->GetBrowserContext())
+ ->DownloadUrl(std::move(params));
+ return;
+ }
+
// The URL passes the original pdf resource url, that will be requested
// by the pdf viewer extension page.
content::NavigationController::LoadURLParams params(
@@ -103,9 +125,8 @@ bool ResourceDispatcherHostDelegateQt::ShouldInterceptResourceAsStream(net::URLR
int render_process_host_id = -1;
int render_frame_id = -1;
- if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_host_id, &render_frame_id)) {
- return false;
- }
+ if (!content::ResourceRequestInfo::GetRenderFrameForRequest(request, &render_process_host_id, &render_frame_id))
+ return false;
ResourceContextQt *context = static_cast<ResourceContextQt *>(info->GetContext());
std::vector<std::string> whitelist = MimeTypesHandler::GetMIMETypeWhitelist();
diff --git a/src/core/type_conversion.cpp b/src/core/type_conversion.cpp
index ef16e2add..02d2db448 100644
--- a/src/core/type_conversion.cpp
+++ b/src/core/type_conversion.cpp
@@ -218,7 +218,7 @@ int flagsFromModifiers(Qt::KeyboardModifiers modifiers)
return modifierFlags;
}
-FaviconInfo::FaviconType toQt(content::FaviconURL::IconType type)
+FaviconInfo::FaviconTypeFlags toQt(content::FaviconURL::IconType type)
{
switch (type) {
case content::FaviconURL::IconType::kFavicon:
diff --git a/src/core/web_contents_adapter.cpp b/src/core/web_contents_adapter.cpp
index fe31a5b51..607412e16 100644
--- a/src/core/web_contents_adapter.cpp
+++ b/src/core/web_contents_adapter.cpp
@@ -240,9 +240,13 @@ static std::unique_ptr<content::WebContents> createBlankWebContents(WebContentsA
content::WebContents::CreateParams create_params(browserContext, NULL);
create_params.routing_id = MSG_ROUTING_NONE;
create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight);
- create_params.context = reinterpret_cast<gfx::NativeView>(adapterClient);
create_params.initially_hidden = true;
- return content::WebContents::Create(create_params);
+
+ std::unique_ptr<content::WebContents> webContents = content::WebContents::Create(create_params);
+ WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(webContents.get())->GetView());
+ contentsView->setClient(adapterClient);
+
+ return webContents;
}
static void serializeNavigationHistory(const content::NavigationController &controller, QDataStream &output)
@@ -468,7 +472,6 @@ void WebContentsAdapter::initialize(content::SiteInstance *site)
if (!m_webContents) {
content::WebContents::CreateParams create_params(m_profileAdapter->profile(), site);
create_params.initial_size = gfx::Size(kTestWindowWidth, kTestWindowHeight);
- create_params.context = reinterpret_cast<gfx::NativeView>(m_adapterClient);
create_params.initially_hidden = true;
m_webContents = content::WebContents::Create(create_params);
}
@@ -506,7 +509,7 @@ void WebContentsAdapter::initialize(content::SiteInstance *site)
// Let the WebContent's view know about the WebContentsAdapterClient.
WebContentsViewQt* contentsView = static_cast<WebContentsViewQt*>(static_cast<content::WebContentsImpl*>(m_webContents.get())->GetView());
- contentsView->initialize(m_adapterClient);
+ contentsView->setClient(m_adapterClient);
// This should only be necessary after having restored the history to a new WebContentsAdapter.
m_webContents->GetController().LoadIfNecessary();
diff --git a/src/core/web_contents_adapter_client.h b/src/core/web_contents_adapter_client.h
index d155ed391..cdfcae450 100644
--- a/src/core/web_contents_adapter_client.h
+++ b/src/core/web_contents_adapter_client.h
@@ -485,6 +485,7 @@ public:
virtual ProfileAdapter *profileAdapter() = 0;
virtual WebContentsAdapter* webContentsAdapter() = 0;
+ virtual void releaseProfile() = 0;
};
diff --git a/src/core/web_contents_delegate_qt.cpp b/src/core/web_contents_delegate_qt.cpp
index 4fcf2944d..ade29c770 100644
--- a/src/core/web_contents_delegate_qt.cpp
+++ b/src/core/web_contents_delegate_qt.cpp
@@ -58,12 +58,14 @@
#include "visited_links_manager_qt.h"
#include "web_contents_adapter_client.h"
#include "web_contents_adapter.h"
+#include "web_contents_view_qt.h"
#include "web_engine_context.h"
#include "web_engine_settings.h"
#include "chrome/browser/custom_handlers/protocol_handler_registry_factory.h"
#include "components/web_cache/browser/web_cache_manager.h"
#include "content/browser/renderer_host/render_widget_host_impl.h"
+#include "content/browser/web_contents/web_contents_impl.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/file_select_listener.h"
#include "content/public/browser/invalidate_type.h"
@@ -414,9 +416,11 @@ void WebContentsDelegateQt::DidUpdateFaviconURL(const std::vector<content::Favic
void WebContentsDelegateQt::WebContentsCreated(content::WebContents */*source_contents*/,
int /*opener_render_process_id*/, int /*opener_render_frame_id*/,
const std::string &/*frame_name*/,
- const GURL &target_url, content::WebContents */*new_contents*/)
+ const GURL &target_url, content::WebContents *newContents)
{
m_initialTargetUrl = toQt(target_url);
+ if (auto *view = static_cast<content::WebContentsImpl *>(newContents)->GetView())
+ static_cast<WebContentsViewQt *>(view)->setFactoryClient(m_viewClient);
}
content::ColorChooser *WebContentsDelegateQt::OpenColorChooser(content::WebContents *source, SkColor color, const std::vector<blink::mojom::ColorSuggestionPtr> &suggestion)
diff --git a/src/core/web_contents_view_qt.cpp b/src/core/web_contents_view_qt.cpp
index 550a98a52..7177a8713 100644
--- a/src/core/web_contents_view_qt.cpp
+++ b/src/core/web_contents_view_qt.cpp
@@ -62,7 +62,19 @@
namespace QtWebEngineCore {
-void WebContentsViewQt::initialize(WebContentsAdapterClient* client)
+void WebContentsViewQt::setFactoryClient(WebContentsAdapterClient* client)
+{
+ if (m_factoryClient)
+ return;
+ m_factoryClient = client;
+
+ // Check if a RWHV was created before the pre-initialization.
+ if (auto view = static_cast<RenderWidgetHostViewQt *>(m_webContents->GetRenderWidgetHostView())) {
+ view->setDelegate(m_factoryClient->CreateRenderWidgetHostViewQtDelegate(view));
+ }
+}
+
+void WebContentsViewQt::setClient(WebContentsAdapterClient* client)
{
m_client = client;
m_factoryClient = client;
@@ -78,10 +90,11 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForWidget(conten
{
RenderWidgetHostViewQt *view = new RenderWidgetHostViewQt(render_widget_host);
- Q_ASSERT(m_factoryClient);
- view->setDelegate(m_factoryClient->CreateRenderWidgetHostViewQtDelegate(view));
- if (m_client)
- view->setAdapterClient(m_client);
+ if (m_factoryClient) {
+ view->setDelegate(m_factoryClient->CreateRenderWidgetHostViewQtDelegate(view));
+ if (m_client)
+ view->setAdapterClient(m_client);
+ }
return view;
}
@@ -99,15 +112,11 @@ content::RenderWidgetHostViewBase* WebContentsViewQt::CreateViewForChildWidget(c
void WebContentsViewQt::CreateView(const gfx::Size& initial_size, gfx::NativeView context)
{
- // This is passed through content::WebContents::CreateParams::context either as the native view's client
- // directly or, in the case of a page-created new window, the client of the creating window's native view.
- m_factoryClient = reinterpret_cast<WebContentsAdapterClient *>(context);
}
gfx::NativeView WebContentsViewQt::GetNativeView() const
{
- // Hack to provide the client to WebContentsImpl::CreateNewWindow.
- return reinterpret_cast<gfx::NativeView>(m_client);
+ return nullptr;
}
void WebContentsViewQt::GetContainerBounds(gfx::Rect* out) const
diff --git a/src/core/web_contents_view_qt.h b/src/core/web_contents_view_qt.h
index c7bac1d97..7cd3910f2 100644
--- a/src/core/web_contents_view_qt.h
+++ b/src/core/web_contents_view_qt.h
@@ -65,7 +65,8 @@ public:
, m_factoryClient(nullptr)
{ }
- void initialize(WebContentsAdapterClient* client);
+ void setFactoryClient(WebContentsAdapterClient* client);
+ void setClient(WebContentsAdapterClient* client);
WebContentsAdapterClient *client() { return m_client; }
content::RenderWidgetHostViewBase *CreateViewForWidget(content::RenderWidgetHost* render_widget_host, bool is_guest_view_hack) override;
@@ -86,9 +87,9 @@ public:
gfx::NativeView GetNativeView() const override;
- gfx::NativeView GetContentNativeView() const override { return 0; }
+ gfx::NativeView GetContentNativeView() const override { return nullptr; }
- gfx::NativeWindow GetTopLevelNativeWindow() const override { return 0; }
+ gfx::NativeWindow GetTopLevelNativeWindow() const override { return nullptr; }
void GetContainerBounds(gfx::Rect* out) const override;
diff --git a/src/core/web_engine_context.cpp b/src/core/web_engine_context.cpp
index 67639dc4f..e9a941bf2 100644
--- a/src/core/web_engine_context.cpp
+++ b/src/core/web_engine_context.cpp
@@ -113,7 +113,9 @@
#include <QStringList>
#include <QSurfaceFormat>
#include <QVector>
-#include <qpa/qplatformnativeinterface.h>
+#include <QNetworkProxy>
+#include <QtGui/qpa/qplatformintegration.h>
+#include <QtGui/private/qguiapplication_p.h>
using namespace QtWebEngineCore;
@@ -137,10 +139,13 @@ bool usingANGLE()
#endif
}
-bool usingQtQuick2DRenderer()
+bool usingDefaultSGBackend()
{
const QStringList args = QGuiApplication::arguments();
- QString device;
+
+ //folow logic from contextFactory in src/quick/scenegraph/qsgcontextplugin.cpp
+ QString device = QQuickWindow::sceneGraphBackend();
+
for (int index = 0; index < args.count(); ++index) {
if (args.at(index).startsWith(QLatin1String("--device="))) {
device = args.at(index).mid(9);
@@ -149,16 +154,11 @@ bool usingQtQuick2DRenderer()
}
if (device.isEmpty())
- device = QQuickWindow::sceneGraphBackend();
- if (device.isEmpty())
device = QString::fromLocal8Bit(qgetenv("QT_QUICK_BACKEND"));
if (device.isEmpty())
device = QString::fromLocal8Bit(qgetenv("QMLSCENE_DEVICE"));
- if (device.isEmpty())
- device = QLatin1String("default");
- // Anything other than the default OpenGL device will need to render in 2D mode.
- return device != QLatin1String("default");
+ return device.isEmpty();
}
#endif //QT_NO_OPENGL
#if QT_CONFIG(webengine_pepper_plugins)
@@ -335,6 +335,18 @@ void WebEngineContext::destroyContextPostRoutine()
m_destroyed = true;
}
+ProxyAuthentication WebEngineContext::qProxyNetworkAuthentication(QString host, int port)
+{
+ if (!QNetworkProxyFactory::usesSystemConfiguration()) {
+ QNetworkProxy proxy = QNetworkProxy::applicationProxy();
+ if (host == proxy.hostName() && port == proxy.port() && !proxy.user().isEmpty()
+ && !proxy.password().isEmpty()) {
+ return std::make_tuple(true, proxy.user(), proxy.password());
+ }
+ }
+ return std::make_tuple(false, QString(), QString());
+}
+
#ifndef CHROMIUM_VERSION
#error Chromium version should be defined at gyp-time. Something must have gone wrong
#define CHROMIUM_VERSION // This is solely to keep Qt Creator happy.
@@ -384,7 +396,11 @@ WebEngineContext::WebEngineContext()
QStringList appArgs = QCoreApplication::arguments();
- bool enableWebGLSoftwareRendering = appArgs.contains(QStringLiteral("--enable-webgl-software-rendering"));
+ // If user requested GL support instead of using Skia rendering to
+ // bitmaps, use software rendering via software OpenGL. This might be less
+ // performant, but at least provides WebGL support.
+ // TODO(miklocek), check if this still works with latest chromium
+ bool enableGLSoftwareRendering = appArgs.contains(QStringLiteral("--enable-webgl-software-rendering"));
bool useEmbeddedSwitches = false;
#if defined(QTWEBENGINE_EMBEDDED_SWITCHES)
@@ -485,15 +501,9 @@ WebEngineContext::WebEngineContext()
const char *glType = 0;
#ifndef QT_NO_OPENGL
- bool tryGL =
- (!usingSoftwareDynamicGL()
- // If user requested WebGL support instead of using Skia rendering to
- // bitmaps, use software rendering via software OpenGL. This might be less
- // performant, but at least provides WebGL support.
- || enableWebGLSoftwareRendering
- )
- && !usingQtQuick2DRenderer();
-
+ const bool tryGL = (usingDefaultSGBackend() && !usingSoftwareDynamicGL() &&
+ QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::OpenGL))
+ || enableGLSoftwareRendering;
if (tryGL) {
if (qt_gl_global_share_context() && qt_gl_global_share_context()->isValid()) {
// If the native handle is QEGLNativeContext try to use GL ES/2.
@@ -560,7 +570,7 @@ WebEngineContext::WebEngineContext()
if (glType) {
parsedCommandLine->AppendSwitchASCII(switches::kUseGL, glType);
parsedCommandLine->AppendSwitch(switches::kInProcessGPU);
- if (enableWebGLSoftwareRendering) {
+ if (enableGLSoftwareRendering) {
parsedCommandLine->AppendSwitch(switches::kDisableGpuRasterization);
parsedCommandLine->AppendSwitch(switches::kIgnoreGpuBlacklist);
}
diff --git a/src/core/web_engine_context.h b/src/core/web_engine_context.h
index 4dc5251cc..2364bacbe 100644
--- a/src/core/web_engine_context.h
+++ b/src/core/web_engine_context.h
@@ -80,10 +80,13 @@ class ProfileAdapter;
bool usingSoftwareDynamicGL();
+typedef std::tuple<bool, QString, QString> ProxyAuthentication;
+
class WebEngineContext : public base::RefCounted<WebEngineContext> {
public:
static WebEngineContext *current();
static void destroyContextPostRoutine();
+ static ProxyAuthentication qProxyNetworkAuthentication(QString host, int port);
ProfileAdapter *createDefaultProfileAdapter();
ProfileAdapter *defaultProfileAdapter();
diff --git a/src/core/web_engine_settings.cpp b/src/core/web_engine_settings.cpp
index 2e48a806a..5a01308a1 100644
--- a/src/core/web_engine_settings.cpp
+++ b/src/core/web_engine_settings.cpp
@@ -67,27 +67,6 @@ QHash<WebEngineSettings::FontSize, int> WebEngineSettings::s_defaultFontSizes;
static const int batchTimerTimeout = 0;
-class BatchTimer : public QTimer {
- Q_OBJECT
-public:
- BatchTimer(WebEngineSettings *settings)
- : m_settings(settings)
- {
- setSingleShot(true);
- setInterval(batchTimerTimeout);
- connect(this, SIGNAL(timeout()), SLOT(onTimeout()));
- }
-
-private Q_SLOTS:
- void onTimeout()
- {
- m_settings->doApply();
- }
-
-private:
- WebEngineSettings *m_settings;
-};
-
static inline bool isTouchEventsAPIEnabled() {
static bool initialized = false;
static bool touchEventsAPIEnabled = false;
@@ -113,12 +92,17 @@ static inline bool isTouchEventsAPIEnabled() {
WebEngineSettings::WebEngineSettings(WebEngineSettings *_parentSettings)
: m_adapter(0)
- , m_batchTimer(new BatchTimer(this))
, parentSettings(_parentSettings)
, m_unknownUrlSchemePolicy(WebEngineSettings::InheritedUnknownUrlSchemePolicy)
{
if (parentSettings)
parentSettings->childSettings.insert(this);
+
+ m_batchTimer.setSingleShot(true);
+ m_batchTimer.setInterval(batchTimerTimeout);
+ QObject::connect(&m_batchTimer, &QTimer::timeout, [this]() {
+ doApply();
+ });
}
WebEngineSettings::~WebEngineSettings()
@@ -299,6 +283,11 @@ void WebEngineSettings::initDefaults()
s_defaultAttributes.insert(WebRTCPublicInterfacesOnly, false);
s_defaultAttributes.insert(JavascriptCanPaste, false);
s_defaultAttributes.insert(DnsPrefetchEnabled, false);
+#if QT_CONFIG(webengine_extensions)
+ s_defaultAttributes.insert(PdfViewerEnabled, true);
+#else
+ s_defaultAttributes.insert(PdfViewerEnabled, false);
+#endif
}
if (s_defaultFontFamilies.isEmpty()) {
@@ -335,8 +324,8 @@ void WebEngineSettings::initDefaults()
void WebEngineSettings::scheduleApply()
{
- if (!m_batchTimer->isActive())
- m_batchTimer->start();
+ if (!m_batchTimer.isActive())
+ m_batchTimer.start();
}
void WebEngineSettings::doApply()
@@ -448,5 +437,3 @@ void WebEngineSettings::setParentSettings(WebEngineSettings *_parentSettings)
}
} // namespace QtWebEngineCore
-
-#include "web_engine_settings.moc"
diff --git a/src/core/web_engine_settings.h b/src/core/web_engine_settings.h
index 06a7a6004..d7eeaa560 100644
--- a/src/core/web_engine_settings.h
+++ b/src/core/web_engine_settings.h
@@ -57,6 +57,7 @@
#include <QHash>
#include <QUrl>
#include <QSet>
+#include <QTimer>
namespace content {
struct RendererPreferences;
@@ -65,7 +66,6 @@ struct WebPreferences;
}
namespace QtWebEngineCore {
-class BatchTimer;
class WebContentsAdapter;
class QWEBENGINECORE_PRIVATE_EXPORT WebEngineSettings {
@@ -103,6 +103,7 @@ public:
WebRTCPublicInterfacesOnly,
JavascriptCanPaste,
DnsPrefetchEnabled,
+ PdfViewerEnabled,
};
// Must match the values from the public API in qwebenginesettings.h.
@@ -177,7 +178,7 @@ private:
QHash<FontSize, int> m_fontSizes;
QString m_defaultEncoding;
QScopedPointer<content::WebPreferences> webPreferences;
- QScopedPointer<BatchTimer> m_batchTimer;
+ QTimer m_batchTimer;
WebEngineSettings *parentSettings;
QSet<WebEngineSettings *> childSettings;
@@ -187,7 +188,6 @@ private:
static QHash<FontSize, int> s_defaultFontSizes;
UnknownUrlSchemePolicy m_unknownUrlSchemePolicy;
- friend class BatchTimer;
friend class WebContentsAdapter;
};
diff --git a/src/webengine/api/qquickwebengineclientcertificateselection.cpp b/src/webengine/api/qquickwebengineclientcertificateselection.cpp
index 56cf1ff64..c48a59887 100644
--- a/src/webengine/api/qquickwebengineclientcertificateselection.cpp
+++ b/src/webengine/api/qquickwebengineclientcertificateselection.cpp
@@ -55,23 +55,10 @@ QT_BEGIN_NAMESPACE
\sa {WebEngineClientCertificateSelection::certificates} {WebEngineClientCertificateSelection.certificates}
*/
-QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption() = default;
-
QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption(QQuickWebEngineClientCertificateSelection *selection, int index)
- : QObject(), m_selection(selection), m_index(index)
-{}
-
-QQuickWebEngineClientCertificateOption::QQuickWebEngineClientCertificateOption(const QQuickWebEngineClientCertificateOption &other)
- : QObject(), m_selection(other.m_selection), m_index(other.m_index)
+ : QObject(selection), m_selection(selection), m_index(index)
{}
-QQuickWebEngineClientCertificateOption &QQuickWebEngineClientCertificateOption::operator=(const QQuickWebEngineClientCertificateOption &other)
-{
- m_selection = other.m_selection;
- m_index = other.m_index;
- return *this;
-}
-
/*!
\qmlproperty string WebEngineClientCertificateOption::issuer
\brief The issuer of the certificate.
@@ -164,7 +151,7 @@ QQuickWebEngineClientCertificateOption *QQuickWebEngineClientCertificateSelectio
QQuickWebEngineClientCertificateSelection *d = static_cast<QQuickWebEngineClientCertificateSelection *>(p->object);
if (idx < 0 || idx >= d->m_certificates.size())
return nullptr;
- return &d->m_certificates[idx];
+ return d->m_certificates[idx];
}
/*!
@@ -177,7 +164,7 @@ QQmlListProperty<QQuickWebEngineClientCertificateOption> QQuickWebEngineClientCe
if (m_certificates.empty()) {
QVector<QSslCertificate> certificates = d_ptr->certificates();
for (int i = 0; i < certificates.count(); ++i)
- m_certificates.push_back(QQuickWebEngineClientCertificateOption(this, i));
+ m_certificates.push_back(new QQuickWebEngineClientCertificateOption(this, i));
}
return QQmlListProperty<QQuickWebEngineClientCertificateOption>(
diff --git a/src/webengine/api/qquickwebengineclientcertificateselection_p.h b/src/webengine/api/qquickwebengineclientcertificateselection_p.h
index 7f5a26296..adf8b5f7c 100644
--- a/src/webengine/api/qquickwebengineclientcertificateselection_p.h
+++ b/src/webengine/api/qquickwebengineclientcertificateselection_p.h
@@ -76,10 +76,6 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineClientCertificateOption : public
Q_PROPERTY(bool isSelfSigned READ isSelfSigned CONSTANT FINAL)
public:
- QQuickWebEngineClientCertificateOption();
- QQuickWebEngineClientCertificateOption(const QQuickWebEngineClientCertificateOption &);
- QQuickWebEngineClientCertificateOption &operator=(const QQuickWebEngineClientCertificateOption &);
-
QString issuer() const;
QString subject() const;
QDateTime effectiveDate() const;
@@ -120,7 +116,7 @@ private:
explicit QQuickWebEngineClientCertificateSelection(QSharedPointer<ClientCertSelectController>);
- mutable QVector<QQuickWebEngineClientCertificateOption> m_certificates;
+ mutable QVector<QQuickWebEngineClientCertificateOption *> m_certificates;
QSharedPointer<ClientCertSelectController> d_ptr;
};
diff --git a/src/webengine/api/qquickwebenginedialogrequests.cpp b/src/webengine/api/qquickwebenginedialogrequests.cpp
index 01e757375..da1aecaf6 100644
--- a/src/webengine/api/qquickwebenginedialogrequests.cpp
+++ b/src/webengine/api/qquickwebenginedialogrequests.cpp
@@ -343,8 +343,8 @@ QString QQuickWebEngineJavaScriptDialogRequest::title() const
\qmlproperty enumeration JavaScriptDialogRequest::type
\readonly
- Returns the type of the requested dialog box, see HTML5's
-
+ Returns the type of the requested dialog box. For more information, see
+ HTML5's
\l{https://www.w3.org/TR/html5/webappapis.html#simple-dialogs}{Simple Dialogs}.
\value JavaScriptDialogRequest.DialogTypeAlert
@@ -353,7 +353,7 @@ QString QQuickWebEngineJavaScriptDialogRequest::title() const
A JavaScript confirmation dialog.
\value JavaScriptDialogRequest.DialogTypePrompt
A JavaScript prompt dialog.
- \value JavaScriptDialogRequest.DialogTypeUnload
+ \value JavaScriptDialogRequest.DialogTypeBeforeUnload
The users should be asked if they want to leave the page.
*/
diff --git a/src/webengine/api/qquickwebenginedownloaditem.cpp b/src/webengine/api/qquickwebenginedownloaditem.cpp
index a80f163d5..981d11633 100644
--- a/src/webengine/api/qquickwebenginedownloaditem.cpp
+++ b/src/webengine/api/qquickwebenginedownloaditem.cpp
@@ -185,10 +185,8 @@ void QQuickWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::Down
Q_EMIT q->totalBytesChanged();
}
- if (info.done != downloadFinished) {
- downloadFinished = info.done;
- Q_EMIT q->isFinishedChanged();
- }
+ if (info.done)
+ setFinished();
if (info.paused != downloadPaused) {
downloadPaused = info.paused;
@@ -206,6 +204,17 @@ void QQuickWebEngineDownloadItemPrivate::updateState(QQuickWebEngineDownloadItem
}
}
+void QQuickWebEngineDownloadItemPrivate::setFinished()
+{
+ Q_Q(QQuickWebEngineDownloadItem);
+
+ if (downloadFinished)
+ return;
+
+ downloadFinished = true;
+ Q_EMIT q->isFinishedChanged();
+}
+
/*!
\qmlmethod void WebEngineDownloadItem::accept()
@@ -255,6 +264,7 @@ void QQuickWebEngineDownloadItem::cancel()
return;
d->updateState(QQuickWebEngineDownloadItem::DownloadCancelled);
+ d->setFinished();
// We directly cancel the download if the user cancels before
// it even started, so no need to notify the profile here.
@@ -593,12 +603,14 @@ bool QQuickWebEngineDownloadItem::isPaused() const
}
/*!
- \qmlproperty bool WebEngineDownloadItem::view
+ \qmlproperty WebEngineView WebEngineDownloadItem::view
\readonly
\since QtWebEngine 1.8
Returns the view the download was requested on. If the download was not triggered by content in a view,
\c nullptr is returned.
+
+ \sa WebEngineView
*/
QQuickWebEngineView *QQuickWebEngineDownloadItem::view() const
{
@@ -615,8 +627,8 @@ QQuickWebEngineDownloadItem::QQuickWebEngineDownloadItem(QQuickWebEngineDownload
QQuickWebEngineDownloadItem::~QQuickWebEngineDownloadItem()
{
- if (d_ptr->profile)
- d_ptr->profile->d_ptr->profileAdapter()->removeDownload(d_ptr->downloadId);
+ if (!isFinished())
+ cancel();
}
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginedownloaditem_p_p.h b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
index 4b89335bd..f444c04a5 100644
--- a/src/webengine/api/qquickwebenginedownloaditem_p_p.h
+++ b/src/webengine/api/qquickwebenginedownloaditem_p_p.h
@@ -85,6 +85,7 @@ public:
void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info);
void updateState(QQuickWebEngineDownloadItem::DownloadState newState);
+ void setFinished();
};
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebengineprofile.cpp b/src/webengine/api/qquickwebengineprofile.cpp
index cf9dae90a..ac75b5356 100644
--- a/src/webengine/api/qquickwebengineprofile.cpp
+++ b/src/webengine/api/qquickwebengineprofile.cpp
@@ -171,11 +171,6 @@ QQuickWebEngineProfilePrivate::QQuickWebEngineProfilePrivate(ProfileAdapter *pro
QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate()
{
-
- while (!m_webContentsAdapterClients.isEmpty()) {
- m_webContentsAdapterClients.first()->destroy();
- }
-
if (m_profileAdapter) {
// 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.
@@ -183,25 +178,20 @@ QQuickWebEngineProfilePrivate::~QQuickWebEngineProfilePrivate()
m_profileAdapter->removeClient(this);
}
- for (QQuickWebEngineDownloadItem *download : qAsConst(m_ongoingDownloads)) {
- if (download)
- download->cancel();
- }
-
- m_ongoingDownloads.clear();
-
if (m_profileAdapter != QtWebEngineCore::ProfileAdapter::defaultProfileAdapter())
delete m_profileAdapter;
}
-void QQuickWebEngineProfilePrivate::addWebContentsAdapterClient(QQuickWebEngineViewPrivate *adapter)
+void QQuickWebEngineProfilePrivate::addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter)
{
- m_webContentsAdapterClients.append(adapter);
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->addWebContentsAdapterClient(adapter);
}
-void QQuickWebEngineProfilePrivate::removeWebContentsAdapterClient(QQuickWebEngineViewPrivate*adapter)
+void QQuickWebEngineProfilePrivate::removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient*adapter)
{
- m_webContentsAdapterClients.removeAll(adapter);
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->removeWebContentsAdapterClient(adapter);
}
QtWebEngineCore::ProfileAdapter *QQuickWebEngineProfilePrivate::profileAdapter() const
@@ -223,6 +213,23 @@ void QQuickWebEngineProfilePrivate::cancelDownload(quint32 downloadId)
void QQuickWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
{
m_ongoingDownloads.remove(downloadId);
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(downloadId);
+}
+
+void QQuickWebEngineProfilePrivate::cleanDownloads()
+{
+ for (auto download : m_ongoingDownloads.values()) {
+ if (!download)
+ continue;
+
+ if (!download->isFinished())
+ download->cancel();
+
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(download->id());
+ }
+ m_ongoingDownloads.clear();
}
void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
@@ -247,6 +254,7 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
QQuickWebEngineDownloadItem *download = new QQuickWebEngineDownloadItem(itemPrivate, q);
m_ongoingDownloads.insert(info.id, download);
+ QObject::connect(download, &QQuickWebEngineDownloadItem::destroyed, q, [id = info.id, this] () { downloadDestroyed(id); });
QQmlEngine::setObjectOwnership(download, QQmlEngine::JavaScriptOwnership);
Q_EMIT q->downloadRequested(download);
@@ -260,7 +268,6 @@ void QQuickWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
if (state == QQuickWebEngineDownloadItem::DownloadRequested) {
// Delete unaccepted downloads.
info.accepted = false;
- m_ongoingDownloads.remove(info.id);
delete download;
}
}
@@ -283,7 +290,6 @@ void QQuickWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info
if (info.state != ProfileAdapterClient::DownloadInProgress) {
Q_EMIT q->downloadFinished(download);
- m_ongoingDownloads.remove(info.id);
}
}
@@ -382,6 +388,7 @@ void QQuickWebEngineProfilePrivate::userScripts_clear(QQmlListProperty<QQuickWeb
/*!
\qmlsignal WebEngineProfile::userNotification(WebEngineNotification notification)
+ \since QtWebEngine 1.9
This signal is emitted whenever there is a newly created user notification.
The \a notification argument holds the notification instance to query data and interact with.
@@ -409,6 +416,7 @@ QQuickWebEngineProfile::QQuickWebEngineProfile(QQuickWebEngineProfilePrivate *pr
*/
QQuickWebEngineProfile::~QQuickWebEngineProfile()
{
+ d_ptr->cleanDownloads();
}
/*!
@@ -880,7 +888,7 @@ bool QQuickWebEngineProfile::isUsedForGlobalCertificateVerification() const
Overrides the default path used for download location.
- If set to the null string, the default path is restored.
+ If set to an empty string, the default path is restored.
\note By default, the download path is QStandardPaths::DownloadLocation.
*/
@@ -893,7 +901,7 @@ bool QQuickWebEngineProfile::isUsedForGlobalCertificateVerification() const
Overrides the default path used for download location, setting it to \a path.
- If set to the null string, the default path is restored.
+ If set to an empty string, the default path is restored.
\note By default, the download path is QStandardPaths::DownloadLocation.
*/
@@ -1056,7 +1064,7 @@ QQuickWebEngineSettings *QQuickWebEngineProfile::settings() const
\property QQuickWebEngineProfile::userScripts
\since 5.9
- \brief the collection of scripts that are injected into all pages that share
+ \brief The collection of scripts that are injected into all pages that share
this profile.
\sa QQuickWebEngineScript, QQmlListReference
@@ -1071,4 +1079,19 @@ QQmlListProperty<QQuickWebEngineScript> QQuickWebEngineProfile::userScripts()
d->userScripts_clear);
}
+/*!
+ \since 5.13
+
+ Returns the profile's client certificate store.
+*/
+QWebEngineClientCertificateStore *QQuickWebEngineProfile::clientCertificateStore()
+{
+#if QT_CONFIG(ssl)
+ Q_D(QQuickWebEngineProfile);
+ return d->profileAdapter()->clientCertificateStore();
+#else
+ return nullptr;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebengineprofile.h b/src/webengine/api/qquickwebengineprofile.h
index ce3285ec9..e6f9fb73d 100644
--- a/src/webengine/api/qquickwebengineprofile.h
+++ b/src/webengine/api/qquickwebengineprofile.h
@@ -54,6 +54,7 @@ class QQuickWebEngineDownloadItem;
class QQuickWebEngineProfilePrivate;
class QQuickWebEngineScript;
class QQuickWebEngineSettings;
+class QWebEngineClientCertificateStore;
class QWebEngineCookieStore;
class QWebEngineNotification;
class QWebEngineUrlRequestInterceptor;
@@ -153,6 +154,8 @@ public:
QString downloadPath() const;
void setDownloadPath(const QString &path);
+ QWebEngineClientCertificateStore *clientCertificateStore();
+
static QQuickWebEngineProfile *defaultProfile();
Q_SIGNALS:
@@ -173,7 +176,7 @@ Q_SIGNALS:
void downloadRequested(QQuickWebEngineDownloadItem *download);
void downloadFinished(QQuickWebEngineDownloadItem *download);
- void userNotification(QWebEngineNotification *notification);
+ Q_REVISION(5) void userNotification(QWebEngineNotification *notification);
private:
Q_DECLARE_PRIVATE(QQuickWebEngineProfile)
diff --git a/src/webengine/api/qquickwebengineprofile_p.h b/src/webengine/api/qquickwebengineprofile_p.h
index 322ec0101..c6d412ab3 100644
--- a/src/webengine/api/qquickwebengineprofile_p.h
+++ b/src/webengine/api/qquickwebengineprofile_p.h
@@ -53,7 +53,7 @@
#include "profile_adapter_client.h"
#include "profile_adapter.h"
-#include "qquickwebengineprofile_p.h"
+#include "qquickwebengineprofile.h"
#include <QExplicitlySharedDataPointer>
#include <QMap>
@@ -71,8 +71,8 @@ public:
Q_DECLARE_PUBLIC(QQuickWebEngineProfile)
QQuickWebEngineProfilePrivate(QtWebEngineCore::ProfileAdapter *profileAdapter);
~QQuickWebEngineProfilePrivate();
- void addWebContentsAdapterClient(QQuickWebEngineViewPrivate *adapter);
- void removeWebContentsAdapterClient(QQuickWebEngineViewPrivate *adapter);
+ void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
+ void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
QtWebEngineCore::ProfileAdapter* profileAdapter() const;
QQuickWebEngineSettings *settings() const;
@@ -80,6 +80,8 @@ public:
void cancelDownload(quint32 downloadId);
void downloadDestroyed(quint32 downloadId);
+ void cleanDownloads();
+
void downloadRequested(DownloadItemInfo &info) override;
void downloadUpdated(const DownloadItemInfo &info) override;
@@ -100,7 +102,6 @@ private:
QPointer<QtWebEngineCore::ProfileAdapter> m_profileAdapter;
QMap<quint32, QPointer<QQuickWebEngineDownloadItem> > m_ongoingDownloads;
QList<QQuickWebEngineScript *> m_userScripts;
- QVector<QQuickWebEngineViewPrivate *> m_webContentsAdapterClients;
};
QT_END_NAMESPACE
diff --git a/src/webengine/api/qquickwebenginesettings.cpp b/src/webengine/api/qquickwebenginesettings.cpp
index 6e96e76cf..93a3668ed 100644
--- a/src/webengine/api/qquickwebenginesettings.cpp
+++ b/src/webengine/api/qquickwebenginesettings.cpp
@@ -457,6 +457,20 @@ bool QQuickWebEngineSettings::dnsPrefetchEnabled() const
}
/*!
+ \qmlproperty bool WebEngineSettings::pdfViewerEnabled
+ \since QtWebEngine 1.9
+
+ Specifies that PDF documents will be opened in the internal PDF viewer
+ instead of being downloaded.
+
+ Enabled by default.
+*/
+bool QQuickWebEngineSettings::pdfViewerEnabled() const
+{
+ return d_ptr->testAttribute(WebEngineSettings::PdfViewerEnabled);
+}
+
+/*!
\qmlproperty string WebEngineSettings::defaultTextEncoding
\since QtWebEngine 1.2
@@ -714,6 +728,14 @@ void QQuickWebEngineSettings::setDnsPrefetchEnabled(bool on)
Q_EMIT dnsPrefetchEnabledChanged();
}
+void QQuickWebEngineSettings::setPdfViewerEnabled(bool on)
+{
+ bool wasOn = d_ptr->testAttribute(WebEngineSettings::PdfViewerEnabled);
+ d_ptr->setAttribute(WebEngineSettings::PdfViewerEnabled, on);
+ if (wasOn != on)
+ Q_EMIT pdfViewerEnabledChanged();
+}
+
void QQuickWebEngineSettings::setUnknownUrlSchemePolicy(QQuickWebEngineSettings::UnknownUrlSchemePolicy policy)
{
WebEngineSettings::UnknownUrlSchemePolicy oldPolicy = d_ptr->unknownUrlSchemePolicy();
diff --git a/src/webengine/api/qquickwebenginesettings_p.h b/src/webengine/api/qquickwebenginesettings_p.h
index 6e1aaca39..ce43e0e9c 100644
--- a/src/webengine/api/qquickwebenginesettings_p.h
+++ b/src/webengine/api/qquickwebenginesettings_p.h
@@ -93,6 +93,7 @@ class Q_WEBENGINE_PRIVATE_EXPORT QQuickWebEngineSettings : public QObject {
Q_PROPERTY(bool webRTCPublicInterfacesOnly READ webRTCPublicInterfacesOnly WRITE setWebRTCPublicInterfacesOnly NOTIFY webRTCPublicInterfacesOnlyChanged REVISION 6 FINAL)
Q_PROPERTY(bool javascriptCanPaste READ javascriptCanPaste WRITE setJavascriptCanPaste NOTIFY javascriptCanPasteChanged REVISION 6 FINAL)
Q_PROPERTY(bool dnsPrefetchEnabled READ dnsPrefetchEnabled WRITE setDnsPrefetchEnabled NOTIFY dnsPrefetchEnabledChanged REVISION 7 FINAL)
+ Q_PROPERTY(bool pdfViewerEnabled READ pdfViewerEnabled WRITE setPdfViewerEnabled NOTIFY pdfViewerEnabledChanged REVISION 8 FINAL)
public:
enum UnknownUrlSchemePolicy {
@@ -135,6 +136,7 @@ public:
bool webRTCPublicInterfacesOnly() const;
bool javascriptCanPaste() const;
bool dnsPrefetchEnabled() const;
+ bool pdfViewerEnabled() const;
void setAutoLoadImages(bool on);
void setJavascriptEnabled(bool on);
@@ -166,6 +168,7 @@ public:
void setWebRTCPublicInterfacesOnly(bool on);
void setJavascriptCanPaste(bool on);
void setDnsPrefetchEnabled(bool on);
+ void setPdfViewerEnabled(bool on);
signals:
void autoLoadImagesChanged();
@@ -198,6 +201,7 @@ signals:
Q_REVISION(6) void webRTCPublicInterfacesOnlyChanged();
Q_REVISION(6) void javascriptCanPasteChanged();
Q_REVISION(7) void dnsPrefetchEnabledChanged();
+ Q_REVISION(8) void pdfViewerEnabledChanged();
private:
explicit QQuickWebEngineSettings(QQuickWebEngineSettings *parentSettings = 0);
diff --git a/src/webengine/api/qquickwebengineview.cpp b/src/webengine/api/qquickwebengineview.cpp
index b6b542f15..f17265cfd 100644
--- a/src/webengine/api/qquickwebengineview.cpp
+++ b/src/webengine/api/qquickwebengineview.cpp
@@ -190,7 +190,7 @@ bool QQuickWebEngineViewPrivate::profileInitialized() const
return m_profileInitialized;
}
-void QQuickWebEngineViewPrivate::destroy()
+void QQuickWebEngineViewPrivate::releaseProfile()
{
// The profile for this web contents is about to be
// garbage collected, delete WebContents first and
@@ -1326,7 +1326,7 @@ void QQuickWebEngineView::setBackgroundColor(const QColor &color)
/*!
\property QQuickWebEngineView::audioMuted
- \brief the state of whether the current page audio is muted.
+ \brief The state of whether the current page audio is muted.
\since 5.7
The default value is false.
diff --git a/src/webengine/api/qquickwebengineview_p_p.h b/src/webengine/api/qquickwebengineview_p_p.h
index 543d7b119..e625e0ccc 100644
--- a/src/webengine/api/qquickwebengineview_p_p.h
+++ b/src/webengine/api/qquickwebengineview_p_p.h
@@ -94,7 +94,7 @@ public:
QQuickWebEngineView *q_ptr;
QQuickWebEngineViewPrivate();
~QQuickWebEngineViewPrivate();
- void destroy();
+ void releaseProfile() override;
void initializeProfile();
QtWebEngineCore::UIDelegatesManager *ui();
diff --git a/src/webengine/doc/src/external-resources.qdoc b/src/webengine/doc/src/external-resources.qdoc
index 7ff6eea6b..e4fe9bba6 100644
--- a/src/webengine/doc/src/external-resources.qdoc
+++ b/src/webengine/doc/src/external-resources.qdoc
@@ -146,3 +146,8 @@
\externalpage https://developer.mozilla.org/en-US/docs/Web/API/Navigator/registerProtocolHandler
\title registerProtocolHandler
*/
+
+/*!
+ \externalpage https://www.w3.org/TR/notifications
+ \title Web Notifications API
+*/
diff --git a/src/webengine/doc/src/qtwebengine-examples.qdoc b/src/webengine/doc/src/qtwebengine-examples.qdoc
index 1f1780764..24604e3dd 100644
--- a/src/webengine/doc/src/qtwebengine-examples.qdoc
+++ b/src/webengine/doc/src/qtwebengine-examples.qdoc
@@ -28,7 +28,7 @@
/*!
\group webengine-examples
\title Qt WebEngine Examples
- \brief Examples demonstrating the Qt WebEngine usage
+ \brief Examples demonstrating the Qt WebEngine usage.
\ingroup all-examples
These examples and demonstrations show a range of different uses for \l{Qt WebEngine},
diff --git a/src/webengine/doc/src/qtwebengine-features.qdoc b/src/webengine/doc/src/qtwebengine-features.qdoc
index 64e9badb1..f53c118a8 100644
--- a/src/webengine/doc/src/qtwebengine-features.qdoc
+++ b/src/webengine/doc/src/qtwebengine-features.qdoc
@@ -50,7 +50,7 @@
\li \l{Touch}
\li \l{View Source}
\li \l{WebRTC}
- \li \l{Notifications}
+ \li \l{Web Notifications}
\endlist
\section1 Audio and Video Codecs
@@ -513,9 +513,9 @@
opening \c https://test.webrtc.org/ in \l{WebEngine Widgets Simple Browser
Example}{Simple Browser} or \l{WebEngine Quick Nano Browser}{Nano Browser}.
- \section1 Notifications
+ \section1 Web Notifications
- Qt WebEngine supports JavaScript Web Notification API.
+ Qt WebEngine supports JavaScript \l{Web Notifications API}.
The application has to explicitly allow the feature by using
QWebEnginePage::Notifications or \l{WebEngineView::Feature}
{WebEngineView.Notifications}.
diff --git a/src/webengine/doc/src/qtwebengine-overview.qdoc b/src/webengine/doc/src/qtwebengine-overview.qdoc
index bd5569e3f..58c0708cc 100644
--- a/src/webengine/doc/src/qtwebengine-overview.qdoc
+++ b/src/webengine/doc/src/qtwebengine-overview.qdoc
@@ -149,9 +149,19 @@
engine must be initialized by using \l QtWebEngine::initialize in the application main source
file, as illustrated by the following code snippet:
- \quotefromfile webengine/minimal/main.cpp
- \skipto main
- \printuntil }
+ \code
+ int main(int argc, char *argv[])
+ {
+ QGuiApplication app(argc, argv);
+
+ QtWebEngine::initialize();
+
+ QQmlApplicationEngine engine;
+ engine.load(QUrl("qrc:/main.qml"));
+
+ return app.exec();
+ }
+ \endcode
An application can load pages into the WebEngineView, using either an URL or HTML string, and
navigate within session history. By default, links to different pages load within the same
@@ -228,14 +238,18 @@
are automatically retrieved from the system. Settings from an installed QNetworkProxyFactory
will be ignored, though.
- Not all properties of QNetworkProxy are supported by Qt WebEngine. That is,
- QNetworkProxy::type(), QNetworkProxy::hostName() and QNetworkProxy::port() are taken into
- account. All other proxy settings such as QNetworkProxy::rawHeader(), QNetworkProxy::user(), or
- QNetworkProxy::password() are ignored.
+ In case QNetworkProxy::user() and QNetworkProxy::password() are set, these credentials
+ will be automatically used for proxy authentication. It is up to the user to provide valid
+ credentials, since there is no error handling callback.
- If a proxy requires authentication, QWebEnginePage::proxyAuthenticationRequired is emitted.
+ If no credentials are set with QNetworkProxy, but the proxy requires authentication,
+ QWebEnginePage::proxyAuthenticationRequired is emitted.
For Qt Quick, a dialog is shown.
+ Not all properties of QNetworkProxy are supported by Qt WebEngine. That is,
+ QNetworkProxy::type(), QNetworkProxy::hostName() and QNetworkProxy::port() are taken into
+ account. All other proxy settings such as QNetworkProxy::rawHeader() are ignored.
+
\section1 High DPI Support
To support High DPI devices, it is recommended that the application attribute
diff --git a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
index 17c29a126..540d74035 100644
--- a/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
+++ b/src/webengine/doc/src/qtwebengine-qmlmodule.qdoc
@@ -26,9 +26,9 @@
****************************************************************************/
/*!
- \qmlmodule QtWebEngine 1.8
+ \qmlmodule QtWebEngine 1.9
\title Qt WebEngine QML Types
- \brief Provides QML types for rendering web content within a QML application
+ \brief Provides QML types for rendering web content within a QML application.
\ingroup qtwebengine-modules
\ingroup qmlmodules
@@ -36,7 +36,7 @@
your .qml file:
\badcode
- import QtWebEngine 1.8
+ import QtWebEngine 1.9
\endcode
To link against the module, add the following QT variable to your qmake .pro
diff --git a/src/webengine/plugin/plugin.cpp b/src/webengine/plugin/plugin.cpp
index b683c09d3..6cef0a329 100644
--- a/src/webengine/plugin/plugin.cpp
+++ b/src/webengine/plugin/plugin.cpp
@@ -160,12 +160,12 @@ public:
msgUncreatableType("RegisterProtocolHandlerRequest"));
qmlRegisterUncreatableType<QQuickWebEngineAction>(uri, 1, 8, "WebEngineAction", msgUncreatableType("WebEngineAction"));
qmlRegisterUncreatableType<QQuickWebEngineClientCertificateSelection>(uri, 1, 9, "WebEngineClientCertificateSelection",
- msgUncreatableType("WebEngineClientCertificateSelection"));
+ msgUncreatableType("WebEngineClientCertificateSelection"));
qmlRegisterUncreatableType<QQuickWebEngineClientCertificateOption>(uri, 1, 9, "WebEngineClientCertificateOption",
- msgUncreatableType("WebEngineClientCertificateOption"));
+ msgUncreatableType("WebEngineClientCertificateOption"));
qmlRegisterUncreatableType<QWebEngineNotification>(uri, 1, 9, "WebEngineNotification", msgUncreatableType("WebEngineNotification"));
qmlRegisterUncreatableType<QQuickWebEngineTooltipRequest>(uri, 1, 10, "TooltipRequest",
- msgUncreatableType("TooltipRequest"));
+ msgUncreatableType("TooltipRequest"));
}
private:
diff --git a/src/webengine/plugin/plugin.pro b/src/webengine/plugin/plugin.pro
index 102f9a9fe..0c1310de3 100644
--- a/src/webengine/plugin/plugin.pro
+++ b/src/webengine/plugin/plugin.pro
@@ -8,4 +8,5 @@ QT_PRIVATE += core-private webenginecore-private webengine-private
SOURCES = plugin.cpp
+QMAKE_QMLPLUGINDUMP_FLAGS = -defaultplatform
load(qml_plugin)
diff --git a/src/webengine/plugin/plugins.qmltypes b/src/webengine/plugin/plugins.qmltypes
index 435124e30..cc2ed502d 100644
--- a/src/webengine/plugin/plugins.qmltypes
+++ b/src/webengine/plugin/plugins.qmltypes
@@ -4,7 +4,7 @@ import QtQuick.tooling 1.2
// It is used for QML tooling purposes only.
//
// This file was auto-generated by:
-// 'qmlplugindump -defaultplatform -dependencies dependencies.json -nonrelocatable QtWebEngine 1.9'
+// 'qmlplugindump -nonrelocatable -defaultplatform -dependencies dependencies.json QtWebEngine 1.9'
Module {
dependencies: ["QtQuick 2.8"]
@@ -80,6 +80,46 @@ Module {
Method { name: "rejectCertificate" }
}
Component {
+ name: "QQuickWebEngineClientCertificateOption"
+ prototype: "QObject"
+ exports: ["QtWebEngine/WebEngineClientCertificateOption 1.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Property { name: "issuer"; type: "string"; isReadonly: true }
+ Property { name: "subject"; type: "string"; isReadonly: true }
+ Property { name: "effectiveDate"; type: "QDateTime"; isReadonly: true }
+ Property { name: "expiryDate"; type: "QDateTime"; isReadonly: true }
+ Property { name: "isSelfSigned"; type: "bool"; isReadonly: true }
+ Method { name: "select" }
+ }
+ Component {
+ name: "QQuickWebEngineClientCertificateSelection"
+ prototype: "QObject"
+ exports: ["QtWebEngine/WebEngineClientCertificateSelection 1.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Property { name: "host"; type: "QUrl"; isReadonly: true }
+ Property {
+ name: "certificates"
+ type: "QQuickWebEngineClientCertificateOption"
+ isList: true
+ isReadonly: true
+ }
+ Method {
+ name: "select"
+ Parameter { name: "idx"; type: "int" }
+ }
+ Method {
+ name: "select"
+ Parameter {
+ name: "certificate"
+ type: "const QQuickWebEngineClientCertificateOption"
+ isPointer: true
+ }
+ }
+ Method { name: "selectNone" }
+ }
+ Component {
name: "QQuickWebEngineColorDialogRequest"
prototype: "QObject"
exports: ["QtWebEngine/ColorDialogRequest 1.4"]
@@ -490,6 +530,11 @@ Module {
name: "downloadFinished"
Parameter { name: "download"; type: "QQuickWebEngineDownloadItem"; isPointer: true }
}
+ Signal {
+ name: "userNotification"
+ revision: 5
+ Parameter { name: "notification"; type: "QWebEngineNotification"; isPointer: true }
+ }
Method { name: "clearHttpCache"; revision: 2 }
}
Component {
@@ -622,6 +667,7 @@ Module {
Property { name: "webRTCPublicInterfacesOnly"; revision: 6; type: "bool" }
Property { name: "javascriptCanPaste"; revision: 6; type: "bool" }
Property { name: "dnsPrefetchEnabled"; revision: 7; type: "bool" }
+ Property { name: "pdfViewerEnabled"; revision: 8; type: "bool" }
Signal { name: "fullScreenSupportEnabledChanged"; revision: 1 }
Signal { name: "screenCaptureEnabledChanged"; revision: 2 }
Signal { name: "webGLEnabledChanged"; revision: 2 }
@@ -639,6 +685,7 @@ Module {
Signal { name: "webRTCPublicInterfacesOnlyChanged"; revision: 6 }
Signal { name: "javascriptCanPasteChanged"; revision: 6 }
Signal { name: "dnsPrefetchEnabledChanged"; revision: 7 }
+ Signal { name: "pdfViewerEnabledChanged"; revision: 8 }
}
Component {
name: "QQuickWebEngineSingleton"
@@ -729,7 +776,8 @@ Module {
"MediaAudioVideoCapture": 2,
"Geolocation": 3,
"DesktopVideoCapture": 4,
- "DesktopAudioVideoCapture": 5
+ "DesktopAudioVideoCapture": 5,
+ "Notifications": 6
}
}
Enum {
@@ -1137,6 +1185,15 @@ Module {
Parameter { name: "request"; type: "QWebEngineRegisterProtocolHandlerRequest" }
}
Signal { name: "printRequested"; revision: 8 }
+ Signal {
+ name: "selectClientCertificate"
+ revision: 9
+ Parameter {
+ name: "clientCertSelection"
+ type: "QQuickWebEngineClientCertificateSelection"
+ isPointer: true
+ }
+ }
Method {
name: "runJavaScript"
Parameter { type: "string" }
@@ -1263,6 +1320,32 @@ Module {
}
}
Component {
+ name: "QWebEngineNotification"
+ prototype: "QObject"
+ exports: ["QtWebEngine/WebEngineNotification 1.9"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Enum {
+ name: "Direction"
+ values: {
+ "LeftToRight": 0,
+ "RightToLeft": 1,
+ "DirectionAuto": 2
+ }
+ }
+ Property { name: "origin"; type: "QUrl"; isReadonly: true }
+ Property { name: "icon"; type: "QIcon"; isReadonly: true }
+ Property { name: "title"; type: "string"; isReadonly: true }
+ Property { name: "message"; type: "string"; isReadonly: true }
+ Property { name: "tag"; type: "string"; isReadonly: true }
+ Property { name: "language"; type: "string"; isReadonly: true }
+ Property { name: "direction"; type: "Direction"; isReadonly: true }
+ Signal { name: "closed" }
+ Method { name: "show" }
+ Method { name: "click" }
+ Method { name: "close" }
+ }
+ Component {
name: "QWebEngineQuotaRequest"
exports: ["QtWebEngine/QuotaRequest 1.7"]
isCreatable: false
diff --git a/src/webengine/testsupport/plugins.qmltypes b/src/webengine/testsupport/plugins.qmltypes
new file mode 100644
index 000000000..12c763724
--- /dev/null
+++ b/src/webengine/testsupport/plugins.qmltypes
@@ -0,0 +1,73 @@
+import QtQuick.tooling 1.2
+
+// This file describes the plugin-supplied types contained in the library.
+// It is used for QML tooling purposes only.
+//
+// This file was auto-generated by:
+// 'qmlplugindump -nonrelocatable QtWebEngine.testsupport 1.0'
+
+Module {
+ dependencies: ["QtQuick 2.0"]
+ Component { name: "QPlatformInputContext"; prototype: "QObject" }
+ Component {
+ name: "QQuickWebEngineErrorPage"
+ prototype: "QObject"
+ exports: ["QtWebEngine.testsupport/WebEngineErrorPage 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Signal {
+ name: "loadingChanged"
+ Parameter { name: "loadRequest"; type: "QQuickWebEngineLoadRequest"; isPointer: true }
+ }
+ }
+ Component {
+ name: "QQuickWebEngineTestEvent"
+ prototype: "QObject"
+ exports: ["QtWebEngine.testsupport/WebEngineTestEvent 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Method {
+ name: "mouseMultiClick"
+ type: "bool"
+ Parameter { name: "item"; type: "QObject"; isPointer: true }
+ Parameter { name: "x"; type: "double" }
+ Parameter { name: "y"; type: "double" }
+ Parameter { name: "clickCount"; type: "int" }
+ }
+ }
+ Component {
+ name: "QQuickWebEngineTestInputContext"
+ prototype: "QPlatformInputContext"
+ exports: ["QtWebEngine.testsupport/TestInputContext 1.0"]
+ isCreatable: false
+ exportMetaObjectRevisions: [0]
+ Method { name: "create" }
+ Method { name: "release" }
+ }
+ Component {
+ name: "QQuickWebEngineTestSupport"
+ prototype: "QObject"
+ exports: ["QtWebEngine.testsupport/WebEngineTestSupport 1.0"]
+ exportMetaObjectRevisions: [0]
+ Property {
+ name: "errorPage"
+ type: "QQuickWebEngineErrorPage"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "testInputContext"
+ type: "QQuickWebEngineTestInputContext"
+ isReadonly: true
+ isPointer: true
+ }
+ Property {
+ name: "testEvent"
+ type: "QQuickWebEngineTestEvent"
+ isReadonly: true
+ isPointer: true
+ }
+ Signal { name: "windowCloseRejected" }
+ Signal { name: "loadVisuallyCommitted" }
+ }
+}
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem.cpp b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
index 55d4fcca8..deb92bfd3 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem.cpp
+++ b/src/webenginewidgets/api/qwebenginedownloaditem.cpp
@@ -197,11 +197,8 @@ void QWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::DownloadI
Q_EMIT q->downloadProgress(receivedBytes, totalBytes);
}
- if (info.done != downloadFinished) {
- downloadFinished = info.done;
- if (downloadFinished)
- Q_EMIT q->finished();
- }
+ if (info.done)
+ setFinished();
if (downloadPaused != info.paused) {
downloadPaused = info.paused;
@@ -209,6 +206,15 @@ void QWebEngineDownloadItemPrivate::update(const ProfileAdapterClient::DownloadI
}
}
+void QWebEngineDownloadItemPrivate::setFinished()
+{
+ if (downloadFinished)
+ return;
+
+ downloadFinished = true;
+ Q_EMIT q_ptr->finished();
+}
+
/*!
Accepts the current download request, which will start the download.
@@ -262,6 +268,7 @@ void QWebEngineDownloadItem::cancel()
} else {
d->downloadState = QWebEngineDownloadItem::DownloadCancelled;
Q_EMIT stateChanged(d->downloadState);
+ d->setFinished();
}
}
@@ -653,8 +660,10 @@ QWebEngineDownloadItem::QWebEngineDownloadItem(QWebEngineDownloadItemPrivate *p,
*/
QWebEngineDownloadItem::~QWebEngineDownloadItem()
{
- if (auto profileAdapter = d_ptr->profile->profileAdapter())
- profileAdapter->removeDownload(d_ptr->downloadId);
+ // MEMO Items are owned by profile by default and will be destroyed on profile's destruction
+ // It's not safe to access profile in that case, so we rely on profile to clean up items
+ if (!isFinished())
+ cancel();
}
QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginedownloaditem_p.h b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
index bdcda5be6..b3bc8a3fe 100644
--- a/src/webenginewidgets/api/qwebenginedownloaditem_p.h
+++ b/src/webenginewidgets/api/qwebenginedownloaditem_p.h
@@ -53,7 +53,7 @@
#include "qtwebenginewidgetsglobal.h"
-#include "qwebenginedownloaditem_p.h"
+#include "qwebenginedownloaditem.h"
#include "qwebengineprofile_p.h"
#include <QString>
@@ -84,6 +84,8 @@ public:
QWebEnginePage *page;
void update(const QtWebEngineCore::ProfileAdapterClient::DownloadItemInfo &info);
+
+ void setFinished();
};
QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp b/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp
index c15a80373..da97c4662 100644
--- a/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp
+++ b/src/webenginewidgets/api/qwebenginenotificationpresenter.cpp
@@ -57,11 +57,15 @@ DefaultNotificationPresenter::~DefaultNotificationPresenter()
void DefaultNotificationPresenter::show(const QWebEngineNotification &notification)
{
- if (!m_activeNotification.isNull())
+ if (m_activeNotification.isValid()) {
m_activeNotification.close();
+ m_activeNotification.disconnect(this);
+ }
+
m_activeNotification = notification;
+
#ifndef QT_NO_SYSTEMTRAYICON
- if (m_systemTrayIcon) {
+ if (m_activeNotification.isValid() && m_systemTrayIcon) {
m_systemTrayIcon->show();
QIcon icon = notification.icon();
if (!icon.isNull())
@@ -76,7 +80,7 @@ void DefaultNotificationPresenter::show(const QWebEngineNotification &notificati
void DefaultNotificationPresenter::messageClicked()
{
- if (!m_activeNotification.isNull())
+ if (m_activeNotification.isValid())
m_activeNotification.click();
}
diff --git a/src/webenginewidgets/api/qwebenginepage.cpp b/src/webenginewidgets/api/qwebenginepage.cpp
index a1ddf88d7..696b6723f 100644
--- a/src/webenginewidgets/api/qwebenginepage.cpp
+++ b/src/webenginewidgets/api/qwebenginepage.cpp
@@ -177,6 +177,8 @@ QWebEnginePagePrivate::QWebEnginePagePrivate(QWebEngineProfile *_profile)
ensureInitialized();
wasShown();
});
+
+ profile->d_ptr->addWebContentsAdapterClient(this);
}
QWebEnginePagePrivate::~QWebEnginePagePrivate()
@@ -185,6 +187,7 @@ QWebEnginePagePrivate::~QWebEnginePagePrivate()
profile->d_ptr->profileAdapter()->removePageRequestInterceptor();
delete history;
delete settings;
+ profile->d_ptr->removeWebContentsAdapterClient(this);
}
RenderWidgetHostViewQtDelegate *QWebEnginePagePrivate::CreateRenderWidgetHostViewQtDelegate(RenderWidgetHostViewQtDelegateClient *client)
@@ -255,7 +258,7 @@ void QWebEnginePagePrivate::didUpdateTargetURL(const QUrl &hoveredUrl)
void QWebEnginePagePrivate::selectionChanged()
{
Q_Q(QWebEnginePage);
- Q_EMIT q->selectionChanged();
+ QTimer::singleShot(0, q, &QWebEnginePage::selectionChanged);
}
void QWebEnginePagePrivate::recentlyAudibleChanged(bool recentlyAudible)
@@ -479,6 +482,13 @@ void QWebEnginePagePrivate::authenticationRequired(QSharedPointer<Authentication
controller->accept(networkAuth.user(), networkAuth.password());
}
+void QWebEnginePagePrivate::releaseProfile()
+{
+ qDebug("Release of profile requested but WebEnginePage still not deleted. Expect troubles !");
+ // this is not the way to go, but might avoid the crash if user code does not make any calls to page.
+ delete q_ptr->d_ptr.take();
+}
+
void QWebEnginePagePrivate::showColorDialog(QSharedPointer<ColorChooserController> controller)
{
#if QT_CONFIG(colordialog)
@@ -845,7 +855,7 @@ QWebEnginePage::QWebEnginePage(QObject* parent)
\property QWebEnginePage::contentsSize
\since 5.7
- The size of the page contents.
+ \brief The size of the page contents.
*/
/*!
@@ -907,11 +917,13 @@ QWebEnginePage::QWebEnginePage(QWebEngineProfile *profile, QObject* parent)
QWebEnginePage::~QWebEnginePage()
{
- Q_D(QWebEnginePage);
- setDevToolsPage(nullptr);
- d->adapter->stopFinding();
- QWebEnginePagePrivate::bindPageAndView(this, nullptr);
- QWebEnginePagePrivate::bindPageAndWidget(this, nullptr);
+ if (d_ptr) {
+ // d_ptr might be exceptionally null if profile adapter got deleted first
+ setDevToolsPage(nullptr);
+ d_ptr->adapter->stopFinding();
+ QWebEnginePagePrivate::bindPageAndView(this, nullptr);
+ QWebEnginePagePrivate::bindPageAndWidget(this, nullptr);
+ }
}
QWebEngineHistory *QWebEnginePage::history() const
@@ -994,7 +1006,7 @@ void QWebEnginePage::setWebChannel(QWebChannel *channel, uint worldId)
/*!
\property QWebEnginePage::backgroundColor
- \brief the page's background color behind the document's body.
+ \brief The page's background color behind the document's body.
\since 5.6
You can set the background color to Qt::transparent or to a translucent
@@ -1045,7 +1057,7 @@ void QWebEnginePage::save(const QString &filePath,
/*!
\property QWebEnginePage::audioMuted
- \brief whether the current page audio is muted.
+ \brief Whether the current page audio is muted.
\since 5.7
The default value is \c false.
@@ -1067,7 +1079,7 @@ void QWebEnginePage::setAudioMuted(bool muted) {
/*!
\property QWebEnginePage::recentlyAudible
- \brief the current page's \e {audible state}, that is, whether audio was recently played
+ \brief The current page's \e {audible state}, that is, whether audio was recently played
or not.
\since 5.7
@@ -2022,7 +2034,7 @@ QUrl QWebEnginePage::requestedUrl() const
/*!
\property QWebEnginePage::iconUrl
- \brief the URL of the icon associated with the page currently viewed
+ \brief The URL of the icon associated with the page currently viewed.
By default, this property contains an empty URL.
@@ -2036,7 +2048,7 @@ QUrl QWebEnginePage::iconUrl() const
/*!
\property QWebEnginePage::icon
- \brief the icon associated with the page currently viewed
+ \brief The icon associated with the page currently viewed.
\since 5.7
By default, this property contains a null icon. If the web page specifies more than one icon,
diff --git a/src/webenginewidgets/api/qwebenginepage_p.h b/src/webenginewidgets/api/qwebenginepage_p.h
index d597383e2..0db462a0a 100644
--- a/src/webenginewidgets/api/qwebenginepage_p.h
+++ b/src/webenginewidgets/api/qwebenginepage_p.h
@@ -130,6 +130,7 @@ public:
void passOnFocus(bool reverse) override;
void javaScriptConsoleMessage(JavaScriptConsoleMessageLevel level, const QString& message, int lineNumber, const QString& sourceID) override;
void authenticationRequired(QSharedPointer<QtWebEngineCore::AuthenticationDialogController>) override;
+ void releaseProfile() override;
void runMediaAccessPermissionRequest(const QUrl &securityOrigin, MediaRequestFlags requestFlags) override;
void runGeolocationPermissionRequest(const QUrl &securityOrigin) override;
void runUserNotificationPermissionRequest(const QUrl &securityOrigin) override;
diff --git a/src/webenginewidgets/api/qwebengineprofile.cpp b/src/webenginewidgets/api/qwebengineprofile.cpp
index 74dc14da0..d69ddb343 100644
--- a/src/webenginewidgets/api/qwebengineprofile.cpp
+++ b/src/webenginewidgets/api/qwebengineprofile.cpp
@@ -182,13 +182,6 @@ QWebEngineProfilePrivate::~QWebEngineProfilePrivate()
m_profileAdapter->removeClient(this);
}
- for (QWebEngineDownloadItem *download : qAsConst(m_ongoingDownloads)) {
- if (download)
- download->cancel();
- }
-
- m_ongoingDownloads.clear();
-
if (m_profileAdapter != QtWebEngineCore::ProfileAdapter::defaultProfileAdapter())
delete m_profileAdapter;
@@ -203,6 +196,23 @@ ProfileAdapter* QWebEngineProfilePrivate::profileAdapter() const
void QWebEngineProfilePrivate::downloadDestroyed(quint32 downloadId)
{
m_ongoingDownloads.remove(downloadId);
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(downloadId);
+}
+
+void QWebEngineProfilePrivate::cleanDownloads()
+{
+ for (auto download : m_ongoingDownloads.values()) {
+ if (!download)
+ continue;
+
+ if (!download->isFinished())
+ download->cancel();
+
+ if (m_profileAdapter)
+ m_profileAdapter->removeDownload(download->id());
+ }
+ m_ongoingDownloads.clear();
}
void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
@@ -226,6 +236,7 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
QWebEngineDownloadItem *download = new QWebEngineDownloadItem(itemPrivate, q);
m_ongoingDownloads.insert(info.id, download);
+ QObject::connect(download, &QWebEngineDownloadItem::destroyed, q, [id = info.id, this] () { downloadDestroyed(id); });
Q_EMIT q->downloadRequested(download);
@@ -239,7 +250,6 @@ void QWebEngineProfilePrivate::downloadRequested(DownloadItemInfo &info)
if (state == QWebEngineDownloadItem::DownloadRequested) {
// Delete unaccepted downloads.
info.accepted = false;
- m_ongoingDownloads.remove(info.id);
delete download;
}
}
@@ -257,9 +267,18 @@ void QWebEngineProfilePrivate::downloadUpdated(const DownloadItemInfo &info)
}
download->d_func()->update(info);
+}
- if (download->isFinished())
- m_ongoingDownloads.remove(info.id);
+void QWebEngineProfilePrivate::addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter)
+{
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->addWebContentsAdapterClient(adapter);
+}
+
+void QWebEngineProfilePrivate::removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter)
+{
+ Q_ASSERT(m_profileAdapter);
+ m_profileAdapter->removeWebContentsAdapterClient(adapter);
}
/*!
@@ -308,6 +327,7 @@ QWebEngineProfile::QWebEngineProfile(QWebEngineProfilePrivate *privatePtr, QObje
*/
QWebEngineProfile::~QWebEngineProfile()
{
+ d_ptr->cleanDownloads();
}
/*!
@@ -577,9 +597,11 @@ QWebEngineCookieStore* QWebEngineProfile::cookieStore()
void QWebEngineProfile::setRequestInterceptor(QWebEngineUrlRequestInterceptor *interceptor)
{
Q_D(QWebEngineProfile);
- interceptor->setProperty("deprecated", true);
+ if (interceptor)
+ interceptor->setProperty("deprecated", true);
d->profileAdapter()->setRequestInterceptor(interceptor);
- qWarning("Use of deprecated not tread-safe setter, use setUrlRequestInterceptor instead.");
+ if (interceptor)
+ qDebug("Use of deprecated not thread-safe setter, use setUrlRequestInterceptor instead.");
}
#endif
/*!
@@ -646,16 +668,7 @@ QWebEngineScriptCollection *QWebEngineProfile::scripts() const
\since 5.13
\sa QWebEngineNotification
*/
-void QWebEngineProfile::setNotificationPresenter(const std::function<void(const QWebEngineNotification &)> &notificationPresenter)
-{
- Q_D(QWebEngineProfile);
- d->m_notificationPresenter = notificationPresenter;
-}
-
-/*!
- \overload
-*/
-void QWebEngineProfile::setNotificationPresenter(std::function<void(const QWebEngineNotification &)> &&notificationPresenter)
+void QWebEngineProfile::setNotificationPresenter(std::function<void(const QWebEngineNotification &)> notificationPresenter)
{
Q_D(QWebEngineProfile);
d->m_notificationPresenter = std::move(notificationPresenter);
@@ -807,12 +820,13 @@ void QWebEngineProfile::removeAllUrlSchemeHandlers()
/*!
\since 5.13
- Sets this profile to be used for downloading and caching when needed during
- certificate verification, for instance for OCSP, CRLs, and AIA.
+ Sets if this profile is to be used for downloading and caching when needed
+ during certificate verification, for instance for OCSP, CRLs, and AIA.
Only one QWebEngineProfile can do this at a time, and it is recommended
that the profile fullfilling this role has a disk HTTP cache to avoid
- needlessly re-downloading.
+ needlessly re-downloading. If you set the option on a second profile,
+ it will be disabled on the profile it is currently set.
Currently only affects Linux/NSS installations where it enables OCSP.
@@ -821,10 +835,10 @@ void QWebEngineProfile::removeAllUrlSchemeHandlers()
\sa isUsedForGlobalCertificateVerification(), httpCacheType()
*/
-void QWebEngineProfile::setUseForGlobalCertificateVerification()
+void QWebEngineProfile::setUseForGlobalCertificateVerification(bool enabled)
{
Q_D(QWebEngineProfile);
- d->profileAdapter()->setUseForGlobalCertificateVerification();
+ d->profileAdapter()->setUseForGlobalCertificateVerification(enabled);
}
/*!
@@ -850,4 +864,19 @@ void QWebEngineProfile::clearHttpCache()
d->profileAdapter()->clearHttpCache();
}
+/*!
+ \since 5.13
+
+ Returns the profile's client certificate store.
+*/
+QWebEngineClientCertificateStore *QWebEngineProfile::clientCertificateStore()
+{
+#if QT_CONFIG(ssl)
+ Q_D(QWebEngineProfile);
+ return d->profileAdapter()->clientCertificateStore();
+#else
+ return nullptr;
+#endif
+}
+
QT_END_NAMESPACE
diff --git a/src/webenginewidgets/api/qwebengineprofile.h b/src/webenginewidgets/api/qwebengineprofile.h
index 5ad999c00..e3ddb594a 100644
--- a/src/webenginewidgets/api/qwebengineprofile.h
+++ b/src/webenginewidgets/api/qwebengineprofile.h
@@ -52,6 +52,7 @@ QT_BEGIN_NAMESPACE
class QObject;
class QUrl;
+class QWebEngineClientCertificateStore;
class QWebEngineCookieStore;
class QWebEngineDownloadItem;
class QWebEngineNotification;
@@ -134,14 +135,15 @@ public:
void setSpellCheckEnabled(bool enabled);
bool isSpellCheckEnabled() const;
- void setUseForGlobalCertificateVerification();
+ void setUseForGlobalCertificateVerification(bool enabled = true);
bool isUsedForGlobalCertificateVerification() const;
QString downloadPath() const;
void setDownloadPath(const QString &path);
- void setNotificationPresenter(const std::function<void(const QWebEngineNotification &)> &notificationPresenter);
- void setNotificationPresenter(std::function<void(const QWebEngineNotification &)> &&notificationPresenter);
+ void setNotificationPresenter(std::function<void(const QWebEngineNotification &)> notificationPresenter);
+
+ QWebEngineClientCertificateStore *clientCertificateStore();
static QWebEngineProfile *defaultProfile();
diff --git a/src/webenginewidgets/api/qwebengineprofile_p.h b/src/webenginewidgets/api/qwebengineprofile_p.h
index 3dd024ffd..91c43cf0a 100644
--- a/src/webenginewidgets/api/qwebengineprofile_p.h
+++ b/src/webenginewidgets/api/qwebengineprofile_p.h
@@ -84,11 +84,16 @@ public:
void downloadDestroyed(quint32 downloadId);
+ void cleanDownloads();
+
void downloadRequested(DownloadItemInfo &info) override;
void downloadUpdated(const DownloadItemInfo &info) override;
void showNotification(QSharedPointer<QtWebEngineCore::UserNotificationController> &) override;
+ void addWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
+ void removeWebContentsAdapterClient(QtWebEngineCore::WebContentsAdapterClient *adapter) override;
+
private:
QWebEngineProfile *q_ptr;
QWebEngineSettings *m_settings;
diff --git a/src/webenginewidgets/api/qwebenginesettings.cpp b/src/webenginewidgets/api/qwebenginesettings.cpp
index d91eb3f97..d9fb3b000 100644
--- a/src/webenginewidgets/api/qwebenginesettings.cpp
+++ b/src/webenginewidgets/api/qwebenginesettings.cpp
@@ -109,7 +109,8 @@ static WebEngineSettings::Attribute toWebEngineAttribute(QWebEngineSettings::Web
return WebEngineSettings::JavascriptCanPaste;
case QWebEngineSettings::DnsPrefetchEnabled:
return WebEngineSettings::DnsPrefetchEnabled;
-
+ case QWebEngineSettings::PdfViewerEnabled:
+ return WebEngineSettings::PdfViewerEnabled;
default:
return WebEngineSettings::UnsupportedInCoreSettings;
}
diff --git a/src/webenginewidgets/api/qwebenginesettings.h b/src/webenginewidgets/api/qwebenginesettings.h
index 9100e32d5..d39291fed 100644
--- a/src/webenginewidgets/api/qwebenginesettings.h
+++ b/src/webenginewidgets/api/qwebenginesettings.h
@@ -96,6 +96,7 @@ public:
WebRTCPublicInterfacesOnly,
JavascriptCanPaste,
DnsPrefetchEnabled,
+ PdfViewerEnabled,
};
enum FontSize {
diff --git a/src/webenginewidgets/api/qwebengineview.cpp b/src/webenginewidgets/api/qwebengineview.cpp
index 576baad17..966b30100 100644
--- a/src/webenginewidgets/api/qwebengineview.cpp
+++ b/src/webenginewidgets/api/qwebengineview.cpp
@@ -238,7 +238,7 @@ QUrl QWebEngineView::iconUrl() const
/*!
\property QWebEngineView::icon
- \brief the icon associated with the page currently viewed
+ \brief The icon associated with the page currently viewed.
\since 5.7
By default, this property contains a null icon.
diff --git a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
index 8accdf062..b6c5cb497 100644
--- a/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
+++ b/src/webenginewidgets/doc/src/qtwebenginewidgets-examples.qdoc
@@ -28,7 +28,7 @@
/*!
\group webengine-widgetexamples
\title Qt WebEngine Widgets Examples
- \brief Examples demonstrating the Qt WebEngine Widgets usage
+ \brief Examples demonstrating the Qt WebEngine Widgets usage.
\ingroup all-examples
Qt provides an integrated Web browser component based on Chromium, the popular
diff --git a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
index 877bf7175..f9ab710d1 100644
--- a/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginepage_lgpl.qdoc
@@ -451,14 +451,14 @@
/*!
\property QWebEnginePage::hasSelection
- \brief whether this page contains selected content or not.
+ \brief Whether this page contains selected content or not.
\sa selectionChanged()
*/
/*!
\property QWebEnginePage::selectedText
- \brief the text currently selected
+ \brief The text currently selected.
By default, this property contains an empty string.
@@ -643,14 +643,20 @@
/*!
\property QWebEnginePage::title
- \brief the title of the page as defined by the HTML \c <title> element
+ \brief The title of the page as defined by the HTML \c <title> element.
+
+ If the page has no \c <title> element, then the URL is used instead. For \c
+ file:// URLs only the filename is used and not the full path.
+
+ By default, before any content has been loaded, this property contains an
+ empty string.
\sa titleChanged()
*/
/*!
\property QWebEnginePage::url
- \brief the URL of the page currently viewed
+ \brief The URL of the page currently viewed.
Setting this property clears the view and loads the URL.
@@ -661,8 +667,8 @@
/*!
\property QWebEnginePage::requestedUrl
- \brief the URL that was originally requested to be loaded by the page
- that is currently viewed
+ \brief The URL that was originally requested to be loaded by the page
+ that is currently viewed.
\note The URL may differ from the one returned by url(), which is the actual
URL that results from DNS resolution or redirection.
@@ -729,7 +735,7 @@
/*!
\property QWebEnginePage::zoomFactor
- \brief the zoom factor for the page content
+ \brief The zoom factor for the page content.
Valid values are within the range from \c{0.25} to \c{5.0}. The default factor is \c{1.0}.
*/
diff --git a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
index 88f6e05c2..ce75a4203 100644
--- a/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebenginesettings_lgpl.qdoc
@@ -188,7 +188,9 @@
\value DnsPrefetchEnabled Specifies whether WebEngine will try to pre-fetch DNS entries to
speed up browsing.
Disabled by default. (Added in Qt 5.12)
-
+ \value PdfViewerEnabled Specifies that PDF documents will be opened in the internal PDF viewer
+ instead of being downloaded.
+ Enabled by default. (Added in Qt 5.13)
*/
/*!
diff --git a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
index 501959ab9..568e7a63a 100644
--- a/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
+++ b/src/webenginewidgets/doc/src/qwebengineview_lgpl.qdoc
@@ -173,16 +173,16 @@
/*!
\property QWebEngineView::title
- \brief the title of the web page currently viewed
+ \brief The title of the page as defined by the HTML \c <title> element.
- By default, this property contains an empty string.
+ Equivalent to \l {QWebEnginePage::title()}.
\sa titleChanged()
*/
/*!
\property QWebEngineView::url
- \brief the URL of the web page currently viewed
+ \brief The URL of the web page currently viewed.
Setting this property clears the view and loads the URL.
@@ -193,7 +193,7 @@
/*!
\property QWebEngineView::iconUrl
- \brief the URL of the icon associated with the page currently viewed
+ \brief The URL of the icon associated with the page currently viewed.
By default, this property contains an empty URL.
@@ -202,7 +202,7 @@
/*!
\property QWebEngineView::hasSelection
- \brief whether this page contains selected content or not.
+ \brief Whether this page contains selected content or not.
By default, this property is \c false.
@@ -211,7 +211,7 @@
/*!
\property QWebEngineView::selectedText
- \brief the text currently selected
+ \brief The text currently selected.
By default, this property contains an empty string.
@@ -238,7 +238,7 @@
/*!
\property QWebEngineView::zoomFactor
- \brief the zoom factor for the view
+ \brief The zoom factor for the view.
Valid values are within the range from \c{0.25} to \c{5.0}. The default factor is \c{1.0}.
*/
diff --git a/tests/auto/core/core.pro b/tests/auto/core/core.pro
index c1b2147bd..1dc5e052c 100644
--- a/tests/auto/core/core.pro
+++ b/tests/auto/core/core.pro
@@ -1,8 +1,9 @@
TEMPLATE = subdirs
+QT_FOR_CONFIG += network-private
SUBDIRS += \
qwebenginecookiestore \
- qwebengineurlrequestinterceptor \
+ qwebengineurlrequestinterceptor
+
+qtConfig(ssl): SUBDIRS += qwebengineclientcertificatestore
-# QTBUG-60268
-boot2qt: SUBDIRS = ""
diff --git a/tests/auto/core/qwebengineclientcertificatestore/qwebengineclientcertificatestore.pro b/tests/auto/core/qwebengineclientcertificatestore/qwebengineclientcertificatestore.pro
new file mode 100644
index 000000000..e99c7f493
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/qwebengineclientcertificatestore.pro
@@ -0,0 +1 @@
+include(../tests.pri)
diff --git a/tests/auto/core/qwebengineclientcertificatestore/resources/certificate.crt b/tests/auto/core/qwebengineclientcertificatestore/resources/certificate.crt
new file mode 100644
index 000000000..1c7a4e6a1
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/resources/certificate.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID6zCCAtOgAwIBAgIUR7/FZjFjCH94EgGF1VOOca1p8PUwDQYJKoZIhvcNAQEL
+BQAwgYQxCzAJBgNVBAYTAkVVMREwDwYDVQQIDAhIRUxTSU5LSTERMA8GA1UEBwwI
+SEVMU0lOS0kxFzAVBgNVBAoMDlRoZSBRdCBDb21wYW55MQ4wDAYDVQQDDAVxdC5p
+bzEmMCQGCSqGSIb3DQEJARYXdmlqaXRoLmtpbmlAY2xheXNvbC5jb20wHhcNMTkw
+MjE5MTIzNjE5WhcNMjAwMjE5MTIzNjE5WjCBhDELMAkGA1UEBhMCRVUxETAPBgNV
+BAgMCEhFTFNJTktJMREwDwYDVQQHDAhIRUxTSU5LSTEXMBUGA1UECgwOVGhlIFF0
+IENvbXBhbnkxDjAMBgNVBAMMBXF0LmlvMSYwJAYJKoZIhvcNAQkBFhd2aWppdGgu
+a2luaUBjbGF5c29sLmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AOprCpRWsPUda98sp2iQse8bUcwaaRaWl2LqKXu9ELpeInS1dq+v8/NMx7c67N2B
++1l5dOM1CPsIZ27mIL2Y04fy58lGOtwtpJg5MnR50Vl8lG/NxoAWjc2XJYhhVHfJ
+k+KOME2Z4gMGU/2UoMkN/la/sSDFtApJKhYgRwjvPdDXDNr/QxpNLmSaYwd+Bx/P
+MqEEcUkk+tGHWI+XTvUuFczSGpjTZ+QdgYg4w/WjDD0z+cSOJ553EoeswRZHY35O
+pqwgIBMFwoUPpXb5TfOm6fBeb8i8MbReR1NV2XXPQ2aPcmuY9Cmi8Tol+sXy0MvY
+Yd16eZb0eD5oIGr9UjvfJMsCAwEAAaNTMFEwHQYDVR0OBBYEFHJG773IyFWSDBvD
+tvm1fmP5UbEfMB8GA1UdIwQYMBaAFHJG773IyFWSDBvDtvm1fmP5UbEfMA8GA1Ud
+EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAAcaPiAufSZwrALeT1BRiBAj
+TdeC2ly1EBw8BwmEhVmma9GRslZzxcTUiZ+W3aYdPOFFDXE+HyAKY2WBQ1iETpIa
+oeqJKzBTzXXXnXT3Wu9BCD928SH8Srtays9yEZO1DRtSKcBrsipdH3KKu3kkAIVL
+GJ4igY2+2EO+64usMROzaL0WiNexHLPCm9KkURPvGRE3GJULYHEEw15ClYryJI5A
+fwVbcMKhQAQipIgrdoPe6aXfTeELD2RpRvU9nMKTelJI5czx4dYGRXVjjF21qiTr
+ov7+d2rXx/133K13kmeeMzOIJkDX3QJwlcKvegygU6QfJwnkRM7ZUAXGTlt3jW0=
+-----END CERTIFICATE-----
diff --git a/tests/auto/core/qwebengineclientcertificatestore/resources/certificate1.crt b/tests/auto/core/qwebengineclientcertificatestore/resources/certificate1.crt
new file mode 100644
index 000000000..cd3ee969e
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/resources/certificate1.crt
@@ -0,0 +1,23 @@
+-----BEGIN CERTIFICATE-----
+MIID4zCCAsugAwIBAgIUcEB7LtzUwdKmEY5b8yDuC/rvMLswDQYJKoZIhvcNAQEL
+BQAwgYAxCzAJBgNVBAYTAklOMRIwEAYDVQQIDAlLYXJuYXRha2ExEjAQBgNVBAcM
+CUJBTkdBTE9SRTEQMA4GA1UECgwHQ2xheXNvbDEUMBIGA1UEAwwLY2xheXNvbC5j
+b20xITAfBgkqhkiG9w0BCQEWEnZpaml0aEBjbGF5c29sLmNvbTAeFw0xOTAyMTkx
+MjM4NDhaFw0yMDAyMTkxMjM4NDhaMIGAMQswCQYDVQQGEwJJTjESMBAGA1UECAwJ
+S2FybmF0YWthMRIwEAYDVQQHDAlCQU5HQUxPUkUxEDAOBgNVBAoMB0NsYXlzb2wx
+FDASBgNVBAMMC2NsYXlzb2wuY29tMSEwHwYJKoZIhvcNAQkBFhJ2aWppdGhAY2xh
+eXNvbC5jb20wggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC9pvbiJJnL
+oe5YA6MCUryOYiTmj3PVdPpKMrBe2sdzvO0cx2NXpxWERK9QNnFaJb4fTY+j9fgv
+ru1tsIH3AbnDbXfpEPSD4DmpSXiKgB2+KZhA82ZerJendxqaXaj2BgTG2Tc++Chk
+0wzx/3KRSb97mgPKJK5yNwx3KQjeXAhR5Mkwmmf+ZUfoYHRu4BNneYs7qX9rEPDl
+vrd3AaPTgjapz7EEnSO19BrZHgLWFsM0Kni2vux1jHq1wYRXRTaOG0MrNuvuHuNC
+2j5C+N/MPcuuN9izbshrlteIi2a4526V4Hp1KX1BKAI2LgI+ufzdDEkuPs/u28J7
+tGiXjAmf4YUBAgMBAAGjUzBRMB0GA1UdDgQWBBQFfq9BP0BwBToA5U6gfNaxPDFt
+3jAfBgNVHSMEGDAWgBQFfq9BP0BwBToA5U6gfNaxPDFt3jAPBgNVHRMBAf8EBTAD
+AQH/MA0GCSqGSIb3DQEBCwUAA4IBAQBmruPekYCAAgHig66OBEHcl2jCp+MH1dmW
+amM5ET3X0mC588S4+JXCVOOh2XJ2ZSRiy0syPbGd0lG6niX5h35gsqSx9uZyXW/+
+KcTf+LsaxZNusLFtAOExnYuTeeAzofMvIGQpujMhD0p/gk8s64gXnlJZZh8S1OGV
+3Me8PV/cat0nuGpLi/0CYj2lAquG0LfeoGZAp+JHAMJTl/xyK4B/KMvbZ7USK9zz
+gqwLag93s4vBW0dpgu+g80GGhb0bF2ZFjD+j8I0i9OjFbTWxAiHomofQ6Qx12eVY
+rfJs/kVG86cOLJarFHBadjlLz4pu1/sp97TsohFYDy7isRbOQdO2
+-----END CERTIFICATE-----
diff --git a/tests/auto/core/qwebengineclientcertificatestore/resources/privatekey.key b/tests/auto/core/qwebengineclientcertificatestore/resources/privatekey.key
new file mode 100644
index 000000000..ff9ce14df
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/resources/privatekey.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvwIBADANBgkqhkiG9w0BAQEFAASCBKkwggSlAgEAAoIBAQDqawqUVrD1HWvf
+LKdokLHvG1HMGmkWlpdi6il7vRC6XiJ0tXavr/PzTMe3OuzdgftZeXTjNQj7CGdu
+5iC9mNOH8ufJRjrcLaSYOTJ0edFZfJRvzcaAFo3NlyWIYVR3yZPijjBNmeIDBlP9
+lKDJDf5Wv7EgxbQKSSoWIEcI7z3Q1wza/0MaTS5kmmMHfgcfzzKhBHFJJPrRh1iP
+l071LhXM0hqY02fkHYGIOMP1oww9M/nEjieedxKHrMEWR2N+TqasICATBcKFD6V2
++U3zpunwXm/IvDG0XkdTVdl1z0Nmj3JrmPQpovE6JfrF8tDL2GHdenmW9Hg+aCBq
+/VI73yTLAgMBAAECggEAXfjLJOwbxCcnNzAPbDuVGOU6xTdRKVz1ExILzy7bpdpW
+tbKJAaTnhoEhDrLwgVu6BwRJd0urbfbQgASA24CIS9d0U5tzvRAPC3biYw7yfY0T
+dD5pdK+V6PTOdv2Nfvev8QJPGsy1bcD7qowKaI7ThrMRrrGSmwz5ciU+VLaTcUP/
+u8H22Wq+nZZGDtzmAgmHLZzOt79QlBDGsO4y15mss46AKan+ameI+iUjrRzSxZAO
+uT+YHPezWE6M8lYSntvmDFxxhkrdHC8qDsmI+AChs+ELu30zsbbj7fdH1esS9/7q
+PLfd0rHv3H3IfR7nvr0wIyX7DIUI3DhuGRvnRS8wAQKBgQD9vrzppukAIfoawlQW
+XFhDFAC89nReMx7T1r68E8VU4Ng/61KeV+sP269jbPHC0K2/bzHbth4im05oZkcZ
+ZaPWeKGmYCUr+lnV6148iFPeVKX4KROvsgIvJ4LVpJUNO4V5Jg2jQcVlkPN2yc7G
+EssVH4ywREedtCFMui1lGJ46wQKBgQDsgFXP/EM0uijSWqZ2it/tdFeeS7F3Uu+V
+2vErnP/xH8i1BkV2t8sLYeAVNW7fEmHcEx3DrZJ2yH3J3h7MivY5g5su1iXHHcRn
+ux9bnb6uzKYS8PRxVnJVjSg9X9q1q6Tsh6Dia5wKHf60rX3MEi7UsJ36uKNKeC3H
++4zh5tq+iwKBgQDQjbmlbRsqkcKHxdro+gNNNp6YsRPZ7LhUsrbXzIQvDBKRDrA8
+FtTLlutjk8JtNajoo9Ld26SPGwjpw86CMEjl2QY7weArcjvuF+K/a+lK3lX/Tnuw
+t2UWLqpZQEmFs7szZLRmz4MXxHhm1N2PbRjfhqvSoHwgQVHxR0BSTFaYwQKBgQDQ
+8+Zdd4UtXdjZWcw/ah3En4kWS8xFH9qcbS+tl+4t7SYYgqz24hYcPWKNeoM1xfj+
+R0mB7KY+Go/AvmY51AEN+bAvJneEQFGaUKK5AFtL93Y3v/pI9NbZrXjDGSCUaE2z
+yXUk92yLJ8s1eR9vIRWNR2qc7WsgTaQtT5w+rwfPVwKBgQC3udM2j59yDCoAOk3g
+Myz3PU9I3gLk+yQ2yHWRjE0Cundr3zQ7PqlsITUe9xhUfj+soBsRw7yeg5/wYcVJ
+F3hDmAOFb54pW912sD9CQbkhJMX6oVuSegUghPrXDhgiJ9i3TArc9xOKoER4A1s6
+N10tV3NPQprnu2m4jTBykPUJBw==
+-----END PRIVATE KEY-----
diff --git a/tests/auto/core/qwebengineclientcertificatestore/resources/privatekey1.key b/tests/auto/core/qwebengineclientcertificatestore/resources/privatekey1.key
new file mode 100644
index 000000000..f4ae0d2d0
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/resources/privatekey1.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQC9pvbiJJnLoe5Y
+A6MCUryOYiTmj3PVdPpKMrBe2sdzvO0cx2NXpxWERK9QNnFaJb4fTY+j9fgvru1t
+sIH3AbnDbXfpEPSD4DmpSXiKgB2+KZhA82ZerJendxqaXaj2BgTG2Tc++Chk0wzx
+/3KRSb97mgPKJK5yNwx3KQjeXAhR5Mkwmmf+ZUfoYHRu4BNneYs7qX9rEPDlvrd3
+AaPTgjapz7EEnSO19BrZHgLWFsM0Kni2vux1jHq1wYRXRTaOG0MrNuvuHuNC2j5C
++N/MPcuuN9izbshrlteIi2a4526V4Hp1KX1BKAI2LgI+ufzdDEkuPs/u28J7tGiX
+jAmf4YUBAgMBAAECggEADLcnEl512UtQGaKUyVEWx00ZQEQZ9hPTvCnN3W45tS7T
+jvxnUrcnICkiv/QGgY7KQnsGyG1zaG8ICDSvYgpBlDLAuWWjnzvnYcxFQrP4Somr
+ZZ9sG6jiuh2oMPVaoLQimdpyc8xbmPb1hTwlSExzhCv9WQ5Ai/PY6BxeNdphzGu2
+sNXm0+BBiwX+UdoVYg9nNEzJe8x1xKIjIw4CWk61ZclLsoScjNOZE7RJ3oqXeYnw
+EqBVqAJTZHYpS3e1LxsstOsZfI4kxdbnGjBydz1aHSP19tycY39kUFmjNq6oiSlv
+22+B1WdZ87POXTF0ISL8l+9HIVOKBCeuDmZ+KgS7KQKBgQD6FunVLHxVtQPS2/e0
+yvtHFqSBHuzL2FMIt6vfl4VhQ6QZ5aNPhbGv1WNcb9Z3pqLPp7zRgIPz63l6yHDT
+xTJEjCAseMoJIb/7ji1/RYE1eOhf3ie1BAuAxjdZ8rNVliZ2i3bt5aOUf4MOQdqE
+HY3/yXqMr1qPJThbyTk4bB3V1wKBgQDCImT4UvQqheMFF9Yev6MhUljm9XOjamk/
+v54pW4De7NR2J+4dR+enEHeO0EKCE+olAXfGztChbY4ytkW5bh5BndGCiYLq6NdS
+X4a1Bf1pM6y9/+QxHIQ99G+TGyfoiTmMT1eZNXZAF4MZN36Qe/Y0P9YlJmnRXDY9
+n8yM4+Tw5wKBgHGr0ITQP4NFT4Ob768BQ81AAW2e/Mp6fONNeJWcbUeUUxZiRiRz
+BByDxTHSs4yW9RGlkDE5VMCdmw2v5Xib/QkjF8ye6lXUPUq9iPh8Qwpm9lf8xdeF
+CyVw8t+zbMfOA5WGNnxTEFMC0jK8w/Gg7VYB4e3oFiVSKZeuko+OtNDpAoGAWFwZ
+QuFW2sfnpVjND1/AGxmE91I+mOGFGAvaLA7G4DBBH6pa+Z7RtDuNf0YRD22LA97g
+Km/Vi7P2peRKZfTV9p2jT1vRZ6Qk5QwvntMkHS707+G5dhT5p81Kv1T73B4hQFiY
+kVZBBTjuZZrZk1+olu17RZtvTGhBE9lY28OaX38CgYEAirReFhouOZc7Ng9gCfTM
+XYzIVZszQ8l8dD2fPhbYw9qSRNvST28s4lLtyRPvoKCpmlUMm5F6Xb65rvICMxc3
+DPnB9iLY6fLY7tETVeV9DEOXki3hoZQ4qkI7OIVbZQn1rA1Du95ZZEGdgE5eEMOC
+SQ9g3B7NYJT3Zs8rkxKajWM=
+-----END PRIVATE KEY-----
diff --git a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp
new file mode 100644
index 000000000..6d51bf7af
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.cpp
@@ -0,0 +1,98 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#include <QtTest/QtTest>
+#include <QtWebEngineCore/qwebengineclientcertificatestore.h>
+#include <QtWebEngineWidgets/qwebengineprofile.h>
+
+class tst_QWebEngineClientCertificateStore : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWebEngineClientCertificateStore();
+ ~tst_QWebEngineClientCertificateStore();
+
+private Q_SLOTS:
+ void addAndListCertificates();
+ void removeAndClearCertificates();
+};
+
+tst_QWebEngineClientCertificateStore::tst_QWebEngineClientCertificateStore()
+{
+}
+
+tst_QWebEngineClientCertificateStore::~tst_QWebEngineClientCertificateStore()
+{
+}
+
+void tst_QWebEngineClientCertificateStore::addAndListCertificates()
+{
+ // Load QSslCertificate
+ QFile certFile(":/resources/certificate.crt");
+ certFile.open(QIODevice::ReadOnly);
+ const QSslCertificate cert(certFile.readAll(), QSsl::Pem);
+
+ // Load QSslKey
+ QFile keyFile(":/resources/privatekey.key");
+ keyFile.open(QIODevice::ReadOnly);
+ const QSslKey sslKey(keyFile.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "");
+
+ // Load second QSslCertificate
+ QFile certFileSecond(":/resources/certificate1.crt");
+ certFileSecond.open(QIODevice::ReadOnly);
+ const QSslCertificate certSecond(certFileSecond.readAll(), QSsl::Pem);
+
+ // Load second QSslKey
+ QFile keyFileSecond(":/resources/privatekey1.key");
+ keyFileSecond.open(QIODevice::ReadOnly);
+ const QSslKey sslKeySecond(keyFileSecond.readAll(), QSsl::Rsa, QSsl::Pem, QSsl::PrivateKey, "");
+
+ // Add certificates to in-memory store
+ QWebEngineProfile::defaultProfile()->clientCertificateStore()->add(cert, sslKey);
+ QWebEngineProfile::defaultProfile()->clientCertificateStore()->add(certSecond, sslKeySecond);
+
+ QCOMPARE(2, QWebEngineProfile::defaultProfile()->clientCertificateStore()->certificates().length());
+}
+
+void tst_QWebEngineClientCertificateStore::removeAndClearCertificates()
+{
+ QCOMPARE(2, QWebEngineProfile::defaultProfile()->clientCertificateStore()->certificates().length());
+
+ // Remove one certificate from in-memory store
+ auto list = QWebEngineProfile::defaultProfile()->clientCertificateStore()->certificates();
+ QWebEngineProfile::defaultProfile()->clientCertificateStore()->remove(list[0]);
+ QCOMPARE(1, QWebEngineProfile::defaultProfile()->clientCertificateStore()->certificates().length());
+
+ // Remove all certificates in-memory store
+ QWebEngineProfile::defaultProfile()->clientCertificateStore()->clear();
+ QCOMPARE(0, QWebEngineProfile::defaultProfile()->clientCertificateStore()->certificates().length());
+}
+
+QTEST_MAIN(tst_QWebEngineClientCertificateStore)
+#include "tst_qwebengineclientcertificatestore.moc"
diff --git a/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.qrc b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.qrc
new file mode 100644
index 000000000..db481fef6
--- /dev/null
+++ b/tests/auto/core/qwebengineclientcertificatestore/tst_qwebengineclientcertificatestore.qrc
@@ -0,0 +1,8 @@
+<RCC>
+ <qresource prefix="/">
+ <file>resources/certificate.crt</file>
+ <file>resources/privatekey.key</file>
+ <file>resources/certificate1.crt</file>
+ <file>resources/privatekey1.key</file>
+ </qresource>
+</RCC>
diff --git a/tests/auto/quick/publicapi/tst_publicapi.cpp b/tests/auto/quick/publicapi/tst_publicapi.cpp
index 5d869c14f..3e5d24381 100644
--- a/tests/auto/quick/publicapi/tst_publicapi.cpp
+++ b/tests/auto/quick/publicapi/tst_publicapi.cpp
@@ -100,6 +100,7 @@ static const QStringList hardcodedTypes = QStringList()
<< "QQuickWebEngineErrorPage*"
<< "const QQuickWebEngineContextMenuData*"
<< "QWebEngineCookieStore*"
+ << "Qt::LayoutDirection"
;
static const QStringList expectedAPI = QStringList()
@@ -140,10 +141,41 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineCertificateError.overridable --> bool"
<< "QQuickWebEngineCertificateError.rejectCertificate() --> void"
<< "QQuickWebEngineCertificateError.url --> QUrl"
+ << "QQuickWebEngineClientCertificateOption.issuer --> QString"
+ << "QQuickWebEngineClientCertificateOption.subject --> QString"
+ << "QQuickWebEngineClientCertificateOption.effectiveDate --> QDateTime"
+ << "QQuickWebEngineClientCertificateOption.expiryDate --> QDateTime"
+ << "QQuickWebEngineClientCertificateOption.isSelfSigned --> bool"
+ << "QQuickWebEngineClientCertificateOption.select() --> void"
+ << "QQuickWebEngineClientCertificateSelection.host --> QUrl"
+ << "QQuickWebEngineClientCertificateSelection.certificates --> QQmlListProperty<QQuickWebEngineClientCertificateOption>"
+ << "QQuickWebEngineClientCertificateSelection.select(int) --> void"
+ << "QQuickWebEngineClientCertificateSelection.select(const QQuickWebEngineClientCertificateOption*) --> void"
+ << "QQuickWebEngineClientCertificateSelection.selectNone() --> void"
<< "QQuickWebEngineColorDialogRequest.accepted --> bool"
<< "QQuickWebEngineColorDialogRequest.color --> QColor"
+ << "QQuickWebEngineContextMenuRequest.CanUndo --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanRedo --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanCut --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanCopy --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanPaste --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanDelete --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanSelectAll --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanTranslate --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.CanEditRichly --> EditFlags"
<< "QQuickWebEngineColorDialogRequest.dialogAccept(QColor) --> void"
<< "QQuickWebEngineColorDialogRequest.dialogReject() --> void"
+ << "QQuickWebEngineContextMenuRequest.editFlags --> EditFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaInError --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaPaused --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaMuted --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaLoop --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanSave --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaHasAudio --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanToggleControls --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaControls --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanPrint --> MediaFlags"
+ << "QQuickWebEngineContextMenuRequest.MediaCanRotate --> MediaFlags"
<< "QQuickWebEngineContextMenuRequest.MediaTypeAudio --> MediaType"
<< "QQuickWebEngineContextMenuRequest.MediaTypeCanvas --> MediaType"
<< "QQuickWebEngineContextMenuRequest.MediaTypeFile --> MediaType"
@@ -155,6 +187,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineContextMenuRequest.isContentEditable --> bool"
<< "QQuickWebEngineContextMenuRequest.linkText --> QString"
<< "QQuickWebEngineContextMenuRequest.linkUrl --> QUrl"
+ << "QQuickWebEngineContextMenuRequest.mediaFlags --> MediaFlags"
<< "QQuickWebEngineContextMenuRequest.mediaType --> MediaType"
<< "QQuickWebEngineContextMenuRequest.mediaUrl --> QUrl"
<< "QQuickWebEngineContextMenuRequest.misspelledWord --> QString"
@@ -226,6 +259,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineDownloadItem.totalBytesChanged() --> void"
<< "QQuickWebEngineDownloadItem.type --> DownloadType"
<< "QQuickWebEngineDownloadItem.typeChanged() --> void"
+ << "QQuickWebEngineDownloadItem.view --> QQuickWebEngineView*"
<< "QQuickWebEngineFileDialogRequest.FileModeOpen --> FileMode"
<< "QQuickWebEngineFileDialogRequest.FileModeOpenMultiple --> FileMode"
<< "QQuickWebEngineFileDialogRequest.FileModeSave --> FileMode"
@@ -296,6 +330,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineProfile.clearHttpCache() --> void"
<< "QQuickWebEngineProfile.downloadFinished(QQuickWebEngineDownloadItem*) --> void"
<< "QQuickWebEngineProfile.downloadRequested(QQuickWebEngineDownloadItem*) --> void"
+ << "QQuickWebEngineProfile.downloadPath --> QString"
+ << "QQuickWebEngineProfile.downloadPathChanged() --> void"
<< "QQuickWebEngineProfile.userNotification(QWebEngineNotification*) --> void"
<< "QQuickWebEngineProfile.httpAcceptLanguage --> QString"
<< "QQuickWebEngineProfile.httpAcceptLanguageChanged() --> void"
@@ -317,6 +353,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineProfile.spellCheckLanguagesChanged() --> void"
<< "QQuickWebEngineProfile.storageName --> QString"
<< "QQuickWebEngineProfile.storageNameChanged() --> void"
+ << "QQuickWebEngineProfile.useForGlobalCertificateVerification --> bool"
+ << "QQuickWebEngineProfile.useForGlobalCertificateVerificationChanged() --> void"
<< "QQuickWebEngineProfile.userScripts --> QQmlListProperty<QQuickWebEngineScript>"
<< "QQuickWebEngineScript.ApplicationWorld --> ScriptWorldId"
<< "QQuickWebEngineScript.Deferred --> InjectionPoint"
@@ -360,6 +398,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineSettings.autoLoadImagesChanged() --> void"
<< "QQuickWebEngineSettings.defaultTextEncoding --> QString"
<< "QQuickWebEngineSettings.defaultTextEncodingChanged() --> void"
+ << "QQuickWebEngineSettings.dnsPrefetchEnabled --> bool"
+ << "QQuickWebEngineSettings.dnsPrefetchEnabledChanged() --> void"
<< "QQuickWebEngineSettings.errorPageEnabled --> bool"
<< "QQuickWebEngineSettings.errorPageEnabledChanged() --> void"
<< "QQuickWebEngineSettings.focusOnNavigationEnabled --> bool"
@@ -372,6 +412,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineSettings.javascriptCanAccessClipboardChanged() --> void"
<< "QQuickWebEngineSettings.javascriptCanOpenWindows --> bool"
<< "QQuickWebEngineSettings.javascriptCanOpenWindowsChanged() --> void"
+ << "QQuickWebEngineSettings.javascriptCanPaste --> bool"
+ << "QQuickWebEngineSettings.javascriptCanPasteChanged() --> void"
<< "QQuickWebEngineSettings.javascriptEnabled --> bool"
<< "QQuickWebEngineSettings.javascriptEnabledChanged() --> void"
<< "QQuickWebEngineSettings.linksIncludedInFocusChain --> bool"
@@ -382,6 +424,8 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineSettings.localContentCanAccessRemoteUrlsChanged() --> void"
<< "QQuickWebEngineSettings.localStorageEnabled --> bool"
<< "QQuickWebEngineSettings.localStorageEnabledChanged() --> void"
+ << "QQuickWebEngineSettings.pdfViewerEnabled --> bool"
+ << "QQuickWebEngineSettings.pdfViewerEnabledChanged() --> void"
<< "QQuickWebEngineSettings.playbackRequiresUserGesture --> bool"
<< "QQuickWebEngineSettings.playbackRequiresUserGestureChanged() --> void"
<< "QQuickWebEngineSettings.pluginsEnabled --> bool"
@@ -667,6 +711,7 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.navigationRequested(QQuickWebEngineNavigationRequest*) --> void"
<< "QQuickWebEngineView.newViewRequested(QQuickWebEngineNewViewRequest*) --> void"
<< "QQuickWebEngineView.pdfPrintingFinished(QString,bool) --> void"
+ << "QQuickWebEngineView.printRequested() --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue) --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId) --> void"
<< "QQuickWebEngineView.printToPdf(QJSValue,PrintedPageSizeId,PrintedPageOrientation) --> void"
@@ -689,11 +734,14 @@ static const QStringList expectedAPI = QStringList()
<< "QQuickWebEngineView.runJavaScript(QString,uint,QJSValue) --> void"
<< "QQuickWebEngineView.scrollPosition --> QPointF"
<< "QQuickWebEngineView.scrollPositionChanged(QPointF) --> void"
+ << "QQuickWebEngineView.selectClientCertificate(QQuickWebEngineClientCertificateSelection*) --> void"
<< "QQuickWebEngineView.setActiveFocusOnPress(bool) --> void"
<< "QQuickWebEngineView.settings --> QQuickWebEngineSettings*"
<< "QQuickWebEngineView.stop() --> void"
+#if QT_CONFIG(webengine_testsupport)
<< "QQuickWebEngineView.testSupport --> QQuickWebEngineTestSupport*"
<< "QQuickWebEngineView.testSupportChanged() --> void"
+#endif
<< "QQuickWebEngineView.title --> QString"
<< "QQuickWebEngineView.titleChanged() --> void"
<< "QQuickWebEngineView.tooltipRequested(QQuickWebEngineTooltipRequest*) --> void"
@@ -722,10 +770,7 @@ static const QStringList expectedAPI = QStringList()
<< "QWebEngineNotification.message --> QString"
<< "QWebEngineNotification.tag --> QString"
<< "QWebEngineNotification.language --> QString"
- << "QWebEngineNotification.direction --> Direction"
- << "QWebEngineNotification.LeftToRight --> Direction"
- << "QWebEngineNotification.RightToLeft --> Direction"
- << "QWebEngineNotification.DirectionAuto --> Direction"
+ << "QWebEngineNotification.direction --> Qt::LayoutDirection"
<< "QWebEngineNotification.show() --> void"
<< "QWebEngineNotification.click() --> void"
<< "QWebEngineNotification.close() --> void"
@@ -824,18 +869,23 @@ void tst_publicapi::publicAPI()
// for (const QString &actual : qAsConst(sortedAPI))
// printf(" << \"%s\"\n", qPrintable(actual));
+ bool apiMatch = true;
// Make sure that nothing slips in the public API unintentionally.
for (const QString &actual : qAsConst(actualAPI)) {
- if (!expectedAPI.contains(actual))
- QEXPECT_FAIL("", qPrintable("Expected list is not up-to-date: " + actual), Continue);
- QVERIFY2(expectedAPI.contains(actual), qPrintable(actual));
+ if (!expectedAPI.contains(actual)) {
+ QWARN(qPrintable("Expected list is not up-to-date: " + actual));
+ apiMatch = false;
+ }
}
// Make sure that the expected list is up-to-date with intentionally added APIs.
for (const QString &expected : expectedAPI) {
- if (!actualAPI.contains(expected))
- QEXPECT_FAIL("", qPrintable("Not implemented: " + expected), Continue);
- QVERIFY2(actualAPI.contains(expected), qPrintable(expected));
+ if (!actualAPI.contains(expected)) {
+ apiMatch = false;
+ QWARN(qPrintable("Not implemented: " + expected));
+ }
}
+
+ QVERIFY2(apiMatch, "Unexpected, missing or misspelled API!");
}
QTEST_MAIN(tst_publicapi)
diff --git a/tests/auto/quick/qmltests/data/tst_favicon.qml b/tests/auto/quick/qmltests/data/tst_favicon.qml
index 563a87c83..50a412384 100644
--- a/tests/auto/quick/qmltests/data/tst_favicon.qml
+++ b/tests/auto/quick/qmltests/data/tst_favicon.qml
@@ -375,5 +375,38 @@ TestWebEngineView {
faviconImage.destroy()
}
+
+ function test_touchIconWithSameURL()
+ {
+ WebEngine.settings.touchIconsEnabled = false;
+
+ var icon = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=";
+
+ webEngineView.loadHtml(
+ "<html>" +
+ "<link rel='icon' type='image/png' href='" + icon + "'/>" +
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>" +
+ "</html>"
+ );
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // The default favicon has to be loaded even if its URL is also set as a touch icon while touch icons are disabled.
+ tryCompare(iconChangedSpy, "count", 1);
+ compare(webEngineView.icon.toString().replace(/^image:\/\/favicon\//, ''), icon);
+
+ iconChangedSpy.clear();
+
+ webEngineView.loadHtml(
+ "<html>" +
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>" +
+ "</html>"
+ );
+ verify(webEngineView.waitForLoadSucceeded());
+
+ // This page only has a touch icon. With disabled touch icons we don't expect any icon to be shown even if the same icon
+ // was loaded previously.
+ tryCompare(iconChangedSpy, "count", 1);
+ verify(!webEngineView.icon.toString().replace(/^image:\/\/favicon\//, ''));
+ }
}
}
diff --git a/tests/auto/quick/qmltests/data/tst_notification.qml b/tests/auto/quick/qmltests/data/tst_notification.qml
index 609a04f61..af4aebafc 100644
--- a/tests/auto/quick/qmltests/data/tst_notification.qml
+++ b/tests/auto/quick/qmltests/data/tst_notification.qml
@@ -37,6 +37,7 @@ TestWebEngineView {
property bool permissionRequested: false
property bool grantPermission: false
+ property url securityOrigin: ''
signal consoleMessage(string message)
@@ -48,7 +49,8 @@ TestWebEngineView {
onFeaturePermissionRequested: {
if (feature === WebEngineView.Notifications) {
- permissionRequested = true
+ view.permissionRequested = true
+ view.securityOrigin = securityOrigin
view.grantFeaturePermission(securityOrigin, feature, grantPermission)
}
}
@@ -111,6 +113,10 @@ TestWebEngineView {
tryVerify(function () { return notification !== null })
compare(notification.title, title)
compare(notification.message, message)
+ compare(notification.direction, Qt.RightToLeft)
+ compare(notification.origin, securityOrigin)
+ compare(notification.tag, 'tst')
+ compare(notification.language, 'de')
}
}
}
diff --git a/tests/auto/quick/quick.pro b/tests/auto/quick/quick.pro
index 46dd57f76..81b62b4e7 100644
--- a/tests/auto/quick/quick.pro
+++ b/tests/auto/quick/quick.pro
@@ -18,4 +18,4 @@ qtConfig(webengine-testsupport) {
}
# QTBUG-66055
-boot2qt: SUBDIRS -= inspectorserver qquickwebenginedefaultsurfaceformat qquickwebengineview qmltests dialogs qtbug-70248
+boot2qt: SUBDIRS -= inspectorserver qquickwebengineview qmltests
diff --git a/tests/auto/shared/data/notification.html b/tests/auto/shared/data/notification.html
index cadcbd942..1d1e9c411 100644
--- a/tests/auto/shared/data/notification.html
+++ b/tests/auto/shared/data/notification.html
@@ -8,7 +8,7 @@
function getPermission() { return document.Notification }
function sendNotification(title, body) {
- let notification = new Notification(title, { body: body })
+ let notification = new Notification(title, { body: body, dir: 'rtl', lang: 'de', tag: 'tst' })
notification.onclick = function() { console.info('onclick') }
notification.onclose = function() { console.info('onclose') }
notification.onerror = function(error) { console.info('onerror: ' + error) }
diff --git a/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp b/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp
index 606d05d9e..540c8d505 100644
--- a/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp
+++ b/tests/auto/widgets/faviconmanager/tst_faviconmanager.cpp
@@ -62,6 +62,7 @@ private Q_SLOTS:
void downloadTouchIconsEnabled_data();
void downloadTouchIconsEnabled();
void dynamicFavicon();
+ void touchIconWithSameURL();
private:
QWebEngineView *m_view;
@@ -508,6 +509,43 @@ void tst_FaviconManager::dynamicFavicon()
}
}
+void tst_FaviconManager::touchIconWithSameURL()
+{
+ m_page->settings()->setAttribute(QWebEngineSettings::TouchIconsEnabled, false);
+
+ const QString icon("data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNk+A8AAQUBAScY42YAAAAASUVORK5CYII=");
+ QSignalSpy loadFinishedSpy(m_page, SIGNAL(loadFinished(bool)));
+ QSignalSpy iconUrlChangedSpy(m_page, SIGNAL(iconUrlChanged(QUrl)));
+ QSignalSpy iconChangedSpy(m_page, SIGNAL(iconChanged(QIcon)));
+
+ m_page->setHtml("<html>"
+ "<link rel='icon' type='image/png' href='" + icon + "'/>"
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>"
+ "</html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ // The default favicon has to be loaded even if its URL is also set as a touch icon while touch icons are disabled.
+ QTRY_COMPARE(iconUrlChangedSpy.count(), 1);
+ QCOMPARE(m_page->iconUrl().toString(), icon);
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+
+ loadFinishedSpy.clear();
+ iconUrlChangedSpy.clear();
+ iconChangedSpy.clear();
+
+ m_page->setHtml("<html>"
+ "<link rel='apple-touch-icon' type='image/png' href='" + icon + "'/>"
+ "</html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ // This page only has a touch icon. With disabled touch icons we don't expect any icon to be shown even if the same icon
+ // was loaded previously.
+ QTRY_COMPARE(iconUrlChangedSpy.count(), 1);
+ QVERIFY(m_page->iconUrl().toString().isEmpty());
+ QTRY_COMPARE(iconChangedSpy.count(), 1);
+
+}
+
QTEST_MAIN(tst_FaviconManager)
#include "tst_faviconmanager.moc"
diff --git a/tests/auto/widgets/offscreen/offscreen.pro b/tests/auto/widgets/offscreen/offscreen.pro
new file mode 100644
index 000000000..b8e5632f9
--- /dev/null
+++ b/tests/auto/widgets/offscreen/offscreen.pro
@@ -0,0 +1,6 @@
+include(../tests.pri)
+QT += webengine
+qpa.name = QT_QPA_PLATFORM
+qpa.value = offscreen
+QT_TOOL_ENV += qpa
+
diff --git a/tests/auto/widgets/offscreen/tst_offscreen.cpp b/tests/auto/widgets/offscreen/tst_offscreen.cpp
new file mode 100644
index 000000000..98cbe55fe
--- /dev/null
+++ b/tests/auto/widgets/offscreen/tst_offscreen.cpp
@@ -0,0 +1,60 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#include "qtwebengineglobal.h"
+#include <QTest>
+#include <QSignalSpy>
+#include <QWebEngineProfile>
+#include <QWebEnginePage>
+#include <QWebEngineView>
+
+class tst_OffScreen : public QObject {
+ Q_OBJECT
+public:
+ tst_OffScreen(){}
+
+private slots:
+ void offscreen();
+};
+
+void tst_OffScreen::offscreen()
+{
+ QWebEngineProfile profile;
+ QWebEnginePage page(&profile);
+ QWebEngineView view;
+ QSignalSpy loadFinishedSpy(&page, SIGNAL(loadFinished(bool)));
+ view.setPage(&page);
+ page.load(QUrl("http://qt.io"));
+ view.show();
+ QTRY_COMPARE(view.isVisible(), true);
+ QTRY_COMPARE_WITH_TIMEOUT(loadFinishedSpy.count() > 0, true, 20000);
+}
+
+#include "tst_offscreen.moc"
+QTEST_MAIN(tst_OffScreen)
+
diff --git a/tests/auto/widgets/proxy/proxy.pro b/tests/auto/widgets/proxy/proxy.pro
new file mode 100644
index 000000000..802dfad05
--- /dev/null
+++ b/tests/auto/widgets/proxy/proxy.pro
@@ -0,0 +1,9 @@
+include(../tests.pri)
+QT += core-private webengine webengine-private
+
+HEADERS += \
+ proxy_server.h
+
+SOURCES += \
+ proxy_server.cpp
+
diff --git a/tests/auto/widgets/proxy/proxy_server.cpp b/tests/auto/widgets/proxy/proxy_server.cpp
new file mode 100644
index 000000000..55f014914
--- /dev/null
+++ b/tests/auto/widgets/proxy/proxy_server.cpp
@@ -0,0 +1,90 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#include "proxy_server.h"
+#include <QDataStream>
+#include <QTcpSocket>
+#include <QDebug>
+
+ProxyServer::ProxyServer(QObject *parent) : QObject(parent)
+{
+ connect(&m_server, &QTcpServer::newConnection, this, &ProxyServer::handleNewConnection);
+}
+
+void ProxyServer::setCredentials(const QByteArray &user, const QByteArray password)
+{
+ m_auth.append(user);
+ m_auth.append(QChar(':'));
+ m_auth.append(password);
+ m_auth = m_auth.toBase64();
+}
+
+bool ProxyServer::isListening()
+{
+ return m_server.isListening();
+}
+
+void ProxyServer::run()
+{
+ if (!m_server.listen(QHostAddress::LocalHost, 5555))
+ qFatal("Could not start the test server");
+}
+
+void ProxyServer::handleNewConnection()
+{
+ // do one connection at the time
+ Q_ASSERT(m_data.isEmpty());
+ QTcpSocket *socket = m_server.nextPendingConnection();
+ Q_ASSERT(socket);
+ connect(socket, &QAbstractSocket::disconnected, socket, &QObject::deleteLater);
+ connect(socket, &QAbstractSocket::readyRead, this, &ProxyServer::handleReadReady);
+}
+
+void ProxyServer::handleReadReady()
+{
+ QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender());
+ Q_ASSERT(socket);
+
+ m_data.append(socket->readAll());
+
+ if (!m_data.endsWith("\r\n\r\n"))
+ return;
+
+ if (!m_data.contains(QByteArrayLiteral("Proxy-Authorization: Basic"))) {
+ socket->write("HTTP/1.1 407 Proxy Authentication Required\nProxy-Authenticate: "
+ "Basic realm=\"Proxy requires authentication\"\r\n"
+ "content-length: 0\r\n"
+ "\r\n");
+ return;
+ }
+
+ if (m_data.contains(m_auth)) {
+ emit success();
+ }
+ m_data.clear();
+}
diff --git a/tests/auto/widgets/proxy/proxy_server.h b/tests/auto/widgets/proxy/proxy_server.h
new file mode 100644
index 000000000..cb7c30600
--- /dev/null
+++ b/tests/auto/widgets/proxy/proxy_server.h
@@ -0,0 +1,59 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#ifndef PROXY_SERVER_H
+#define PROXY_SERVER_H
+
+#include <QObject>
+#include <QTcpServer>
+
+class ProxyServer : public QObject
+{
+ Q_OBJECT
+
+public:
+ explicit ProxyServer(QObject *parent = nullptr);
+ void setCredentials(const QByteArray &user, const QByteArray password);
+ bool isListening();
+
+public slots:
+ void run();
+
+private slots:
+ void handleNewConnection();
+ void handleReadReady();
+
+signals:
+ void success();
+private:
+ QByteArray m_data;
+ QTcpServer m_server;
+ QByteArray m_auth;
+};
+
+#endif // PROXY_SERVER_H
diff --git a/tests/auto/widgets/proxy/tst_proxy.cpp b/tests/auto/widgets/proxy/tst_proxy.cpp
new file mode 100644
index 000000000..5f5dec016
--- /dev/null
+++ b/tests/auto/widgets/proxy/tst_proxy.cpp
@@ -0,0 +1,69 @@
+/****************************************************************************
+**
+** Copyright (C) 2019 The Qt Company Ltd.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the QtWebEngine module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE: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$
+**
+****************************************************************************/
+
+#include "proxy_server.h"
+#include <QTest>
+#include <QSignalSpy>
+#include <QNetworkProxy>
+#include <QWebEnginePage>
+#include <QWebEngineView>
+
+
+class tst_Proxy : public QObject {
+ Q_OBJECT
+public:
+ tst_Proxy(){}
+
+private slots:
+ void proxyAuthentication();
+};
+
+void tst_Proxy::proxyAuthentication()
+{
+ QByteArray user(QByteArrayLiteral("test"));
+ QByteArray password(QByteArrayLiteral("pass"));
+ QNetworkProxy proxy;
+ proxy.setType(QNetworkProxy::HttpProxy);
+ proxy.setHostName("localhost");
+ proxy.setPort(5555);
+ proxy.setUser(user);
+ proxy.setPassword(password);
+ QNetworkProxy::setApplicationProxy(proxy);
+ ProxyServer server;
+ server.setCredentials(user,password);
+ server.run();
+ QTRY_VERIFY2(server.isListening(), "Could not setup authentication server");
+ QWebEnginePage page;
+ QSignalSpy successSpy(&server, &ProxyServer::success);
+ page.load(QUrl("http://www.qt.io"));
+ QTRY_VERIFY2(successSpy.count() > 0, "Could not get authentication token");
+}
+
+#include "tst_proxy.moc"
+QTEST_MAIN(tst_Proxy)
+
diff --git a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
index 32823d30d..ee1e6ee04 100644
--- a/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
+++ b/tests/auto/widgets/qwebenginedownloaditem/tst_qwebenginedownloaditem.cpp
@@ -70,6 +70,7 @@ private Q_SLOTS:
void downloadFileNot1();
void downloadFileNot2();
void downloadDeleted();
+ void downloadDeletedByProfile();
void downloadUniqueFilename_data();
void downloadUniqueFilename();
void downloadUniqueFileNameWithTimeStamp();
@@ -821,6 +822,37 @@ void tst_QWebEngineDownloadItem::downloadDeleted()
QTRY_COMPARE(finishedCount, 1);
}
+void tst_QWebEngineDownloadItem::downloadDeletedByProfile()
+{
+ m_server->setExpectError(true);
+
+ QPointer<QWebEngineProfile> profile(new QWebEngineProfile);
+ profile->setHttpCacheType(QWebEngineProfile::NoCache);
+ profile->settings()->setAttribute(QWebEngineSettings::AutoLoadIconsForPage, false);
+
+ bool downloadFinished = false;
+ QPointer<QWebEngineDownloadItem> downloadItem;
+ connect(profile, &QWebEngineProfile::downloadRequested, [&] (QWebEngineDownloadItem *item) {
+ connect(item, &QWebEngineDownloadItem::finished, [&] () {
+ downloadFinished = true;
+ });
+ downloadItem = item;
+ item->accept();
+ });
+
+ QPointer<QWebEnginePage> page(new QWebEnginePage(profile));
+ page->download(m_server->url(QByteArrayLiteral("/file")));
+
+ QTRY_COMPARE(downloadItem.isNull(), false);
+ QVERIFY(downloadItem);
+
+ page->deleteLater();
+ profile->deleteLater();
+
+ QTRY_COMPARE(downloadFinished, true);
+ QTRY_COMPARE(downloadItem.isNull(), true);
+}
+
void tst_QWebEngineDownloadItem::downloadUniqueFilename_data()
{
QTest::addColumn<QString>("baseName");
diff --git a/tests/auto/widgets/qwebenginepage/BLACKLIST b/tests/auto/widgets/qwebenginepage/BLACKLIST
index 228efd61c..f3dc51fdd 100644
--- a/tests/auto/widgets/qwebenginepage/BLACKLIST
+++ b/tests/auto/widgets/qwebenginepage/BLACKLIST
@@ -1,9 +1,3 @@
-[comboBoxPopupPositionAfterMove]
-*
-
-[comboBoxPopupPositionAfterChildMove]
-*
-
[macCopyUnicodeToClipboard]
osx
diff --git a/tests/auto/widgets/qwebenginepage/resources/reload.html b/tests/auto/widgets/qwebenginepage/resources/reload.html
new file mode 100644
index 000000000..d9c33dfcd
--- /dev/null
+++ b/tests/auto/widgets/qwebenginepage/resources/reload.html
@@ -0,0 +1,8 @@
+<html>
+<head>
+<meta http-equiv="refresh" content="2">
+</head>
+<body>
+This is test content
+</body>
+</html>
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
index 0504d39fa..3792b5522 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.cpp
@@ -138,6 +138,7 @@ private Q_SLOTS:
void runJavaScript();
void runJavaScriptDisabled();
+ void runJavaScriptFromSlot();
void fullScreenRequested();
void quotaRequested();
@@ -561,11 +562,17 @@ void tst_QWebEnginePage::acceptNavigationRequestNavigationType()
QTRY_COMPARE(loadSpy.count(), 4);
QTRY_COMPARE(page.navigations.count(), 4);
+ page.load(QUrl("qrc:///resources/reload.html"));
+ QTRY_COMPARE(loadSpy.count(), 6);
+ QTRY_COMPARE(page.navigations.count(), 6);
+
QList<QWebEnginePage::NavigationType> expectedList;
expectedList << QWebEnginePage::NavigationTypeTyped
<< QWebEnginePage::NavigationTypeTyped
<< QWebEnginePage::NavigationTypeBackForward
- << QWebEnginePage::NavigationTypeReload;
+ << QWebEnginePage::NavigationTypeReload
+ << QWebEnginePage::NavigationTypeTyped
+ << QWebEnginePage::NavigationTypeOther;
QVERIFY(expectedList.count() == page.navigations.count());
for (int i = 0; i < expectedList.count(); ++i) {
QCOMPARE(page.navigations[i].type, expectedList[i]);
@@ -1008,9 +1015,8 @@ static QWindow *findNewTopLevelWindow(const QWindowList &oldTopLevelWindows)
void tst_QWebEnginePage::comboBoxPopupPositionAfterMove()
{
- QScreen *screen = QGuiApplication::primaryScreen();
QWebEngineView view;
- view.move(screen->availableGeometry().topLeft());
+ view.move(QGuiApplication::primaryScreen()->availableGeometry().topLeft());
view.resize(640, 480);
view.show();
@@ -1026,18 +1032,29 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterMove()
QWindow *popup = nullptr;
QTRY_VERIFY(popup = findNewTopLevelWindow(oldTlws));
+ QTRY_VERIFY(QGuiApplication::topLevelWindows().contains(popup));
+ QTRY_VERIFY(!popup->position().isNull());
QPoint popupPos = popup->position();
// Close the popup by clicking somewhere into the page.
QTest::mouseClick(window, Qt::LeftButton, Qt::KeyboardModifiers(), QPoint(1, 1));
QTRY_VERIFY(!QGuiApplication::topLevelWindows().contains(popup));
+ auto jsViewPosition = [&view]() {
+ QLatin1String script("(function() { return [window.screenX, window.screenY]; })()");
+ QVariantList posList = evaluateJavaScriptSync(view.page(), script).toList();
+ return QPoint(posList.at(0).toInt(), posList.at(1).toInt());
+ };
+
// Move the top-level QWebEngineView a little and check the popup's position.
const QPoint offset(12, 13);
- view.move(screen->availableGeometry().topLeft() + offset);
+ view.move(view.pos() + offset);
+ QTRY_COMPARE(jsViewPosition(), view.pos());
QTest::mouseClick(window, Qt::LeftButton, Qt::KeyboardModifiers(),
elementCenter(view.page(), "foo"));
QTRY_VERIFY(popup = findNewTopLevelWindow(oldTlws));
+ QTRY_VERIFY(QGuiApplication::topLevelWindows().contains(popup));
+ QTRY_VERIFY(!popup->position().isNull());
QCOMPARE(popupPos + offset, popup->position());
}
@@ -1047,7 +1064,6 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterChildMove()
mainWidget.setLayout(new QHBoxLayout);
QWidget spacer;
- spacer.setMinimumWidth(50);
mainWidget.layout()->addWidget(&spacer);
QWebEngineView view;
@@ -1070,6 +1086,8 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterChildMove()
QWindow *popup = nullptr;
QTRY_VERIFY(popup = findNewTopLevelWindow(oldTlws));
+ QTRY_VERIFY(QGuiApplication::topLevelWindows().contains(popup));
+ QTRY_VERIFY(!popup->position().isNull());
QPoint popupPos = popup->position();
// Close the popup by clicking somewhere into the page.
@@ -1077,11 +1095,22 @@ void tst_QWebEnginePage::comboBoxPopupPositionAfterChildMove()
view.mapTo(view.window(), QPoint(1, 1)));
QTRY_VERIFY(!QGuiApplication::topLevelWindows().contains(popup));
+ int originalViewWidth = view.size().width();
+ auto jsViewWidth = [&view]() {
+ QLatin1String script("(function() { return window.innerWidth; })()");
+ int viewWidth = evaluateJavaScriptSync(view.page(), script).toInt();
+ return viewWidth;
+ };
+
// Resize the "spacer" widget, and implicitly change the global position of the QWebEngineView.
- spacer.setMinimumWidth(100);
+ const int offset = 50;
+ spacer.setMinimumWidth(spacer.size().width() + offset);
+ QTRY_COMPARE(jsViewWidth(), originalViewWidth - offset);
+
QTest::mouseClick(window, Qt::LeftButton, Qt::KeyboardModifiers(),
view.mapTo(view.window(), elementCenter(view.page(), "foo")));
QTRY_VERIFY(popup = findNewTopLevelWindow(oldTlws));
+ QTRY_VERIFY(!popup->position().isNull());
QCOMPARE(popupPos + QPoint(50, 0), popup->position());
}
@@ -1644,6 +1673,28 @@ void tst_QWebEnginePage::runJavaScriptDisabled()
QVariant(2));
}
+// Based on https://bugreports.qt.io/browse/QTBUG-73876
+void tst_QWebEnginePage::runJavaScriptFromSlot()
+{
+ QWebEngineProfile profile;
+ QWebEnginePage page(&profile);
+
+ QSignalSpy loadFinishedSpy(&page, &QWebEnginePage::loadFinished);
+ page.setHtml("<html><body>"
+ " <input type='text' id='input1' value='QtWebEngine' size='50' />"
+ "</body></html>");
+ QTRY_COMPARE(loadFinishedSpy.count(), 1);
+
+ QVariant result(-1);
+ connect(&page, &QWebEnginePage::selectionChanged, [&]() {
+ result = evaluateJavaScriptSync(&page, QStringLiteral("2+2"));
+ });
+ evaluateJavaScriptSync(&page, QStringLiteral("const input = document.getElementById('input1');"
+ "input.focus();"
+ "input.select();"));
+ QTRY_COMPARE(result, QVariant(4));
+}
+
void tst_QWebEnginePage::fullScreenRequested()
{
JavaScriptCallbackWatcher watcher;
@@ -3284,10 +3335,13 @@ void tst_QWebEnginePage::sendNotification()
auto notification = presenter.waitForResult();
QVERIFY(presenter.wasCalled());
- QVERIFY(!notification.isNull());
+ QVERIFY(notification.isValid());
QCOMPARE(notification.title(), title);
QCOMPARE(notification.message(), message);
QCOMPARE(notification.origin(), origin);
+ QCOMPARE(notification.direction(), Qt::RightToLeft);
+ QCOMPARE(notification.language(), "de");
+ QCOMPARE(notification.tag(), "tst");
notification.show();
QTRY_VERIFY2(page.messages.contains("onshow"), page.messages.join("\n").toLatin1().constData());
diff --git a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
index 757e151c1..cf32486e7 100644
--- a/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
+++ b/tests/auto/widgets/qwebenginepage/tst_qwebenginepage.qrc
@@ -14,6 +14,7 @@
<file>resources/user.css</file>
<file>resources/image.png</file>
<file>resources/pasteimage.html</file>
+ <file>resources/reload.html</file>
<file>resources/style.css</file>
<file>resources/test1.html</file>
<file>resources/test2.html</file>
diff --git a/tests/auto/widgets/widgets.pro b/tests/auto/widgets/widgets.pro
index 0addb9671..15b3efd3b 100644
--- a/tests/auto/widgets/widgets.pro
+++ b/tests/auto/widgets/widgets.pro
@@ -8,7 +8,9 @@ SUBDIRS += \
devtools \
faviconmanager \
loadsignals \
+ offscreen \
origins \
+ proxy \
proxypac \
schemes \
shutdown \
@@ -38,7 +40,8 @@ qtConfig(webengine-spellchecker):!cross_compile {
# QTBUG-60268
boot2qt: SUBDIRS -= accessibility defaultsurfaceformat devtools \
- faviconmanager qwebenginepage qwebenginehistory \
- qwebengineprofile qwebenginescript \
- qwebengineview qwebenginedownloaditem qwebenginesettings \
- schemes origins loadsignals proxypac
+ qwebenginepage \
+ qwebengineprofile \
+ qwebengineview \
+ qwebenginescript \
+ proxypac offscreen