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:
		@ -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()) {
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
@ -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
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								src/global.h
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								src/global.h
									
									
									
									
									
								
							@ -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
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user