diff --git a/src/components/file/FileDownloader.cpp b/src/components/file/FileDownloader.cpp index ff4f45f4d..ecf988242 100644 --- a/src/components/file/FileDownloader.cpp +++ b/src/components/file/FileDownloader.cpp @@ -81,25 +81,28 @@ void FileDownloader::download () { QNetworkReply *data = mNetworkReply.data(); + QObject::connect(data, &QNetworkReply::readyRead, this, &FileDownloader::handleReadyData); + QObject::connect(data, &QNetworkReply::finished, this, &FileDownloader::handleDownloadFinished); + QObject::connect(data, QNonConstOverload::of(&QNetworkReply::error), this, &FileDownloader::handleError); + QObject::connect(data, &QNetworkReply::downloadProgress, this, &FileDownloader::handleDownloadProgress); + #if QT_CONFIG(ssl) QObject::connect(data, &QNetworkReply::sslErrors, this, &FileDownloader::handleSslErrors); #endif - QObject::connect(data, &QNetworkReply::downloadProgress, this, &FileDownloader::handleDownloadProgress); - QObject::connect(data, &QNetworkReply::readyRead, this, &FileDownloader::handleReadyData); - QObject::connect(data, &QNetworkReply::finished, this, &FileDownloader::handleDownloadFinished); - if (mDownloadFolder.isEmpty()) { mDownloadFolder = CoreManager::getInstance()->getSettingsModel()->getDownloadFolder(); emit downloadFolderChanged(mDownloadFolder); } - // TODO: Deal with connection error like timeout. - Q_ASSERT(!mDestinationFile.isOpen()); mDestinationFile.setFileName(getDownloadFilePath(QDir::cleanPath(mDownloadFolder) + QDir::separator(), mUrl)); if (!mDestinationFile.open(QIODevice::WriteOnly)) emitOutputError(); + else { + mTimeoutReadBytes = 0; + mTimeout.start(); + } } bool FileDownloader::remove () { @@ -112,6 +115,12 @@ void FileDownloader::emitOutputError () { mNetworkReply->abort(); } +void FileDownloader::cleanDownloadEnd () { + mTimeout.stop(); + mNetworkReply->deleteLater(); + setDownloading(false); +} + void FileDownloader::handleReadyData () { QByteArray data = mNetworkReply->readAll(); if (mDestinationFile.write(data) == -1) @@ -119,27 +128,32 @@ void FileDownloader::handleReadyData () { } void FileDownloader::handleDownloadFinished() { - QNetworkReply::NetworkError error = mNetworkReply->error(); - if (error != QNetworkReply::NoError) { - if (error != QNetworkReply::OperationCanceledError) - qWarning() << QStringLiteral("Download of %1 failed: %2") - .arg(mUrl.toString()).arg(mNetworkReply->errorString()); + if (mNetworkReply->error() != QNetworkReply::NoError) + return; + + // TODO: Deal with redirection. + if (isHttpRedirect(mNetworkReply)) { + qWarning() << QStringLiteral("Request was redirected."); mDestinationFile.remove(); emit downloadFailed(); } else { - // TODO: Deal with redirection. - if (isHttpRedirect(mNetworkReply)) { - qWarning() << QStringLiteral("Request was redirected."); - mDestinationFile.remove(); - emit downloadFailed(); - } else { - mDestinationFile.close(); - emit downloadFinished(mDestinationFile.fileName()); - } + qInfo() << QStringLiteral("Download of %1 finished.").arg(mUrl.toString()); + mDestinationFile.close(); + emit downloadFinished(mDestinationFile.fileName()); } - mNetworkReply->deleteLater(); - setDownloading(false); + cleanDownloadEnd(); +} + +void FileDownloader::handleError (QNetworkReply::NetworkError code) { + if (code != QNetworkReply::OperationCanceledError) + qWarning() << QStringLiteral("Download of %1 failed: %2") + .arg(mUrl.toString()).arg(mNetworkReply->errorString()); + mDestinationFile.remove(); + + cleanDownloadEnd(); + + emit downloadFailed(); } void FileDownloader::handleSslErrors (const QList &sslErrors) { @@ -151,6 +165,14 @@ void FileDownloader::handleSslErrors (const QList &sslErrors) { #endif } +void FileDownloader::handleTimeout () { + if (mReadBytes == mTimeoutReadBytes) { + qWarning() << QStringLiteral("Download of %1 failed: timeout.").arg(mUrl.toString()); + mNetworkReply->abort(); + } else + mTimeoutReadBytes = mReadBytes; +} + void FileDownloader::handleDownloadProgress (qint64 readBytes, qint64 totalBytes) { setReadBytes(readBytes); setTotalBytes(totalBytes); diff --git a/src/components/file/FileDownloader.hpp b/src/components/file/FileDownloader.hpp index 691a875d0..4c845a022 100644 --- a/src/components/file/FileDownloader.hpp +++ b/src/components/file/FileDownloader.hpp @@ -42,7 +42,13 @@ class FileDownloader : public QObject { Q_PROPERTY(bool downloading READ getDownloading NOTIFY downloadingChanged); public: - FileDownloader (QObject *parent = Q_NULLPTR) : QObject(parent) {} + FileDownloader (QObject *parent = Q_NULLPTR) : QObject(parent) { + // See: https://bugreports.qt.io/browse/QTBUG-57390 + mTimeout.setInterval(DefaultTimeout); + QObject::connect(&mTimeout, &QTimer::timeout, this, &FileDownloader::handleTimeout); + } + + ~FileDownloader () { if (mNetworkReply) mNetworkReply->abort(); } Q_INVOKABLE void download (); Q_INVOKABLE bool remove(); @@ -74,10 +80,14 @@ private: void emitOutputError (); + void cleanDownloadEnd (); + void handleReadyData (); void handleDownloadFinished (); + void handleError (QNetworkReply::NetworkError code); void handleSslErrors (const QList &errors); + void handleTimeout (); void handleDownloadProgress (qint64 readBytes, qint64 totalBytes); QUrl mUrl; @@ -90,6 +100,11 @@ private: QPointer mNetworkReply; QNetworkAccessManager mManager; + + qint64 mTimeoutReadBytes; + QTimer mTimeout; + + static constexpr int DefaultTimeout = 5000; }; #endif // FILE_DOWNLOADER_H_ diff --git a/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml b/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml index 6e1e1cf81..060e018e9 100644 --- a/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml +++ b/ui/modules/Linphone/Dialog/OnlineInstallerDialog.qml @@ -32,8 +32,12 @@ DialogPlus { function _endInstall (exitStatus) { if (dialog.extract) { fileDownloader.remove() - Utils.write(installFolder + mime + '.txt', downloadUrl) } + + if (exitStatus === 1) { + Utils.write(installFolder + mime + '.txt', downloadUrl) + } + dialog._exitStatus = exitStatus dialog._installing = false }