AusweisApp2/src/services/AppUpdater.cpp

154 lines
4.7 KiB
C++

/*!
* \copyright Copyright (c) 2016-2019 Governikus GmbH & Co. KG, Germany
*/
#include "AppUpdater.h"
#include "AppSettings.h"
#include "Downloader.h"
#include "ProviderConfiguration.h"
#include "SecureStorage.h"
#include "SingletonHelper.h"
#include "VersionNumber.h"
#if defined(Q_OS_WIN) || defined(Q_OS_MACOS) || (defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID))
#include "ReaderConfiguration.h"
#endif
#include <QLoggingCategory>
using namespace governikus;
defineSingleton(AppUpdater)
Q_DECLARE_LOGGING_CATEGORY(appupdate)
AppUpdater::AppUpdater()
: mIgnoreNextVersionskip(false)
, mAppUpdateJsonUrl()
, mAppUpdateData()
{
const auto* secureStorage = Env::getSingleton<SecureStorage>();
mAppUpdateJsonUrl = VersionNumber::getApplicationVersion().isDeveloperVersion() ? secureStorage->getAppcastBetaUpdateUrl() : secureStorage->getAppcastUpdateUrl();
}
AppUpdater& AppUpdater::getInstance()
{
return *Instance;
}
void AppUpdater::checkAppUpdate(bool pIgnoreNextVersionskip)
{
mIgnoreNextVersionskip = pIgnoreNextVersionskip;
mAppUpdateData = AppUpdateData();
auto* downloader = Env::getSingleton<Downloader>();
connect(downloader, &Downloader::fireDownloadSuccess, this, &AppUpdater::onUpdateDownloadFinished);
connect(downloader, &Downloader::fireDownloadFailed, this, &AppUpdater::onUpdateDownloadFailed);
connect(downloader, &Downloader::fireDownloadUnnecessary, this, &AppUpdater::onUpdateDownloadUnnecessary);
downloader->download(mAppUpdateJsonUrl);
}
const AppUpdateData& AppUpdater::getUpdateData() const
{
return mAppUpdateData;
}
void AppUpdater::skipVersion(const QString& pVersion)
{
qCInfo(appupdate) << "Skip application update:" << pVersion;
Env::getSingleton<AppSettings>()->getGeneralSettings().skipVersion(pVersion);
}
void AppUpdater::onUpdateDownloadFinished(const QUrl& pUpdateUrl, const QDateTime& pNewTimestamp, const QByteArray& pData)
{
Q_UNUSED(pNewTimestamp)
if (pUpdateUrl == mAppUpdateJsonUrl)
{
AppUpdateData newData = AppUpdateData::parse(pData);
if (newData.isValid())
{
mAppUpdateData = newData;
const auto& version = mAppUpdateData.getVersion();
if (VersionNumber(version) > VersionNumber::getApplicationVersion())
{
if (!mIgnoreNextVersionskip && version == Env::getSingleton<AppSettings>()->getGeneralSettings().getSkipVersion())
{
qCInfo(appupdate) << "Version will be skipped:" << version;
Q_EMIT fireAppUpdateCheckFinished(false, GlobalStatus::Code::No_Error);
}
else
{
mIgnoreNextVersionskip = false;
qCInfo(appupdate) << "Found new version:" << version << ", greater than old version" << QCoreApplication::applicationVersion();
Env::getSingleton<Downloader>()->download(mAppUpdateData.getNotesUrl());
return;
}
}
else
{
qCDebug(appupdate) << "No new version:" << version;
Q_EMIT fireAppUpdateCheckFinished(false, GlobalStatus::Code::No_Error);
}
}
else
{
Q_EMIT fireAppUpdateCheckFinished(false, newData.getParsingResult().getStatusCode());
}
clearDownloaderConnection();
}
if (pUpdateUrl == mAppUpdateData.getNotesUrl())
{
qCDebug(appupdate) << "Release notes downloaded successfully";
mAppUpdateData.setNotes(QString::fromUtf8(pData));
Q_EMIT fireAppUpdateCheckFinished(true, GlobalStatus::Code::No_Error);
clearDownloaderConnection();
}
}
void AppUpdater::onUpdateDownloadFailed(const QUrl& pUpdateUrl, GlobalStatus::Code pErrorCode)
{
if (pUpdateUrl == mAppUpdateJsonUrl)
{
qCDebug(appupdate) << "App Update JSON failed:" << GlobalStatus(pErrorCode).toErrorDescription();
Q_EMIT fireAppUpdateCheckFinished(false, pErrorCode);
clearDownloaderConnection();
return;
}
if (mAppUpdateData.isValid() && pUpdateUrl == mAppUpdateData.getNotesUrl())
{
qCDebug(appupdate) << "Release Notes Download failed:" << GlobalStatus(pErrorCode).toErrorDescription();
Q_EMIT fireAppUpdateCheckFinished(true, GlobalStatus::Code::No_Error);
clearDownloaderConnection();
}
}
void AppUpdater::onUpdateDownloadUnnecessary(const QUrl& pUpdateUrl)
{
if (pUpdateUrl == mAppUpdateJsonUrl || pUpdateUrl == mAppUpdateData.getNotesUrl())
{
qCCritical(appupdate) << "Got a DownloadUnnecessary from Downloader, but App Updates always have to be fresh, this should not be happening";
Q_EMIT fireAppUpdateCheckFinished(false, GlobalStatus::Code::Network_Other_Error);
clearDownloaderConnection();
}
}
void AppUpdater::clearDownloaderConnection()
{
auto* const downloader = Env::getSingleton<Downloader>();
disconnect(downloader, &Downloader::fireDownloadSuccess, this, &AppUpdater::onUpdateDownloadFinished);
disconnect(downloader, &Downloader::fireDownloadFailed, this, &AppUpdater::onUpdateDownloadFailed);
disconnect(downloader, &Downloader::fireDownloadUnnecessary, this, &AppUpdater::onUpdateDownloadUnnecessary);
}