Commit d71d3889 authored by Aleix Pol Gonzalez's avatar Aleix Pol Gonzalez 🐧

Revert "fwupd: Port away from querying from another thread"

Required Fwupd API is too new for our CI

This reverts commit 96959195.
parent 96959195
......@@ -8,7 +8,7 @@ set(fwupd-backend_SRCS
)
add_library(fwupd-backend MODULE ${fwupd-backend_SRCS})
target_link_libraries(fwupd-backend Qt5::Core KF5::CoreAddons KF5::ConfigCore Discover::Common PkgConfig::Fwupd)
target_link_libraries(fwupd-backend Qt5::Core Qt5::Widgets Qt5::Concurrent KF5::CoreAddons KF5::ConfigCore Discover::Common PkgConfig::Fwupd)
install(TARGETS fwupd-backend DESTINATION ${PLUGIN_INSTALL_DIR}/discover)
......@@ -13,7 +13,7 @@
#include <resources/SourcesModel.h>
#include <Transaction/Transaction.h>
#include <QCoreApplication>
#include <QtConcurrent>
#include <KAboutData>
#include <KLocalizedString>
#include <KPluginFactory>
......@@ -28,7 +28,6 @@ FwupdBackend::FwupdBackend(QObject* parent)
, m_updater(new StandardBackendUpdater(this))
, m_cancellable(g_cancellable_new())
{
fwupd_client_set_user_agent_for_package(client, "plasma-discover", "1.0");
connect(m_updater, &StandardBackendUpdater::updatesCountChanged, this, &FwupdBackend::updatesCountChanged);
SourcesModel::global()->addSourcesBackend(new FwupdSourcesBackend(this));
......@@ -50,6 +49,9 @@ QMap<GChecksumType, QCryptographicHash::Algorithm> FwupdBackend::gchecksumToQChr
FwupdBackend::~FwupdBackend()
{
g_cancellable_cancel(m_cancellable);
if (!m_threadPool.waitForDone(200))
qWarning("Could not stop all fwupd threads");
m_threadPool.clear();
g_object_unref(m_cancellable);
g_object_unref(client);
......@@ -221,6 +223,113 @@ FwupdResource* FwupdBackend::createApp(FwupdDevice *device)
return app.take();
}
bool FwupdBackend::downloadFile(const QUrl &uri, const QString &filename)
{
Q_ASSERT(QThread::currentThread() != QCoreApplication::instance()->thread());
QScopedPointer<QNetworkAccessManager> manager(new QNetworkAccessManager);
QEventLoop loop;
QTimer getTimer;
connect(&getTimer, &QTimer::timeout, &loop, &QEventLoop::quit);
connect(manager.data(), &QNetworkAccessManager::finished, &loop, &QEventLoop::quit);
QScopedPointer<QNetworkReply> reply(manager->get(QNetworkRequest(uri)));
getTimer.start(600000); // 60 Seconds TimeOout Period
loop.exec();
if (!reply)
{
return false;
} else if (QNetworkReply::NoError != reply->error() ) {
qWarning() << "error fetching" << uri;
return false;
} else if (reply->error() == QNetworkReply::NoError) {
QFile file(filename);
if (file.open(QIODevice::WriteOnly)) {
file.write(reply->readAll());
} else {
qWarning() << "Fwupd Error: Cannot Open File to write Data" << filename;
}
}
return true;
}
void FwupdBackend::refreshRemote(FwupdBackend* backend, FwupdRemote* remote, quint64 cacheAge, GCancellable *cancellable)
{
if (!fwupd_remote_get_filename_cache_sig(remote))
{
qWarning() << "Fwupd Error: " << "Remote " << fwupd_remote_get_id(remote) << "has no cache signature!";
return;
}
/* check cache age */
if (cacheAge > 0)
{
const quint64 age = fwupd_remote_get_age(remote);
if (age < cacheAge)
{
// qDebug() << "Fwupd Info:" << fwupd_remote_get_id(remote) << "is only" << age << "seconds old, so ignoring refresh! ";
return;
}
}
const QString cacheId = QStringLiteral("fwupd/remotes.d/%1").arg(QString::fromUtf8(fwupd_remote_get_id(remote)));
const auto basenameSig = QString::fromUtf8(g_path_get_basename(fwupd_remote_get_filename_cache_sig(remote)));
const QString filenameSig = cacheFile(cacheId, basenameSig);
if (filenameSig.isEmpty())
return;
/* download the signature first*/
const QUrl urlSig(QString::fromUtf8(fwupd_remote_get_metadata_uri_sig(remote)));
const QString filenameSigTmp(filenameSig + QStringLiteral(".tmp"));
if (!downloadFile(urlSig, filenameSigTmp)) {
qWarning() << "failed to download" << urlSig;
return;
}
Q_ASSERT(QFile::exists(filenameSigTmp));
const auto checksum = fwupd_remote_get_checksum(remote);
const QCryptographicHash::Algorithm hashAlgorithm = gchecksumToQChryptographicHash()[fwupd_checksum_guess_kind(checksum)];
const QByteArray hash = getChecksum(filenameSigTmp, hashAlgorithm);
const QByteArray oldHash = getChecksum(filenameSig, hashAlgorithm);
if (oldHash == hash) {
qDebug() << "remote hasn't changed:" << fwupd_remote_get_id(remote);
QFile::remove(filenameSigTmp);
return;
}
QFile::remove(filenameSig);
if (!QFile::rename(filenameSigTmp, filenameSig)) {
QFile::remove(filenameSigTmp);
qWarning() << "Fwupd Error: cannot save remote signature" << filenameSigTmp << "to" << filenameSig;
return;
}
QFile::remove(filenameSigTmp);
const auto basename = QString::fromUtf8(g_path_get_basename(fwupd_remote_get_filename_cache(remote)));
const QString filename = cacheFile(cacheId, basename);
if (filename.isEmpty())
return;
qDebug() << "Fwupd Info: saving new firmware metadata to:" << filename;
const QUrl url(QString::fromUtf8(fwupd_remote_get_metadata_uri(remote)));
if (!downloadFile(url, filename))
{
qWarning() << "Fwupd Error: cannot download file:" << filename;
return;
}
g_autoptr(GError) error = nullptr;
if (!fwupd_client_update_metadata(backend->client, fwupd_remote_get_id(remote), filename.toUtf8().constData(), filenameSig.toUtf8().constData(), cancellable, &error))
{
backend->handleError(error);
}
}
void FwupdBackend::handleError(GError *perror)
{
//TODO: localise the error message
......@@ -249,104 +358,82 @@ QString FwupdBackend::cacheFile(const QString &kind, const QString &basename)
return cacheDir.filePath(kind + QLatin1Char('/') + basename);
}
static void fwupd_client_get_devices_cb (GObject */*source*/, GAsyncResult *res, gpointer user_data)
{
FwupdBackend *helper = (FwupdBackend *) user_data;
g_autoptr(GError) error = nullptr;
auto array = fwupd_client_get_devices_finish(helper->client, res, &error);
if (!error)
helper->setDevices(array);
else
helper->handleError(error);
}
void FwupdBackend::setDevices(GPtrArray *devices)
void FwupdBackend::checkForUpdates()
{
for(uint i = 0; devices && i < devices->len; i++) {
FwupdDevice *device = (FwupdDevice *) g_ptr_array_index(devices, i);
if (m_fetching)
return;
if (!fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_SUPPORTED))
continue;
auto fw = new QFutureWatcher<GPtrArray*>(this);
connect(fw, &QFutureWatcher<GPtrArray*>::finished, this, [this, fw]() {
m_fetching = true;
emit fetchingChanged();
g_autoptr(GError) error = nullptr;
g_autoptr(GPtrArray) releases = fwupd_client_get_releases(client, fwupd_device_get_id(device), m_cancellable, &error);
auto devices = fw->result();
for(uint i = 0; devices && i < devices->len; i++) {
FwupdDevice *device = (FwupdDevice *) g_ptr_array_index(devices, i);
if (error) {
if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) {
qWarning() << "fwupd: Device not supported:" << fwupd_device_get_name(device) << error->message;
if (!fwupd_device_has_flag (device, FWUPD_DEVICE_FLAG_SUPPORTED))
continue;
}
if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE)) {
continue;
}
handleError(error);
}
auto res = createDevice(device);
for (uint i=0; releases && i<releases->len; ++i) {
FwupdRelease *release = (FwupdRelease *)g_ptr_array_index(releases, i);
if (res->installedVersion().toUtf8() == fwupd_release_get_version(release)) {
res->setReleaseDetails(release);
break;
}
}
addResourceToList(res);
}
g_ptr_array_unref(devices);
addUpdates();
m_fetching = false;
emit fetchingChanged();
emit initialized();
}
g_autoptr(GError) error = nullptr;
g_autoptr(GPtrArray) releases = fwupd_client_get_releases(client, fwupd_device_get_id(device), m_cancellable, &error);
static void fwupd_client_get_remotes_cb (GObject */*source*/, GAsyncResult *res, gpointer user_data)
{
FwupdBackend *helper = (FwupdBackend *) user_data;
g_autoptr(GError) error = nullptr;
auto array = fwupd_client_get_remotes_finish(helper->client, res, &error);
if (!error)
helper->setRemotes(array);
else
helper->handleError(error);
}
if (error) {
if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_NOT_SUPPORTED)) {
qWarning() << "fwupd: Device not supported:" << fwupd_device_get_name(device) << error->message;
continue;
}
if (g_error_matches(error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE)) {
continue;
}
void FwupdBackend::setRemotes(GPtrArray *remotes)
{
for(uint i = 0; remotes && i < remotes->len; i++)
{
FwupdRemote *remote = (FwupdRemote *)g_ptr_array_index(remotes, i);
if (!fwupd_remote_get_enabled(remote))
continue;
handleError(error);
}
if (fwupd_remote_get_kind(remote) == FWUPD_REMOTE_KIND_LOCAL)
continue;
auto res = createDevice(device);
for (uint i=0; releases && i<releases->len; ++i) {
FwupdRelease *release = (FwupdRelease *)g_ptr_array_index(releases, i);
if (res->installedVersion().toUtf8() == fwupd_release_get_version(release)) {
res->setReleaseDetails(release);
break;
}
}
addResourceToList(res);
}
g_ptr_array_unref(devices);
g_autoptr(GError) error = nullptr;
fwupd_client_refresh_remote(client, remote, m_cancellable, &error);
handleError(error);
}
}
addUpdates();
void FwupdBackend::checkForUpdates()
{
if (m_fetching)
return;
m_fetching = false;
emit fetchingChanged();
emit initialized();
fw->deleteLater();
});
fw->setFuture(QtConcurrent::run(&m_threadPool, [this] () -> GPtrArray*
{
const uint cacheAge = (24*60*60); // Check for updates every day
g_autoptr(GError) error = nullptr;
g_autoptr(GError) error = nullptr;
/* get devices */
GPtrArray* devices = fwupd_client_get_devices(client, m_cancellable, &error);
handleError(error);
if (!fwupd_client_connect (client, m_cancellable, &error)) {
handleError(error);
return;
}
g_autoptr(GPtrArray) remotes = fwupd_client_get_remotes(client, m_cancellable, &error);
handleError(error);
for(uint i = 0; remotes && i < remotes->len; i++)
{
FwupdRemote *remote = (FwupdRemote *)g_ptr_array_index(remotes, i);
if (!fwupd_remote_get_enabled(remote))
continue;
m_fetching = true;
emit fetchingChanged();
if (fwupd_remote_get_kind(remote) == FWUPD_REMOTE_KIND_LOCAL)
continue;
fwupd_client_get_devices_async(client, m_cancellable, fwupd_client_get_devices_cb, this);
fwupd_client_get_remotes_async(client, m_cancellable, fwupd_client_get_remotes_cb, this);
refreshRemote(this, remote, cacheAge, m_cancellable);
}
return devices;
}
));
}
int FwupdBackend::updatesCount() const
......
......@@ -13,6 +13,7 @@
#include <QString>
#include <QDir>
#include <QDebug>
#include <QThread>
#include <QTimer>
#include <QAction>
#include <QMimeDatabase>
......@@ -24,6 +25,8 @@
#include <QNetworkRequest>
#include <QCryptographicHash>
#include <QMap>
#include <QEventLoop>
#include <QThreadPool>
extern "C" {
#include <fwupd.h>
......@@ -60,8 +63,6 @@ public:
void handleError(GError *perror);
static QString cacheFile(const QString &kind, const QString &baseName);
void setDevices(GPtrArray*);
void setRemotes(GPtrArray*);
Q_SIGNALS:
void initialized();
......@@ -76,6 +77,7 @@ private:
static QMap<GChecksumType,QCryptographicHash::Algorithm> gchecksumToQChryptographicHash();
static void refreshRemote(FwupdBackend* backend, FwupdRemote *remote, quint64 cacheAge, GCancellable *cancellable);
static QByteArray getChecksum(const QString &filename, QCryptographicHash::Algorithm hashAlgorithm);
static bool downloadFile(const QUrl &uri, const QString &filename);
FwupdResource * createDevice(FwupdDevice *device);
FwupdResource * createRelease(FwupdDevice *device);
......@@ -87,6 +89,7 @@ private:
int m_startElements;
QList<AbstractResource*> m_toUpdate;
GCancellable *m_cancellable;
QThreadPool m_threadPool;
};
#endif // FWUPDBACKEND_H
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment