diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2018-07-30 17:16:01 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2018-07-31 14:57:02 +0000 |
commit | 2dfa41e0eac65f5772ec61364f9afd0ce49fecc7 (patch) | |
tree | 958ff5a71a2a9341d7d70a92a1c19a118c5ef9e4 | |
parent | f43e947dc405b6a2324656f631c804db8e8dec3d (diff) |
Return to eventloop after emitting encrypted
When the connection has been encrypted we will,
in QHttpNetworkConnectionChannel::_q_encrypted, emit 'reply->encrypted'
in which user slots can be called.
In the event that the user calls abort it will, however, not abort until
the next time it goes back to the event loop (which might not happen
until after the request has already been sent).
Task-number: QTBUG-65960
Change-Id: I96865f83c47f89deb9f644c86a71948dbb0ec0d0
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
3 files changed, 48 insertions, 1 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 0ac14c78f6..5726925cb0 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -251,6 +251,20 @@ bool QHttpNetworkConnectionChannel::sendRequest() return protocolHandler->sendRequest(); } +/* + * Invoke "protocolHandler->sendRequest" using a queued connection. + * It's used to return to the event loop before invoking sendRequest when + * there's a very real chance that the request could have been aborted + * (i.e. after having emitted 'encrypted'). + */ +void QHttpNetworkConnectionChannel::sendRequestDelayed() +{ + QMetaObject::invokeMethod(this, [this] { + Q_ASSERT(!protocolHandler.isNull()); + if (reply) + protocolHandler->sendRequest(); + }, Qt::ConnectionType::QueuedConnection); +} void QHttpNetworkConnectionChannel::_q_receiveReply() { @@ -1234,7 +1248,7 @@ void QHttpNetworkConnectionChannel::_q_encrypted() emit reply->encrypted(); } if (reply) - sendRequest(); + sendRequestDelayed(); } } diff --git a/src/network/access/qhttpnetworkconnectionchannel_p.h b/src/network/access/qhttpnetworkconnectionchannel_p.h index e9cdae5653..270b3eb9ba 100644 --- a/src/network/access/qhttpnetworkconnectionchannel_p.h +++ b/src/network/access/qhttpnetworkconnectionchannel_p.h @@ -174,6 +174,7 @@ public: void abort(); bool sendRequest(); + void sendRequestDelayed(); bool ensureConnection(); diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 0ef3dc0b61..9c77e156d7 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -392,6 +392,7 @@ private Q_SLOTS: void ignoreSslErrorsListWithSlot_data(); void ignoreSslErrorsListWithSlot(); void encrypted(); + void abortOnEncrypted(); void sslConfiguration_data(); void sslConfiguration(); #ifdef QT_BUILD_INTERNAL @@ -6244,6 +6245,37 @@ void tst_QNetworkReply::encrypted() reply->deleteLater(); } +void tst_QNetworkReply::abortOnEncrypted() +{ + SslServer server; + server.listen(); + if (!server.isListening()) + QSKIP("Server fails to listen. Skipping since QTcpServer is covered in another test."); + + server.connect(&server, &SslServer::newEncryptedConnection, [&server]() { + connect(server.socket, &QTcpSocket::readyRead, server.socket, []() { + // This slot must not be invoked! + QVERIFY(false); + }); + }); + + QNetworkAccessManager nm; + QNetworkReply *reply = nm.get(QNetworkRequest(QUrl(QString("https://localhost:%1").arg(server.serverPort())))); + reply->ignoreSslErrors(); + + connect(reply, &QNetworkReply::encrypted, [reply, &nm]() { + reply->abort(); + nm.clearConnectionCache(); + }); + + QSignalSpy spyEncrypted(reply, &QNetworkReply::encrypted); + QTRY_COMPARE(spyEncrypted.count(), 1); + + // Wait for the socket to be closed again in order to be sure QTcpSocket::readyRead would have been emitted. + QTRY_VERIFY(server.socket != nullptr); + QTRY_COMPARE(server.socket->state(), QAbstractSocket::UnconnectedState); +} + void tst_QNetworkReply::sslConfiguration() { QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/index.html")); |