[PATCH] KProcessRunner: Fix launching actions without executable
authorBalló György <ballogyor@gmail.com>
Fri, 4 Apr 2025 06:08:31 +0000 (08:08 +0200)
committerAurélien COUDERC <coucouf@debian.org>
Sun, 8 Jun 2025 12:42:29 +0000 (14:42 +0200)
If D-Bus activation is possible, it's not needed to have an executable,
since everything is done via D-Bus. Therefore look for the matching action
name instead of the exec value when launching an action. The specification
allows to omit the "Exec" key if "DBusActivatable" is true.

Most applications specify the Exec parameter for compatibility reasons, but
if the action's "Exec" line got removed from a D-Bus activatable desktop
file, then KIO just activates the application rather than calling the
requested action. This change fixes that issue.

Gbp-Pq: Name upstream_31806c51_KProcessRunner-Fix-launching-actions-without-executable.patch

src/gui/applicationlauncherjob.cpp
src/gui/kprocessrunner.cpp
src/gui/kprocessrunner_p.h

index 463cec1bef29e857f4ad2c16f61331178f9a358a..f3cafafc8ffbf3a5847d9e54c704769b44283da0 100644 (file)
@@ -49,6 +49,7 @@ public:
     KService::Ptr m_service;
     QString m_serviceEntryPath;
     QList<QUrl> m_urls;
+    QString m_actionName;
     KIO::ApplicationLauncherJob::RunFlags m_runFlags;
     QString m_suggestedFileName;
     QString m_mimeTypeName;
@@ -75,6 +76,7 @@ KIO::ApplicationLauncherJob::ApplicationLauncherJob(const KServiceAction &servic
     Q_ASSERT(d->m_service);
     d->m_service.detach();
     d->m_service->setExec(serviceAction.exec());
+    d->m_actionName = serviceAction.name();
 }
 KIO::ApplicationLauncherJob::ApplicationLauncherJob(const KDesktopFileAction &desktopFileAction, QObject *parent)
     : ApplicationLauncherJob(KService::Ptr(new KService(desktopFileAction.desktopFilePath())), parent)
@@ -82,6 +84,7 @@ KIO::ApplicationLauncherJob::ApplicationLauncherJob(const KDesktopFileAction &de
     Q_ASSERT(d->m_service);
     d->m_service.detach();
     d->m_service->setExec(desktopFileAction.exec());
+    d->m_actionName = desktopFileAction.name();
 }
 
 KIO::ApplicationLauncherJob::ApplicationLauncherJob(QObject *parent)
@@ -196,7 +199,7 @@ void KIO::ApplicationLauncherJob::proceedAfterSecurityChecks()
         d->m_processRunners.reserve(d->m_numProcessesPending);
         for (int i = 1; i < d->m_urls.count(); ++i) {
             auto *processRunner =
-                KProcessRunner::fromApplication(d->m_service, d->m_serviceEntryPath, {d->m_urls.at(i)}, d->m_runFlags, d->m_suggestedFileName, QByteArray{});
+                KProcessRunner::fromApplication(d->m_service, d->m_serviceEntryPath, {d->m_urls.at(i)}, d->m_actionName, d->m_runFlags, d->m_suggestedFileName, QByteArray{});
             d->m_processRunners.push_back(processRunner);
             connect(processRunner, &KProcessRunner::processStarted, this, [this](qint64 pid) {
                 d->slotStarted(pid);
@@ -208,7 +211,7 @@ void KIO::ApplicationLauncherJob::proceedAfterSecurityChecks()
     }
 
     auto *processRunner =
-        KProcessRunner::fromApplication(d->m_service, d->m_serviceEntryPath, d->m_urls, d->m_runFlags, d->m_suggestedFileName, d->m_startupId);
+        KProcessRunner::fromApplication(d->m_service, d->m_serviceEntryPath, d->m_urls, d->m_actionName, d->m_runFlags, d->m_suggestedFileName, d->m_startupId);
     d->m_processRunners.push_back(processRunner);
     connect(processRunner, &KProcessRunner::error, this, [this](const QString &errorText) {
         setError(KJob::UserDefinedError);
index 64fa3afb2d22dac9c1d863e14d0861c702069385..00f7811e852c089ad9334c1bd11994ee11fd4248 100644 (file)
@@ -88,6 +88,7 @@ static void modifyEnv(KProcess &process, QProcessEnvironment mod)
 KProcessRunner *KProcessRunner::fromApplication(const KService::Ptr &service,
                                                 const QString &serviceEntryPath,
                                                 const QList<QUrl> &urls,
+                                                const QString &actionName,
                                                 KIO::ApplicationLauncherJob::RunFlags flags,
                                                 const QString &suggestedFileName,
                                                 const QByteArray &asn)
@@ -103,9 +104,12 @@ KProcessRunner *KProcessRunner::fromApplication(const KService::Ptr &service,
     const bool notYetSupportedOpenActivationNeeded = !urls.isEmpty();
     if (!notYetSupportedOpenActivationNeeded && DBusActivationRunner::activationPossible(service, flags, suggestedFileName)) {
         const auto actions = service->actions();
-        auto action = std::find_if(actions.cbegin(), actions.cend(), [service](const KServiceAction &action) {
-            return action.exec() == service->exec();
+        auto action = std::find_if(actions.cbegin(), actions.cend(), [actionName](const KServiceAction &action) {
+            return action.name() == actionName;
         });
+        if (!actionName.isEmpty() && action == actions.cend()) {
+            qCWarning(KIO_GUI) << "Requested action" << actionName << "cannot be found for" << service->name();
+        }
         instance = new DBusActivationRunner(action != actions.cend() ? action->name() : QString());
     } else {
         instance = makeInstance();
index 63e517d376807f3a30a5037b6de6551a80d8310a..7f084a49e6fdd2c0d82bd5bbd4305c626119653f 100644 (file)
@@ -59,6 +59,7 @@ public:
     static KProcessRunner *fromApplication(const KService::Ptr &service,
                                            const QString &serviceEntryPath,
                                            const QList<QUrl> &urls,
+                                           const QString &actionName = {},
                                            KIO::ApplicationLauncherJob::RunFlags flags = {},
                                            const QString &suggestedFileName = {},
                                            const QByteArray &asn = {});