summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorYigit Akcay <yigit.akcay@qt.io>2023-03-14 17:31:11 +0100
committerYigit Akcay <yigit.akcay@qt.io>2023-04-28 00:52:19 +0200
commit6b3e7f2baa17a5bff7051949f743f2ec6926ec06 (patch)
tree2780164be712708f0018ff61306c872c2c033048
parenta2d0bb9ef69bb5d677d177d91dd9ad414b915436 (diff)
downloadqtwebengine-6b3e7f2baa17a5bff7051949f743f2ec6926ec06.tar.gz
Allow configuration of DNS-over-HTTPS
Implement QWebEngineGlobalSettings, a singleton class that contains global web engine settings (currently only for DoH). Allow the user to configure the stub host resolver to enable DNS-over-HTTPS. Fixes: QTBUG-98284 Change-Id: I1b06737c84e1b8d613aa257f4a891f82cac21013 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
-rw-r--r--src/core/api/CMakeLists.txt2
-rw-r--r--src/core/api/qwebengineglobalsettings.cpp92
-rw-r--r--src/core/api/qwebengineglobalsettings.h42
-rw-r--r--src/core/api/qwebengineglobalsettings_p.h43
-rw-r--r--src/core/net/system_network_context_manager.cpp36
-rw-r--r--src/core/net/system_network_context_manager.h4
-rw-r--r--tests/auto/core/CMakeLists.txt1
-rw-r--r--tests/auto/core/qwebengineglobalsettings/CMakeLists.txt29
-rw-r--r--tests/auto/core/qwebengineglobalsettings/cert/RootCA.pem20
-rw-r--r--tests/auto/core/qwebengineglobalsettings/cert/localhost.crt22
-rw-r--r--tests/auto/core/qwebengineglobalsettings/cert/localhost.key28
-rw-r--r--tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp107
-rw-r--r--tests/auto/httpserver/httpserver.h2
-rw-r--r--tests/auto/httpserver/httpsserver.h12
14 files changed, 429 insertions, 11 deletions
diff --git a/src/core/api/CMakeLists.txt b/src/core/api/CMakeLists.txt
index ba973fd32..32b3451bd 100644
--- a/src/core/api/CMakeLists.txt
+++ b/src/core/api/CMakeLists.txt
@@ -38,6 +38,7 @@ qt_internal_add_module(WebEngineCore
qwebengineurlrequestjob.cpp qwebengineurlrequestjob.h
qwebengineurlscheme.cpp qwebengineurlscheme.h
qwebengineurlschemehandler.cpp qwebengineurlschemehandler.h
+ qwebengineglobalsettings.cpp qwebengineglobalsettings.h qwebengineglobalsettings_p.h
DEFINES
BUILDING_CHROMIUM
NOMINMAX
@@ -46,6 +47,7 @@ qt_internal_add_module(WebEngineCore
../../3rdparty/chromium
../../3rdparty/chromium/third_party/abseil-cpp
../../3rdparty/chromium/third_party/perfetto/include
+ ../../3rdparty/chromium/third_party/boringssl/src/include
LIBRARIES
Qt::CorePrivate
Qt::GuiPrivate
diff --git a/src/core/api/qwebengineglobalsettings.cpp b/src/core/api/qwebengineglobalsettings.cpp
new file mode 100644
index 000000000..685d9d593
--- /dev/null
+++ b/src/core/api/qwebengineglobalsettings.cpp
@@ -0,0 +1,92 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include "services/network/network_service.h"
+#include "content/public/browser/network_service_instance.h"
+
+#include "qwebengineglobalsettings.h"
+#include "qwebengineglobalsettings_p.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QWebEngineGlobalSettings
+ \brief The QWebEngineGlobalSettings class configures global properties of the web engine.
+ \since 6.6
+ \inmodule QtWebEngineCore
+
+ The QWebEngineGlobalSettings class is a singleton that configures global properties
+ of the web engine.
+
+ Invoke configureDnsOverHttps() to configure DNS-over-HTTPS capabilities.
+
+ \sa QWebEngineGlobalSettings::configureDnsOverHttps()
+*/
+
+QWebEngineGlobalSettings::QWebEngineGlobalSettings(QObject *p)
+ : QObject(p), d_ptr(new QWebEngineGlobalSettingsPrivate)
+{
+}
+
+QWebEngineGlobalSettings::~QWebEngineGlobalSettings() { }
+
+/*!
+ \fn QWebEngineGlobalSettings *QWebEngineGlobalSettings::GetInstance()
+
+ Gets the global instance of QWebEngineGlobalSettings.
+*/
+QWebEngineGlobalSettings *QWebEngineGlobalSettings::GetInstance()
+{
+ static QWebEngineGlobalSettings settings;
+ return &settings;
+}
+
+/*!
+ \enum QWebEngineGlobalSettings::DnsMode
+
+ This enum sets the DNS-over-HTTPS mode:
+
+ \value WithFallback Enable DNS-over-HTTPS with fallbacks. If a host
+ can't be resolved, try the insecure DNS client of Chromium. If that fails as
+ well, try the system DNS host resolution, which can be secure or insecure.
+ \value Secure Enable DNS-over-HTTPS and only allow the secure Chromium
+ DNS client to resolve hosts.
+*/
+
+/*!
+ \fn QWebEngineGlobalSettings::configureDnsOverHttps(const DnsMode dnsMode,
+ const QString &dnsOverHttpsTemplates)
+
+ Configures the Chromium stub host resolver, thus allowing DNS-over-HTTPS functionality.
+
+ Set \a dnsMode to QWebEngineGlobalSettings::DnsMode::WithFallback to enable secure DNS
+ host resolution with a fallback to insecure DNS host resolution and a final fallback to
+ the system DNS resolution, which can be secure or insecure. Set it to
+ QWebEngineGlobalSettings::DnsMode::Secure to only allow secure DNS host resolution via
+ the Chromium DNS client.
+
+ Independently of \a {dnsMode}, \a dnsOverHttpsTemplates has to be set to one or multiple
+ valid \l{https://datatracker.ietf.org/doc/html/rfc6570}{URI templates} separated by
+ whitespace characters. One example URI template is https://dns.google/dns-query{?dns}.
+*/
+void QWebEngineGlobalSettings::configureDnsOverHttps(const DnsMode dnsMode,
+ const QString &dnsOverHttpsTemplates)
+{
+ Q_D(QWebEngineGlobalSettings);
+
+ d->dnsMode = dnsMode;
+ d->dnsOverHttpsTemplates = dnsOverHttpsTemplates.toStdString();
+ d->isDnsOverHttpsUserConfigured = true;
+
+ // Make sure that DoH settings are in effect immediately if the network service already exists,
+ // thus allowing to change DoH configuration at any point
+ network::mojom::NetworkService *networkService = content::GetNetworkService();
+ if (networkService) {
+ networkService->ConfigureStubHostResolver(
+ d->insecureDnsClientEnabled, net::SecureDnsMode(d->dnsMode),
+ *net::DnsOverHttpsConfig::FromString(d->dnsOverHttpsTemplates),
+ d->additionalInsecureDnsTypesEnabled);
+ }
+}
+
+QT_END_NAMESPACE
diff --git a/src/core/api/qwebengineglobalsettings.h b/src/core/api/qwebengineglobalsettings.h
new file mode 100644
index 000000000..a65a08359
--- /dev/null
+++ b/src/core/api/qwebengineglobalsettings.h
@@ -0,0 +1,42 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWEBENGINEGLOBALSETTINGS_H
+#define QWEBENGINEGLOBALSETTINGS_H
+
+#include <QtWebEngineCore/qtwebenginecoreglobal.h>
+#include <QtCore/QObject>
+#include <QtCore/QScopedPointer>
+
+namespace QtWebEngineCore {
+class SystemNetworkContextManager;
+}
+
+QT_BEGIN_NAMESPACE
+
+class QWebEngineGlobalSettingsPrivate;
+
+class Q_WEBENGINECORE_EXPORT QWebEngineGlobalSettings : public QObject
+{
+ Q_OBJECT
+ Q_DISABLE_COPY(QWebEngineGlobalSettings)
+public:
+ static QWebEngineGlobalSettings *GetInstance();
+
+ // Mapping net::SecureDnsMode
+ enum class DnsMode { WithFallback = 1, Secure = 2 };
+
+ void configureDnsOverHttps(const DnsMode dnsMode, const QString &dnsOverHttpsTemplates);
+
+private:
+ QWebEngineGlobalSettings(QObject *p = nullptr);
+ ~QWebEngineGlobalSettings();
+
+ friend class QtWebEngineCore::SystemNetworkContextManager;
+ Q_DECLARE_PRIVATE(QWebEngineGlobalSettings)
+ QScopedPointer<QWebEngineGlobalSettingsPrivate> d_ptr;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBENGINEGLOBALSETTINGS_H
diff --git a/src/core/api/qwebengineglobalsettings_p.h b/src/core/api/qwebengineglobalsettings_p.h
new file mode 100644
index 000000000..4c15f62b0
--- /dev/null
+++ b/src/core/api/qwebengineglobalsettings_p.h
@@ -0,0 +1,43 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#ifndef QWEBENGINEGLOBALSETTINGS_P_H
+#define QWEBENGINEGLOBALSETTINGS_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 "qwebengineglobalsettings.h"
+#include <string>
+
+QT_BEGIN_NAMESPACE
+
+class Q_WEBENGINECORE_PRIVATE_EXPORT QWebEngineGlobalSettingsPrivate
+{
+public:
+ QWebEngineGlobalSettingsPrivate()
+ : dnsMode(QWebEngineGlobalSettings::DnsMode::WithFallback)
+ , dnsOverHttpsTemplates("")
+ , insecureDnsClientEnabled(true)
+ , additionalInsecureDnsTypesEnabled(true)
+ , isDnsOverHttpsUserConfigured(false){};
+
+ QWebEngineGlobalSettings::DnsMode dnsMode;
+ std::string dnsOverHttpsTemplates;
+ bool insecureDnsClientEnabled;
+ bool additionalInsecureDnsTypesEnabled;
+ bool isDnsOverHttpsUserConfigured;
+};
+
+QT_END_NAMESPACE
+
+#endif // QWEBENGINEGLOBALSETTINGS_P_H
diff --git a/src/core/net/system_network_context_manager.cpp b/src/core/net/system_network_context_manager.cpp
index 83e122aab..8df65b7a5 100644
--- a/src/core/net/system_network_context_manager.cpp
+++ b/src/core/net/system_network_context_manager.cpp
@@ -29,6 +29,8 @@
#include "services/network/public/mojom/cert_verifier_service.mojom.h"
#include "services/network/public/mojom/network_context.mojom.h"
#include "services/proxy_resolver/public/mojom/proxy_resolver.mojom.h"
+#include "api/qwebengineglobalsettings.h"
+#include "api/qwebengineglobalsettings_p.h"
#if BUILDFLAG(IS_WIN)
#include "chrome/browser/net/chrome_mojo_proxy_resolver_win.h"
@@ -38,9 +40,6 @@
namespace {
-// The global instance of the SystemNetworkContextmanager.
-SystemNetworkContextManager *g_system_network_context_manager = nullptr;
-
network::mojom::HttpAuthStaticParamsPtr CreateHttpAuthStaticParams()
{
network::mojom::HttpAuthStaticParamsPtr auth_static_params =
@@ -65,6 +64,11 @@ network::mojom::HttpAuthDynamicParamsPtr CreateHttpAuthDynamicParams()
} // namespace
+namespace QtWebEngineCore {
+
+// The global instance of the SystemNetworkContextmanager.
+SystemNetworkContextManager *g_system_network_context_manager = nullptr;
+
// SharedURLLoaderFactory backed by a SystemNetworkContextManager and its
// network context. Transparently handles crashes.
class SystemNetworkContextManager::URLLoaderFactoryForSystem : public network::SharedURLLoaderFactory
@@ -255,12 +259,24 @@ void SystemNetworkContextManager::OnNetworkServiceCreated(network::mojom::Networ
network_service->SetExplicitlyAllowedPorts(explicitly_allowed_network_ports);
}
- // Configure the stub resolver. This must be done after the system
- // NetworkContext is created, but before anything has the chance to use it.
- // bool stub_resolver_enabled;
- // absl::optional<std::vector<network::mojom::DnsOverHttpsServerPtr>> dns_over_https_servers;
- // GetStubResolverConfig(local_state_, &stub_resolver_enabled, &dns_over_https_servers);
- // content::GetNetworkService()->ConfigureStubHostResolver(stub_resolver_enabled, std::move(dns_over_https_servers));
+
+ // The network service is a singleton that can be reinstantiated for different reasons,
+ // e.g., when the network service crashes. Therefore, we configure the stub host
+ // resolver of the network service here, each time it is instantiated, with our global
+ // DNS-Over-HTTPS settings. This ensures that the global settings don't get lost
+ // on reinstantiation and are in effect upon initial instantiation.
+ QWebEngineGlobalSettings *const globalSettings = QWebEngineGlobalSettings::GetInstance();
+ if (globalSettings->d_ptr->isDnsOverHttpsUserConfigured) {
+ const bool insecureDnsClientEnabled = globalSettings->d_ptr->insecureDnsClientEnabled;
+ const bool additionalInsecureDnsTypesEnabled =
+ globalSettings->d_ptr->additionalInsecureDnsTypesEnabled;
+ const net::SecureDnsMode dnsMode = net::SecureDnsMode(globalSettings->d_ptr->dnsMode);
+ const absl::optional<net::DnsOverHttpsConfig> dnsOverHttpsTemplates =
+ net::DnsOverHttpsConfig::FromString(globalSettings->d_ptr->dnsOverHttpsTemplates);
+ content::GetNetworkService()->ConfigureStubHostResolver(insecureDnsClientEnabled, dnsMode,
+ *dnsOverHttpsTemplates,
+ additionalInsecureDnsTypesEnabled);
+ }
}
void SystemNetworkContextManager::AddSSLConfigToNetworkContextParams(network::mojom::NetworkContextParams *network_context_params)
@@ -320,3 +336,5 @@ network::mojom::NetworkContextParamsPtr SystemNetworkContextManager::CreateNetwo
content::GetCertVerifierParams(std::move(cert_verifier_creation_params));
return network_context_params;
}
+
+} // namespace QtWebEngineCore
diff --git a/src/core/net/system_network_context_manager.h b/src/core/net/system_network_context_manager.h
index fa761cb44..d56bdab78 100644
--- a/src/core/net/system_network_context_manager.h
+++ b/src/core/net/system_network_context_manager.h
@@ -28,6 +28,8 @@ class URLLoaderFactory;
class SharedURLLoaderFactory;
} // namespace network
+namespace QtWebEngineCore {
+
// Responsible for creating and managing access to the system NetworkContext.
// Lives on the UI thread. The NetworkContext this owns is intended for requests
// not associated with a profile. It stores no data on disk, and has no HTTP
@@ -114,4 +116,6 @@ private:
ProxyConfigMonitor proxy_config_monitor_;
};
+} // namespace QtWebEngineCore
+
#endif // SYSTEM_NETWORK_CONTEXT_MANAGER_H_
diff --git a/tests/auto/core/CMakeLists.txt b/tests/auto/core/CMakeLists.txt
index 9d131da56..ae10d918b 100644
--- a/tests/auto/core/CMakeLists.txt
+++ b/tests/auto/core/CMakeLists.txt
@@ -4,6 +4,7 @@
add_subdirectory(qwebenginecookiestore)
add_subdirectory(qwebengineloadinginfo)
add_subdirectory(qwebenginesettings)
+add_subdirectory(qwebengineglobalsettings)
add_subdirectory(qwebengineurlrequestinterceptor)
add_subdirectory(qwebengineurlresponseinterceptor)
add_subdirectory(qwebengineurlrequestjob)
diff --git a/tests/auto/core/qwebengineglobalsettings/CMakeLists.txt b/tests/auto/core/qwebengineglobalsettings/CMakeLists.txt
new file mode 100644
index 000000000..fa81ba8df
--- /dev/null
+++ b/tests/auto/core/qwebengineglobalsettings/CMakeLists.txt
@@ -0,0 +1,29 @@
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: BSD-3-Clause
+
+include(../../httpserver/httpserver.cmake)
+include(../../util/util.cmake)
+
+qt_internal_add_test(tst_qwebengineglobalsettings
+ SOURCES
+ tst_qwebengineglobalsettings.cpp
+ LIBRARIES
+ Qt::WebEngineCore
+ Test::HttpServer
+ Qt::WebEngineWidgets
+ Test::Util
+)
+
+# Resources:
+set(tst_qwebengineglobalsettings_resource_files
+ "cert/localhost.crt"
+ "cert/localhost.key"
+ "cert/RootCA.pem"
+)
+
+qt_add_resources(tst_qwebengineglobalsettings "tst_qwebengineglobalsettings"
+ PREFIX
+ "/"
+ FILES
+ ${tst_qwebengineglobalsettings_resource_files}
+)
diff --git a/tests/auto/core/qwebengineglobalsettings/cert/RootCA.pem b/tests/auto/core/qwebengineglobalsettings/cert/RootCA.pem
new file mode 100644
index 000000000..16be384bb
--- /dev/null
+++ b/tests/auto/core/qwebengineglobalsettings/cert/RootCA.pem
@@ -0,0 +1,20 @@
+-----BEGIN CERTIFICATE-----
+MIIDTzCCAjegAwIBAgIUNYpmREIW67Fh7WNzCwPL6nnSgRMwDQYJKoZIhvcNAQEL
+BQAwNzELMAkGA1UEBhMCREUxKDAmBgNVBAMMH1dlYkVuZ2luZUdsb2JhbFNldHRp
+bmdzLVRlc3QtQ0EwHhcNMjMwMzI5MTYwMzMzWhcNMjYwMTE2MTYwMzMzWjA3MQsw
+CQYDVQQGEwJERTEoMCYGA1UEAwwfV2ViRW5naW5lR2xvYmFsU2V0dGluZ3MtVGVz
+dC1DQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJhZ9DwcdbVBzMyY
+/nEqt5KUi74LFwEnS0G2ne8IYco9+Pbkpb8wV5u6n43IsQ2c3u8D/KVtu1Vy3tf2
+G3aKOwhFzaj7GWLE9FweZyMoL6ASOtWEa55myT5zAysVQtHAkePu0smAPP0gVq3E
+vjSTwV1W1mVXv4wMwffR8AvNGhKrJIa3L2/uYKGbzEmaCk2kt0vIqfrx8095RlXC
+lUcwTMJ6/d/e/DMDtqQ1ypUuz5QYQybIVKwuqkhojT2DXbitv0rE4HLQub8CxOZ+
+9GcQjeAt8Tzrlp1UP6c9OtlsMoo37gJYzb/XDE6OPnk42chQXDxGQjtVRs+60kcT
+Dx/YHG0CAwEAAaNTMFEwHQYDVR0OBBYEFP1FK1U9CUHQEp7coaab7IdR18zDMB8G
+A1UdIwQYMBaAFP1FK1U9CUHQEp7coaab7IdR18zDMA8GA1UdEwEB/wQFMAMBAf8w
+DQYJKoZIhvcNAQELBQADggEBAGTlcxmRsuwBeRW0CsjX/qbdcB0OWkIC857Jn8RU
+6yGa7P9i6EQb1O/DEF+Z7dkASx5zfN6LPIrph6J56/mmcNBeqArovWJwxQUTNO9i
+1kOU3xoH5n/ya+gdBr3reA90bAMKWXwa6uI3smPJKy+2hOkdDaSBa5KECYWhniH0
+yRxL7YdhQhuCc7Ijf+S6WzeHRwdLkdiV8c2vAGWdunDFuGT2iYVOZ1qbp6O/tmjv
+TxWAnvP4+0ykFIlMor0vYWD8xbnq28263VmNh7mrFwkBYnHJiY/nTDwxaL+g6Uji
+9n6+VuxUDgfQWX1YRHC4a89zI/Zvnn2z/92To7zRmNd73RQ=
+-----END CERTIFICATE-----
diff --git a/tests/auto/core/qwebengineglobalsettings/cert/localhost.crt b/tests/auto/core/qwebengineglobalsettings/cert/localhost.crt
new file mode 100644
index 000000000..c063bf268
--- /dev/null
+++ b/tests/auto/core/qwebengineglobalsettings/cert/localhost.crt
@@ -0,0 +1,22 @@
+-----BEGIN CERTIFICATE-----
+MIIDtDCCApygAwIBAgIURotPFTfDJxwaqhZsr0IpAahl2EMwDQYJKoZIhvcNAQEL
+BQAwNzELMAkGA1UEBhMCREUxKDAmBgNVBAMMH1dlYkVuZ2luZUdsb2JhbFNldHRp
+bmdzLVRlc3QtQ0EwHhcNMjMwMzI5MTYwNDI1WhcNMjYwMTE2MTYwNDI1WjB0MQsw
+CQYDVQQGEwJERTEPMA0GA1UECAwGQmVybGluMQ8wDQYDVQQHDAZCZXJsaW4xKTAn
+BgNVBAoMIFFXZWJFbmdpbmVHbG9iYWxTZXR0aW5ncy1FeGFtcGxlMRgwFgYDVQQD
+DA9sb2NhbGhvc3QubG9jYWwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQCY9FX/8YetuJKSFSoYPxMKPvjt2zJ5g13DywqZtbDzLAIASCxn4iad3qgxaoWB
+uI0g4ykzrhUa98YHU8fDH4T4Vwhwu72SRYW4+MgT9ohc1oCKBX05b+BWSuTSeuHy
+leqdL78bj3bu5TtFs2dJt2t8eA6SNR9lDa5g4v7oA4xVp93gMo2YqZwaLONmxIKY
+cI4lcETnHHsvc6+dB2UqWHJEN75UkdC/XnDLM/VbL3/4zxU+9x34nvvfSJwCHVnE
+u+zYwrZXkbiDVDovT855phVC/K5skVgBL2miz3eygljuw1tIwnmVix/e/xHZyqMg
+Lje/LZN53v5G61Wut6bbdkeVAgMBAAGjezB5MB8GA1UdIwQYMBaAFP1FK1U9CUHQ
+Ep7coaab7IdR18zDMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgTwMB8GA1UdEQQYMBaC
+CWxvY2FsaG9zdIIJMTI3LjAuMC4xMB0GA1UdDgQWBBQv20ImViFtvMm5gHqTeML6
+pi5BtTANBgkqhkiG9w0BAQsFAAOCAQEAGsL7eOms30+IPdKQZ2pjtX22GfM6EiUs
+xsQfsX/Q3bus30B2m9GJ6AVIwVUJimOGiMauDCLjDeXWCMZpihzodExhC0D/X1B+
+FsCLagcjlgfWwekKEo8sUWUZp0DNCyacPtTPxqoS2RA7foEzQhRLViLSvf+UXU8g
+jZAwWGB/5V849zcbbNBcWKzRsPvNOqeENWEn1ByGcsWhas2V0KzRcUODuA9UHv1x
++eDlLZYsWV9c1MuL8a1VDEluIR19eR/Gl9axjPZY2oiPvlp2b7I4z1bY+wV2i6vh
+NeDCAxAxJ42tXeb86vtnVXfSDbzedDbLv0l2kEhcywVN3MwhsEpmpg==
+-----END CERTIFICATE-----
diff --git a/tests/auto/core/qwebengineglobalsettings/cert/localhost.key b/tests/auto/core/qwebengineglobalsettings/cert/localhost.key
new file mode 100644
index 000000000..49502ab9a
--- /dev/null
+++ b/tests/auto/core/qwebengineglobalsettings/cert/localhost.key
@@ -0,0 +1,28 @@
+-----BEGIN PRIVATE KEY-----
+MIIEvAIBADANBgkqhkiG9w0BAQEFAASCBKYwggSiAgEAAoIBAQCY9FX/8YetuJKS
+FSoYPxMKPvjt2zJ5g13DywqZtbDzLAIASCxn4iad3qgxaoWBuI0g4ykzrhUa98YH
+U8fDH4T4Vwhwu72SRYW4+MgT9ohc1oCKBX05b+BWSuTSeuHyleqdL78bj3bu5TtF
+s2dJt2t8eA6SNR9lDa5g4v7oA4xVp93gMo2YqZwaLONmxIKYcI4lcETnHHsvc6+d
+B2UqWHJEN75UkdC/XnDLM/VbL3/4zxU+9x34nvvfSJwCHVnEu+zYwrZXkbiDVDov
+T855phVC/K5skVgBL2miz3eygljuw1tIwnmVix/e/xHZyqMgLje/LZN53v5G61Wu
+t6bbdkeVAgMBAAECggEAF7ADX5NivUsv29LORZoDE1ukRoXjX8Ex9MANoLdsM4S1
+vKBwzBfQfjN83cZO7cOMi7LSby//EcGcmAboEXZgq+siof7ZQX1l07snlTvha2tG
+1dk6xvnmBscrf9NLCbwg7P33fUevFhlHICjEDr0KtuiK7Sav+YDwaA3Ph1QBWERd
+GO3sVlnuGsDpf/0GijlwqEGuDKUePEEANOhXcByh693VmvlKVf9SbrimYeunKW1O
+FvvcAiBMzqurhZotb9/juiq+fIMID29OULCCxlZZSySRYw0REpnAAxgWvaSZqyWd
+tGosSKEgc4SptPTmC8DzRDDfN/zqvXmkmYnN9o4qMwKBgQC3tVYdEPn3fHX973Df
+Ukp55cRpZFuNxjOiV3Qo1aTAKqpbmJ4/x8tUL7rhsmJXSxlW7xdNQ/WIHM1PJlZx
+UAIr5eBq1MUVd5OENP8PuVIdAIumHXICB5FioJR/WnXRXLJEbGxSRr5gwaTw3sXd
+ObPRQEUOrJtK+W0aeBKePRtIiwKBgQDVJN7A26vy8PMcE4TcDp75vAY/qasZl6ES
+oksaHf3c4/jsnr70wRoOXi3fPo/DpWmVFylttMSEnzh3nfnOkDXZD3mQx3sdVw8l
+12++t59733hllJZlwqk5OAc990kE1X44UW/gPA+5Vb9kpo6ahpFtqwhDmqa4RjtZ
+0R/1H/KUXwKBgGjR7Qq0rwwJVgHIZ2zlNV2MPp+sBZlFaBzPLZZHILQNJBsTX+gg
+heHJQiaZdAc+8Hxr+624gxZg6LyqsVQCRNrrVTtfn/x5uBANdSNxqGqn7wafcne5
+/bh6y4BHC0akT4s/Gidv+hyXIRfW5Ksvy2wv8bdHwWvsGdaqgGUNlM21AoGAe9Vc
+BbibAh6zYBCHFEL6YiW3i61L1yadUnIwKBBcucVJjk/8qb63ILne9OEoLYcg/Jnk
+W/S2aEcJS5Xg2P44CtBO1KrRAI7gIiA0sB2G7zU6gen+J0kdgDzpGDtflQtktdu6
+oBDFIeyLsjKCj4y3WXwQ5RYo3s8PFHPHmWbiTQkCgYBViqAHaAaPJQZG7Q6/Xqhf
+rFosC0DeZk5PHrEDbpAnuJbySafGZ4LxY5Oq05+aM8BeR+IuGopciBBDWXoh7msO
+N8WItu7WI86lIu7JZRbeju2w59tgj0EA+GyU1udPjTjseP5qpB27X1JEGV6TYBNs
+LMmQSgdGWqwteKsc50UrkA==
+-----END PRIVATE KEY-----
diff --git a/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
new file mode 100644
index 000000000..40bd525bc
--- /dev/null
+++ b/tests/auto/core/qwebengineglobalsettings/tst_qwebengineglobalsettings.cpp
@@ -0,0 +1,107 @@
+// Copyright (C) 2023 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
+
+#include <QtTest>
+#include <widgetutil.h>
+#include <QWebEngineProfile>
+#include <QWebEnginePage>
+#include <QWebEngineGlobalSettings>
+#include <QWebEngineLoadingInfo>
+
+#include "httpsserver.h"
+#include "httpreqrep.h"
+
+class tst_QWebEngineGlobalSettings : public QObject
+{
+ Q_OBJECT
+
+public:
+ tst_QWebEngineGlobalSettings() { }
+ ~tst_QWebEngineGlobalSettings() { }
+
+public Q_SLOTS:
+ void init() { }
+ void cleanup() { }
+
+private Q_SLOTS:
+ void initTestCase() { }
+ void cleanupTestCase() { }
+ void dnsOverHttps_data();
+ void dnsOverHttps();
+};
+
+Q_LOGGING_CATEGORY(lc, "qt.webengine.tests")
+
+void tst_QWebEngineGlobalSettings::dnsOverHttps_data()
+{
+ QTest::addColumn<QWebEngineGlobalSettings::DnsMode>("dnsMode");
+ QTest::addColumn<QString>("uriTemplate");
+ QTest::addColumn<bool>("isWithCustomDnsServer");
+ QTest::addColumn<bool>("isDnsResolutionSuccessExpected");
+ QTest::newRow("DnsMode::Secure (mock DNS)")
+ << QWebEngineGlobalSettings::DnsMode::Secure
+ << QStringLiteral("https://127.0.0.1:3000/dns-query{?dns}") << true << false;
+ QTest::newRow("DnsMode::Secure (real DNS)")
+ << QWebEngineGlobalSettings::DnsMode::Secure
+ << QStringLiteral("https://dns.google/dns-query{?dns}") << false << true;
+
+ // Note: In the following test, we can't verify that the DoH server is called first and
+ // afterwards insecure DNS is tried, because for the DoH server to ever be used when the DNS
+ // mode is set to DnsMode::WithFallback, Chromium starts an asynchronous DoH server DnsProbe and
+ // requires that the connection is successful. That is, we'd have to implement a correct
+ // DNS response, which in turn requires that certificate errors aren't ignored and
+ // non-self-signed certificates are used for correct encryption. Instead of implementing
+ // all of that, this test verifies that Chromium tries probing the configured DoH server only.
+ QTest::newRow("DnsMode::WithFallback (mock DNS)")
+ << QWebEngineGlobalSettings::DnsMode::WithFallback
+ << QStringLiteral("https://127.0.0.1:3000/dns-query{?dns}") << true << true;
+}
+
+void tst_QWebEngineGlobalSettings::dnsOverHttps()
+{
+ QFETCH(QWebEngineGlobalSettings::DnsMode, dnsMode);
+ QFETCH(QString, uriTemplate);
+ QFETCH(bool, isWithCustomDnsServer);
+ QFETCH(bool, isDnsResolutionSuccessExpected);
+ bool isDnsServerCalled = false;
+ bool isLoadSuccessful = false;
+
+ HttpsServer *httpsServer;
+ if (isWithCustomDnsServer) {
+ httpsServer = new HttpsServer(":/cert/localhost.crt", ":/cert/localhost.key",
+ ":/cert/RootCA.pem", 3000, this);
+ QObject::connect(
+ httpsServer, &HttpsServer::newRequest, this, [&isDnsServerCalled](HttpReqRep *rr) {
+ QVERIFY(rr->requestPath().contains(QByteArrayLiteral("/dns-query?dns=")));
+ isDnsServerCalled = true;
+ rr->close();
+ });
+ QVERIFY(httpsServer->start());
+ httpsServer->setExpectError(true);
+ httpsServer->setVerifyMode(QSslSocket::PeerVerifyMode::VerifyNone);
+ }
+
+ QWebEngineProfile profile;
+ QWebEnginePage page(&profile);
+ QSignalSpy loadSpy(&page, SIGNAL(loadFinished(bool)));
+
+ connect(&page, &QWebEnginePage::loadFinished, this,
+ [&isLoadSuccessful](bool ok) { isLoadSuccessful = ok; });
+
+ QWebEngineGlobalSettings *globalSettings = QWebEngineGlobalSettings::GetInstance();
+ globalSettings->configureDnsOverHttps(dnsMode, uriTemplate);
+
+ page.load(QUrl("https://google.com/"));
+ QVERIFY(loadSpy.wait());
+
+ QTRY_COMPARE(isDnsServerCalled, isWithCustomDnsServer);
+ QCOMPARE(isLoadSuccessful, isDnsResolutionSuccessExpected);
+
+ if (isWithCustomDnsServer)
+ QVERIFY(httpsServer->stop());
+}
+
+static QByteArrayList params = QByteArrayList() << "--ignore-certificate-errors";
+
+W_QTEST_MAIN(tst_QWebEngineGlobalSettings, params)
+#include "tst_qwebengineglobalsettings.moc"
diff --git a/tests/auto/httpserver/httpserver.h b/tests/auto/httpserver/httpserver.h
index 270b6265f..201eef4c6 100644
--- a/tests/auto/httpserver/httpserver.h
+++ b/tests/auto/httpserver/httpserver.h
@@ -59,6 +59,8 @@ public:
Q_INVOKABLE void setHostDomain(const QString &host) { m_url.setHost(host); }
+ Q_INVOKABLE QTcpServer *getTcpServer() const { return m_tcpServer; }
+
Q_SIGNALS:
// Emitted after a HTTP request has been successfully parsed.
void newRequest(HttpReqRep *reqRep);
diff --git a/tests/auto/httpserver/httpsserver.h b/tests/auto/httpserver/httpsserver.h
index 10deeb322..d029851aa 100644
--- a/tests/auto/httpserver/httpsserver.h
+++ b/tests/auto/httpserver/httpsserver.h
@@ -55,11 +55,19 @@ static QSslServer *createServer(const QString &certificateFileName, const QStrin
struct HttpsServer : HttpServer
{
HttpsServer(const QString &certPath, const QString &keyPath, const QString &ca,
- QObject *parent = nullptr)
- : HttpServer(createServer(certPath, keyPath, ca), "https", QHostAddress::LocalHost, 0,
+ quint16 port = 0, QObject *parent = nullptr)
+ : HttpServer(createServer(certPath, keyPath, ca), "https", QHostAddress::LocalHost, port,
parent)
{
}
+
+ void setVerifyMode(const QSslSocket::PeerVerifyMode verifyMode)
+ {
+ QSslServer *server = static_cast<QSslServer *>(getTcpServer());
+ QSslConfiguration config = server->sslConfiguration();
+ config.setPeerVerifyMode(verifyMode);
+ server->setSslConfiguration(config);
+ }
};
#endif