summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShane Kearns <ext-shane.2.kearns@nokia.com>2012-04-13 18:05:33 +0100
committerQt by Nokia <qt-info@nokia.com>2012-04-19 19:46:07 +0200
commitaf100dbd7e23076f8873f9ee8847d1ac90bb1700 (patch)
treed22ffeea04285d446bfecbd7fee89dad510bef30
parentddf040eccb56098db4f81a72fd9db0010697da94 (diff)
Abort background requests if policy changes to disallow them
Using the policy change signal from QNetworkSession. If the new policy disallows background requests and this is a background request, then generate an error. This results in a TCP RST on the socket, and a BackgroundRequestNotAllowedError on the QNetworkReply. If the reply is already finished, no action is taken. Change-Id: I4ff5c681a8b7b852727bb95f03664d666f4efe07 Reviewed-by: Martin Petersson <Martin.Petersson@nokia.com>
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp19
-rw-r--r--src/network/access/qnetworkreplyimpl.cpp27
-rw-r--r--tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp73
3 files changed, 110 insertions, 9 deletions
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index 624c39f292..4796e4bb86 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -1521,6 +1521,9 @@ bool QNetworkReplyHttpImplPrivate::start()
if (managerPrivate->networkSession->isOpen() &&
managerPrivate->networkSession->state() == QNetworkSession::Connected) {
+ Q_Q(QNetworkReplyHttpImpl);
+ QObject::connect(managerPrivate->networkSession.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)),
+ q, SLOT(_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)));
postRequest();
return true;
}
@@ -1564,8 +1567,6 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation()
if (session) {
QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)),
q, SLOT(_q_networkSessionFailed()));
- QObject::connect(session, SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)),
- q, SLOT(_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)));
if (!session->isOpen()) {
session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground);
@@ -1767,8 +1768,20 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed()
}
}
-void QNetworkReplyHttpImplPrivate::_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)
+void QNetworkReplyHttpImplPrivate::_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies newPolicies)
{
+ if (request.attribute(QNetworkRequest::BackgroundRequestAttribute).toBool()) {
+ if (newPolicies & QNetworkSession::NoBackgroundTrafficPolicy) {
+ // Abort waiting and working replies.
+ if (state == WaitingForSession || state == Working) {
+ state = Working;
+ error(QNetworkReply::BackgroundRequestNotAllowedError,
+ QCoreApplication::translate("QNetworkReply", "Background request not allowed."));
+ finished();
+ }
+ // ### if canResume(), then we could resume automatically
+ }
+ }
}
#endif
diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp
index c9efcbb1fe..d535cbda65 100644
--- a/src/network/access/qnetworkreplyimpl.cpp
+++ b/src/network/access/qnetworkreplyimpl.cpp
@@ -73,6 +73,8 @@ inline QNetworkReplyImplPrivate::QNetworkReplyImplPrivate()
void QNetworkReplyImplPrivate::_q_startOperation()
{
+ Q_Q(QNetworkReplyImpl);
+
// ensure this function is only being called once
if (state == Working || state == Finished) {
qDebug("QNetworkReplyImpl::_q_startOperation was called more than once");
@@ -110,12 +112,8 @@ void QNetworkReplyImplPrivate::_q_startOperation()
state = WaitingForSession;
if (session) {
- Q_Q(QNetworkReplyImpl);
-
QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)),
q, SLOT(_q_networkSessionFailed()));
- QObject::connect(session.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)),
- q, SLOT(_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)));
if (!session->isOpen()) {
session->setSessionProperty(QStringLiteral("ConnectInBackground"), isBackground);
@@ -138,6 +136,12 @@ void QNetworkReplyImplPrivate::_q_startOperation()
return;
}
+ if (session) {
+ //get notification of policy changes.
+ QObject::connect(session.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)),
+ q, SLOT(_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)));
+ }
+
if (backend && backend->isSynchronous()) {
state = Finished;
q_func()->setFinished(true);
@@ -321,9 +325,20 @@ void QNetworkReplyImplPrivate::_q_networkSessionFailed()
}
}
-void QNetworkReplyImplPrivate::_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies)
+void QNetworkReplyImplPrivate::_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies newPolicies)
{
-
+ if (backend->request().attribute(QNetworkRequest::BackgroundRequestAttribute).toBool()) {
+ if (newPolicies & QNetworkSession::NoBackgroundTrafficPolicy) {
+ // Abort waiting and working replies.
+ if (state == WaitingForSession || state == Working) {
+ state = Working;
+ error(QNetworkReply::BackgroundRequestNotAllowedError,
+ QCoreApplication::translate("QNetworkReply", "Background request not allowed."));
+ finished();
+ }
+ // ### if backend->canResume(), then we could resume automatically, however no backend supports resuming
+ }
+ }
}
#endif
diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
index 35d4add0f8..aede0d290b 100644
--- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
+++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp
@@ -405,6 +405,9 @@ private Q_SLOTS:
void backgroundRequest_data();
void backgroundRequest();
+ void backgroundRequestInterruption_data();
+ void backgroundRequestInterruption();
+
// NOTE: This test must be last!
void parentingRepliesToTheApp();
@@ -6844,6 +6847,7 @@ void tst_QNetworkReply::backgroundRequest_data()
}
+//test purpose: background requests can't be started when not allowed
void tst_QNetworkReply::backgroundRequest()
{
#ifdef QT_BUILD_INTERNAL
@@ -6883,6 +6887,75 @@ void tst_QNetworkReply::backgroundRequest()
#endif
}
+void tst_QNetworkReply::backgroundRequestInterruption_data()
+{
+ QTest::addColumn<QUrl>("url");
+ QTest::addColumn<bool>("background");
+ QTest::addColumn<QNetworkReply::NetworkError>("error");
+
+ QUrl httpurl("http://" + QtNetworkSettings::serverName() + "/qtest/mediumfile");
+ QUrl httpsurl("https://" + QtNetworkSettings::serverName() + "/qtest/mediumfile");
+ QUrl ftpurl("ftp://" + QtNetworkSettings::serverName() + "/qtest/bigfile");
+
+ QTest::newRow("http, fg, nobg") << httpurl << false << QNetworkReply::NoError;
+ QTest::newRow("http, bg, nobg") << httpurl << true << QNetworkReply::BackgroundRequestNotAllowedError;
+
+#ifndef QT_NO_SSL
+ QTest::newRow("https, fg, nobg") << httpsurl << false << QNetworkReply::NoError;
+ QTest::newRow("https, bg, nobg") << httpsurl << true << QNetworkReply::BackgroundRequestNotAllowedError;
+#endif
+
+ QTest::newRow("ftp, fg, nobg") << ftpurl << false << QNetworkReply::NoError;
+ QTest::newRow("ftp, bg, nobg") << ftpurl << true << QNetworkReply::BackgroundRequestNotAllowedError;
+
+}
+
+//test purpose: background requests in progress are aborted when policy changes to disallow them
+void tst_QNetworkReply::backgroundRequestInterruption()
+{
+#ifdef QT_BUILD_INTERNAL
+#ifndef QT_NO_BEARERMANAGEMENT
+ QFETCH(QUrl, url);
+ QFETCH(bool, background);
+ QFETCH(QNetworkReply::NetworkError, error);
+
+ QNetworkRequest request(url);
+
+ if (background)
+ request.setAttribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(true));
+
+ //this preconstructs the session so we can change policies in advance
+ manager.setConfiguration(networkConfiguration);
+
+#ifndef QT_NO_SSL
+ connect(&manager, SIGNAL(sslErrors(QNetworkReply*,QList<QSslError>)),
+ SLOT(sslErrors(QNetworkReply*,QList<QSslError>)));
+#endif
+
+ const QWeakPointer<const QNetworkSession> session = QNetworkAccessManagerPrivate::getNetworkSession(&manager);
+ QVERIFY(session);
+ QNetworkSession::UsagePolicies original = session.data()->usagePolicies();
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoPolicy);
+
+ request.setAttribute(QNetworkRequest::MaximumDownloadBufferSizeAttribute, 8192);
+ QNetworkReplyPtr reply(manager.get(request));
+ reply->setReadBufferSize(1024);
+
+ QSignalSpy spy(reply.data(), SIGNAL(readyRead()));
+ QTRY_VERIFY(spy.count() > 0);
+
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), QNetworkSession::NoBackgroundTrafficPolicy);
+
+ QVERIFY(waitForFinish(reply) != Timeout);
+ if (session)
+ QNetworkSessionPrivate::setUsagePolicies(*const_cast<QNetworkSession *>(session.data()), original);
+
+ QVERIFY(reply->isFinished());
+ QCOMPARE(reply->error(), error);
+#endif
+#endif
+}
+
// NOTE: This test must be last testcase in tst_qnetworkreply!
void tst_QNetworkReply::parentingRepliesToTheApp()
{