summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xmkspecs/features/uikit/devices.py10
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache.cpp31
-rw-r--r--src/gui/opengl/qopenglprogrambinarycache_p.h6
-rw-r--r--src/gui/opengl/qopenglshaderprogram.cpp8
-rw-r--r--src/gui/painting/qbackingstore.cpp2
-rw-r--r--src/network/access/qhttp2protocolhandler.cpp25
-rw-r--r--src/network/access/qhttpthreaddelegate.cpp36
-rw-r--r--src/network/access/qnetworkaccessmanager.cpp9
-rw-r--r--src/plugins/platforms/wasm/qwasmeventtranslator.cpp26
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.cpp6
-rw-r--r--src/plugins/platforms/winrt/qwinrtscreen.h1
-rw-r--r--src/plugins/styles/mac/qmacstyle_mac.mm46
-rw-r--r--tests/auto/network/access/http2/tst_http2.cpp123
-rw-r--r--tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp20
14 files changed, 289 insertions, 60 deletions
diff --git a/mkspecs/features/uikit/devices.py b/mkspecs/features/uikit/devices.py
index 0443e838f2..8cdcb370a0 100755
--- a/mkspecs/features/uikit/devices.py
+++ b/mkspecs/features/uikit/devices.py
@@ -46,11 +46,17 @@ import json
import subprocess
from distutils.version import StrictVersion
+def is_available(object):
+ if "isAvailable" in object:
+ return object["isAvailable"] # introduced in Xcode 11
+ else:
+ return "unavailable" not in object["availability"]
+
def is_suitable_runtime(runtimes, runtime_name, platform, min_version):
for runtime in runtimes:
identifier = runtime["identifier"]
if (runtime["name"] == runtime_name or identifier == runtime_name) \
- and "unavailable" not in runtime["availability"] \
+ and is_available(runtime) \
and identifier.startswith("com.apple.CoreSimulator.SimRuntime.{}".format(platform)) \
and StrictVersion(runtime["version"]) >= min_version:
return True
@@ -77,6 +83,6 @@ if __name__ == "__main__":
for runtime_name in device_dict:
if is_suitable_runtime(runtimes, runtime_name, args.platform, args.minimum_deployment_target):
for device in device_dict[runtime_name]:
- if "unavailable" not in device["availability"] \
+ if is_available(device) \
and (args.state is None or device["state"].lower() in args.state):
print(device["udid"])
diff --git a/src/gui/opengl/qopenglprogrambinarycache.cpp b/src/gui/opengl/qopenglprogrambinarycache.cpp
index 74b91086ee..1f1ac1fd80 100644
--- a/src/gui/opengl/qopenglprogrambinarycache.cpp
+++ b/src/gui/opengl/qopenglprogrambinarycache.cpp
@@ -168,12 +168,19 @@ bool QOpenGLProgramBinaryCache::verifyHeader(const QByteArray &buf) const
bool QOpenGLProgramBinaryCache::setProgramBinary(uint programId, uint blobFormat, const void *p, uint blobSize)
{
- QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions();
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QOpenGLExtraFunctions *funcs = context->extraFunctions();
while (true) {
GLenum error = funcs->glGetError();
if (error == GL_NO_ERROR || error == GL_CONTEXT_LOST)
break;
}
+#if defined(QT_OPENGL_ES_2)
+ if (context->isOpenGLES() && context->format().majorVersion() < 3) {
+ initializeProgramBinaryOES(context);
+ programBinaryOES(programId, blobFormat, p, blobSize);
+ } else
+#endif
funcs->glProgramBinary(programId, blobFormat, p, blobSize);
GLenum err = funcs->glGetError();
@@ -347,7 +354,8 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
GLEnvInfo info;
- QOpenGLExtraFunctions *funcs = QOpenGLContext::currentContext()->extraFunctions();
+ QOpenGLContext *context = QOpenGLContext::currentContext();
+ QOpenGLExtraFunctions *funcs = context->extraFunctions();
GLint blobSize = 0;
while (true) {
GLenum error = funcs->glGetError();
@@ -390,6 +398,12 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
*p++ = 0;
GLint outSize = 0;
+#if defined(QT_OPENGL_ES_2)
+ if (context->isOpenGLES() && context->format().majorVersion() < 3) {
+ initializeProgramBinaryOES(context);
+ getProgramBinaryOES(programId, blobSize, &outSize, &blobFormat, p);
+ } else
+#endif
funcs->glGetProgramBinary(programId, blobSize, &outSize, &blobFormat, p);
if (blobSize != outSize) {
qCDebug(DBG_SHADER_CACHE, "glGetProgramBinary returned size %d instead of %d", outSize, blobSize);
@@ -414,4 +428,17 @@ void QOpenGLProgramBinaryCache::save(const QByteArray &cacheKey, uint programId)
}
}
+#if defined(QT_OPENGL_ES_2)
+void QOpenGLProgramBinaryCache::initializeProgramBinaryOES(QOpenGLContext *context)
+{
+ if (m_programBinaryOESInitialized)
+ return;
+ m_programBinaryOESInitialized = true;
+
+ Q_ASSERT(context);
+ getProgramBinaryOES = (void (QOPENGLF_APIENTRYP)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary))context->getProcAddress("glGetProgramBinaryOES");
+ programBinaryOES = (void (QOPENGLF_APIENTRYP)(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLint length))context->getProcAddress("glProgramBinaryOES");
+}
+#endif
+
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglprogrambinarycache_p.h b/src/gui/opengl/qopenglprogrambinarycache_p.h
index a0e1f91e25..9fade08e66 100644
--- a/src/gui/opengl/qopenglprogrambinarycache_p.h
+++ b/src/gui/opengl/qopenglprogrambinarycache_p.h
@@ -93,6 +93,12 @@ private:
uint format;
};
QCache<QByteArray, MemCacheEntry> m_memCache;
+#if defined(QT_OPENGL_ES_2)
+ void (QOPENGLF_APIENTRYP programBinaryOES)(GLuint program, GLenum binaryFormat, const GLvoid *binary, GLsizei length);
+ void (QOPENGLF_APIENTRYP getProgramBinaryOES)(GLuint program, GLsizei bufSize, GLsizei *length, GLenum *binaryFormat, GLvoid *binary);
+ void initializeProgramBinaryOES(QOpenGLContext *context);
+ bool m_programBinaryOESInitialized = false;
+#endif
};
QT_END_NAMESPACE
diff --git a/src/gui/opengl/qopenglshaderprogram.cpp b/src/gui/opengl/qopenglshaderprogram.cpp
index f225d5dc75..3c7bd4f90d 100644
--- a/src/gui/opengl/qopenglshaderprogram.cpp
+++ b/src/gui/opengl/qopenglshaderprogram.cpp
@@ -3755,8 +3755,14 @@ QOpenGLProgramBinarySupportCheck::QOpenGLProgramBinarySupportCheck(QOpenGLContex
if (ctx) {
if (ctx->isOpenGLES()) {
qCDebug(DBG_SHADER_CACHE, "OpenGL ES v%d context", ctx->format().majorVersion());
- if (ctx->format().majorVersion() >= 3)
+ if (ctx->format().majorVersion() >= 3) {
m_supported = true;
+ } else {
+ const bool hasExt = ctx->hasExtension("GL_OES_get_program_binary");
+ qCDebug(DBG_SHADER_CACHE, "GL_OES_get_program_binary support = %d", hasExt);
+ if (hasExt)
+ m_supported = true;
+ }
} else {
const bool hasExt = ctx->hasExtension("GL_ARB_get_program_binary");
qCDebug(DBG_SHADER_CACHE, "GL_ARB_get_program_binary support = %d", hasExt);
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 3fab903c4d..3240b83451 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -186,7 +186,7 @@ QPaintDevice *QBackingStore::paintDevice()
void QBackingStore::endPaint()
{
if (paintDevice()->paintingActive())
- qWarning() << "QBackingStore::endPaint() called with active painter on backingstore paint device";
+ qWarning("QBackingStore::endPaint() called with active painter; did you forget to destroy it or call QPainter::end() on it?");
handle()->endPaint();
}
diff --git a/src/network/access/qhttp2protocolhandler.cpp b/src/network/access/qhttp2protocolhandler.cpp
index 93afcf0ee1..0ece5b7179 100644
--- a/src/network/access/qhttp2protocolhandler.cpp
+++ b/src/network/access/qhttp2protocolhandler.cpp
@@ -170,7 +170,6 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
encoder(HPack::FieldLookupTable::DefaultSize, true)
{
Q_ASSERT(channel && m_connection);
-
continuedFrames.reserve(20);
const ProtocolParameters params(m_connection->http2Parameters());
@@ -328,10 +327,32 @@ bool QHttp2ProtocolHandler::sendRequest()
return false;
}
+ // Process 'fake' (created by QNetworkAccessManager::connectToHostEncrypted())
+ // requests first:
+ auto &requests = m_channel->spdyRequestsToSend;
+ for (auto it = requests.begin(), endIt = requests.end(); it != endIt;) {
+ const auto &pair = *it;
+ const QString scheme(pair.first.url().scheme());
+ if (scheme == QLatin1String("preconnect-http")
+ || scheme == QLatin1String("preconnect-https")) {
+ m_connection->preConnectFinished();
+ emit pair.second->finished();
+ it = requests.erase(it);
+ if (!requests.size()) {
+ // Normally, after a connection was established and H2
+ // was negotiated, we send a client preface. connectToHostEncrypted
+ // though is not meant to send any data, it's just a 'preconnect'.
+ // Thus we return early:
+ return true;
+ }
+ } else {
+ ++it;
+ }
+ }
+
if (!prefaceSent && !sendClientPreface())
return false;
- auto &requests = m_channel->spdyRequestsToSend;
if (!requests.size())
return true;
diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp
index 6fb4710d77..acc551a7c9 100644
--- a/src/network/access/qhttpthreaddelegate.cpp
+++ b/src/network/access/qhttpthreaddelegate.cpp
@@ -128,7 +128,8 @@ static QByteArray makeCacheKey(QUrl &url, QNetworkProxy *proxy, const QString &p
QString result;
QUrl copy = url;
QString scheme = copy.scheme();
- bool isEncrypted = scheme == QLatin1String("https");
+ bool isEncrypted = scheme == QLatin1String("https")
+ || scheme == QLatin1String("preconnect-https");
copy.setPort(copy.port(isEncrypted ? 443 : 80));
if (scheme == QLatin1String("preconnect-http")) {
copy.setScheme(QLatin1String("http"));
@@ -296,17 +297,29 @@ void QHttpThreadDelegate::startRequest()
connectionType = QHttpNetworkConnection::ConnectionTypeHTTP2Direct;
}
+ const bool isH2 = httpRequest.isHTTP2Allowed() || httpRequest.isHTTP2Direct();
+ if (isH2) {
+#if QT_CONFIG(ssl)
+ if (ssl) {
+ if (!httpRequest.isHTTP2Direct()) {
+ QList<QByteArray> protocols;
+ protocols << QSslConfiguration::ALPNProtocolHTTP2
+ << QSslConfiguration::NextProtocolHttp1_1;
+ incomingSslConfiguration->setAllowedNextProtocols(protocols);
+ }
+ urlCopy.setScheme(QStringLiteral("h2s"));
+ } else
+#endif // QT_CONFIG(ssl)
+ {
+ urlCopy.setScheme(QStringLiteral("h2"));
+ }
+ }
+
#ifndef QT_NO_SSL
if (ssl && !incomingSslConfiguration.data())
incomingSslConfiguration.reset(new QSslConfiguration);
- if (httpRequest.isHTTP2Allowed() && ssl) {
- // With HTTP2Direct we do not try any protocol negotiation.
- QList<QByteArray> protocols;
- protocols << QSslConfiguration::ALPNProtocolHTTP2
- << QSslConfiguration::NextProtocolHttp1_1;
- incomingSslConfiguration->setAllowedNextProtocols(protocols);
- } else if (httpRequest.isSPDYAllowed() && ssl) {
+ if (!isH2 && httpRequest.isSPDYAllowed() && ssl) {
connectionType = QHttpNetworkConnection::ConnectionTypeSPDY;
urlCopy.setScheme(QStringLiteral("spdy")); // to differentiate SPDY requests from HTTPS requests
QList<QByteArray> nextProtocols;
@@ -323,12 +336,11 @@ void QHttpThreadDelegate::startRequest()
cacheKey = makeCacheKey(urlCopy, &cacheProxy, httpRequest.peerVerifyName());
else
#endif
- cacheKey = makeCacheKey(urlCopy, 0, httpRequest.peerVerifyName());
-
+ cacheKey = makeCacheKey(urlCopy, nullptr, httpRequest.peerVerifyName());
// the http object is actually a QHttpNetworkConnection
httpConnection = static_cast<QNetworkAccessCachedHttpConnection *>(connections.localData()->requestEntryNow(cacheKey));
- if (httpConnection == 0) {
+ if (!httpConnection) {
// no entry in cache; create an object
// the http object is actually a QHttpNetworkConnection
#ifdef QT_NO_BEARERMANAGEMENT
@@ -358,7 +370,7 @@ void QHttpThreadDelegate::startRequest()
connections.localData()->addEntry(cacheKey, httpConnection);
} else {
if (httpRequest.withCredentials()) {
- QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), 0);
+ QNetworkAuthenticationCredential credential = authenticationManager->fetchCachedCredentials(httpRequest.url(), nullptr);
if (!credential.user.isEmpty() && !credential.password.isEmpty()) {
QAuthenticator auth;
auth.setUser(credential.user);
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp
index 92778acd6a..29192ae7b0 100644
--- a/src/network/access/qnetworkaccessmanager.cpp
+++ b/src/network/access/qnetworkaccessmanager.cpp
@@ -1236,10 +1236,11 @@ void QNetworkAccessManager::connectToHostEncrypted(const QString &hostName, quin
if (sslConfiguration != QSslConfiguration::defaultConfiguration())
request.setSslConfiguration(sslConfiguration);
- // There is no way to enable SPDY via a request, so we need to check
- // the ssl configuration whether SPDY is allowed here.
- if (sslConfiguration.allowedNextProtocols().contains(
- QSslConfiguration::NextProtocolSpdy3_0))
+ // There is no way to enable SPDY/HTTP2 via a request, so we need to check
+ // the ssl configuration whether SPDY/HTTP2 is allowed here.
+ if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::ALPNProtocolHTTP2))
+ request.setAttribute(QNetworkRequest::HTTP2AllowedAttribute, true);
+ else if (sslConfiguration.allowedNextProtocols().contains(QSslConfiguration::NextProtocolSpdy3_0))
request.setAttribute(QNetworkRequest::SpdyAllowedAttribute, true);
request.setPeerVerifyName(peerName);
diff --git a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
index a34b957537..ad94ba9c77 100644
--- a/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
+++ b/src/plugins/platforms/wasm/qwasmeventtranslator.cpp
@@ -138,16 +138,16 @@ static constexpr const auto KeyTbl = qMakeArray(
Emkb2Qt< Qt::Key_Minus, '-' >,
Emkb2Qt< Qt::Key_Period, '.' >,
Emkb2Qt< Qt::Key_Slash, '/' >,
- Emkb2Qt< Qt::Key_0, '0' >,
- Emkb2Qt< Qt::Key_1, '1' >,
- Emkb2Qt< Qt::Key_2, '2' >,
- Emkb2Qt< Qt::Key_3, '3' >,
- Emkb2Qt< Qt::Key_4, '4' >,
- Emkb2Qt< Qt::Key_5, '5' >,
- Emkb2Qt< Qt::Key_6, '6' >,
- Emkb2Qt< Qt::Key_7, '7' >,
- Emkb2Qt< Qt::Key_8, '8' >,
- Emkb2Qt< Qt::Key_9, '9' >,
+ Emkb2Qt< Qt::Key_0, 'D','i','g','i','t','0' >,
+ Emkb2Qt< Qt::Key_1, 'D','i','g','i','t','1' >,
+ Emkb2Qt< Qt::Key_2, 'D','i','g','i','t','2' >,
+ Emkb2Qt< Qt::Key_3, 'D','i','g','i','t','3' >,
+ Emkb2Qt< Qt::Key_4, 'D','i','g','i','t','4' >,
+ Emkb2Qt< Qt::Key_5, 'D','i','g','i','t','5' >,
+ Emkb2Qt< Qt::Key_6, 'D','i','g','i','t','6' >,
+ Emkb2Qt< Qt::Key_7, 'D','i','g','i','t','7' >,
+ Emkb2Qt< Qt::Key_8, 'D','i','g','i','t','8' >,
+ Emkb2Qt< Qt::Key_9, 'D','i','g','i','t','9' >,
Emkb2Qt< Qt::Key_Semicolon, ';' >,
Emkb2Qt< Qt::Key_Equal, '=' >,
Emkb2Qt< Qt::Key_A, 'K','e','y','A' >,
@@ -432,7 +432,8 @@ Qt::Key QWasmEventTranslator::translateEmscriptKey(const EmscriptenKeyboardEvent
{
Qt::Key qtKey = Qt::Key_unknown;
- if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0) {
+ if (qstrncmp(emscriptKey->code, "Key", 3) == 0 || qstrncmp(emscriptKey->code, "Numpad", 6) == 0 ||
+ qstrncmp(emscriptKey->code, "Digit", 5) == 0) {
emkb2qt_t searchKey{emscriptKey->code, 0}; // search emcsripten code
auto it1 = std::lower_bound(KeyTbl.cbegin(), KeyTbl.cend(), searchKey);
@@ -862,11 +863,10 @@ Qt::Key QWasmEventTranslator::translateDeadKey(Qt::Key deadKey, Qt::Key accentBa
case Qt::Key_Apostrophe:// linux
wasmKey = find(circumflexKeyTable, accentBaseKey);
break;
- break;
default:
break;
- };
+ };
return wasmKey;
}
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.cpp b/src/plugins/platforms/winrt/qwinrtscreen.cpp
index 0d77889a36..86ab7651c6 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.cpp
+++ b/src/plugins/platforms/winrt/qwinrtscreen.cpp
@@ -669,12 +669,6 @@ QDpi QWinRTScreen::logicalDpi() const
return QDpi(d->logicalDpi, d->logicalDpi);
}
-qreal QWinRTScreen::pixelDensity() const
-{
- Q_D(const QWinRTScreen);
- return qMax(1, qRound(d->logicalDpi / 96));
-}
-
qreal QWinRTScreen::scaleFactor() const
{
Q_D(const QWinRTScreen);
diff --git a/src/plugins/platforms/winrt/qwinrtscreen.h b/src/plugins/platforms/winrt/qwinrtscreen.h
index 63c254940d..6b57780fa1 100644
--- a/src/plugins/platforms/winrt/qwinrtscreen.h
+++ b/src/plugins/platforms/winrt/qwinrtscreen.h
@@ -96,7 +96,6 @@ public:
QImage::Format format() const override;
QSizeF physicalSize() const override;
QDpi logicalDpi() const override;
- qreal pixelDensity() const override;
qreal scaleFactor() const;
QPlatformCursor *cursor() const override;
Qt::KeyboardModifiers keyboardModifiers() const;
diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm
index 85bf71be3f..258aba2cda 100644
--- a/src/plugins/styles/mac/qmacstyle_mac.mm
+++ b/src/plugins/styles/mac/qmacstyle_mac.mm
@@ -75,6 +75,8 @@
#include <QtWidgets/qwizard.h>
#endif
+#include <cmath>
+
QT_USE_NAMESPACE
static QWindow *qt_getWindow(const QWidget *widget)
@@ -456,6 +458,37 @@ static bool setupSlider(NSSlider *slider, const QStyleOptionSlider *sl)
return true;
}
+static void fixStaleGeometry(NSSlider *slider)
+{
+ // If it's later fixed in AppKit, this function is not needed.
+ // On macOS Mojave we suddenly have NSSliderCell with a cached
+ // (and stale) geometry, thus its -drawKnob, -drawBarInside:flipped:,
+ // -drawTickMarks fail to render the slider properly. Setting the number
+ // of tickmarks triggers an update in geometry.
+
+ Q_ASSERT(slider);
+
+ if (QOperatingSystemVersion::current() < QOperatingSystemVersion::MacOSMojave)
+ return;
+
+ NSSliderCell *cell = slider.cell;
+ const NSRect barRect = [cell barRectFlipped:NO];
+ const NSSize sliderSize = slider.frame.size;
+ CGFloat difference = 0.;
+ if (slider.vertical)
+ difference = std::abs(sliderSize.height - barRect.size.height);
+ else
+ difference = std::abs(sliderSize.width - barRect.size.width);
+
+ if (difference > 6.) {
+ // Stale ...
+ const auto nOfTicks = slider.numberOfTickMarks;
+ // Non-zero, different from nOfTicks to force update
+ slider.numberOfTickMarks = nOfTicks + 10;
+ slider.numberOfTickMarks = nOfTicks;
+ }
+}
+
static bool isInMacUnifiedToolbarArea(QWindow *window, int windowY)
{
QPlatformNativeInterface *nativeInterface = QGuiApplication::platformNativeInterface();
@@ -2083,10 +2116,9 @@ void QMacStyle::unpolish(QWidget* w)
#if QT_CONFIG(menu)
qobject_cast<QMenu*>(w) &&
#endif
- !w->testAttribute(Qt::WA_SetPalette)) {
- QPalette pal = qApp->palette(w);
- w->setPalette(pal);
- w->setAttribute(Qt::WA_SetPalette, false);
+ !w->testAttribute(Qt::WA_SetPalette))
+ {
+ w->setPalette(QPalette());
w->setWindowOpacity(1.0);
}
@@ -2102,9 +2134,9 @@ void QMacStyle::unpolish(QWidget* w)
#if QT_CONFIG(tabbar)
if (qobject_cast<QTabBar*>(w)) {
if (!w->testAttribute(Qt::WA_SetFont))
- w->setFont(qApp->font(w));
+ w->setFont(QFont());
if (!w->testAttribute(Qt::WA_SetPalette))
- w->setPalette(qApp->palette(w));
+ w->setPalette(QPalette());
}
#endif
@@ -5276,6 +5308,8 @@ void QMacStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex
#endif
{
[slider calcSize];
+ if (!hasDoubleTicks)
+ fixStaleGeometry(slider);
NSSliderCell *cell = slider.cell;
const int numberOfTickMarks = slider.numberOfTickMarks;
diff --git a/tests/auto/network/access/http2/tst_http2.cpp b/tests/auto/network/access/http2/tst_http2.cpp
index 502ffba3de..bf3d936446 100644
--- a/tests/auto/network/access/http2/tst_http2.cpp
+++ b/tests/auto/network/access/http2/tst_http2.cpp
@@ -85,6 +85,8 @@ private slots:
void goaway_data();
void goaway();
void earlyResponse();
+ void connectToHost_data();
+ void connectToHost();
protected slots:
// Slots to listen to our in-process server:
@@ -545,6 +547,127 @@ void tst_Http2::earlyResponse()
QVERIFY(serverGotSettingsACK);
}
+void tst_Http2::connectToHost_data()
+{
+ // The attribute to set on a new request:
+ QTest::addColumn<QNetworkRequest::Attribute>("requestAttribute");
+ // The corresponding (to the attribute above) connection type the
+ // server will use:
+ QTest::addColumn<H2Type>("connectionType");
+
+#if QT_CONFIG(ssl)
+ QTest::addRow("encrypted-h2-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2Direct;
+ if (!clearTextHTTP2)
+ QTest::addRow("encrypted-h2-ALPN") << QNetworkRequest::HTTP2AllowedAttribute << H2Type::h2Alpn;
+#endif // QT_CONFIG(ssl)
+ // This works for all configurations, tests 'preconnect-http' scheme:
+ // h2 with protocol upgrade is not working for now (the logic is a bit
+ // complicated there ...).
+ QTest::addRow("h2-direct") << QNetworkRequest::Http2DirectAttribute << H2Type::h2cDirect;
+}
+
+void tst_Http2::connectToHost()
+{
+ // QNetworkAccessManager::connectToHostEncrypted() and connectToHost()
+ // creates a special request with 'preconnect-https' or 'preconnect-http'
+ // schemes. At the level of the protocol handler we are supposed to report
+ // these requests as finished and wait for the real requests. This test will
+ // connect to a server with the first reply 'finished' signal meaning we
+ // indeed connected. At this point we check that a client preface was not
+ // sent yet, and no response received. Then we send the second (the real)
+ // request and do our usual checks. Since our server closes its listening
+ // socket on the first incoming connection (would not accept a new one),
+ // the successful completion of the second requests also means we were able
+ // to find a cached connection and re-use it.
+
+ QFETCH(const QNetworkRequest::Attribute, requestAttribute);
+ QFETCH(const H2Type, connectionType);
+
+ clearHTTP2State();
+
+ serverPort = 0;
+ nRequests = 2;
+
+ ServerPtr targetServer(newServer(defaultServerSettings, connectionType));
+
+#if QT_CONFIG(ssl)
+ Q_ASSERT(!clearTextHTTP2 || connectionType != H2Type::h2Alpn);
+#else
+ Q_ASSERT(connectionType == H2Type::h2c || connectionType == H2Type::h2cDirect);
+ Q_ASSERT(targetServer->isClearText());
+#endif // QT_CONFIG(ssl)
+
+ QMetaObject::invokeMethod(targetServer.data(), "startServer", Qt::QueuedConnection);
+ runEventLoop();
+
+ QVERIFY(serverPort != 0);
+
+ auto url = requestUrl(connectionType);
+ url.setPath("/index.html");
+
+ QNetworkReply *reply = nullptr;
+ // Here some mess with how we create this first reply:
+#if QT_CONFIG(ssl)
+ if (!targetServer->isClearText()) {
+ // Let's emulate what QNetworkAccessManager::connectToHostEncrypted() does.
+ // Alas, we cannot use it directly, since it does not return the reply and
+ // also does not know the difference between H2 with ALPN or direct.
+ auto copyUrl = url;
+ copyUrl.setScheme(QLatin1String("preconnect-https"));
+ QNetworkRequest request(copyUrl);
+ request.setAttribute(requestAttribute, true);
+ reply = manager->get(request);
+ // Since we're using self-signed certificates, ignore SSL errors:
+ reply->ignoreSslErrors();
+ } else
+#endif // QT_CONFIG(ssl)
+ {
+ // Emulating what QNetworkAccessManager::connectToHost() does with
+ // additional information that it cannot provide (the attribute).
+ auto copyUrl = url;
+ copyUrl.setScheme(QLatin1String("preconnect-http"));
+ QNetworkRequest request(copyUrl);
+ request.setAttribute(requestAttribute, true);
+ reply = manager->get(request);
+ }
+
+ connect(reply, &QNetworkReply::finished, [this, reply]() {
+ --nRequests;
+ eventLoop.exitLoop();
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(reply->isFinished());
+ // Nothing must be sent yet:
+ QVERIFY(!prefaceOK);
+ QVERIFY(!serverGotSettingsACK);
+ // Nothing received back:
+ QVERIFY(reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).isNull());
+ QCOMPARE(reply->readAll().size(), 0);
+ });
+
+ runEventLoop();
+ STOP_ON_FAILURE
+
+ QCOMPARE(nRequests, 1);
+
+ QNetworkRequest request(url);
+ request.setAttribute(requestAttribute, QVariant(true));
+ reply = manager->get(request);
+ connect(reply, &QNetworkReply::finished, this, &tst_Http2::replyFinished);
+ // Note, unlike the first request, when the connection is ecnrytped, we
+ // do not ignore TLS errors on this reply - we should re-use existing
+ // connection, there TLS errors were already ignored.
+
+ runEventLoop();
+ STOP_ON_FAILURE
+
+ QVERIFY(nRequests == 0);
+ QVERIFY(prefaceOK);
+ QVERIFY(serverGotSettingsACK);
+
+ QCOMPARE(reply->error(), QNetworkReply::NoError);
+ QVERIFY(reply->isFinished());
+}
+
void tst_Http2::serverStarted(quint16 port)
{
serverPort = port;
diff --git a/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp
index bd0889bf4a..d26ac016b9 100644
--- a/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp
+++ b/tests/benchmarks/gui/painting/lancebench/tst_lancebench.cpp
@@ -305,17 +305,17 @@ void tst_LanceBench::runTestSuite(GraphicsEngine engine, QImage::Format format,
void tst_LanceBench::paint(QPaintDevice *device, GraphicsEngine engine, QImage::Format format, const QStringList &script, const QString &filePath)
{
- PaintCommands pcmd(script, 800, 800, format);
- switch (engine) {
- case OpenGL:
- pcmd.setType(OpenGLBufferType); // version/profile is communicated through the context's format()
- break;
- case Raster:
- pcmd.setType(ImageType);
- break;
- }
- pcmd.setFilePath(filePath);
QBENCHMARK {
+ PaintCommands pcmd(script, 800, 800, format);
+ switch (engine) {
+ case OpenGL:
+ pcmd.setType(OpenGLBufferType); // version/profile is communicated through the context's format()
+ break;
+ case Raster:
+ pcmd.setType(ImageType);
+ break;
+ }
+ pcmd.setFilePath(filePath);
QPainter p(device);
pcmd.setPainter(&p);
pcmd.runCommands();