diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2019-04-26 12:56:23 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2019-05-15 12:48:07 +0000 |
commit | cd816d4b6ac4358a92dbda906288ba6d969fc1cd (patch) | |
tree | e310a7225d2b7e8353f902b46ce8965e376e8f58 | |
parent | 927eba344c2dbabc7275a4f561dd97f0e30760a2 (diff) |
Add setAutoDeleteReplies to QNetworkAccessManager
Following the introduction of AutoDeleteReplyOnFinishAttribute to
QNetworkRequest it seems natural to make it easy to enable for all
replies created with the current QNetworkAccessManager.
[ChangeLog][QtNetwork][QNetworkAccessManager] Added setAutoDeleteReplies
to QNetworkAccessManager to enable the AutoDeleteReplyOnFinishAttribute
attribute for all QNetworkRequests that are passed to
QNetworkAccessManager.
Change-Id: I7f96dd1fc9a899328e89732be17780b4e710c2a2
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Markus Goetz (Woboq GmbH) <markus@woboq.com>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 39 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.h | 3 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager_p.h | 2 | ||||
-rw-r--r-- | tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 91 |
4 files changed, 135 insertions, 0 deletions
diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index f1f63ad00a..a2996e3533 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -1402,6 +1402,11 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, redirectPolicy()); } + if (autoDeleteReplies() + && req.attribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute).isNull()) { + req.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, true); + } + bool isLocalFile = req.url().isLocalFile(); QString scheme = req.url().scheme(); @@ -1672,6 +1677,40 @@ void QNetworkAccessManager::clearConnectionCache() QNetworkAccessManagerPrivate::clearConnectionCache(this); } + +/*! + \since 5.14 + + Returns the true if QNetworkAccessManager is currently configured + to automatically delete QNetworkReplies, false otherwise. + + \sa setAutoDeleteReplies, + QNetworkRequest::AutoDeleteReplyOnFinishAttribute +*/ +bool QNetworkAccessManager::autoDeleteReplies() +{ + return d_func()->autoDeleteReplies; +} + +/*! + \since 5.14 + + Enables or disables automatic deletion of \l {QNetworkReply} {QNetworkReplies}. + + Setting \a shouldAutoDelete to true is the same as setting the + QNetworkRequest::AutoDeleteReplyOnFinishAttribute attribute to + true on all \e{future} \l {QNetworkRequest} {QNetworkRequests} + passed to this instance of QNetworkAccessManager unless the + attribute was already explicitly set on the QNetworkRequest. + + \sa autoDeleteReplies, + QNetworkRequest::AutoDeleteReplyOnFinishAttribute +*/ +void QNetworkAccessManager::setAutoDeleteReplies(bool shouldAutoDelete) +{ + d_func()->autoDeleteReplies = shouldAutoDelete; +} + void QNetworkAccessManagerPrivate::_q_replyFinished() { Q_Q(QNetworkAccessManager); diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index fa23537c68..601d0420ff 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -167,6 +167,9 @@ public: void setRedirectPolicy(QNetworkRequest::RedirectPolicy policy); QNetworkRequest::RedirectPolicy redirectPolicy() const; + bool autoDeleteReplies(); + void setAutoDeleteReplies(bool autoDelete); + Q_SIGNALS: #ifndef QT_NO_NETWORKPROXY void proxyAuthenticationRequired(const QNetworkProxy &proxy, QAuthenticator *authenticator); diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index dfd747a767..67ea2094b3 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -227,6 +227,8 @@ public: bool stsEnabled = false; mutable QNetworkStatusMonitor statusMonitor; + bool autoDeleteReplies = false; + #ifndef QT_NO_BEARERMANAGEMENT Q_AUTOTEST_EXPORT static const QWeakPointer<const QNetworkSession> getNetworkSession(const QNetworkAccessManager *manager); #endif diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 5e3018366c..43739be4a3 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -505,6 +505,8 @@ private Q_SLOTS: void autoDeleteRepliesAttribute_data(); void autoDeleteRepliesAttribute(); + void autoDeleteReplies_data(); + void autoDeleteReplies(); // NOTE: This test must be last! void parentingRepliesToTheApp(); @@ -9241,6 +9243,95 @@ void tst_QNetworkReply::autoDeleteRepliesAttribute() } } +void tst_QNetworkReply::autoDeleteReplies_data() +{ + autoDeleteRepliesAttribute_data(); +} + +void tst_QNetworkReply::autoDeleteReplies() +{ + QFETCH(QUrl, destination); + manager.setAutoDeleteReplies(true); + auto cleanup = qScopeGuard([this] { manager.setAutoDeleteReplies(false); }); + { + // Get + QNetworkRequest request(destination); + QNetworkReply *reply = manager.get(request); + QSignalSpy finishedSpy(reply, &QNetworkReply::finished); + QSignalSpy destroyedSpy(reply, &QObject::destroyed); + QVERIFY(finishedSpy.wait()); + QCOMPARE(destroyedSpy.count(), 0); + QVERIFY(destroyedSpy.wait()); + } + { + // Post + QNetworkRequest request(destination); + QNetworkReply *reply = manager.post(request, QByteArrayLiteral("datastring")); + QSignalSpy finishedSpy(reply, &QNetworkReply::finished); + QSignalSpy destroyedSpy(reply, &QObject::destroyed); + QVERIFY(finishedSpy.wait()); + QCOMPARE(destroyedSpy.count(), 0); + QVERIFY(destroyedSpy.wait()); + } + // Here we repeat the test, but override the auto-deletion in the QNetworkRequest + // We need two calls to processEvents to test that the QNetworkReply doesn't get deleted. + // The first call executes a metacall event which adds the deleteLater meta event which + // would be executed in the second call. But that shouldn't happen in this case. + { + // Get + QNetworkRequest request(destination); + request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false); + QScopedPointer<QNetworkReply> reply(manager.get(request)); + QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished); + QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed); + QVERIFY(finishedSpy.wait()); + QCOMPARE(destroyedSpy.count(), 0); + QCoreApplication::processEvents(); + QCoreApplication::processEvents(); + QCOMPARE(destroyedSpy.count(), 0); + } + { + // Post + QNetworkRequest request(destination); + request.setAttribute(QNetworkRequest::AutoDeleteReplyOnFinishAttribute, false); + QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring"))); + QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished); + QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed); + QVERIFY(finishedSpy.wait()); + QCOMPARE(destroyedSpy.count(), 0); + QCoreApplication::processEvents(); + QCoreApplication::processEvents(); + QCOMPARE(destroyedSpy.count(), 0); + } + // Now we repeat the test with autoDeleteReplies set to false + cleanup.dismiss(); + manager.setAutoDeleteReplies(false); + { + // Get + QNetworkRequest request(destination); + QScopedPointer<QNetworkReply> reply(manager.get(request)); + QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished); + QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed); + QVERIFY(finishedSpy.wait()); + QCOMPARE(destroyedSpy.count(), 0); + QCoreApplication::processEvents(); + QCoreApplication::processEvents(); + QCOMPARE(destroyedSpy.count(), 0); + } + { + // Post + QNetworkRequest request(destination); + QScopedPointer<QNetworkReply> reply(manager.post(request, QByteArrayLiteral("datastring"))); + QSignalSpy finishedSpy(reply.data(), &QNetworkReply::finished); + QSignalSpy destroyedSpy(reply.data(), &QObject::destroyed); + QVERIFY(finishedSpy.wait()); + QCOMPARE(destroyedSpy.count(), 0); + QCoreApplication::processEvents(); + QCoreApplication::processEvents(); + QCOMPARE(destroyedSpy.count(), 0); + } +} + // NOTE: This test must be last testcase in tst_qnetworkreply! void tst_QNetworkReply::parentingRepliesToTheApp() { |