feat: replace exec during autostart process

create directory of user applciation if dosen't exists

Signed-off-by: ComixHe <heyuming@deepin.org>
This commit is contained in:
ComixHe 2024-01-03 11:58:54 +08:00 committed by Comix
parent 2fb5567eaf
commit 71b3b0a6c0
5 changed files with 86 additions and 29 deletions

View File

@ -12,6 +12,7 @@
#include "desktopfilegenerator.h"
#include "processguesser1service.h"
#include <QFile>
#include <QHash>
#include <QDBusMessage>
#include <QStringBuilder>
#include <unistd.h>
@ -123,13 +124,13 @@ void ApplicationManager1Service::initService(QDBusConnection &connection) noexce
auto *sigCon = new (std::nothrow) QMetaObject::Connection{};
auto singleSlot = [watcher, sigCon, autostartList = std::move(needLaunch)]() {
auto singleSlot = [watcher, sigCon, autostartMap = std::move(needLaunch)]() {
QObject::disconnect(*sigCon);
delete sigCon;
qDebug() << XSettings << "is registered.";
for (const auto &app : autostartList) {
app->Launch({}, {}, {});
for (const auto &[app, realExec] : autostartMap.asKeyValueRange()) {
app->Launch({}, {}, {}, realExec);
}
watcher->deleteLater();
@ -294,9 +295,9 @@ void ApplicationManager1Service::scanInstances() noexcept
}
}
QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoStart() noexcept
QHash<QSharedPointer<ApplicationService>, QString> ApplicationManager1Service::scanAutoStart() noexcept
{
QList<QSharedPointer<ApplicationService>> ret;
QHash<QSharedPointer<ApplicationService>, QString> ret;
auto autostartDirs = getAutoStartDirs();
std::map<QString, DesktopFile> autostartItems;
@ -374,7 +375,9 @@ QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoSt
}
if (app) {
ret.append(app);
auto realExec = tmp.value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
qInfo() << "launch normal autostart application " << app->id() << " by " << realExec;
ret.insert(app, realExec);
continue;
}
@ -388,8 +391,9 @@ QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoSt
m_applicationList.cend(),
[&desktopFile](const auto &app) { return desktopFile.desktopId() == app->id(); });
appIt != m_applicationList.cend()) {
qInfo() << "app already exists. use it to launch instance.";
ret.append(*appIt);
auto realExec = tmp.value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
qInfo() << "launch exist autostart application " << (*appIt)->id() << " by " << realExec;
ret.insert(*appIt, realExec);
continue;
}
@ -401,7 +405,9 @@ QList<QSharedPointer<ApplicationService>> ApplicationManager1Service::scanAutoSt
continue;
}
ret.append(newApp);
auto realExec = newApp->m_entry->value(DesktopFileEntryKey, "Exec").value_or(QString{""}).toString();
qInfo() << "launch new autostart application " << newApp->id() << " by " << realExec;
ret.insert(newApp, realExec);
}
return ret;
@ -642,7 +648,14 @@ QString ApplicationManager1Service::addUserApplication(const QVariantMap &deskto
return {};
}
QDir xdgDataHome{getXDGDataHome() + "/applications"};
QDir xdgDataHome;
QString dir{getXDGDataHome() + "/applications"};
if (!xdgDataHome.mkpath(dir)) {
sendErrorReply(QDBusError::Failed, "couldn't create directory of user applications.");
return {};
}
xdgDataHome.setPath(dir);
const auto &filePath = xdgDataHome.filePath(name);
if (QFileInfo info{filePath}; info.exists() and info.isFile()) {

View File

@ -74,7 +74,7 @@ private:
void scanMimeInfos() noexcept;
void scanApplications() noexcept;
void scanInstances() noexcept;
QList<QSharedPointer<ApplicationService>> scanAutoStart() noexcept;
QHash<QSharedPointer<ApplicationService>, QString> scanAutoStart() noexcept;
void loadHooks() noexcept;
void addInstanceToApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);
void removeInstanceFromApplication(const QString &unitName, const QDBusObjectPath &systemdUnitPath);

View File

@ -173,9 +173,10 @@ bool ApplicationService::shouldBeShown(const std::unique_ptr<DesktopEntry> &entr
return true;
}
QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options)
QDBusObjectPath
ApplicationService::Launch(const QString &action, const QStringList &fields, const QVariantMap &options, const QString &realExec)
{
QString execStr;
QString execStr{};
bool ok;
const auto &supportedActions = actions();
auto optionsMap = options;
@ -190,7 +191,16 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
optionsMap.insert("env", oldEnv);
}
while (!action.isEmpty() and !supportedActions.isEmpty()) { // break trick
if (!realExec.isNull()) { // we want to replace exec of this applications.
if (realExec.isEmpty()) {
qWarning() << "try to replace exec but it's empty.";
return {};
}
execStr = realExec;
}
while (execStr.isEmpty() and !action.isEmpty() and !supportedActions.isEmpty()) { // break trick
if (auto index = supportedActions.indexOf(action); index == -1) {
qWarning() << "can't find " << action << " in supported actions List. application will use default action to launch.";
break;
@ -215,7 +225,9 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
if (!Actions) {
QString msg{"application can't be executed."};
qWarning() << msg;
sendErrorReply(QDBusError::Failed, msg);
if (calledFromDBus()) {
sendErrorReply(QDBusError::Failed, msg);
}
return {};
}
@ -223,7 +235,9 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
if (execStr.isEmpty()) {
QString msg{"maybe entry actions's format is invalid, abort launch."};
qWarning() << msg;
sendErrorReply(QDBusError::Failed, msg);
if (calledFromDBus()) {
sendErrorReply(QDBusError::Failed, msg);
}
return {};
}
}
@ -235,14 +249,18 @@ QDBusObjectPath ApplicationService::Launch(const QString &action, const QStringL
auto cmds = generateCommand(optionsMap);
auto task = unescapeExec(execStr, fields);
if (!task) {
sendErrorReply(QDBusError::InternalError, "Invalid Command.");
if (calledFromDBus()) {
sendErrorReply(QDBusError::InternalError, "Invalid Command.");
}
return {};
}
auto [bin, execCmds, res] = std::move(task);
if (bin.isEmpty()) {
qCritical() << "error command is detected, abort.";
sendErrorReply(QDBusError::Failed);
if (calledFromDBus()) {
sendErrorReply(QDBusError::Failed);
}
return {};
}
@ -592,20 +610,30 @@ bool ApplicationService::autostartCheck(const QString &filePath) noexcept
bool ApplicationService::isAutoStart() const noexcept
{
auto autostartDirs = getAutoStartDirs();
auto sourcePath = m_desktopSource.sourcePath();
auto userAutostart = QDir{autostartDirs.first()}.filePath(id() + ".desktop");
auto appId = id();
auto dirs = getAutoStartDirs();
QString destDesktopFile;
QFileInfo info{userAutostart};
auto isOverride = info.exists() and info.isFile();
applyIteratively(
QList<QDir>(dirs.crbegin(), dirs.crend()),
[&appId, &destDesktopFile](const QFileInfo &file) {
auto filePath = file.absoluteFilePath();
if (appId == getAutostartAppIdFromAbsolutePath(filePath)) {
destDesktopFile = filePath;
return true;
}
return false;
},
QDir::Readable | QDir::AllDirs | QDir::Files | QDir::NoDotAndDotDot,
{"*.desktop"},
QDir::Name | QDir::DirsLast);
if (std::any_of(autostartDirs.cbegin(), autostartDirs.cend(), [&sourcePath](const QString &dir) {
return sourcePath.startsWith(dir);
})) { // load from autostart
return isOverride ? autostartCheck(userAutostart) : autostartCheck(sourcePath);
if (destDesktopFile.isEmpty()) {
qDebug() << "couldn't find autostart desktopFile.";
return false;
}
return isOverride and autostartCheck(userAutostart);
return autostartCheck(destDesktopFile);
}
void ApplicationService::setAutoStart(bool autostart) noexcept

View File

@ -133,7 +133,9 @@ private Q_SLOTS:
void onGlobalScaleFactorChanged() noexcept;
public Q_SLOTS:
QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options);
// NOTE: 'realExec' only for internal implementation
QDBusObjectPath
Launch(const QString &action, const QStringList &fields, const QVariantMap &options, const QString &realExec = {});
[[nodiscard]] ObjectMap GetManagedObjects() const;
[[nodiscard]] bool SendToDesktop() const noexcept;
[[nodiscard]] bool RemoveFromDesktop() const noexcept;

View File

@ -630,4 +630,18 @@ inline uint getPidFromPidFd(const QDBusUnixFileDescriptor &pidfd) noexcept
return pid;
}
inline QString getAutostartAppIdFromAbsolutePath(const QString &path)
{
constexpr decltype(auto) desktopSuffix{u8".desktop"};
auto tmp = path.chopped(sizeof(desktopSuffix) - 1);
auto components = tmp.split(QDir::separator(), Qt::SkipEmptyParts);
auto location = std::find(components.cbegin(), components.cend(), "autostart");
if (location == components.cend()) {
return {};
}
auto appId = QStringList{location + 1, components.cend()}.join('-');
return appId;
}
#endif