From: Shane Kearns Date: Thu, 31 May 2012 15:09:38 +0000 (+0100) Subject: QNAM - maintain a weak reference to the QNetworkSession X-Git-Tag: 071012110112~651 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=bae1613c4c3d8c38b90ed2ba5c1b149e1bc87987;p=profile%2Fivi%2Fqtbase.git QNAM - maintain a weak reference to the QNetworkSession When handling signals from the session, a pointer is needed. Also the QNetworkReplyImpl needs to access the manager's session. So, the manager should have a strong and weak reference. The strong reference is held during connection establishment. The weak reference is held all the time, though it will become null when the session is destroyed in idle. The non static member function getNetworkSession() is used to create strong references from the weak reference where required. Task-number: ou1cimx#1004278 Change-Id: I4b5b36b1d996b98e659d993969006c61b4440c15 Reviewed-by: Martin Petersson --- diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index f998696..d5f3007 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -358,13 +358,14 @@ bool QNetworkAccessBackend::start() { #ifndef QT_NO_BEARERMANAGEMENT // For bearer, check if session start is required - if (manager->networkSession) { + QSharedPointer networkSession(manager->getNetworkSession()); + if (networkSession) { // session required - if (manager->networkSession->isOpen() && - manager->networkSession->state() == QNetworkSession::Connected) { + if (networkSession->isOpen() && + networkSession->state() == QNetworkSession::Connected) { // Session is already open and ready to use. // copy network session down to the backend - setProperty("_q_networksession", QVariant::fromValue(manager->networkSession)); + setProperty("_q_networksession", QVariant::fromValue(networkSession)); } else { // Session not ready, but can skip for loopback connections @@ -386,7 +387,7 @@ bool QNetworkAccessBackend::start() #ifndef QT_NO_BEARERMANAGEMENT // Get the proxy settings from the network session (in the case of service networks, // the proxy settings change depending which AP was activated) - QNetworkSession *session = manager->networkSession.data(); + QNetworkSession *session = networkSession.data(); QNetworkConfiguration config; if (session) { QNetworkConfigurationManager configManager; diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index 283bf86..f83dc4f 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -833,8 +833,9 @@ QNetworkConfiguration QNetworkAccessManager::configuration() const { Q_D(const QNetworkAccessManager); - if (d->networkSession) - return d->networkSession->configuration(); + QSharedPointer session(d->getNetworkSession()); + if (session) + return session->configuration(); else return QNetworkConfiguration(); } @@ -858,11 +859,12 @@ QNetworkConfiguration QNetworkAccessManager::activeConfiguration() const { Q_D(const QNetworkAccessManager); - if (d->networkSession) { + QSharedPointer networkSession(d->getNetworkSession()); + if (networkSession) { QNetworkConfigurationManager manager; return manager.configurationFromIdentifier( - d->networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString()); + networkSession->sessionProperty(QLatin1String("ActiveConfiguration")).toString()); } else { return QNetworkConfiguration(); } @@ -897,7 +899,8 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess { Q_D(const QNetworkAccessManager); - if (d->networkSession) { + QSharedPointer networkSession(d->getNetworkSession()); + if (networkSession) { // d->online holds online/offline state of this network session. if (d->online) return d->networkAccessible; @@ -917,7 +920,14 @@ QNetworkAccessManager::NetworkAccessibility QNetworkAccessManager::networkAccess */ const QWeakPointer QNetworkAccessManagerPrivate::getNetworkSession(const QNetworkAccessManager *q) { - return q->d_func()->networkSession.toWeakRef(); + return q->d_func()->networkSessionWeakRef; +} + +QSharedPointer QNetworkAccessManagerPrivate::getNetworkSession() const +{ + if (networkSessionStrongRef) + return networkSessionStrongRef; + return networkSessionWeakRef.toStrongRef(); } #endif // QT_NO_BEARERMANAGEMENT @@ -1009,7 +1019,7 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera return new QDisabledNetworkReply(this, req, op); } - if (!d->networkSession && (d->initializeSession || !d->networkConfiguration.isEmpty())) { + if (!d->networkSessionStrongRef && (d->initializeSession || !d->networkConfiguration.isEmpty())) { QNetworkConfigurationManager manager; if (!d->networkConfiguration.isEmpty()) { d->createSession(manager.configurationFromIdentifier(d->networkConfiguration)); @@ -1116,8 +1126,8 @@ void QNetworkAccessManagerPrivate::_q_replyFinished() // It will not be destroyed immediately, but rather when the connection cache is flushed // after 2 minutes. activeReplyCount--; - if (networkSession && activeReplyCount == 0) - networkSession.clear(); + if (networkSessionStrongRef && activeReplyCount == 0) + networkSessionStrongRef.clear(); #endif } @@ -1294,25 +1304,29 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co initializeSession = false; + //resurrect weak ref if possible + networkSessionStrongRef = networkSessionWeakRef.toStrongRef(); + QSharedPointer newSession; if (config.isValid()) newSession = QSharedNetworkSessionManager::getSession(config); - if (networkSession) { + if (networkSessionStrongRef) { //do nothing if new and old session are the same - if (networkSession == newSession) + if (networkSessionStrongRef == newSession) return; //disconnect from old session - QObject::disconnect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); - QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); - QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), + QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected())); + QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); + QObject::disconnect(networkSessionStrongRef.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); } //switch to new session (null if config was invalid) - networkSession = newSession; + networkSessionStrongRef = newSession; + networkSessionWeakRef = networkSessionStrongRef.toWeakRef(); - if (!networkSession) { + if (!networkSessionStrongRef) { online = false; if (networkAccessible == QNetworkAccessManager::NotAccessible) @@ -1324,18 +1338,19 @@ void QNetworkAccessManagerPrivate::createSession(const QNetworkConfiguration &co } //connect to new session - QObject::connect(networkSession.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection); + QObject::connect(networkSessionStrongRef.data(), SIGNAL(opened()), q, SIGNAL(networkSessionConnected()), Qt::QueuedConnection); //QueuedConnection is used to avoid deleting the networkSession inside its closed signal - QObject::connect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); - QObject::connect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), + QObject::connect(networkSessionStrongRef.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed()), Qt::QueuedConnection); + QObject::connect(networkSessionStrongRef.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State)), Qt::QueuedConnection); - _q_networkSessionStateChanged(networkSession->state()); + _q_networkSessionStateChanged(networkSessionStrongRef->state()); } void QNetworkAccessManagerPrivate::_q_networkSessionClosed() { Q_Q(QNetworkAccessManager); + QSharedPointer networkSession(getNetworkSession()); if (networkSession) { networkConfiguration = networkSession->configuration().identifier(); @@ -1344,7 +1359,8 @@ void QNetworkAccessManagerPrivate::_q_networkSessionClosed() QObject::disconnect(networkSession.data(), SIGNAL(closed()), q, SLOT(_q_networkSessionClosed())); QObject::disconnect(networkSession.data(), SIGNAL(stateChanged(QNetworkSession::State)), q, SLOT(_q_networkSessionStateChanged(QNetworkSession::State))); - networkSession.clear(); + networkSessionStrongRef.clear(); + networkSessionWeakRef.clear(); } } diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index bd3dc39..94238db 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -78,7 +78,6 @@ public: proxyFactory(0), #endif #ifndef QT_NO_BEARERMANAGEMENT - networkSession(0), lastSessionState(QNetworkSession::Invalid), networkAccessible(QNetworkAccessManager::Accessible), activeReplyCount(0), @@ -120,6 +119,7 @@ public: #ifndef QT_NO_BEARERMANAGEMENT void createSession(const QNetworkConfiguration &config); + QSharedPointer getNetworkSession() const; void _q_networkSessionClosed(); void _q_networkSessionNewConfigurationActivated(); @@ -144,7 +144,8 @@ public: #endif #ifndef QT_NO_BEARERMANAGEMENT - QSharedPointer networkSession; + QSharedPointer networkSessionStrongRef; + QWeakPointer networkSessionWeakRef; QNetworkSession::State lastSessionState; QString networkConfiguration; QNetworkAccessManager::NetworkAccessibility networkAccessible; diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index eb4edc8..5be59e2 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -759,7 +759,7 @@ void QNetworkReplyHttpImplPrivate::postRequest() // Create the HTTP thread delegate QHttpThreadDelegate *delegate = new QHttpThreadDelegate; #ifndef QT_NO_BEARERMANAGEMENT - delegate->networkSession = managerPrivate->networkSession; + delegate->networkSession = managerPrivate->getNetworkSession(); #endif // For the synchronous HTTP, this is the normal way the delegate gets deleted @@ -1505,7 +1505,8 @@ void QNetworkReplyHttpImplPrivate::setResumeOffset(quint64 offset) bool QNetworkReplyHttpImplPrivate::start() { #ifndef QT_NO_BEARERMANAGEMENT - if (!managerPrivate->networkSession) { + QSharedPointer networkSession(managerPrivate->getNetworkSession()); + if (!networkSession) { #endif postRequest(); return true; @@ -1521,10 +1522,10 @@ bool QNetworkReplyHttpImplPrivate::start() return true; } - if (managerPrivate->networkSession->isOpen() && - managerPrivate->networkSession->state() == QNetworkSession::Connected) { + if (networkSession->isOpen() && + networkSession->state() == QNetworkSession::Connected) { Q_Q(QNetworkReplyHttpImpl); - QObject::connect(managerPrivate->networkSession.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)), + QObject::connect(networkSession.data(), SIGNAL(usagePoliciesChanged(QNetworkSession::UsagePolicies)), q, SLOT(_q_networkSessionUsagePoliciesChanged(QNetworkSession::UsagePolicies))); postRequest(); return true; @@ -1547,7 +1548,7 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() #ifndef QT_NO_BEARERMANAGEMENT // Do not start background requests if they are not allowed by session policy - QSharedPointer session(manager->d_func()->networkSession); + QSharedPointer session(manager->d_func()->getNetworkSession()); QVariant isBackground = request.attribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(false)); if (isBackground.toBool() && session && session->usagePolicies().testFlag(QNetworkSession::NoBackgroundTrafficPolicy)) { QMetaObject::invokeMethod(q, "_q_error", synchronous ? Qt::DirectConnection : Qt::QueuedConnection, @@ -1564,10 +1565,9 @@ void QNetworkReplyHttpImplPrivate::_q_startOperation() // QNetworkAccessManager will call reply->backend->start() again for us when the session // state changes. state = WaitingForSession; - QNetworkSession *session = managerPrivate->networkSession.data(); if (session) { - QObject::connect(session, SIGNAL(error(QNetworkSession::SessionError)), + QObject::connect(session.data(), SIGNAL(error(QNetworkSession::SessionError)), q, SLOT(_q_networkSessionFailed()), Qt::QueuedConnection); if (!session->isOpen()) { @@ -1724,7 +1724,7 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionConnected() if (!manager) return; - QNetworkSession *session = managerPrivate->networkSession.data(); + QSharedPointer session = managerPrivate->getNetworkSession(); if (!session) return; @@ -1752,7 +1752,7 @@ void QNetworkReplyHttpImplPrivate::_q_networkSessionFailed() // Abort waiting and working replies. if (state == WaitingForSession || state == Working) { state = Working; - QSharedPointer session(manager->d_func()->networkSession); + QSharedPointer session(manager->d_func()->getNetworkSession()); QString errorStr; if (session) errorStr = session->errorString(); @@ -1837,7 +1837,7 @@ void QNetworkReplyHttpImplPrivate::finished() if (manager) { #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *session = managerPrivate->networkSession.data(); + QSharedPointer session = managerPrivate->getNetworkSession(); if (session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index 377f257..7cbbe38 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -94,7 +94,7 @@ void QNetworkReplyImplPrivate::_q_startOperation() #ifndef QT_NO_BEARERMANAGEMENT // Do not start background requests if they are not allowed by session policy - QSharedPointer session(manager->d_func()->networkSession); + QSharedPointer session(manager->d_func()->getNetworkSession()); QVariant isBackground = backend->request().attribute(QNetworkRequest::BackgroundRequestAttribute, QVariant::fromValue(false)); if (isBackground.toBool() && session && session->usagePolicies().testFlag(QNetworkSession::NoBackgroundTrafficPolicy)) { error(QNetworkReply::BackgroundRequestNotAllowedError, @@ -288,7 +288,7 @@ void QNetworkReplyImplPrivate::_q_networkSessionConnected() if (manager.isNull()) return; - QNetworkSession *session = manager->d_func()->networkSession.data(); + QSharedPointer session = manager->d_func()->getNetworkSession(); if (!session) return; @@ -316,7 +316,7 @@ void QNetworkReplyImplPrivate::_q_networkSessionFailed() // Abort waiting and working replies. if (state == WaitingForSession || state == Working) { state = Working; - QSharedPointer session(manager->d_func()->networkSession); + QSharedPointer session(manager->d_func()->getNetworkSession()); QString errorStr; if (session) errorStr = session->errorString(); @@ -764,7 +764,7 @@ void QNetworkReplyImplPrivate::finished() if (!manager.isNull()) { #ifndef QT_NO_BEARERMANAGEMENT - QNetworkSession *session = manager->d_func()->networkSession.data(); + QSharedPointer session (manager->d_func()->getNetworkSession()); if (session && session->state() == QNetworkSession::Roaming && state == Working && errorCode != QNetworkReply::OperationCanceledError) { // only content with a known size will fail with a temporary network failure error