diff --git a/launcher/net/ByteArraySink.h b/launcher/net/ByteArraySink.h index ac64052b9..f68230838 100644 --- a/launcher/net/ByteArraySink.h +++ b/launcher/net/ByteArraySink.h @@ -58,6 +58,7 @@ class ByteArraySink : public Sink { qWarning() << "ByteArraySink did not initialize the buffer because it's not addressable"; if (initAllValidators(request)) return Task::State::Running; + m_fail_reason = "Failed to initialize validators"; return Task::State::Failed; }; @@ -69,12 +70,14 @@ class ByteArraySink : public Sink { qWarning() << "ByteArraySink did not write the buffer because it's not addressable"; if (writeAllValidators(data)) return Task::State::Running; + m_fail_reason = "Failed to write validators"; return Task::State::Failed; } auto abort() -> Task::State override { failAllValidators(); + m_fail_reason = "Aborted"; return Task::State::Failed; } @@ -82,12 +85,13 @@ class ByteArraySink : public Sink { { if (finalizeAllValidators(reply)) return Task::State::Succeeded; + m_fail_reason = "Failed to finalize validators"; return Task::State::Failed; } auto hasLocalData() -> bool override { return false; } - private: + protected: std::shared_ptr m_output; }; } // namespace Net diff --git a/launcher/net/FileSink.cpp b/launcher/net/FileSink.cpp index 3a58a4667..1f519708f 100644 --- a/launcher/net/FileSink.cpp +++ b/launcher/net/FileSink.cpp @@ -51,6 +51,7 @@ Task::State FileSink::init(QNetworkRequest& request) // create a new save file and open it for writing if (!FS::ensureFilePathExists(m_filename)) { qCCritical(taskNetLogC) << "Could not create folder for " + m_filename; + m_fail_reason = "Could not create folder"; return Task::State::Failed; } @@ -58,11 +59,13 @@ Task::State FileSink::init(QNetworkRequest& request) m_output_file.reset(new PSaveFile(m_filename)); if (!m_output_file->open(QIODevice::WriteOnly)) { qCCritical(taskNetLogC) << "Could not open " + m_filename + " for writing"; + m_fail_reason = "Could not open file"; return Task::State::Failed; } if (initAllValidators(request)) return Task::State::Running; + m_fail_reason = "Failed to initialize validators"; return Task::State::Failed; } @@ -73,6 +76,7 @@ Task::State FileSink::write(QByteArray& data) m_output_file->cancelWriting(); m_output_file.reset(); m_wroteAnyData = false; + m_fail_reason = "Failed to write validators"; return Task::State::Failed; } @@ -105,13 +109,16 @@ Task::State FileSink::finalize(QNetworkReply& reply) if (gotFile || m_wroteAnyData) { // ask validators for data consistency // we only do this for actual downloads, not 'your data is still the same' cache hits - if (!finalizeAllValidators(reply)) + if (!finalizeAllValidators(reply)) { + m_fail_reason = "Failed to finalize validators"; return Task::State::Failed; + } // nothing went wrong... if (!m_output_file->commit()) { qCCritical(taskNetLogC) << "Failed to commit changes to " << m_filename; m_output_file->cancelWriting(); + m_fail_reason = "Failed to commit changes"; return Task::State::Failed; } } diff --git a/launcher/net/NetRequest.cpp b/launcher/net/NetRequest.cpp index ef533f599..7d8468a97 100644 --- a/launcher/net/NetRequest.cpp +++ b/launcher/net/NetRequest.cpp @@ -84,7 +84,8 @@ void NetRequest::executeTask() break; case State::Inactive: case State::Failed: - emit failed("Failed to initialize sink"); + m_failReason = m_sink->failReason(); + emit failed(m_sink->failReason()); emit finished(); return; case State::AbortedByUser: @@ -259,6 +260,7 @@ void NetRequest::downloadFinished() } else if (m_state == State::Failed) { qCDebug(logCat) << getUid().toString() << "Request failed in previous step:" << m_url.toString(); m_sink->abort(); + m_failReason = m_reply->errorString(); emit failed(m_reply->errorString()); emit finished(); return; @@ -278,7 +280,8 @@ void NetRequest::downloadFinished() if (m_state != State::Succeeded) { qCDebug(logCat) << getUid().toString() << "Request failed to write:" << m_url.toString(); m_sink->abort(); - emit failed("failed to write in sink"); + m_failReason = m_sink->failReason(); + emit failed(m_sink->failReason()); emit finished(); return; } @@ -289,7 +292,8 @@ void NetRequest::downloadFinished() if (m_state != State::Succeeded) { qCDebug(logCat) << getUid().toString() << "Request failed to finalize:" << m_url.toString(); m_sink->abort(); - emit failed("failed to finalize the request"); + m_failReason = m_sink->failReason(); + emit failed(m_sink->failReason()); emit finished(); return; } @@ -305,7 +309,7 @@ void NetRequest::downloadReadyRead() auto data = m_reply->readAll(); m_state = m_sink->write(data); if (m_state == State::Failed) { - qCCritical(logCat) << getUid().toString() << "Failed to process response chunk"; + qCCritical(logCat) << getUid().toString() << "Failed to process response chunk:" << m_sink->failReason(); } // qDebug() << "Request" << m_url.toString() << "gained" << data.size() << "bytes"; } else { diff --git a/launcher/net/Sink.h b/launcher/net/Sink.h index d1fd9de10..3f04cbd82 100644 --- a/launcher/net/Sink.h +++ b/launcher/net/Sink.h @@ -52,6 +52,8 @@ class Sink { virtual auto hasLocalData() -> bool = 0; + QString failReason() const { return m_fail_reason; } + void addValidator(Validator* validator) { if (validator) { @@ -95,5 +97,6 @@ class Sink { protected: std::vector> validators; + QString m_fail_reason; }; } // namespace Net diff --git a/launcher/screenshots/ImgurAlbumCreation.cpp b/launcher/screenshots/ImgurAlbumCreation.cpp index 7ee98760a..1355c74c0 100644 --- a/launcher/screenshots/ImgurAlbumCreation.cpp +++ b/launcher/screenshots/ImgurAlbumCreation.cpp @@ -86,6 +86,7 @@ auto ImgurAlbumCreation::Sink::write(QByteArray& data) -> Task::State auto ImgurAlbumCreation::Sink::abort() -> Task::State { m_output.clear(); + m_fail_reason = "Aborted"; return Task::State::Failed; } @@ -95,11 +96,13 @@ auto ImgurAlbumCreation::Sink::finalize(QNetworkReply&) -> Task::State QJsonDocument doc = QJsonDocument::fromJson(m_output, &jsonError); if (jsonError.error != QJsonParseError::NoError) { qDebug() << jsonError.errorString(); + m_fail_reason = "Invalid json reply"; return Task::State::Failed; } auto object = doc.object(); if (!object.value("success").toBool()) { qDebug() << doc.toJson(); + m_fail_reason = "Failed to create album"; return Task::State::Failed; } m_result->deleteHash = object.value("data").toObject().value("deletehash").toString(); diff --git a/launcher/screenshots/ImgurUpload.cpp b/launcher/screenshots/ImgurUpload.cpp index 8b4ef5327..835a1ab81 100644 --- a/launcher/screenshots/ImgurUpload.cpp +++ b/launcher/screenshots/ImgurUpload.cpp @@ -90,6 +90,7 @@ auto ImgurUpload::Sink::write(QByteArray& data) -> Task::State auto ImgurUpload::Sink::abort() -> Task::State { m_output.clear(); + m_fail_reason = "Aborted"; return Task::State::Failed; } @@ -99,11 +100,13 @@ auto ImgurUpload::Sink::finalize(QNetworkReply&) -> Task::State QJsonDocument doc = QJsonDocument::fromJson(m_output, &jsonError); if (jsonError.error != QJsonParseError::NoError) { qDebug() << "imgur server did not reply with JSON" << jsonError.errorString(); + m_fail_reason = "Invalid json reply"; return Task::State::Failed; } auto object = doc.object(); if (!object.value("success").toBool()) { qDebug() << "Screenshot upload not successful:" << doc.toJson(); + m_fail_reason = "Screenshot was not uploaded successfully"; return Task::State::Failed; } m_shot->m_imgurId = object.value("data").toObject().value("id").toString(); diff --git a/launcher/tasks/ConcurrentTask.cpp b/launcher/tasks/ConcurrentTask.cpp index ad2a14c42..5cff93017 100644 --- a/launcher/tasks/ConcurrentTask.cpp +++ b/launcher/tasks/ConcurrentTask.cpp @@ -118,10 +118,14 @@ void ConcurrentTask::executeNextSubTask() } if (m_queue.isEmpty()) { if (m_doing.isEmpty()) { - if (m_failed.isEmpty()) + if (m_failed.isEmpty()) { emitSucceeded(); - else + } else if (m_failed.count() == 1) { + auto task = m_failed.keys().first(); + emitFailed(task->failReason()); + } else { emitFailed(tr("One or more subtasks failed")); + } } return; }