diff --git a/src/gui/creds/oauth.cpp b/src/gui/creds/oauth.cpp index e711755b5..9926700f7 100644 --- a/src/gui/creds/oauth.cpp +++ b/src/gui/creds/oauth.cpp @@ -20,6 +20,7 @@ #include #include #include "theme.h" +#include "networkjobs.h" namespace OCC { @@ -82,9 +83,8 @@ void OAuth::start() requestToken.setPassword(Theme::instance()->oauthClientSecret()); QNetworkRequest req; req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - auto reply = _account->sendRequest("POST", requestToken, req); - QTimer::singleShot(30 * 1000, reply, &QNetworkReply::abort); - QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, socket] { + auto job = _account->sendRequest("POST", requestToken, req); + QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this, socket](QNetworkReply *reply) { auto jsonData = reply->readAll(); QJsonParseError jsonParseError; QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); diff --git a/src/libsync/abstractnetworkjob.cpp b/src/libsync/abstractnetworkjob.cpp index 070a0e689..55bbb0a72 100644 --- a/src/libsync/abstractnetworkjob.cpp +++ b/src/libsync/abstractnetworkjob.cpp @@ -120,15 +120,20 @@ QNetworkReply *AbstractNetworkJob::addTimer(QNetworkReply *reply) QNetworkReply *AbstractNetworkJob::sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *requestBody) { - auto reply = _account->sendRequest(verb, url, req, requestBody); + auto reply = _account->sendRawRequest(verb, url, req, requestBody); _requestBody = requestBody; if (_requestBody) { _requestBody->setParent(reply); } + adoptRequest(reply); + return reply; +} + +void AbstractNetworkJob::adoptRequest(QNetworkReply *reply) +{ addTimer(reply); setReply(reply); setupConnections(reply); - return reply; } QUrl AbstractNetworkJob::makeAccountUrl(const QString &relativePath) const diff --git a/src/libsync/abstractnetworkjob.h b/src/libsync/abstractnetworkjob.h index 03de2d458..ae61e0c58 100644 --- a/src/libsync/abstractnetworkjob.h +++ b/src/libsync/abstractnetworkjob.h @@ -126,6 +126,13 @@ protected: QNetworkRequest req = QNetworkRequest(), QIODevice *requestBody = 0); + /** Makes this job drive a pre-made QNetworkReply + * + * This reply cannot have a QIODevice request body because we can't get + * at it and thus not resend it in case of redirects. + */ + void adoptRequest(QNetworkReply *reply); + /// Creates a url for the account from a relative path QUrl makeAccountUrl(const QString &relativePath) const; diff --git a/src/libsync/account.cpp b/src/libsync/account.cpp index 2caa58713..d70e7ac9e 100644 --- a/src/libsync/account.cpp +++ b/src/libsync/account.cpp @@ -226,7 +226,7 @@ QSharedPointer Account::sharedNetworkAccessManager() return _am; } -QNetworkReply *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) +QNetworkReply *Account::sendRawRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) { req.setUrl(url); req.setSslConfiguration(this->getOrCreateSslConfig()); @@ -244,6 +244,13 @@ QNetworkReply *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNe return _am->sendCustomRequest(req, verb, data); } +SimpleNetworkJob *Account::sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req, QIODevice *data) +{ + auto job = new SimpleNetworkJob(sharedFromThis(), this); + job->startRequest(verb, url, req, data); + return job; +} + void Account::setSslConfiguration(const QSslConfiguration &config) { _sslConfiguration = config; diff --git a/src/libsync/account.h b/src/libsync/account.h index fa2ccb8f9..c9f361feb 100644 --- a/src/libsync/account.h +++ b/src/libsync/account.h @@ -44,6 +44,7 @@ class Account; typedef QSharedPointer AccountPtr; class QuotaInfo; class AccessManager; +class SimpleNetworkJob; /** @@ -114,9 +115,22 @@ public: AbstractCredentials *credentials() const; void setCredentials(AbstractCredentials *cred); + /** Create a network request on the account's QNAM. + * + * Network requests in AbstractNetworkJobs are created through + * this function. Other places should prefer to use jobs or + * sendRequest(). + */ + QNetworkReply *sendRawRequest(const QByteArray &verb, + const QUrl &url, + QNetworkRequest req = QNetworkRequest(), + QIODevice *data = 0); - // For creating various network requests - QNetworkReply *sendRequest(const QByteArray &verb, + /** Create and start network job for a simple one-off request. + * + * More complicated requests typically create their own job types. + */ + SimpleNetworkJob *sendRequest(const QByteArray &verb, const QUrl &url, QNetworkRequest req = QNetworkRequest(), QIODevice *data = 0); diff --git a/src/libsync/creds/httpcredentials.cpp b/src/libsync/creds/httpcredentials.cpp index 82c0c768d..53f4b89ce 100644 --- a/src/libsync/creds/httpcredentials.cpp +++ b/src/libsync/creds/httpcredentials.cpp @@ -303,10 +303,8 @@ bool HttpCredentials::refreshAccessToken() requestToken.setPassword(Theme::instance()->oauthClientSecret()); QNetworkRequest req; req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); - auto reply = _account->sendRequest("POST", requestToken, req); - QTimer::singleShot(30 * 1000, reply, &QNetworkReply::abort); - QObject::connect(reply, &QNetworkReply::finished, this, [this, reply] { - reply->deleteLater(); + auto job = _account->sendRequest("POST", requestToken, req); + QObject::connect(job, &SimpleNetworkJob::finishedSignal, this, [this](QNetworkReply *reply) { auto jsonData = reply->readAll(); QJsonParseError jsonParseError; QJsonObject json = QJsonDocument::fromJson(jsonData, &jsonParseError).object(); diff --git a/src/libsync/networkjobs.cpp b/src/libsync/networkjobs.cpp index 37fd1b71a..3a87571cf 100644 --- a/src/libsync/networkjobs.cpp +++ b/src/libsync/networkjobs.cpp @@ -886,4 +886,23 @@ void DetermineAuthTypeJob::send(const QUrl &url) sendRequest("GET", url, req); } +SimpleNetworkJob::SimpleNetworkJob(AccountPtr account, QObject *parent) + : AbstractNetworkJob(account, QString(), parent) +{ +} + +QNetworkReply *SimpleNetworkJob::startRequest(const QByteArray &verb, const QUrl &url, + QNetworkRequest req, QIODevice *requestBody) +{ + auto reply = sendRequest(verb, url, req, requestBody); + start(); + return reply; +} + +bool SimpleNetworkJob::finished() +{ + emit finishedSignal(reply()); + return true; +} + } // namespace OCC diff --git a/src/libsync/networkjobs.h b/src/libsync/networkjobs.h index 7992be25a..2965d5ae3 100644 --- a/src/libsync/networkjobs.h +++ b/src/libsync/networkjobs.h @@ -377,6 +377,28 @@ private: int _redirects; }; +/** + * @brief A basic job around a network request without extra funtionality + * @ingroup libsync + * + * Primarily adds timeout and redirection handling. + */ +class OWNCLOUDSYNC_EXPORT SimpleNetworkJob : public AbstractNetworkJob +{ + Q_OBJECT +public: + explicit SimpleNetworkJob(AccountPtr account, QObject *parent = 0); + + QNetworkReply *startRequest(const QByteArray &verb, const QUrl &url, + QNetworkRequest req = QNetworkRequest(), + QIODevice *requestBody = 0); + +signals: + void finishedSignal(QNetworkReply *reply); +private slots: + bool finished() Q_DECL_OVERRIDE; +}; + } // namespace OCC #endif // NETWORKJOBS_H