diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index f99869621f..d5f3007831 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 283bf86eea..f83dc4fb48 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 bd3dc3953d..94238db246 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 eb4edc8eee..5be59e20ce 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 377f2574ce..7cbbe389da 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