diff options
-rw-r--r-- | src/network/access/qhttpnetworkconnectionchannel.cpp | 2 | ||||
-rw-r--r-- | src/network/access/qhttpnetworkreply_p.h | 1 | ||||
-rw-r--r-- | src/network/access/qhttpthreaddelegate.cpp | 9 | ||||
-rw-r--r-- | src/network/access/qhttpthreaddelegate_p.h | 2 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessbackend.cpp | 7 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessbackend_p.h | 1 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.cpp | 37 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager.h | 2 | ||||
-rw-r--r-- | src/network/access/qnetworkaccessmanager_p.h | 1 | ||||
-rw-r--r-- | src/network/access/qnetworkreply.cpp | 25 | ||||
-rw-r--r-- | src/network/access/qnetworkreply.h | 1 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyhttpimpl.cpp | 8 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyhttpimpl_p.h | 2 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl.cpp | 8 | ||||
-rw-r--r-- | src/network/access/qnetworkreplyimpl_p.h | 1 | ||||
-rw-r--r-- | tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp | 19 |
16 files changed, 126 insertions, 0 deletions
diff --git a/src/network/access/qhttpnetworkconnectionchannel.cpp b/src/network/access/qhttpnetworkconnectionchannel.cpp index 4dfed762f5..4b8fe8aca7 100644 --- a/src/network/access/qhttpnetworkconnectionchannel.cpp +++ b/src/network/access/qhttpnetworkconnectionchannel.cpp @@ -1225,6 +1225,8 @@ void QHttpNetworkConnectionChannel::_q_encrypted() if (!reply) connection->d_func()->dequeueRequest(socket); if (reply) + emit reply->encrypted(); + if (reply) sendRequest(); } diff --git a/src/network/access/qhttpnetworkreply_p.h b/src/network/access/qhttpnetworkreply_p.h index e849c66659..7aea9f14ec 100644 --- a/src/network/access/qhttpnetworkreply_p.h +++ b/src/network/access/qhttpnetworkreply_p.h @@ -142,6 +142,7 @@ public: void ignoreSslErrors(const QList<QSslError> &errors); Q_SIGNALS: + void encrypted(); void sslErrors(const QList<QSslError> &errors); #endif diff --git a/src/network/access/qhttpthreaddelegate.cpp b/src/network/access/qhttpthreaddelegate.cpp index 117265dbfb..a2cee48b22 100644 --- a/src/network/access/qhttpthreaddelegate.cpp +++ b/src/network/access/qhttpthreaddelegate.cpp @@ -315,6 +315,7 @@ void QHttpThreadDelegate::startRequest() connect(httpReply,SIGNAL(readyRead()), this, SLOT(readyReadSlot())); connect(httpReply,SIGNAL(dataReadProgress(qint64,qint64)), this, SLOT(dataReadProgressSlot(qint64,qint64))); #ifndef QT_NO_SSL + connect(httpReply,SIGNAL(encrypted()), this, SLOT(encryptedSlot())); connect(httpReply,SIGNAL(sslErrors(QList<QSslError>)), this, SLOT(sslErrorsSlot(QList<QSslError>))); #endif @@ -589,6 +590,14 @@ void QHttpThreadDelegate::cacheCredentialsSlot(const QHttpNetworkRequest &reques #ifndef QT_NO_SSL +void QHttpThreadDelegate::encryptedSlot() +{ + if (!httpReply) + return; + + emit encrypted(); +} + void QHttpThreadDelegate::sslErrorsSlot(const QList<QSslError> &errors) { if (!httpReply) diff --git a/src/network/access/qhttpthreaddelegate_p.h b/src/network/access/qhttpthreaddelegate_p.h index 86192c77cc..d9ef1a0a55 100644 --- a/src/network/access/qhttpthreaddelegate_p.h +++ b/src/network/access/qhttpthreaddelegate_p.h @@ -135,6 +135,7 @@ signals: void proxyAuthenticationRequired(const QNetworkProxy &, QAuthenticator *); #endif #ifndef QT_NO_SSL + void encrypted(); void sslErrors(const QList<QSslError> &, bool *, QList<QSslError> *); void sslConfigurationChanged(const QSslConfiguration); #endif @@ -164,6 +165,7 @@ protected slots: void dataReadProgressSlot(qint64 done, qint64 total); void cacheCredentialsSlot(const QHttpNetworkRequest &request, QAuthenticator *authenticator); #ifndef QT_NO_SSL + void encryptedSlot(); void sslErrorsSlot(const QList<QSslError> &errors); #endif diff --git a/src/network/access/qnetworkaccessbackend.cpp b/src/network/access/qnetworkaccessbackend.cpp index 84f9b82a22..a895864d76 100644 --- a/src/network/access/qnetworkaccessbackend.cpp +++ b/src/network/access/qnetworkaccessbackend.cpp @@ -340,6 +340,13 @@ void QNetworkAccessBackend::redirectionRequested(const QUrl &target) reply->redirectionRequested(target); } +void QNetworkAccessBackend::encrypted() +{ +#ifndef QT_NO_SSL + reply->encrypted(); +#endif +} + void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors) { #ifndef QT_NO_SSL diff --git a/src/network/access/qnetworkaccessbackend_p.h b/src/network/access/qnetworkaccessbackend_p.h index 23f8416e0e..bf284414e0 100644 --- a/src/network/access/qnetworkaccessbackend_p.h +++ b/src/network/access/qnetworkaccessbackend_p.h @@ -196,6 +196,7 @@ protected slots: void authenticationRequired(QAuthenticator *auth); void metaDataChanged(); void redirectionRequested(const QUrl &destination); + void encrypted(); void sslErrors(const QList<QSslError> &errors); void emitReplyUploadProgress(qint64 bytesSent, qint64 bytesTotal); diff --git a/src/network/access/qnetworkaccessmanager.cpp b/src/network/access/qnetworkaccessmanager.cpp index f185f7f695..b83b437b2c 100644 --- a/src/network/access/qnetworkaccessmanager.cpp +++ b/src/network/access/qnetworkaccessmanager.cpp @@ -374,6 +374,32 @@ static void ensureInitialized() */ /*! + \fn void QNetworkAccessManager::encrypted(QNetworkReply *reply) + \since 5.1 + + This signal is emitted when an SSL/TLS session has successfully + completed the initial handshake. At this point, no user data + has been transmitted. The signal can be used to perform + additional checks on the certificate chain, for example to + notify users when the certificate for a website has changed. The + \a reply parameter specifies which network reply is responsible. + If the reply does not match the expected criteria then it should + be aborted by calling QNetworkReply::abort() by a slot connected + to this signal. The SSL configuration in use can be inspected + using the QNetworkReply::sslConfiguration() method. + + Internally, QNetworkAccessManager may open multiple connections + to a server, in order to allow it process requests in parallel. + These connections may be reused, which means that the encrypted() + signal would not be emitted. This means that you are only + guaranteed to receive this signal for the first connection to a + site in the lifespan of the QNetworkAccessManager. + + \sa QSslSocket::encrypted() + \sa QNetworkReply::encrypted() +*/ + +/*! \fn void QNetworkAccessManager::sslErrors(QNetworkReply *reply, const QList<QSslError> &errors) This signal is emitted if the SSL/TLS session encountered errors @@ -1132,6 +1158,16 @@ void QNetworkAccessManagerPrivate::_q_replyFinished() #endif } +void QNetworkAccessManagerPrivate::_q_replyEncrypted() +{ +#ifndef QT_NO_SSL + Q_Q(QNetworkAccessManager); + QNetworkReply *reply = qobject_cast<QNetworkReply *>(q->sender()); + if (reply) + emit q->encrypted(reply); +#endif +} + void QNetworkAccessManagerPrivate::_q_replySslErrors(const QList<QSslError> &errors) { #ifndef QT_NO_SSL @@ -1152,6 +1188,7 @@ QNetworkReply *QNetworkAccessManagerPrivate::postProcess(QNetworkReply *reply) #ifndef QT_NO_SSL /* In case we're compiled without SSL support, we don't have this signal and we need to * avoid getting a connection error. */ + q->connect(reply, SIGNAL(encrypted()), SLOT(_q_replyEncrypted())); q->connect(reply, SIGNAL(sslErrors(QList<QSslError>)), SLOT(_q_replySslErrors(QList<QSslError>))); #endif #ifndef QT_NO_BEARERMANAGEMENT diff --git a/src/network/access/qnetworkaccessmanager.h b/src/network/access/qnetworkaccessmanager.h index 0caba127fc..826c8e47d7 100644 --- a/src/network/access/qnetworkaccessmanager.h +++ b/src/network/access/qnetworkaccessmanager.h @@ -139,6 +139,7 @@ Q_SIGNALS: void authenticationRequired(QNetworkReply *reply, QAuthenticator *authenticator); void finished(QNetworkReply *reply); #ifndef QT_NO_SSL + void encrypted(QNetworkReply *reply); void sslErrors(QNetworkReply *reply, const QList<QSslError> &errors); #endif @@ -159,6 +160,7 @@ private: Q_DECLARE_PRIVATE(QNetworkAccessManager) Q_PRIVATE_SLOT(d_func(), void _q_replyFinished()) + Q_PRIVATE_SLOT(d_func(), void _q_replyEncrypted()) Q_PRIVATE_SLOT(d_func(), void _q_replySslErrors(QList<QSslError>)) #ifndef QT_NO_BEARERMANAGEMENT Q_PRIVATE_SLOT(d_func(), void _q_networkSessionClosed()) diff --git a/src/network/access/qnetworkaccessmanager_p.h b/src/network/access/qnetworkaccessmanager_p.h index b4ad3511fa..cf756dad7b 100644 --- a/src/network/access/qnetworkaccessmanager_p.h +++ b/src/network/access/qnetworkaccessmanager_p.h @@ -90,6 +90,7 @@ public: ~QNetworkAccessManagerPrivate(); void _q_replyFinished(); + void _q_replyEncrypted(); void _q_replySslErrors(const QList<QSslError> &errors); QNetworkReply *postProcess(QNetworkReply *reply); void createCookieJar() const; diff --git a/src/network/access/qnetworkreply.cpp b/src/network/access/qnetworkreply.cpp index fd3b7760cb..dc42adc612 100644 --- a/src/network/access/qnetworkreply.cpp +++ b/src/network/access/qnetworkreply.cpp @@ -195,6 +195,31 @@ QNetworkReplyPrivate::QNetworkReplyPrivate() */ /*! + \fn void QNetworkReply::encrypted() + \since 5.1 + + This signal is emitted when an SSL/TLS session has successfully + completed the initial handshake. At this point, no user data + has been transmitted. The signal can be used to perform + additional checks on the certificate chain, for example to + notify users when the certificate for a website has changed. + If the reply does not match the expected criteria then it should + be aborted by calling QNetworkReply::abort() by a slot connected + to this signal. The SSL configuration in use can be inspected + using the QNetworkReply::sslConfiguration() method. + + Internally, QNetworkAccessManager may open multiple connections + to a server, in order to allow it process requests in parallel. + These connections may be reused, which means that the encrypted() + signal would not be emitted. This means that you are only + guaranteed to receive this signal for the first connection to a + site in the lifespan of the QNetworkAccessManager. + + \sa QSslSocket::encrypted() + \sa QNetworkAccessManager::encrypted() +*/ + +/*! \fn void QNetworkReply::sslErrors(const QList<QSslError> &errors) This signal is emitted if the SSL/TLS session encountered errors diff --git a/src/network/access/qnetworkreply.h b/src/network/access/qnetworkreply.h index 39901aafb6..a7db2d189c 100644 --- a/src/network/access/qnetworkreply.h +++ b/src/network/access/qnetworkreply.h @@ -148,6 +148,7 @@ Q_SIGNALS: void finished(); void error(QNetworkReply::NetworkError); #ifndef QT_NO_SSL + void encrypted(); void sslErrors(const QList<QSslError> &errors); #endif diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp index 522965c104..c04421e5c7 100644 --- a/src/network/access/qnetworkreplyhttpimpl.cpp +++ b/src/network/access/qnetworkreplyhttpimpl.cpp @@ -830,6 +830,8 @@ void QNetworkReplyHttpImplPrivate::postRequest() Qt::BlockingQueuedConnection); #endif #ifndef QT_NO_SSL + QObject::connect(delegate, SIGNAL(encrypted()), q, SLOT(replyEncrypted()), + Qt::BlockingQueuedConnection); QObject::connect(delegate, SIGNAL(sslErrors(QList<QSslError>,bool*,QList<QSslError>*)), q, SLOT(replySslErrors(QList<QSslError>,bool*,QList<QSslError>*)), Qt::BlockingQueuedConnection); @@ -1220,6 +1222,12 @@ void QNetworkReplyHttpImplPrivate::httpError(QNetworkReply::NetworkError errorCo } #ifndef QT_NO_SSL +void QNetworkReplyHttpImplPrivate::replyEncrypted() +{ + Q_Q(QNetworkReplyHttpImpl); + emit q->encrypted(); +} + void QNetworkReplyHttpImplPrivate::replySslErrors( const QList<QSslError> &list, bool *ignoreAll, QList<QSslError> *toBeIgnored) { diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h index 5f8f0badf7..15cc0ec476 100644 --- a/src/network/access/qnetworkreplyhttpimpl_p.h +++ b/src/network/access/qnetworkreplyhttpimpl_p.h @@ -116,6 +116,7 @@ public: Q_PRIVATE_SLOT(d_func(), void httpAuthenticationRequired(const QHttpNetworkRequest &, QAuthenticator *)) Q_PRIVATE_SLOT(d_func(), void httpError(QNetworkReply::NetworkError, const QString &)) #ifndef QT_NO_SSL + Q_PRIVATE_SLOT(d_func(), void replyEncrypted()) Q_PRIVATE_SLOT(d_func(), void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *)) Q_PRIVATE_SLOT(d_func(), void replySslConfigurationChanged(const QSslConfiguration&)) #endif @@ -280,6 +281,7 @@ public: void httpAuthenticationRequired(const QHttpNetworkRequest &request, QAuthenticator *auth); void httpError(QNetworkReply::NetworkError error, const QString &errorString); #ifndef QT_NO_SSL + void replyEncrypted(); void replySslErrors(const QList<QSslError> &, bool *, QList<QSslError> *); void replySslConfigurationChanged(const QSslConfiguration&); #endif diff --git a/src/network/access/qnetworkreplyimpl.cpp b/src/network/access/qnetworkreplyimpl.cpp index e12286c459..33357293a3 100644 --- a/src/network/access/qnetworkreplyimpl.cpp +++ b/src/network/access/qnetworkreplyimpl.cpp @@ -879,6 +879,14 @@ void QNetworkReplyImplPrivate::redirectionRequested(const QUrl &target) attributes.insert(QNetworkRequest::RedirectionTargetAttribute, target); } +void QNetworkReplyImplPrivate::encrypted() +{ +#ifndef QT_NO_SSL + Q_Q(QNetworkReplyImpl); + emit q->encrypted(); +#endif +} + void QNetworkReplyImplPrivate::sslErrors(const QList<QSslError> &errors) { #ifndef QT_NO_SSL diff --git a/src/network/access/qnetworkreplyimpl_p.h b/src/network/access/qnetworkreplyimpl_p.h index ca9a3b5fd1..9edc0f6b59 100644 --- a/src/network/access/qnetworkreplyimpl_p.h +++ b/src/network/access/qnetworkreplyimpl_p.h @@ -176,6 +176,7 @@ public: void error(QNetworkReply::NetworkError code, const QString &errorString); void metaDataChanged(); void redirectionRequested(const QUrl &target); + void encrypted(); void sslErrors(const QList<QSslError> &errors); QNetworkAccessBackend *backend; diff --git a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp index 4847dedac4..bcc0641973 100644 --- a/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp +++ b/tests/auto/network/access/qnetworkreply/tst_qnetworkreply.cpp @@ -361,6 +361,7 @@ private Q_SLOTS: void ignoreSslErrorsList(); void ignoreSslErrorsListWithSlot_data(); void ignoreSslErrorsListWithSlot(); + void encrypted(); void sslConfiguration_data(); void sslConfiguration(); #ifdef QT_BUILD_INTERNAL @@ -5867,6 +5868,24 @@ void tst_QNetworkReply::sslConfiguration_data() QTest::newRow("secure") << conf << true; } +void tst_QNetworkReply::encrypted() +{ + qDebug() << QtNetworkSettings::serverName(); + QUrl url("https://" + QtNetworkSettings::serverName()); + QNetworkRequest request(url); + QNetworkReply *reply = manager.get(request); + reply->ignoreSslErrors(); + + QSignalSpy spy(reply, SIGNAL(encrypted())); + connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop())); + QTestEventLoop::instance().enterLoop(20); + QVERIFY(!QTestEventLoop::instance().timeout()); + + QCOMPARE(spy.count(), 1); + + reply->deleteLater(); +} + void tst_QNetworkReply::sslConfiguration() { QNetworkRequest request(QUrl("https://" + QtNetworkSettings::serverName() + "/index.html")); |