File indexing completed on 2024-11-17 04:55:40

0001 /*
0002  *   SPDX-FileCopyrightText: 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com>
0003  *   SPDX-FileCopyrightText: 2018 Abhijeet Sharma <sharma.abhijeet2096@gmail.com>
0004  *
0005  *   SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL
0006  */
0007 
0008 #include "FwupdTransaction.h"
0009 #include "../DiscoverVersion.h"
0010 
0011 #include <QTimer>
0012 #include <resources/AbstractBackendUpdater.h>
0013 
0014 FwupdTransaction::FwupdTransaction(FwupdResource *app, FwupdBackend *backend)
0015     : Transaction(backend, app, Transaction::InstallRole, {})
0016     , m_app(app)
0017     , m_backend(backend)
0018 {
0019     setCancellable(true);
0020     setStatus(QueuedStatus);
0021 
0022     Q_ASSERT(!m_app->deviceId().isEmpty());
0023     QTimer::singleShot(0, this, &FwupdTransaction::install);
0024 }
0025 
0026 FwupdTransaction::~FwupdTransaction() = default;
0027 
0028 void FwupdTransaction::install()
0029 {
0030     g_autoptr(GError) error = nullptr;
0031 
0032     if (m_app->isDeviceLocked()) {
0033         QString device_id = m_app->deviceId();
0034         if (device_id.isEmpty()) {
0035             qWarning() << "Fwupd Error: No Device ID set, cannot unlock device " << this << m_app->name();
0036         } else if (!fwupd_client_unlock(m_backend->client, device_id.toUtf8().constData(), nullptr, &error)) {
0037             m_backend->handleError(error);
0038         }
0039         setStatus(DoneWithErrorStatus);
0040         return;
0041     }
0042 
0043     const QString fileName = m_app->cacheFile();
0044     if (!QFileInfo::exists(fileName)) {
0045         const QUrl uri(m_app->updateURI());
0046         setStatus(DownloadingStatus);
0047         QNetworkAccessManager *manager = new QNetworkAccessManager(this);
0048         auto req = QNetworkRequest(uri);
0049         req.setHeader(QNetworkRequest::UserAgentHeader, QStringLiteral("plasma-discover/%1").arg(version));
0050         req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
0051         auto reply = manager->get(req);
0052         QFile *file = new QFile(fileName);
0053         if (!file->open(QFile::WriteOnly)) {
0054             qWarning() << "Fwupd Error: Could not open to write" << fileName << uri;
0055             setStatus(DoneWithErrorStatus);
0056             file->deleteLater();
0057             return;
0058         }
0059 
0060         connect(reply, &QNetworkReply::finished, this, [this, file, reply]() {
0061             file->close();
0062             file->deleteLater();
0063 
0064             if (reply->error() != QNetworkReply::NoError) {
0065                 qWarning() << "Fwupd Error: Could not download" << reply->url() << reply->errorString();
0066                 file->remove();
0067                 setStatus(DoneWithErrorStatus);
0068             } else {
0069                 fwupdInstall(file->fileName());
0070             }
0071         });
0072         connect(reply, &QNetworkReply::readyRead, this, [file, reply]() {
0073             file->write(reply->readAll());
0074         });
0075     } else {
0076         fwupdInstall(fileName);
0077     }
0078 }
0079 
0080 void FwupdTransaction::fwupdInstall(const QString &file)
0081 {
0082     FwupdInstallFlags install_flags = FWUPD_INSTALL_FLAG_NONE;
0083     g_autoptr(GError) error = nullptr;
0084 
0085     /* only offline supported */
0086     if (m_app->isOnlyOffline())
0087         install_flags = static_cast<FwupdInstallFlags>(install_flags | FWUPD_INSTALL_FLAG_OFFLINE);
0088 
0089     if (!fwupd_client_install(m_backend->client, m_app->deviceId().toUtf8().constData(), file.toUtf8().constData(), install_flags, nullptr, &error)) {
0090         m_backend->handleError(error);
0091         setStatus(DoneWithErrorStatus);
0092     } else
0093         finishTransaction();
0094 }
0095 
0096 void FwupdTransaction::updateProgress()
0097 {
0098     setProgress(fwupd_client_get_percentage(m_backend->client));
0099 }
0100 
0101 void FwupdTransaction::proceed()
0102 {
0103     finishTransaction();
0104 }
0105 
0106 void FwupdTransaction::cancel()
0107 {
0108     setStatus(CancelledStatus);
0109 }
0110 
0111 void FwupdTransaction::finishTransaction()
0112 {
0113     AbstractResource::State newState = AbstractResource::None;
0114     switch (role()) {
0115     case InstallRole:
0116     case ChangeAddonsRole:
0117         newState = AbstractResource::Installed;
0118         break;
0119     case RemoveRole:
0120         newState = AbstractResource::None;
0121         break;
0122     }
0123     m_app->setState(newState);
0124     if (m_app->needsReboot()) {
0125         m_app->backend()->backendUpdater()->setNeedsReboot(true);
0126     }
0127     setStatus(DoneStatus);
0128     deleteLater();
0129 }