From 83c3d769667fa58e2c67835b4f7c9ea6163d231a Mon Sep 17 00:00:00 2001 From: Markus Goetz Date: Tue, 24 Mar 2015 21:30:42 +0100 Subject: [PATCH] Proxy: Look up system proxy from different thread We should actually upstream this into QNAM. This is for #2993 and #2802 --- src/gui/owncloudsetupwizard.cpp | 3 ++ src/libsync/clientproxy.cpp | 47 ++++++++++++++++++++++++++++- src/libsync/clientproxy.h | 16 ++++++++-- src/libsync/connectionvalidator.cpp | 30 ++++++++++++++++++ src/libsync/connectionvalidator.h | 5 +++ 5 files changed, 98 insertions(+), 3 deletions(-) diff --git a/src/gui/owncloudsetupwizard.cpp b/src/gui/owncloudsetupwizard.cpp index 13c3b5544..509b26293 100644 --- a/src/gui/owncloudsetupwizard.cpp +++ b/src/gui/owncloudsetupwizard.cpp @@ -145,6 +145,9 @@ void OwncloudSetupWizard::slotDetermineAuthType(const QString &urlString) } AccountPtr account = _ocWizard->account(); account->setUrl(url); + // Reset the proxy which might had been determined previously in ConnectionValidator::checkServerAndAuth() + // when there was a previous account. + account->networkAccessManager()->setProxy(QNetworkProxy(QNetworkProxy::DefaultProxy)); // Set fake credentials beforfe we check what credential it actually is. account->setCredentials(CredentialsFactory::create("dummy")); CheckServerJob *job = new CheckServerJob(_ocWizard->account(), this); diff --git a/src/libsync/clientproxy.cpp b/src/libsync/clientproxy.cpp index 0ced12b4f..85b386414 100644 --- a/src/libsync/clientproxy.cpp +++ b/src/libsync/clientproxy.cpp @@ -15,6 +15,7 @@ #include "configfile.h" #include +#include namespace OCC { @@ -23,7 +24,7 @@ ClientProxy::ClientProxy(QObject *parent) : { } -QNetworkProxy ClientProxy::proxyFromConfig(const ConfigFile& cfg) +static QNetworkProxy proxyFromConfig(const ConfigFile& cfg) { QNetworkProxy proxy; @@ -39,6 +40,17 @@ QNetworkProxy ClientProxy::proxyFromConfig(const ConfigFile& cfg) return proxy; } +bool ClientProxy::isUsingSystemDefault() { + OCC::ConfigFile cfg; + + // if there is no config file, default to system proxy. + if( cfg.exists() ) { + return cfg.proxyType() == QNetworkProxy::DefaultProxy; + } + + return false; +} + void ClientProxy::setupQtProxyFromConfig() { OCC::ConfigFile cfg; @@ -57,15 +69,18 @@ void ClientProxy::setupQtProxyFromConfig() QNetworkProxy::setApplicationProxy(QNetworkProxy::NoProxy); break; case QNetworkProxy::DefaultProxy: + qDebug() << "Set proxy configuration to use system configuration"; QNetworkProxyFactory::setUseSystemConfiguration(true); break; case QNetworkProxy::Socks5Proxy: proxy.setType(QNetworkProxy::Socks5Proxy); + qDebug() << "Set proxy configuration to SOCKS5" << proxy; QNetworkProxyFactory::setUseSystemConfiguration(false); QNetworkProxy::setApplicationProxy(proxy); break; case QNetworkProxy::HttpProxy: proxy.setType(QNetworkProxy::HttpProxy); + qDebug() << "Set proxy configuration to HTTP" << proxy; QNetworkProxyFactory::setUseSystemConfiguration(false); QNetworkProxy::setApplicationProxy(proxy); break; @@ -96,6 +111,7 @@ const char* ClientProxy::proxyTypeToCStr(QNetworkProxy::ProxyType type) void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ) { +#ifdef USE_NEON /* Store proxy */ QList proxies = QNetworkProxyFactory::proxyForQuery(QNetworkProxyQuery(url)); // We set at least one in Application @@ -118,7 +134,36 @@ void ClientProxy::setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ) csync_set_module_property( csync_ctx, "proxy_port", &proxy_port ); csync_set_module_property( csync_ctx, "proxy_user", proxy.user().toUtf8().data()); csync_set_module_property( csync_ctx, "proxy_pwd", proxy.password().toUtf8().data()); +#endif +} + + +void ClientProxy::lookupSystemProxyAsync(const QUrl &url, QObject *dst, const char *slot) +{ + SystemProxyRunnable *runnable = new SystemProxyRunnable(url); + QObject::connect(runnable, SIGNAL(systemProxyLookedUp(QNetworkProxy)), dst, slot); + QThreadPool::globalInstance()->start(runnable); // takes ownership and deletes } +SystemProxyRunnable::SystemProxyRunnable(const QUrl &url) : QObject(), QRunnable(), _url(url) +{ + +} + +void SystemProxyRunnable::run() +{ + qDebug() << Q_FUNC_INFO << "Starting system proxy lookup"; + QList proxies = QNetworkProxyFactory::systemProxyForQuery(QNetworkProxyQuery(_url)); + qDebug() << Q_FUNC_INFO << proxies.count() << "proxies: " << proxies; + + if (proxies.isEmpty()) { + emit systemProxyLookedUp(QNetworkProxy(QNetworkProxy::NoProxy)); + } else { + emit systemProxyLookedUp(proxies.first()); + // FIXME Would we really ever return more? + } +} + + } diff --git a/src/libsync/clientproxy.h b/src/libsync/clientproxy.h index bf6e7360b..769152e8f 100644 --- a/src/libsync/clientproxy.h +++ b/src/libsync/clientproxy.h @@ -16,6 +16,7 @@ #include #include +#include #include #include "utility.h" @@ -30,17 +31,28 @@ class OWNCLOUDSYNC_EXPORT ClientProxy : public QObject public: explicit ClientProxy(QObject *parent = 0); -signals: + static bool isUsingSystemDefault(); + static void lookupSystemProxyAsync(const QUrl &url, QObject *dst, const char *slot); public slots: void setCSyncProxy( const QUrl& url, CSYNC *csync_ctx ); void setupQtProxyFromConfig(); private: - QNetworkProxy proxyFromConfig(const ConfigFile& cfg); const char* proxyTypeToCStr(QNetworkProxy::ProxyType type); }; +class SystemProxyRunnable : public QObject, public QRunnable { + Q_OBJECT +public: + SystemProxyRunnable(const QUrl &url); + void run(); +signals: + void systemProxyLookedUp(const QNetworkProxy &url); +private: + QUrl _url; +}; + } #endif // CLIENTPROXY_H diff --git a/src/libsync/connectionvalidator.cpp b/src/libsync/connectionvalidator.cpp index b9da29f6b..0e6043983 100644 --- a/src/libsync/connectionvalidator.cpp +++ b/src/libsync/connectionvalidator.cpp @@ -13,11 +13,13 @@ #include #include +#include #include "connectionvalidator.h" #include "theme.h" #include "account.h" #include "networkjobs.h" +#include "clientproxy.h" #include namespace OCC { @@ -63,6 +65,34 @@ void ConnectionValidator::checkServerAndAuth() } _isCheckingServerAndAuth = true; + // Lookup system proxy in a thread https://github.com/owncloud/client/issues/2993 + if (ClientProxy::isUsingSystemDefault()) { + qDebug() << "Trying to look up system proxy"; + ClientProxy::lookupSystemProxyAsync(_account->url(), + this, SLOT(systemProxyLookupDone(QNetworkProxy))); + } else { + // use a queued invocation so we're as asynchronous as with the other code path + QMetaObject::invokeMethod(this, "slotCheckServerAndAuth", Qt::QueuedConnection); + } +} + +void ConnectionValidator::systemProxyLookupDone(const QNetworkProxy &proxy) { + if (!_account) { + qDebug() << "Bailing out, Account had been deleted"; + return; + } + + if (proxy.type() != QNetworkProxy::DefaultProxy) { + qDebug() << Q_FUNC_INFO << "Setting QNAM proxy to be system proxy" << proxy; + _account->networkAccessManager()->setProxy(proxy); + } + + slotCheckServerAndAuth(); +} + +// The actual check +void ConnectionValidator::slotCheckServerAndAuth() +{ CheckServerJob *checkJob = new CheckServerJob(_account, this); checkJob->setIgnoreCredentialFailure(true); connect(checkJob, SIGNAL(instanceFound(QUrl,QVariantMap)), SLOT(slotStatusFound(QUrl,QVariantMap))); diff --git a/src/libsync/connectionvalidator.h b/src/libsync/connectionvalidator.h index f804d7f70..92ffae505 100644 --- a/src/libsync/connectionvalidator.h +++ b/src/libsync/connectionvalidator.h @@ -36,6 +36,8 @@ namespace OCC { *---> checkServerAndAuth (check status.php) + Will asynchronously check for system proxy (if using system proxy) + And then invoke slotCheckServerAndAuth CheckServerJob | +-> slotNoStatusFound --> X @@ -85,6 +87,7 @@ public: public slots: /// Checks the server and the authentication. void checkServerAndAuth(); + void systemProxyLookupDone(const QNetworkProxy &proxy); /// Checks authentication only. void checkAuthentication(); @@ -93,6 +96,8 @@ signals: void connectionResult( ConnectionValidator::Status status, QStringList errors ); protected slots: + void slotCheckServerAndAuth(); + void slotStatusFound(const QUrl&url, const QVariantMap &info); void slotNoStatusFound(QNetworkReply *reply); void slotJobTimeout(const QUrl& url); -- 2.30.2