File indexing completed on 2024-11-17 04:55:45
0001 /* 0002 * SPDX-FileCopyrightText: 2013 Aleix Pol Gonzalez <aleixpol@blue-systems.com> 0003 * 0004 * SPDX-License-Identifier: GPL-2.0-only OR GPL-3.0-only OR LicenseRef-KDE-Accepted-GPL 0005 */ 0006 0007 #include "SnapTransaction.h" 0008 #include "SnapBackend.h" 0009 #include "SnapResource.h" 0010 #include "libsnapclient/config-paths.h" 0011 #include "utils.h" 0012 #include <KLocalizedString> 0013 #include <QJsonArray> 0014 #include <QJsonDocument> 0015 #include <QProcess> 0016 #include <QTimer> 0017 #include <Snapd/Request> 0018 0019 SnapTransaction::SnapTransaction(QSnapdClient *client, SnapResource *app, Role role, AbstractResource::State newState) 0020 : Transaction(app, app, role) 0021 , m_client(client) 0022 , m_app(app) 0023 , m_newState(newState) 0024 { 0025 if (role == RemoveRole) 0026 setRequest(m_client->remove(app->packageName())); 0027 else 0028 setRequest(m_client->install(app->packageName())); 0029 } 0030 0031 void SnapTransaction::cancel() 0032 { 0033 m_request->cancel(); 0034 } 0035 0036 void SnapTransaction::finishTransaction() 0037 { 0038 switch (m_request->error()) { 0039 case QSnapdRequest::NoError: 0040 static_cast<SnapBackend *>(m_app->backend())->refreshStates(); 0041 setStatus(DoneStatus); 0042 m_app->setState(m_newState); 0043 break; 0044 case QSnapdRequest::Cancelled: 0045 setStatus(CancelledStatus); 0046 break; 0047 case QSnapdRequest::NeedsClassic: 0048 setStatus(SetupStatus); 0049 if (role() == Transaction::InstallRole) { 0050 Q_EMIT proceedRequest(m_app->name(), 0051 i18n("This Snap application is not compatible with security sandboxing " 0052 "and will have full access to this computer. Install it anyway?")); 0053 return; 0054 } 0055 break; 0056 case QSnapdRequest::AuthDataRequired: { 0057 setStatus(SetupStatus); 0058 QProcess *p = new QProcess; 0059 p->setProgram(QStringLiteral(CMAKE_INSTALL_FULL_LIBEXECDIR "/discover/SnapMacaroonDialog")); 0060 p->start(); 0061 0062 connect(p, &QProcess::finished, this, [this, p](int code, QProcess::ExitStatus status) { 0063 p->deleteLater(); 0064 if (code != 0) { 0065 qWarning() << "login failed... code:" << code << status << p->readAll(); 0066 Q_EMIT passiveMessage(m_request->errorString()); 0067 setStatus(DoneWithErrorStatus); 0068 return; 0069 } 0070 const auto doc = QJsonDocument::fromJson(p->readAllStandardOutput()); 0071 const auto result = doc.object(); 0072 0073 const auto macaroon = result[QStringLiteral("macaroon")].toString(); 0074 const auto discharges = kTransform<QStringList>(result[QStringLiteral("discharges")].toArray(), [](const QJsonValue &val) { 0075 return val.toString(); 0076 }); 0077 static_cast<SnapBackend *>(m_app->backend())->client()->setAuthData(new QSnapdAuthData(macaroon, discharges)); 0078 m_request->runAsync(); 0079 }); 0080 } 0081 return; 0082 default: 0083 qDebug() << "snap error" << m_request.get() << m_request->error() << m_request->errorString(); 0084 Q_EMIT passiveMessage(m_request->errorString()); 0085 setStatus(DoneWithErrorStatus); 0086 break; 0087 } 0088 } 0089 0090 void SnapTransaction::proceed() 0091 { 0092 setRequest(m_client->install(QSnapdClient::Classic, m_app->packageName())); 0093 } 0094 0095 void SnapTransaction::setRequest(QSnapdRequest *req) 0096 { 0097 m_request.reset(req); 0098 0099 setCancellable(true); 0100 connect(m_request.data(), &QSnapdRequest::progress, this, &SnapTransaction::progressed); 0101 connect(m_request.data(), &QSnapdRequest::complete, this, &SnapTransaction::finishTransaction); 0102 0103 setStatus(CommittingStatus); 0104 m_request->runAsync(); 0105 } 0106 0107 void SnapTransaction::progressed() 0108 { 0109 const auto change = m_request->change(); 0110 int percentage = 0, count = 0; 0111 0112 auto status = SetupStatus; 0113 for (int i = 0, c = change->taskCount(); i < c; ++i) { 0114 ++count; 0115 auto task = change->task(i); 0116 if (task->kind() == QLatin1String("download-snap")) { 0117 status = task->status() == QLatin1String("doing") || task->status() == QLatin1String("do") ? DownloadingStatus : CommittingStatus; 0118 } else if (task->kind() == QLatin1String("clear-snap")) { 0119 status = CommittingStatus; 0120 } 0121 percentage += (100 * task->progressDone()) / task->progressTotal(); 0122 } 0123 setProgress(percentage / qMax(count, 1)); 0124 setStatus(status); 0125 }