Projects
Eulaceura:Factory
plasma-pk-updates
_service:obs_scm:0030-Add-support-for-license-p...
Sign Up
Log In
Username
Password
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File _service:obs_scm:0030-Add-support-for-license-prompts.patch of Package plasma-pk-updates
From 92675896ed9d1b4a6f41143803630768a46eab7a Mon Sep 17 00:00:00 2001 From: Fabian Vogt <fabian@ritter-vogt.de> Date: Mon, 26 Aug 2019 13:22:25 +0200 Subject: [PATCH 30/51] Add support for license prompts Summary: Currently, if a transaction requires accepting a license, it just fails. This implements a basic dialog (which makes it easier to read the license than displaying it inline) and the necessary backend functionality. It was necessary to move the list of packages out of a QObject property into a new member to allow restarting the transaction outside of the onFinished slot. Test Plan: Downgraded two packages with EULAs and searched for updates. Hit the install updates button and got two license prompts. Only after accepting both with the "Yes" button are the updates installed. Reviewers: lukas, jgrulich, bruns, antlarr Differential Revision: https://phabricator.kde.org/D23462 --- src/declarative/pkupdates.cpp | 61 ++++++++++++++++++++++++++++----- src/declarative/pkupdates.h | 29 ++++++++++++++++ src/plasma/contents/ui/Full.qml | 59 +++++++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 8 deletions(-) diff --git a/src/declarative/pkupdates.cpp b/src/declarative/pkupdates.cpp index db85eb1..9eac70f 100644 --- a/src/declarative/pkupdates.cpp +++ b/src/declarative/pkupdates.cpp @@ -296,8 +296,9 @@ void PkUpdates::installUpdates(const QStringList &packageIds, bool simulate, boo flags = PackageKit::Transaction::TransactionFlagNone; } - m_installTrans = PackageKit::Daemon::updatePackages(packageIds, flags); - m_installTrans->setProperty("packages", packageIds); + m_requiredEulas.clear(); + m_packages = packageIds; + m_installTrans = PackageKit::Daemon::updatePackages(m_packages, flags); setActivity(InstallingUpdates); connect(m_installTrans.data(), &PackageKit::Transaction::statusChanged, this, &PkUpdates::onStatusChanged); @@ -306,6 +307,7 @@ void PkUpdates::installUpdates(const QStringList &packageIds, bool simulate, boo connect(m_installTrans.data(), &PackageKit::Transaction::package, this, &PkUpdates::onPackageUpdating); connect(m_installTrans.data(), &PackageKit::Transaction::requireRestart, this, &PkUpdates::onRequireRestart); connect(m_installTrans.data(), &PackageKit::Transaction::repoSignatureRequired, this, &PkUpdates::onRepoSignatureRequired); + connect(m_installTrans.data(), &PackageKit::Transaction::eulaRequired, this, &PkUpdates::onEulaRequired); } void PkUpdates::onChanged() @@ -431,16 +433,19 @@ void PkUpdates::onFinished(PackageKit::Transaction::Exit status, uint runtime) qCDebug(PLASMA_PK_UPDATES) << "Total number of updates: " << count(); emit done(); } else if (trans->role() == PackageKit::Transaction::RoleUpdatePackages) { - const QStringList packages = trans->property("packages").toStringList(); - qCDebug(PLASMA_PK_UPDATES) << "Finished updating packages:" << packages; + qCDebug(PLASMA_PK_UPDATES) << "Finished updating packages:" << m_packages; if (status == PackageKit::Transaction::ExitNeedUntrusted) { qCDebug(PLASMA_PK_UPDATES) << "Transaction needs untrusted packages"; // restart transaction with "untrusted" flag - installUpdates(packages, false /*simulate*/, true /*untrusted*/); + installUpdates(m_packages, false /*simulate*/, true /*untrusted*/); + return; + } else if (status == PackageKit::Transaction::ExitEulaRequired) { + qCDebug(PLASMA_PK_UPDATES) << "Acceptance of EULAs required"; + promptNextEulaAgreement(); return; } else if (status == PackageKit::Transaction::ExitSuccess && trans->transactionFlags().testFlag(PackageKit::Transaction::TransactionFlagSimulate)) { qCDebug(PLASMA_PK_UPDATES) << "Simulation finished with success, restarting the transaction"; - installUpdates(packages, false /*simulate*/, false /*untrusted*/); + installUpdates(m_packages, false /*simulate*/, false /*untrusted*/); return; } else if (status == PackageKit::Transaction::ExitSuccess) { qCDebug(PLASMA_PK_UPDATES) << "Update packages transaction finished successfully"; @@ -449,7 +454,7 @@ void PkUpdates::onFinished(PackageKit::Transaction::Exit status, uint runtime) } KNotification::event(s_eventIdUpdatesInstalled, i18n("Updates Installed"), - i18np("Successfully updated %1 package", "Successfully updated %1 packages", packages.count()), + i18np("Successfully updated %1 package", "Successfully updated %1 packages", m_packages.count()), s_pkUpdatesIconName, nullptr, KNotification::CloseOnTimeout, s_componentName); @@ -475,7 +480,7 @@ void PkUpdates::onFinished(PackageKit::Transaction::Exit status, uint runtime) void PkUpdates::onErrorCode(PackageKit::Transaction::Error error, const QString &details) { qWarning() << "PK error:" << details << "type:" << PackageKit::Daemon::enumToString<PackageKit::Transaction>((int)error, "Error"); - if (error == PackageKit::Transaction::ErrorBadGpgSignature) + if (error == PackageKit::Transaction::ErrorBadGpgSignature || error == PackageKit::Transaction::ErrorNoLicenseAgreement) return; KNotification::event(s_eventIdError, i18n("Update Error"), @@ -553,6 +558,46 @@ void PkUpdates::onRepoSignatureRequired(const QString &packageID, const QString qCDebug(PLASMA_PK_UPDATES) << "Repo sig required" << packageID; } +void PkUpdates::onEulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement) +{ + m_requiredEulas[eulaID] = {packageID, vendor, licenseAgreement}; +} + +void PkUpdates::promptNextEulaAgreement() +{ + if(m_requiredEulas.empty()) { + // Restart the transaction + installUpdates(m_packages, false, false); + return; + } + + QString eulaID = m_requiredEulas.firstKey(); + const EulaData &eula = m_requiredEulas[eulaID]; + emit eulaRequired(eulaID, eula.packageID, eula.vendor, eula.licenseAgreement); +} + +void PkUpdates::eulaAgreementResult(const QString &eulaID, bool agreed) +{ + if(!agreed) { + qCDebug(PLASMA_PK_UPDATES) << "EULA declined"; + // Do the same as the failure case in onFinished + checkUpdates(false /* force */); + return; + } + + m_eulaTrans = PackageKit::Daemon::acceptEula(eulaID); + connect(m_eulaTrans.data(), &PackageKit::Transaction::finished, this, + [this, eulaID] (PackageKit::Transaction::Exit exit, uint) { + if (exit == PackageKit::Transaction::ExitSuccess) { + m_requiredEulas.remove(eulaID); + promptNextEulaAgreement(); + } else { + qCWarning(PLASMA_PK_UPDATES) << "EULA acceptance failed"; + } + } + ); +} + void PkUpdates::setStatusMessage(const QString &message) { m_statusMessage = message; diff --git a/src/declarative/pkupdates.h b/src/declarative/pkupdates.h index 877bd52..0f48d2d 100644 --- a/src/declarative/pkupdates.h +++ b/src/declarative/pkupdates.h @@ -156,6 +156,17 @@ signals: */ void updateDetail(const QString &packageID, const QString &updateText, const QStringList &urls); + /** + * Emitted when an EULA agreement prevents the transaction from running + * @param eulaId the EULA identifier + * @param packageID ID of the package for which an EULA is required + * @param vendorName the vendor name + * @param licenseAgreement the EULA text + * + * @see eulaAgreementResult() + */ + void eulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement); + // private ;) void statusMessageChanged(); void isActiveChanged(); @@ -205,6 +216,11 @@ public slots: Q_INVOKABLE void doDelayedCheckUpdates(); + /** + * If agreed to eulaID, starts an EULA acceptance transaction and continues. + */ + Q_INVOKABLE void eulaAgreementResult(const QString &eulaID, bool agreed); + private slots: void getUpdates(); void onChanged(); @@ -221,15 +237,25 @@ private slots: const QDateTime &issued, const QDateTime &updated); void onRepoSignatureRequired(const QString & packageID, const QString & repoName, const QString & keyUrl, const QString & keyUserid, const QString & keyId, const QString & keyFingerprint, const QString & keyTimestamp, PackageKit::Transaction::SigType type); + void onEulaRequired(const QString &eulaID, const QString &packageID, const QString &vendor, const QString &licenseAgreement); private: + struct EulaData { + QString packageID; + QString vendor; + QString licenseAgreement; + }; + void setStatusMessage(const QString &message); void setActivity(Activity act); void setPercentage(int value); + void promptNextEulaAgreement(); QPointer<PackageKit::Transaction> m_updatesTrans; QPointer<PackageKit::Transaction> m_cacheTrans; QPointer<PackageKit::Transaction> m_installTrans; QPointer<PackageKit::Transaction> m_detailTrans; + QPointer<PackageKit::Transaction> m_eulaTrans; + QStringList m_packages; QPointer<KNotification> m_lastNotification; int m_lastUpdateCount = 0; QVariantMap m_updateList; @@ -241,6 +267,9 @@ private: bool m_lastCheckSuccessful = false; bool m_checkUpdatesWhenNetworkOnline = false; bool m_isOnBattery; + // If a transaction failed because of required EULAs, + // this contains a map of their IDs to their data + QMap<QString, EulaData> m_requiredEulas; }; #endif // PLASMA_PK_UPDATES_H diff --git a/src/plasma/contents/ui/Full.qml b/src/plasma/contents/ui/Full.qml index 7cf37eb..de2a47e 100644 --- a/src/plasma/contents/ui/Full.qml +++ b/src/plasma/contents/ui/Full.qml @@ -22,6 +22,7 @@ import QtQuick 2.1 import QtQuick.Layouts 1.1 import QtQuick.Controls 1.3 +import QtQuick.Dialogs 1.2 import org.kde.plasma.components 2.0 as PlasmaComponents import org.kde.plasma.extras 2.0 as PlasmaExtras import org.kde.plasma.core 2.0 as PlasmaCore @@ -46,10 +47,68 @@ Item { onUpdatesChanged: populateModel() onUpdateDetail: updateDetails(packageID, updateText, urls) onUpdatesInstalled: plasmoid.expanded = false + onEulaRequired: eulaDialog.showPrompt(eulaID, packageID, vendor, licenseAgreement) } Component.onCompleted: populateModel() + Dialog { + property string eulaID: "" + property string packageName: "" + property string vendor: "" + property string licenseText: "" + + property bool buttonClicked: false + + id: eulaDialog + title: i18n("License Agreement for %1").arg(packageName) + standardButtons: StandardButton.Yes | StandardButton.No + + ColumnLayout { + anchors.fill: parent + + Label { + text: i18n("License agreement required for %1 (from %2):").arg(eulaDialog.packageName).arg(eulaDialog.vendor) + } + + TextArea { + Layout.fillWidth: true + Layout.fillHeight: true + Layout.minimumWidth: 400 + Layout.minimumHeight: 200 + text: eulaDialog.licenseText + readOnly: true + } + + Label { + text: i18n("Do you accept?") + } + } + + onVisibleChanged: { + // onRejected does not fire on dialog closing, so implement that ourselves + if(!visible && !buttonClicked) + onNo(); + } + onNo: { + buttonClicked = true; + PkUpdates.eulaAgreementResult(this.eulaID, false); + } + onYes: { + buttonClicked = true; + PkUpdates.eulaAgreementResult(this.eulaID, true); + } + + function showPrompt(eulaID, packageID, vendor, licenseAgreement) { + this.eulaID = eulaID; + this.packageName = PkUpdates.packageName(packageID); + this.vendor = vendor; + this.licenseText = licenseAgreement; + + this.visible = true; + } + } + ListModel { id: updatesModel } -- 2.28.0
Locations
Projects
Search
Status Monitor
Help
Open Build Service
OBS Manuals
API Documentation
OBS Portal
Reporting a Bug
Contact
Mailing List
Forums
Chat (IRC)
Twitter
Open Build Service (OBS)
is an
openSUSE project
.
浙ICP备2022010568号-2