Merge branch 'master' of git://scm.dev.nokia.troll.no/qt/qtbase-earth-staging
* 'master' of git://scm.dev.nokia.troll.no/qt/qtbase-earth-staging: Skip test on MacOS due to problems with corewlan plugin Fix QNetworkConfigurationManager usage outside main thread first Update QTBUG-17223 for Qt 4.8 fix tst_qnetworkreply::httpProxyCommands autotest Send User-Agent from the network request in http proxy CONNECT command Add autotests for configuration dependent network proxies Fix QNetworkReplyImpl error handling Enable per network configuration proxy settings in QNetworkAccessManager Allow a network configuration to be included in a proxy query Fix error handling in write for socks socket engine
This commit is contained in:
commit
e8aceff195
@ -520,6 +520,15 @@ bool QHttpNetworkConnectionPrivate::dequeueRequest(QAbstractSocket *socket)
|
||||
return false;
|
||||
}
|
||||
|
||||
QHttpNetworkRequest QHttpNetworkConnectionPrivate::predictNextRequest()
|
||||
{
|
||||
if (!highPriorityQueue.isEmpty())
|
||||
return highPriorityQueue.last().first;
|
||||
if (!lowPriorityQueue.isEmpty())
|
||||
return lowPriorityQueue.last().first;
|
||||
return QHttpNetworkRequest();
|
||||
}
|
||||
|
||||
// this is called from _q_startNextRequest and when a request has been sent down a socket from the channel
|
||||
void QHttpNetworkConnectionPrivate::fillPipeline(QAbstractSocket *socket)
|
||||
{
|
||||
|
@ -169,6 +169,7 @@ public:
|
||||
void requeueRequest(const HttpMessagePair &pair); // e.g. after pipeline broke
|
||||
bool dequeueRequest(QAbstractSocket *socket);
|
||||
void prepareRequest(HttpMessagePair &request);
|
||||
QHttpNetworkRequest predictNextRequest();
|
||||
|
||||
void fillPipeline(QAbstractSocket *socket);
|
||||
bool fillPipeline(QList<HttpMessagePair> &queue, QHttpNetworkConnectionChannel &channel);
|
||||
|
@ -579,6 +579,17 @@ bool QHttpNetworkConnectionChannel::ensureConnection()
|
||||
connectHost = connection->d_func()->networkProxy.hostName();
|
||||
connectPort = connection->d_func()->networkProxy.port();
|
||||
}
|
||||
if (socket->proxy().type() == QNetworkProxy::HttpProxy) {
|
||||
// Make user-agent field available to HTTP proxy socket engine (QTBUG-17223)
|
||||
QByteArray value;
|
||||
// ensureConnection is called before any request has been assigned, but can also be called again if reconnecting
|
||||
if (request.url().isEmpty())
|
||||
value = connection->d_func()->predictNextRequest().headerField("user-agent");
|
||||
else
|
||||
value = request.headerField("user-agent");
|
||||
if (!value.isEmpty())
|
||||
socket->setProperty("_q_user-agent", value);
|
||||
}
|
||||
#endif
|
||||
if (ssl) {
|
||||
#ifndef QT_NO_OPENSSL
|
||||
|
@ -41,6 +41,7 @@
|
||||
|
||||
#include "qnetworkaccessbackend_p.h"
|
||||
#include "qnetworkaccessmanager_p.h"
|
||||
#include "qnetworkconfigmanager.h"
|
||||
#include "qnetworkrequest.h"
|
||||
#include "qnetworkreply.h"
|
||||
#include "qnetworkreply_p.h"
|
||||
@ -343,8 +344,6 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
|
||||
/*!
|
||||
Starts the backend. Returns true if the backend is started. Returns false if the backend
|
||||
could not be started due to an unopened or roaming session. The caller should recall this
|
||||
@ -352,31 +351,62 @@ void QNetworkAccessBackend::sslErrors(const QList<QSslError> &errors)
|
||||
*/
|
||||
bool QNetworkAccessBackend::start()
|
||||
{
|
||||
if (!manager->networkSession) {
|
||||
open();
|
||||
return true;
|
||||
}
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
// For bearer, check if session start is required
|
||||
if (manager->networkSession) {
|
||||
// session required
|
||||
if (manager->networkSession->isOpen() &&
|
||||
manager->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));
|
||||
} else {
|
||||
// Session not ready, but can skip for loopback connections
|
||||
|
||||
// This is not ideal.
|
||||
const QString host = reply->url.host();
|
||||
if (host == QLatin1String("localhost") ||
|
||||
QHostAddress(host) == QHostAddress::LocalHost ||
|
||||
QHostAddress(host) == QHostAddress::LocalHostIPv6) {
|
||||
// Don't need an open session for localhost access.
|
||||
open();
|
||||
return true;
|
||||
}
|
||||
// This is not ideal.
|
||||
const QString host = reply->url.host();
|
||||
|
||||
if (manager->networkSession->isOpen() &&
|
||||
manager->networkSession->state() == QNetworkSession::Connected) {
|
||||
//copy network session down to the backend
|
||||
setProperty("_q_networksession", QVariant::fromValue(manager->networkSession));
|
||||
open();
|
||||
return true;
|
||||
if (host == QLatin1String("localhost") ||
|
||||
QHostAddress(host) == QHostAddress::LocalHost ||
|
||||
QHostAddress(host) == QHostAddress::LocalHostIPv6) {
|
||||
// Don't need an open session for localhost access.
|
||||
} else {
|
||||
// need to wait for session to be opened
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
#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();
|
||||
QNetworkConfiguration config;
|
||||
if (session) {
|
||||
QNetworkConfigurationManager configManager;
|
||||
// The active configuration tells us what IAP is in use
|
||||
QVariant v = session->sessionProperty(QLatin1String("ActiveConfiguration"));
|
||||
if (v.isValid())
|
||||
config = configManager.configurationFromIdentifier(qvariant_cast<QString>(v));
|
||||
// Fallback to using the configuration if no active configuration
|
||||
if (!config.isValid())
|
||||
config = session->configuration();
|
||||
// or unspecified configuration if that is no good either
|
||||
if (!config.isValid())
|
||||
config = QNetworkConfiguration();
|
||||
}
|
||||
reply->proxyList = manager->queryProxy(QNetworkProxyQuery(config, url()));
|
||||
#else // QT_NO_BEARERMANAGEMENT
|
||||
// Without bearer management, the proxy depends only on the url
|
||||
reply->proxyList = manager->queryProxy(QNetworkProxyQuery(url()));
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// now start the request
|
||||
open();
|
||||
return true;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -1004,10 +1004,6 @@ QNetworkReply *QNetworkAccessManager::createRequest(QNetworkAccessManager::Opera
|
||||
// third step: find a backend
|
||||
priv->backend = d->findBackend(op, request);
|
||||
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
QList<QNetworkProxy> proxyList = d->queryProxy(QNetworkProxyQuery(request.url()));
|
||||
priv->proxyList = proxyList;
|
||||
#endif
|
||||
if (priv->backend) {
|
||||
priv->backend->setParent(reply);
|
||||
priv->backend->reply = priv;
|
||||
|
@ -89,10 +89,10 @@ void QNetworkReplyImplPrivate::_q_startOperation()
|
||||
return;
|
||||
}
|
||||
|
||||
if (!backend->start()) {
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
if (!backend->start()) { // ### we should call that method even if bearer is not used
|
||||
// backend failed to start because the session state is not Connected.
|
||||
// QNetworkAccessManager will call reply->backend->start() again for us when the session
|
||||
// QNetworkAccessManager will call _q_startOperation again for us when the session
|
||||
// state changes.
|
||||
state = WaitingForSession;
|
||||
|
||||
@ -108,11 +108,20 @@ void QNetworkReplyImplPrivate::_q_startOperation()
|
||||
session->open();
|
||||
} else {
|
||||
qWarning("Backend is waiting for QNetworkSession to connect, but there is none!");
|
||||
state = Working;
|
||||
error(QNetworkReplyImpl::UnknownNetworkError,
|
||||
QCoreApplication::translate("QNetworkReply", "Network session error."));
|
||||
finished();
|
||||
}
|
||||
|
||||
#else
|
||||
qWarning("Backend start failed");
|
||||
state = Working;
|
||||
error(QNetworkReplyImpl::UnknownNetworkError,
|
||||
QCoreApplication::translate("QNetworkReply", "backend start error."));
|
||||
finished();
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (backend && backend->isSynchronous()) {
|
||||
state = Finished;
|
||||
|
@ -385,8 +385,6 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
|
||||
this, SLOT(configurationRemoved(QNetworkConfigurationPrivatePointer)));
|
||||
connect(engine, SIGNAL(configurationChanged(QNetworkConfigurationPrivatePointer)),
|
||||
this, SLOT(configurationChanged(QNetworkConfigurationPrivatePointer)));
|
||||
|
||||
QMetaObject::invokeMethod(engine, "initialize");
|
||||
}
|
||||
}
|
||||
|
||||
@ -410,8 +408,19 @@ void QNetworkConfigurationManagerPrivate::updateConfigurations()
|
||||
startPolling();
|
||||
}
|
||||
|
||||
if (firstUpdate)
|
||||
if (firstUpdate) {
|
||||
firstUpdate = false;
|
||||
QList<QBearerEngine*> enginesToInitialize = sessionEngines; //shallow copy the list in case it is modified when we unlock mutex
|
||||
Qt::ConnectionType connectionType;
|
||||
if (QCoreApplicationPrivate::mainThread() == QThread::currentThread())
|
||||
connectionType = Qt::DirectConnection;
|
||||
else
|
||||
connectionType = Qt::BlockingQueuedConnection;
|
||||
locker.unlock();
|
||||
foreach (QBearerEngine* engine, enginesToInitialize) {
|
||||
QMetaObject::invokeMethod(engine, "initialize", connectionType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void QNetworkConfigurationManagerPrivate::performAsyncConfigurationUpdate()
|
||||
|
@ -228,6 +228,10 @@
|
||||
#include "qmutex.h"
|
||||
#include "qurl.h"
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
#include <QtNetwork/QNetworkConfiguration>
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
class QSocks5SocketEngineHandler;
|
||||
@ -716,6 +720,9 @@ public:
|
||||
QUrl remote;
|
||||
int localPort;
|
||||
QNetworkProxyQuery::QueryType type;
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
QNetworkConfiguration config;
|
||||
#endif
|
||||
};
|
||||
|
||||
template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
|
||||
@ -777,6 +784,11 @@ template<> void QSharedDataPointer<QNetworkProxyQueryPrivate>::detach()
|
||||
like choosing an caching HTTP proxy for HTTP-based connections,
|
||||
but a more powerful SOCKSv5 proxy for all others.
|
||||
|
||||
The network configuration specifies which configuration to use,
|
||||
when bearer management is used. For example on a mobile phone
|
||||
the proxy settings are likely to be different for the cellular
|
||||
network vs WLAN.
|
||||
|
||||
Some of the criteria may not make sense in all of the types of
|
||||
query. The following table lists the criteria that are most
|
||||
commonly used, according to the type of query.
|
||||
@ -902,6 +914,68 @@ QNetworkProxyQuery::QNetworkProxyQuery(quint16 bindPort, const QString &protocol
|
||||
d->type = queryType;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
/*!
|
||||
Constructs a QNetworkProxyQuery with the URL \a requestUrl and
|
||||
sets the query type to \a queryType. The specified \a networkConfiguration
|
||||
is used to resolve the proxy settings.
|
||||
|
||||
\sa protocolTag(), peerHostName(), peerPort(), networkConfiguration()
|
||||
*/
|
||||
QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
|
||||
const QUrl &requestUrl, QueryType queryType)
|
||||
{
|
||||
d->config = networkConfiguration;
|
||||
d->remote = requestUrl;
|
||||
d->type = queryType;
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QNetworkProxyQuery of type \a queryType and sets the
|
||||
protocol tag to be \a protocolTag. This constructor is suitable
|
||||
for QNetworkProxyQuery::TcpSocket queries, because it sets the
|
||||
peer hostname to \a hostname and the peer's port number to \a
|
||||
port. The specified \a networkConfiguration
|
||||
is used to resolve the proxy settings.
|
||||
|
||||
\sa networkConfiguration()
|
||||
*/
|
||||
QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
|
||||
const QString &hostname, int port,
|
||||
const QString &protocolTag,
|
||||
QueryType queryType)
|
||||
{
|
||||
d->config = networkConfiguration;
|
||||
d->remote.setScheme(protocolTag);
|
||||
d->remote.setHost(hostname);
|
||||
d->remote.setPort(port);
|
||||
d->type = queryType;
|
||||
}
|
||||
|
||||
/*!
|
||||
Constructs a QNetworkProxyQuery of type \a queryType and sets the
|
||||
protocol tag to be \a protocolTag. This constructor is suitable
|
||||
for QNetworkProxyQuery::TcpSocket queries because it sets the
|
||||
local port number to \a bindPort. The specified \a networkConfiguration
|
||||
is used to resolve the proxy settings.
|
||||
|
||||
Note that \a bindPort is of type quint16 to indicate the exact
|
||||
port number that is requested. The value of -1 (unknown) is not
|
||||
allowed in this context.
|
||||
|
||||
\sa localPort(), networkConfiguration()
|
||||
*/
|
||||
QNetworkProxyQuery::QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
|
||||
quint16 bindPort, const QString &protocolTag,
|
||||
QueryType queryType)
|
||||
{
|
||||
d->config = networkConfiguration;
|
||||
d->remote.setScheme(protocolTag);
|
||||
d->localPort = bindPort;
|
||||
d->type = queryType;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
Constructs a QNetworkProxyQuery object that is a copy of \a other.
|
||||
*/
|
||||
@ -1116,6 +1190,30 @@ void QNetworkProxyQuery::setUrl(const QUrl &url)
|
||||
d->remote = url;
|
||||
}
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
QNetworkConfiguration QNetworkProxyQuery::networkConfiguration() const
|
||||
{
|
||||
return d ? d->config : QNetworkConfiguration();
|
||||
}
|
||||
|
||||
/*!
|
||||
Sets the network configuration component of this QNetworkProxyQuery
|
||||
object to be \a networkConfiguration. The network configuration can
|
||||
be used to return different proxy settings based on the network in
|
||||
use, for example WLAN vs cellular networks on a mobile phone.
|
||||
|
||||
In the case of "user choice" or "service network" configurations,
|
||||
you should first start the QNetworkSession and obtain the active
|
||||
configuration from its properties.
|
||||
|
||||
\sa networkConfiguration
|
||||
*/
|
||||
void QNetworkProxyQuery::setNetworkConfiguration(const QNetworkConfiguration &networkConfiguration)
|
||||
{
|
||||
d->config = networkConfiguration;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*!
|
||||
\class QNetworkProxyFactory
|
||||
\brief The QNetworkProxyFactory class provides fine-grained proxy selection.
|
||||
|
@ -54,6 +54,7 @@ QT_BEGIN_NAMESPACE
|
||||
QT_MODULE(Network)
|
||||
|
||||
class QUrl;
|
||||
class QNetworkConfiguration;
|
||||
|
||||
class QNetworkProxyQueryPrivate;
|
||||
class Q_NETWORK_EXPORT QNetworkProxyQuery
|
||||
@ -73,6 +74,16 @@ public:
|
||||
QNetworkProxyQuery(quint16 bindPort, const QString &protocolTag = QString(),
|
||||
QueryType queryType = TcpServer);
|
||||
QNetworkProxyQuery(const QNetworkProxyQuery &other);
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
|
||||
const QUrl &requestUrl, QueryType queryType = UrlRequest);
|
||||
QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
|
||||
const QString &hostname, int port, const QString &protocolTag = QString(),
|
||||
QueryType queryType = TcpSocket);
|
||||
QNetworkProxyQuery(const QNetworkConfiguration &networkConfiguration,
|
||||
quint16 bindPort, const QString &protocolTag = QString(),
|
||||
QueryType queryType = TcpServer);
|
||||
#endif
|
||||
~QNetworkProxyQuery();
|
||||
QNetworkProxyQuery &operator=(const QNetworkProxyQuery &other);
|
||||
bool operator==(const QNetworkProxyQuery &other) const;
|
||||
@ -97,6 +108,11 @@ public:
|
||||
QUrl url() const;
|
||||
void setUrl(const QUrl &url);
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
QNetworkConfiguration networkConfiguration() const;
|
||||
void setNetworkConfiguration(const QNetworkConfiguration &networkConfiguration);
|
||||
#endif
|
||||
|
||||
private:
|
||||
QSharedDataPointer<QNetworkProxyQueryPrivate> d;
|
||||
};
|
||||
|
@ -58,6 +58,7 @@
|
||||
#include <commsdattypeinfov1_1.h> // CCDIAPRecord, CCDProxiesRecord
|
||||
#include <commsdattypesv1_1.h> // KCDTIdIAPRecord, KCDTIdProxiesRecord
|
||||
#include <QtNetwork/QNetworkConfigurationManager>
|
||||
#include <QtNetwork/QNetworkConfiguration>
|
||||
#include <QFlags>
|
||||
|
||||
using namespace CommsDat;
|
||||
@ -88,7 +89,7 @@ class SymbianProxyQuery
|
||||
{
|
||||
public:
|
||||
static QNetworkConfiguration findCurrentConfiguration(QNetworkConfigurationManager& configurationManager);
|
||||
static SymbianIapId getIapId(QNetworkConfigurationManager& configurationManager);
|
||||
static SymbianIapId getIapId(QNetworkConfigurationManager &configurationManager, const QNetworkProxyQuery &query);
|
||||
static CCDIAPRecord *getIapRecordLC(TUint32 aIAPId, CMDBSession &aDb);
|
||||
static CMDBRecordSet<CCDProxiesRecord> *prepareQueryLC(TUint32 serviceId, TDesC& serviceType);
|
||||
static QList<QNetworkProxy> proxyQueryL(TUint32 aIAPId, const QNetworkProxyQuery &query);
|
||||
@ -137,11 +138,15 @@ QNetworkConfiguration SymbianProxyQuery::findCurrentConfiguration(QNetworkConfig
|
||||
return currentConfig;
|
||||
}
|
||||
|
||||
SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager)
|
||||
SymbianIapId SymbianProxyQuery::getIapId(QNetworkConfigurationManager& configurationManager, const QNetworkProxyQuery &query)
|
||||
{
|
||||
SymbianIapId iapId;
|
||||
|
||||
QNetworkConfiguration currentConfig = findCurrentConfiguration(configurationManager);
|
||||
QNetworkConfiguration currentConfig = query.networkConfiguration();
|
||||
if (!currentConfig.isValid()) {
|
||||
//If config is not specified, then try to find out an active or default one
|
||||
currentConfig = findCurrentConfiguration(configurationManager);
|
||||
}
|
||||
if (currentConfig.isValid()) {
|
||||
// Note: the following code assumes that the identifier is in format
|
||||
// I_xxxx where xxxx is the identifier of IAP. This is meant as a
|
||||
@ -249,7 +254,7 @@ QList<QNetworkProxy> QNetworkProxyFactory::systemProxyForQuery(const QNetworkPro
|
||||
SymbianIapId iapId;
|
||||
TInt error;
|
||||
QNetworkConfigurationManager manager;
|
||||
iapId = SymbianProxyQuery::getIapId(manager);
|
||||
iapId = SymbianProxyQuery::getIapId(manager, query);
|
||||
if (iapId.isValid()) {
|
||||
TRAP(error, proxies = SymbianProxyQuery::proxyQueryL(iapId.iapId(), query))
|
||||
if (error != KErrNone) {
|
||||
|
@ -556,6 +556,10 @@ bool QAbstractSocketPrivate::initSocketLayer(QAbstractSocket::NetworkLayerProtoc
|
||||
q->setErrorString(QAbstractSocket::tr("Operation on socket is not supported"));
|
||||
return false;
|
||||
}
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
//copy user agent to socket engine (if it has been set)
|
||||
socketEngine->setProperty("_q_user-agent", q->property("_q_user-agent"));
|
||||
#endif
|
||||
if (!socketEngine->initialize(q->socketType(), protocol)) {
|
||||
#if defined (QABSTRACTSOCKET_DEBUG)
|
||||
qDebug("QAbstractSocketPrivate::initSocketLayer(%s, %s) failed (%s)",
|
||||
|
@ -501,7 +501,13 @@ void QHttpSocketEngine::slotSocketConnected()
|
||||
data += path;
|
||||
data += " HTTP/1.1\r\n";
|
||||
data += "Proxy-Connection: keep-alive\r\n"
|
||||
"User-Agent: Mozilla/5.0\r\n"
|
||||
"User-Agent: ";
|
||||
QVariant v = property("_q_user-agent");
|
||||
if (v.isValid())
|
||||
data += v.toByteArray();
|
||||
else
|
||||
data += "Mozilla/5.0";
|
||||
data += "\r\n"
|
||||
"Host: " + peerAddress + "\r\n";
|
||||
QAuthenticatorPrivate *priv = QAuthenticatorPrivate::getPrivate(d->authenticator);
|
||||
//qDebug() << "slotSocketConnected: priv=" << priv << (priv ? (int)priv->method : -1);
|
||||
|
@ -1540,8 +1540,13 @@ qint64 QSocks5SocketEngine::write(const char *data, qint64 len)
|
||||
// ### Handle this error.
|
||||
}
|
||||
|
||||
d->data->controlSocket->write(sealedBuf);
|
||||
qint64 written = d->data->controlSocket->write(sealedBuf);
|
||||
if (written <= 0) {
|
||||
QSOCKS5_Q_DEBUG << "native write returned" << written;
|
||||
return written;
|
||||
}
|
||||
d->data->controlSocket->waitForBytesWritten(0);
|
||||
//NB: returning len rather than written for the OK case, because the "sealing" may increase the length
|
||||
return len;
|
||||
#ifndef QT_NO_UDPSOCKET
|
||||
} else if (d->mode == QSocks5SocketEnginePrivate::UdpAssociateMode) {
|
||||
|
@ -1736,6 +1736,8 @@ void QSslSocket::connectToHostImplementation(const QString &hostName, quint16 po
|
||||
}
|
||||
#ifndef QT_NO_NETWORKPROXY
|
||||
d->plainSocket->setProxy(proxy());
|
||||
//copy user agent down to the plain socket (if it has been set)
|
||||
d->plainSocket->setProperty("_q_user-agent", property("_q_user-agent"));
|
||||
#endif
|
||||
QIODevice::open(openMode);
|
||||
d->plainSocket->connectToHost(hostName, port, openMode);
|
||||
|
@ -62,6 +62,7 @@ public slots:
|
||||
void cleanup();
|
||||
|
||||
private slots:
|
||||
void usedInThread(); // this test must be first, or it will falsely pass
|
||||
void allConfigurations();
|
||||
void defaultConfiguration();
|
||||
void configurationFromIdentifier();
|
||||
@ -329,6 +330,47 @@ void tst_QNetworkConfigurationManager::configurationFromIdentifier()
|
||||
QVERIFY(!invalid.isValid());
|
||||
}
|
||||
|
||||
class QNCMTestThread : public QThread
|
||||
{
|
||||
protected:
|
||||
virtual void run()
|
||||
{
|
||||
QNetworkConfigurationManager manager;
|
||||
preScanConfigs = manager.allConfigurations();
|
||||
QSignalSpy spy(&manager, SIGNAL(updateCompleted()));
|
||||
manager.updateConfigurations(); //initiate scans
|
||||
QTRY_VERIFY(spy.count() == 1); //wait for scan to complete
|
||||
configs = manager.allConfigurations();
|
||||
}
|
||||
public:
|
||||
QList<QNetworkConfiguration> configs;
|
||||
QList<QNetworkConfiguration> preScanConfigs;
|
||||
};
|
||||
|
||||
// regression test for QTBUG-18795
|
||||
void tst_QNetworkConfigurationManager::usedInThread()
|
||||
{
|
||||
#if defined Q_OS_MAC && !defined (QT_NO_COREWLAN)
|
||||
QSKIP("QTBUG-19070 Mac CoreWlan plugin is broken", SkipAll);
|
||||
#else
|
||||
QNCMTestThread thread;
|
||||
connect(&thread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
thread.start();
|
||||
QTestEventLoop::instance().enterLoop(100); //QTRY_VERIFY could take ~90 seconds to time out in the thread
|
||||
QVERIFY(thread.isFinished());
|
||||
qDebug() << "prescan:" << thread.preScanConfigs.count();
|
||||
qDebug() << "postscan:" << thread.configs.count();
|
||||
|
||||
QNetworkConfigurationManager manager;
|
||||
QList<QNetworkConfiguration> preScanConfigs = manager.allConfigurations();
|
||||
QSignalSpy spy(&manager, SIGNAL(updateCompleted()));
|
||||
manager.updateConfigurations(); //initiate scans
|
||||
QTRY_VERIFY(spy.count() == 1); //wait for scan to complete
|
||||
QList<QNetworkConfiguration> configs = manager.allConfigurations();
|
||||
QCOMPARE(thread.configs, configs);
|
||||
QCOMPARE(thread.preScanConfigs, preScanConfigs);
|
||||
#endif
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QNetworkConfigurationManager)
|
||||
#include "tst_qnetworkconfigurationmanager.moc"
|
||||
|
@ -7,5 +7,5 @@ QT = core network
|
||||
|
||||
SOURCES += tst_qnetworkproxyfactory.cpp
|
||||
|
||||
symbian: TARGET.CAPABILITY = NetworkServices
|
||||
symbian: TARGET.CAPABILITY = NetworkServices ReadUserData
|
||||
|
||||
|
@ -41,20 +41,64 @@
|
||||
|
||||
|
||||
#include <QtTest/QTest>
|
||||
#include <QtTest/QTestEventLoop>
|
||||
|
||||
#include <qcoreapplication.h>
|
||||
#include <qdebug.h>
|
||||
#include <qnetworkproxy.h>
|
||||
|
||||
#include <QNetworkConfiguration>
|
||||
#include <QNetworkConfigurationManager>
|
||||
#include <QNetworkSession>
|
||||
#include <QNetworkAccessManager>
|
||||
#include <QNetworkReply>
|
||||
#include <QNetworkRequest>
|
||||
#include <QList>
|
||||
|
||||
Q_DECLARE_METATYPE(QNetworkConfiguration);
|
||||
Q_DECLARE_METATYPE(QList<QNetworkProxy>);
|
||||
|
||||
#include <QThread>
|
||||
|
||||
class tst_QNetworkProxyFactory : public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
tst_QNetworkProxyFactory();
|
||||
|
||||
class QDebugProxyFactory : public QNetworkProxyFactory
|
||||
{
|
||||
public:
|
||||
virtual QList<QNetworkProxy> queryProxy(const QNetworkProxyQuery &query = QNetworkProxyQuery())
|
||||
{
|
||||
returnedList = QNetworkProxyFactory::systemProxyForQuery(query);
|
||||
requestCounter++;
|
||||
return returnedList;
|
||||
}
|
||||
QList<QNetworkProxy> returnedList;
|
||||
int requestCounter;
|
||||
};
|
||||
|
||||
private slots:
|
||||
void systemProxyForQueryCalledFromThread();
|
||||
void systemProxyForQuery() const;
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
void fromConfigurations();
|
||||
void inNetworkAccessManager_data();
|
||||
void inNetworkAccessManager();
|
||||
#endif
|
||||
|
||||
private:
|
||||
QString formatProxyName(const QNetworkProxy & proxy) const;
|
||||
QDebugProxyFactory *factory;
|
||||
};
|
||||
|
||||
tst_QNetworkProxyFactory::tst_QNetworkProxyFactory()
|
||||
{
|
||||
factory = new QDebugProxyFactory;
|
||||
QNetworkProxyFactory::setApplicationProxyFactory(factory);
|
||||
}
|
||||
|
||||
QString tst_QNetworkProxyFactory::formatProxyName(const QNetworkProxy & proxy) const
|
||||
{
|
||||
QString proxyName;
|
||||
@ -96,5 +140,136 @@ void tst_QNetworkProxyFactory::systemProxyForQuery() const
|
||||
QFAIL("One or more system proxy lookup failures occurred.");
|
||||
}
|
||||
|
||||
#ifndef QT_NO_BEARERMANAGEMENT
|
||||
|
||||
//Purpose of this test is just to check systemProxyForQuery doesn't hang or crash
|
||||
//with any given configuration including no configuration.
|
||||
//We can't test it returns the right proxies without implementing the native proxy code
|
||||
//again here, which would be testing our implementation against itself.
|
||||
//Therefore it's just testing that something valid is returned (at least a NoProxy entry)
|
||||
void tst_QNetworkProxyFactory::fromConfigurations()
|
||||
{
|
||||
QNetworkConfigurationManager manager;
|
||||
QList<QNetworkProxy> proxies;
|
||||
QUrl url(QLatin1String("http://qt.nokia.com"));
|
||||
//get from known configurations
|
||||
foreach (QNetworkConfiguration config, manager.allConfigurations()) {
|
||||
QNetworkProxyQuery query(config, url, QNetworkProxyQuery::UrlRequest);
|
||||
proxies = QNetworkProxyFactory::systemProxyForQuery(query);
|
||||
QVERIFY(!proxies.isEmpty());
|
||||
foreach (QNetworkProxy proxy, proxies) {
|
||||
qDebug() << config.name() << " - " << config.identifier() << " - " << formatProxyName(proxy);
|
||||
}
|
||||
}
|
||||
|
||||
//get from default configuration
|
||||
QNetworkProxyQuery defaultquery(url, QNetworkProxyQuery::UrlRequest);
|
||||
proxies = QNetworkProxyFactory::systemProxyForQuery(defaultquery);
|
||||
QVERIFY(!proxies.isEmpty());
|
||||
foreach (QNetworkProxy proxy, proxies) {
|
||||
qDebug() << "default - " << formatProxyName(proxy);
|
||||
}
|
||||
|
||||
//get from active configuration
|
||||
QNetworkSession session(manager.defaultConfiguration());
|
||||
session.open();
|
||||
QVERIFY(session.waitForOpened(30000));
|
||||
proxies = QNetworkProxyFactory::systemProxyForQuery(defaultquery);
|
||||
QVERIFY(!proxies.isEmpty());
|
||||
foreach (QNetworkProxy proxy, proxies) {
|
||||
qDebug() << "active - " << formatProxyName(proxy);
|
||||
}
|
||||
|
||||
//get from known configurations while there is one active
|
||||
foreach (QNetworkConfiguration config, manager.allConfigurations()) {
|
||||
QNetworkProxyQuery query(config, url, QNetworkProxyQuery::UrlRequest);
|
||||
proxies = QNetworkProxyFactory::systemProxyForQuery(query);
|
||||
QVERIFY(!proxies.isEmpty());
|
||||
foreach (QNetworkProxy proxy, proxies) {
|
||||
qDebug() << config.name() << " - " << config.identifier() << " - " << formatProxyName(proxy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void tst_QNetworkProxyFactory::inNetworkAccessManager_data()
|
||||
{
|
||||
QTest::addColumn<QNetworkConfiguration>("config");
|
||||
QTest::addColumn<QList<QNetworkProxy> >("proxies");
|
||||
QNetworkConfigurationManager manager;
|
||||
//get from known configurations
|
||||
foreach (QNetworkConfiguration config, manager.allConfigurations()) {
|
||||
QNetworkProxyQuery query(config, QUrl(QString("http://qt.nokia.com")), QNetworkProxyQuery::UrlRequest);
|
||||
QList<QNetworkProxy> proxies = QNetworkProxyFactory::systemProxyForQuery(query);
|
||||
QTest::newRow(config.name().toUtf8()) << config << proxies;
|
||||
}
|
||||
}
|
||||
|
||||
//Purpose of this test is to check that QNetworkAccessManager uses the proxy from the configuration it
|
||||
//has been given. Needs two or more working configurations to be a good test.
|
||||
void tst_QNetworkProxyFactory::inNetworkAccessManager()
|
||||
{
|
||||
QFETCH(QNetworkConfiguration, config);
|
||||
QFETCH(QList<QNetworkProxy>, proxies);
|
||||
|
||||
int count = factory->requestCounter;
|
||||
|
||||
QNetworkAccessManager manager;
|
||||
manager.setConfiguration(config);
|
||||
|
||||
//using an internet server, because cellular APs won't have a route to the test server.
|
||||
QNetworkRequest req(QUrl(QString("http://qt.nokia.com")));
|
||||
QNetworkReply *reply = manager.get(req);
|
||||
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
QTestEventLoop::instance().enterLoop(30);
|
||||
delete reply;
|
||||
|
||||
if (count == factory->requestCounter) {
|
||||
//RND phones are preconfigured with several test access points which won't work without a matching SIM
|
||||
//If the network fails to start, QNAM won't ask the factory for proxies so we can't test.
|
||||
QSKIP("network configuration didn't start", SkipSingle);
|
||||
}
|
||||
|
||||
qDebug() << "testing network configuration for" << config.name();
|
||||
foreach (QNetworkProxy proxy, factory->returnedList) {
|
||||
qDebug() << formatProxyName(proxy);
|
||||
}
|
||||
qDebug() << " <vs> ";
|
||||
foreach (QNetworkProxy proxy, proxies) {
|
||||
qDebug() << formatProxyName(proxy);
|
||||
}
|
||||
if (config.type() != QNetworkConfiguration::InternetAccessPoint)
|
||||
QEXPECT_FAIL("","QNetworkProxyFactory::systemProxyForQuery doesn't work for service networks yet", Continue);
|
||||
QCOMPARE(factory->returnedList, proxies);
|
||||
}
|
||||
|
||||
#endif //QT_NO_BEARERMANAGEMENT
|
||||
|
||||
|
||||
class QSPFQThread : public QThread
|
||||
{
|
||||
protected:
|
||||
virtual void run()
|
||||
{
|
||||
proxies = QNetworkProxyFactory::systemProxyForQuery(query);
|
||||
}
|
||||
public:
|
||||
QNetworkProxyQuery query;
|
||||
QList<QNetworkProxy> proxies;
|
||||
};
|
||||
|
||||
//regression test for QTBUG-18799
|
||||
void tst_QNetworkProxyFactory::systemProxyForQueryCalledFromThread()
|
||||
{
|
||||
QUrl url(QLatin1String("http://qt.nokia.com"));
|
||||
QNetworkProxyQuery query(url);
|
||||
QSPFQThread thread;
|
||||
thread.query = query;
|
||||
connect(&thread, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
thread.start();
|
||||
QTestEventLoop::instance().enterLoop(5);
|
||||
QVERIFY(thread.isFinished());
|
||||
QCOMPARE(thread.proxies, QNetworkProxyFactory::systemProxyForQuery(query));
|
||||
}
|
||||
|
||||
QTEST_MAIN(tst_QNetworkProxyFactory)
|
||||
#include "tst_qnetworkproxyfactory.moc"
|
||||
|
@ -4970,17 +4970,24 @@ void tst_QNetworkReply::httpProxyCommands()
|
||||
QNetworkProxy proxy(QNetworkProxy::HttpProxy, "127.0.0.1", proxyServer.serverPort());
|
||||
|
||||
manager.setProxy(proxy);
|
||||
QNetworkReplyPtr reply = manager.get(QNetworkRequest(url));
|
||||
manager.setProxy(QNetworkProxy());
|
||||
QNetworkRequest request(url);
|
||||
request.setRawHeader("User-Agent", "QNetworkReplyAutoTest/1.0");
|
||||
QNetworkReplyPtr reply = manager.get(request);
|
||||
//clearing the proxy here causes the test to fail.
|
||||
//the proxy isn't used until after the bearer has been started
|
||||
//which is correct in general, because system proxy isn't known until that time.
|
||||
//removing this line is safe, as the proxy is also reset by the cleanup() function
|
||||
//manager.setProxy(QNetworkProxy());
|
||||
|
||||
// wait for the finished signal
|
||||
connect(reply, SIGNAL(finished()), &QTestEventLoop::instance(), SLOT(exitLoop()));
|
||||
|
||||
QTestEventLoop::instance().enterLoop(1);
|
||||
QTestEventLoop::instance().enterLoop(15);
|
||||
|
||||
QVERIFY(!QTestEventLoop::instance().timeout());
|
||||
|
||||
//qDebug() << reply->error() << reply->errorString();
|
||||
//qDebug() << proxyServer.receivedData;
|
||||
|
||||
// we don't really care if the request succeeded
|
||||
// especially since it won't succeed in the HTTPS case
|
||||
@ -4988,6 +4995,12 @@ void tst_QNetworkReply::httpProxyCommands()
|
||||
|
||||
QString receivedHeader = proxyServer.receivedData.left(expectedCommand.length());
|
||||
QCOMPARE(receivedHeader, expectedCommand);
|
||||
|
||||
//QTBUG-17223 - make sure the user agent from the request is sent to proxy server even for CONNECT
|
||||
int uapos = proxyServer.receivedData.indexOf("User-Agent");
|
||||
int uaend = proxyServer.receivedData.indexOf("\r\n", uapos);
|
||||
QByteArray uaheader = proxyServer.receivedData.mid(uapos, uaend - uapos);
|
||||
QCOMPARE(uaheader, QByteArray("User-Agent: QNetworkReplyAutoTest/1.0"));
|
||||
}
|
||||
|
||||
class ProxyChangeHelper : public QObject {
|
||||
|
Loading…
x
Reference in New Issue
Block a user