feat: watch systemd unit new and remove to sync state
add default values to XDG_DATA_DIRS if it dosen't set Signed-off-by: ComixHe <heyuming@deepin.org> Signed-off-by: black-desk <me@black-desk.cn>
This commit is contained in:
parent
4687265e65
commit
799100436c
@ -6,5 +6,9 @@ target_link_libraries(${APP_LAUNCH_HELPER_BIN} PRIVATE
|
|||||||
PkgConfig::SYSTEMD
|
PkgConfig::SYSTEMD
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_include_directories(${APP_LAUNCH_HELPER_BIN} PRIVATE
|
||||||
|
${PROJECT_SOURCE_DIR}/src
|
||||||
|
)
|
||||||
|
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(TARGETS ${APP_LAUNCH_HELPER_BIN} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/deepin/application-manager/)
|
install(TARGETS ${APP_LAUNCH_HELPER_BIN} DESTINATION ${CMAKE_INSTALL_LIBEXECDIR}/deepin/application-manager/)
|
||||||
|
@ -15,6 +15,7 @@
|
|||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <thread>
|
#include <thread>
|
||||||
|
#include "constant.h"
|
||||||
|
|
||||||
enum class ExitCode { SystemdError = -3, InvalidInput = -2, InternalError = -1, Done = 0, Waiting = 1 };
|
enum class ExitCode { SystemdError = -3, InvalidInput = -2, InternalError = -1, Done = 0, Waiting = 1 };
|
||||||
|
|
||||||
@ -25,10 +26,6 @@ struct JobRemoveResult
|
|||||||
ExitCode result{ExitCode::Waiting};
|
ExitCode result{ExitCode::Waiting};
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr static auto SystemdService = "org.freedesktop.systemd1";
|
|
||||||
constexpr static auto SystemdObjectPath = "/org/freedesktop/systemd1";
|
|
||||||
constexpr static auto SystemdInterfaceName = "org.freedesktop.systemd1.Manager";
|
|
||||||
|
|
||||||
using msg_ptr = sd_bus_message *;
|
using msg_ptr = sd_bus_message *;
|
||||||
using bus_ptr = sd_bus *;
|
using bus_ptr = sd_bus *;
|
||||||
|
|
||||||
|
@ -21,17 +21,19 @@ int main(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
QCoreApplication app{argc, argv};
|
QCoreApplication app{argc, argv};
|
||||||
auto &bus = ApplicationManager1DBus::instance();
|
auto &bus = ApplicationManager1DBus::instance();
|
||||||
bus.init(DBusType::Session);
|
bus.initGlobalServerBus(DBusType::Session);
|
||||||
auto &AMBus = bus.globalBus();
|
bus.setDestBus("");
|
||||||
|
auto &AMBus = bus.globalServerBus();
|
||||||
|
|
||||||
registerComplexDbusType();
|
registerComplexDbusType();
|
||||||
ApplicationManager1Service AMService{std::make_unique<CGroupsIdentifier>(), AMBus};
|
ApplicationManager1Service AMService{std::make_unique<CGroupsIdentifier>(), AMBus};
|
||||||
QList<DesktopFile> fileList{};
|
QList<DesktopFile> fileList{};
|
||||||
auto pathEnv = qgetenv("XDG_DATA_DIRS");
|
QByteArray XDGDataDirs;
|
||||||
if (pathEnv.isEmpty()) {
|
XDGDataDirs = qgetenv("XDG_DATA_DIRS");
|
||||||
qFatal() << "environment variable $XDG_DATA_DIRS is empty.";
|
if (XDGDataDirs.isEmpty()) {
|
||||||
|
XDGDataDirs.append("/usr/local/share/:/usr/share/");
|
||||||
}
|
}
|
||||||
auto desktopFileDirs = pathEnv.split(':');
|
auto desktopFileDirs = XDGDataDirs.split(':');
|
||||||
|
|
||||||
for (const auto &dir : desktopFileDirs) {
|
for (const auto &dir : desktopFileDirs) {
|
||||||
auto dirPath = QDir{QDir::cleanPath(dir) + "/applications"};
|
auto dirPath = QDir{QDir::cleanPath(dir) + "/applications"};
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
|
|
||||||
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface)
|
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface)
|
||||||
{
|
{
|
||||||
auto &con = ApplicationManager1DBus::instance().globalBus();
|
auto &con = ApplicationManager1DBus::instance().globalServerBus();
|
||||||
if (!con.registerObject(path, interface, o, QDBusConnection::RegisterOption::ExportAllContents)) {
|
if (!con.registerObject(path, interface, o, QDBusConnection::RegisterOption::ExportAllContents)) {
|
||||||
qFatal() << "register object failed:" << path << interface << con.lastError();
|
qFatal() << "register object failed:" << path << interface << con.lastError();
|
||||||
} else {
|
} else {
|
||||||
@ -17,6 +17,7 @@ bool registerObjectToDBus(QObject *o, const QString &path, const QString &interf
|
|||||||
|
|
||||||
void unregisterObjectFromDBus(const QString &path)
|
void unregisterObjectFromDBus(const QString &path)
|
||||||
{
|
{
|
||||||
auto &con = ApplicationManager1DBus::instance().globalBus();
|
auto &con = ApplicationManager1DBus::instance().globalServerBus();
|
||||||
con.unregisterObject(path);
|
con.unregisterObject(path);
|
||||||
|
qInfo() << "unregister object:" << path;
|
||||||
}
|
}
|
||||||
|
22
src/constant.h
Normal file
22
src/constant.h
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef CONSTANT_H
|
||||||
|
#define CONSTANT_H
|
||||||
|
|
||||||
|
constexpr auto SystemdService = u8"org.freedesktop.systemd1";
|
||||||
|
constexpr auto SystemdObjectPath = u8"/org/freedesktop/systemd1";
|
||||||
|
constexpr auto SystemdInterfaceName = u8"org.freedesktop.systemd1.Manager";
|
||||||
|
constexpr auto DDEApplicationManager1ServiceName = u8"org.deepin.dde.ApplicationManager1";
|
||||||
|
constexpr auto DDEApplicationManager1ObjectPath = u8"/org/deepin/dde/ApplicationManager1";
|
||||||
|
constexpr auto DDEApplicationManager1ApplicationObjectPath = u8"/org/deepin/dde/ApplicationManager1/Application/";
|
||||||
|
constexpr auto DDEApplicationManager1InstanceObjectPath = u8"/org/deepin/dde/ApplicationManager1/Instance/";
|
||||||
|
constexpr auto DDEApplicationManager1JobManagerObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1";
|
||||||
|
constexpr auto DDEApplicationManager1JobObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1/Job/";
|
||||||
|
constexpr auto DesktopFileEntryKey = u8"Desktop Entry";
|
||||||
|
constexpr auto DesktopFileActionKey = u8"Desktop Action ";
|
||||||
|
constexpr auto ApplicationManagerServerDBusName = u8"deepin_application_manager_server_bus";
|
||||||
|
constexpr auto ApplicationManagerDestDBusName = "deepin_application_manager_dest_bus";
|
||||||
|
|
||||||
|
#endif
|
@ -22,6 +22,105 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr<Identifie
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_jobManager.reset(new JobManager1Service(this));
|
m_jobManager.reset(new JobManager1Service(this));
|
||||||
|
|
||||||
|
auto &dispatcher = SystemdSignalDispatcher::instance();
|
||||||
|
|
||||||
|
connect(&dispatcher,
|
||||||
|
&SystemdSignalDispatcher::SystemdUnitNew,
|
||||||
|
this,
|
||||||
|
[this](QString serviceName, QDBusObjectPath systemdUnitPath) {
|
||||||
|
auto [appId, instanceId] = processServiceName(serviceName);
|
||||||
|
if (appId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &app : m_applicationList) {
|
||||||
|
if (app->id() == appId) [[unlikely]] {
|
||||||
|
const auto &applicationPath = app->m_applicationPath.path();
|
||||||
|
if (!app->addOneInstance(instanceId, applicationPath, systemdUnitPath.path())) {
|
||||||
|
qWarning() << "add Instance failed:" << applicationPath << serviceName << systemdUnitPath.path();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qWarning() << "couldn't find application:" << serviceName << "in application manager.";
|
||||||
|
});
|
||||||
|
|
||||||
|
connect(&dispatcher,
|
||||||
|
&SystemdSignalDispatcher::SystemdUnitRemoved,
|
||||||
|
this,
|
||||||
|
[this](QString serviceName, QDBusObjectPath systemdUnitPath) {
|
||||||
|
auto pair = processServiceName(serviceName);
|
||||||
|
auto appId = pair.first, instanceId = pair.second;
|
||||||
|
if (appId.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto appIt = std::find_if(m_applicationList.cbegin(),
|
||||||
|
m_applicationList.cend(),
|
||||||
|
[&appId](const QSharedPointer<ApplicationService> &app) {
|
||||||
|
if (app->id() == appId) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (appIt == m_applicationList.cend()) [[unlikely]] {
|
||||||
|
qWarning() << "couldn't find app" << appId << "in application manager.";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto &appRef = *appIt;
|
||||||
|
|
||||||
|
auto instanceIt = std::find_if(appRef->m_Instances.cbegin(),
|
||||||
|
appRef->m_Instances.cend(),
|
||||||
|
[&systemdUnitPath](const QSharedPointer<InstanceService> &value) {
|
||||||
|
if (value->systemdUnitPath() == systemdUnitPath) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (instanceIt != appRef->m_Instances.cend()) [[likely]] {
|
||||||
|
appRef->removeOneInstance(instanceIt.key());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
QPair<QString, QString> ApplicationManager1Service::processServiceName(const QString &serviceName)
|
||||||
|
{
|
||||||
|
QString instanceId;
|
||||||
|
QString applicationId;
|
||||||
|
|
||||||
|
if (serviceName.endsWith(".service")) {
|
||||||
|
auto lastDotIndex = serviceName.lastIndexOf('.');
|
||||||
|
auto app = serviceName.sliced(0, lastDotIndex - 1); // remove suffix
|
||||||
|
|
||||||
|
if (app.contains('@')) {
|
||||||
|
auto atIndex = app.indexOf('@');
|
||||||
|
instanceId = app.sliced(atIndex + 1);
|
||||||
|
app.remove(atIndex, instanceId.length() + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
applicationId = app.split('-').last(); // drop launcher if it exists.
|
||||||
|
} else if (serviceName.endsWith(".scope")) {
|
||||||
|
auto lastDotIndex = serviceName.lastIndexOf('.');
|
||||||
|
auto app = serviceName.sliced(0, lastDotIndex - 1);
|
||||||
|
|
||||||
|
auto components = app.split('-');
|
||||||
|
instanceId = components.takeLast();
|
||||||
|
applicationId = components.takeLast();
|
||||||
|
} else {
|
||||||
|
qDebug() << "it's not service or slice or scope.";
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instanceId.isEmpty()) {
|
||||||
|
instanceId = QUuid::createUuid().toString(QUuid::Id128);
|
||||||
|
}
|
||||||
|
|
||||||
|
return qMakePair(std::move(applicationId), std::move(instanceId));
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
QList<QDBusObjectPath> ApplicationManager1Service::list() const
|
||||||
|
@ -60,6 +60,8 @@ private:
|
|||||||
std::unique_ptr<Identifier> m_identifier;
|
std::unique_ptr<Identifier> m_identifier;
|
||||||
QScopedPointer<JobManager1Service> m_jobManager{nullptr};
|
QScopedPointer<JobManager1Service> m_jobManager{nullptr};
|
||||||
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList;
|
QMap<QDBusObjectPath, QSharedPointer<ApplicationService>> m_applicationList;
|
||||||
|
|
||||||
|
QPair<QString, QString> processServiceName(const QString &serviceName);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -19,6 +19,16 @@ ApplicationService::~ApplicationService()
|
|||||||
m_desktopSource.destruct(m_isPersistence);
|
m_desktopSource.destruct(m_isPersistence);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
qsizetype ApplicationService::applicationCheck(const QString &serviceName)
|
||||||
|
{
|
||||||
|
const auto &ApplicationId = id();
|
||||||
|
if (!serviceName.startsWith(ApplicationId)) [[likely]] {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ApplicationId.size();
|
||||||
|
}
|
||||||
|
|
||||||
QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env)
|
QString ApplicationService::GetActionName(const QString &identifier, const QStringList &env)
|
||||||
{
|
{
|
||||||
const auto &supportedActions = actions();
|
const auto &supportedActions = actions();
|
||||||
@ -130,16 +140,16 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
|
|||||||
auto resourceFile = variantValue.toString();
|
auto resourceFile = variantValue.toString();
|
||||||
if (resourceFile.isEmpty()) {
|
if (resourceFile.isEmpty()) {
|
||||||
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
auto instanceRandomUUID = QUuid::createUuid().toString(QUuid::Id128);
|
||||||
commands.push_front(QString{R"(--unitName=DDE-%1@%2.service)"}.arg(
|
commands.push_front(QString{R"(--unitName=app-DDE-%1@%2.service)"}.arg(
|
||||||
this->id(), instanceRandomUUID)); // launcher should use this instanceId
|
this->id(), instanceRandomUUID)); // launcher should use this instanceId
|
||||||
QProcess process;
|
QProcess process;
|
||||||
process.start(m_launcher, commands);
|
process.start(m_launcher, commands);
|
||||||
process.waitForFinished();
|
process.waitForFinished();
|
||||||
if (auto code = process.exitCode(); code != 0) {
|
if (auto code = process.exitCode(); code != 0) {
|
||||||
qWarning() << "Launch Application Failed. exitCode:" << code;
|
qWarning() << "Launch Application Failed. exitCode:" << code;
|
||||||
return false;
|
return QString{""};
|
||||||
}
|
}
|
||||||
return addOneInstance(instanceRandomUUID, m_applicationPath.path()); // TODO: pass correct Systemd Unit Path
|
return DDEApplicationManager1InstanceObjectPath + instanceRandomUUID;
|
||||||
}
|
}
|
||||||
|
|
||||||
int location{0};
|
int location{0};
|
||||||
@ -167,8 +177,9 @@ QDBusObjectPath ApplicationService::Launch(QString action, QStringList fields, Q
|
|||||||
auto exitCode = process.exitCode();
|
auto exitCode = process.exitCode();
|
||||||
if (exitCode != 0) {
|
if (exitCode != 0) {
|
||||||
qWarning() << "Launch Application Failed:" << binary << tmp;
|
qWarning() << "Launch Application Failed:" << binary << tmp;
|
||||||
|
return QString{""};
|
||||||
}
|
}
|
||||||
return addOneInstance(instanceRandomUUID, m_applicationPath.path());
|
return DDEApplicationManager1InstanceObjectPath + instanceRandomUUID;
|
||||||
},
|
},
|
||||||
std::move(res));
|
std::move(res));
|
||||||
}
|
}
|
||||||
@ -254,8 +265,8 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
|
|||||||
|
|
||||||
void ApplicationService::removeOneInstance(const QDBusObjectPath &instance)
|
void ApplicationService::removeOneInstance(const QDBusObjectPath &instance)
|
||||||
{
|
{
|
||||||
m_Instances.remove(instance);
|
|
||||||
unregisterObjectFromDBus(instance.path());
|
unregisterObjectFromDBus(instance.path());
|
||||||
|
m_Instances.remove(instance);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplicationService::removeAllInstance()
|
void ApplicationService::removeAllInstance()
|
||||||
|
@ -18,6 +18,7 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "desktopentry.h"
|
#include "desktopentry.h"
|
||||||
#include "desktopicons.h"
|
#include "desktopicons.h"
|
||||||
|
#include "systemdsignaldispatcher.h"
|
||||||
#include "dbus/jobmanager1service.h"
|
#include "dbus/jobmanager1service.h"
|
||||||
|
|
||||||
class ApplicationService : public QObject
|
class ApplicationService : public QObject
|
||||||
@ -52,9 +53,9 @@ public:
|
|||||||
const QString &getLauncher() const noexcept { return m_launcher; }
|
const QString &getLauncher() const noexcept { return m_launcher; }
|
||||||
void setLauncher(const QString &launcher) noexcept { m_launcher = launcher; }
|
void setLauncher(const QString &launcher) noexcept { m_launcher = launcher; }
|
||||||
|
|
||||||
bool addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath = "/");
|
bool addOneInstance(const QString &instanceId, const QString &application, const QString &systemdUnitPath);
|
||||||
void recoverInstances(const QList<QDBusObjectPath>) noexcept;
|
void recoverInstances(const QList<QDBusObjectPath>) noexcept;
|
||||||
void removeOneInstance(const QDBusObjectPath &instance); // TODO: remove instance when app closed
|
void removeOneInstance(const QDBusObjectPath &instance);
|
||||||
void removeAllInstance();
|
void removeAllInstance();
|
||||||
|
|
||||||
public Q_SLOTS:
|
public Q_SLOTS:
|
||||||
@ -133,6 +134,7 @@ private:
|
|||||||
QSharedPointer<DesktopIcons> m_Icons{nullptr};
|
QSharedPointer<DesktopIcons> m_Icons{nullptr};
|
||||||
QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
|
QMap<QDBusObjectPath, QSharedPointer<InstanceService>> m_Instances;
|
||||||
QString userNameLookup(uid_t uid);
|
QString userNameLookup(uid_t uid);
|
||||||
|
qsizetype applicationCheck(const QString &serviceName);
|
||||||
[[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
|
[[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <QMutex>
|
#include <QMutex>
|
||||||
#include <QMutexLocker>
|
#include <QMutexLocker>
|
||||||
#include <QtConcurrent>
|
#include <QtConcurrent>
|
||||||
|
#include <QDBusError>
|
||||||
#include <QFuture>
|
#include <QFuture>
|
||||||
#include <QUuid>
|
#include <QUuid>
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
@ -76,7 +77,7 @@ public:
|
|||||||
|
|
||||||
QString result{job->status()};
|
QString result{job->status()};
|
||||||
for (const auto &val : future.result()) {
|
for (const auto &val : future.result()) {
|
||||||
if (val.canConvert<QDBusError>()) {
|
if (val.metaType().id() == QMetaType::fromType<QDBusError>().id()) {
|
||||||
result = "failed";
|
result = "failed";
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
95
src/global.h
95
src/global.h
@ -18,19 +18,11 @@
|
|||||||
#include <QDBusObjectPath>
|
#include <QDBusObjectPath>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
|
#include "constant.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
|
||||||
using IconMap = QMap<QString, QMap<uint, QMap<QString, QDBusUnixFileDescriptor>>>;
|
using IconMap = QMap<QString, QMap<uint, QMap<QString, QDBusUnixFileDescriptor>>>;
|
||||||
|
|
||||||
constexpr auto DDEApplicationManager1ServiceName = u8"org.deepin.dde.ApplicationManager1";
|
|
||||||
constexpr auto DDEApplicationManager1ObjectPath = u8"/org/deepin/dde/ApplicationManager1";
|
|
||||||
constexpr auto DDEApplicationManager1ApplicationObjectPath = u8"/org/deepin/dde/ApplicationManager1/Application/";
|
|
||||||
constexpr auto DDEApplicationManager1InstanceObjectPath = u8"/org/deepin/dde/ApplicationManager1/Instance/";
|
|
||||||
constexpr auto DDEApplicationManager1JobManagerObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1";
|
|
||||||
constexpr auto DDEApplicationManager1JobObjectPath = u8"/org/deepin/dde/ApplicationManager1/JobManager1/Job/";
|
|
||||||
constexpr auto DesktopFileEntryKey = u8"Desktop Entry";
|
|
||||||
constexpr auto DesktopFileActionKey = u8"Desktop Action ";
|
|
||||||
inline QString getApplicationLauncherBinary()
|
inline QString getApplicationLauncherBinary()
|
||||||
{
|
{
|
||||||
auto value = qgetenv("DEEPIN_APPLICATION_MANAGER_APP_LAUNCH_HELPER_BIN");
|
auto value = qgetenv("DEEPIN_APPLICATION_MANAGER_APP_LAUNCH_HELPER_BIN");
|
||||||
@ -41,7 +33,6 @@ inline QString getApplicationLauncherBinary()
|
|||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
constexpr auto ApplicationManagerDBusName = u8"deepin_application_manager_bus";
|
|
||||||
|
|
||||||
enum class DBusType { Session = QDBusConnection::SessionBus, System = QDBusConnection::SystemBus, Custom };
|
enum class DBusType { Session = QDBusConnection::SessionBus, System = QDBusConnection::SystemBus, Custom };
|
||||||
|
|
||||||
@ -52,52 +43,53 @@ public:
|
|||||||
ApplicationManager1DBus(ApplicationManager1DBus &&) = delete;
|
ApplicationManager1DBus(ApplicationManager1DBus &&) = delete;
|
||||||
ApplicationManager1DBus &operator=(const ApplicationManager1DBus &) = delete;
|
ApplicationManager1DBus &operator=(const ApplicationManager1DBus &) = delete;
|
||||||
ApplicationManager1DBus &operator=(ApplicationManager1DBus &&) = delete;
|
ApplicationManager1DBus &operator=(ApplicationManager1DBus &&) = delete;
|
||||||
const QString &BusAddress() { return m_busAddress; }
|
const QString &globalDestBusAddress() const { return m_destBusAddress; }
|
||||||
void init(DBusType type, const QString &busAddress = "")
|
const QString &globalServerBusAddress() const { return m_serverBusAddress; }
|
||||||
|
void initGlobalServerBus(DBusType type, const QString &busAddress = "")
|
||||||
{
|
{
|
||||||
if (m_initFlag) {
|
if (m_initFlag) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_busAddress = busAddress;
|
m_serverBusAddress = busAddress;
|
||||||
m_type = type;
|
m_serverType = type;
|
||||||
m_initFlag = true;
|
m_initFlag = true;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QDBusConnection &globalBus()
|
QDBusConnection &globalServerBus()
|
||||||
{
|
{
|
||||||
if (m_connection.has_value()) {
|
if (m_serverConnection.has_value()) {
|
||||||
return m_connection.value();
|
return m_serverConnection.value();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!m_initFlag) {
|
if (!m_initFlag) {
|
||||||
qFatal() << "invoke init at first.";
|
qFatal() << "invoke init at first.";
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_serverType) {
|
||||||
case DBusType::Session:
|
case DBusType::Session:
|
||||||
[[fallthrough]];
|
[[fallthrough]];
|
||||||
case DBusType::System: {
|
case DBusType::System: {
|
||||||
m_connection.emplace(
|
m_serverConnection.emplace(QDBusConnection::connectToBus(static_cast<QDBusConnection::BusType>(m_serverType),
|
||||||
QDBusConnection::connectToBus(static_cast<QDBusConnection::BusType>(m_type), ApplicationManagerDBusName));
|
ApplicationManagerServerDBusName));
|
||||||
if (!m_connection->isConnected()) {
|
if (!m_serverConnection->isConnected()) {
|
||||||
qFatal() << m_connection->lastError();
|
qFatal() << m_serverConnection->lastError();
|
||||||
}
|
}
|
||||||
return m_connection.value();
|
return m_serverConnection.value();
|
||||||
}
|
}
|
||||||
case DBusType::Custom: {
|
case DBusType::Custom: {
|
||||||
if (m_busAddress.isEmpty()) {
|
if (m_serverBusAddress.isEmpty()) {
|
||||||
qFatal() << "connect to custom dbus must init this object by custom dbus address";
|
qFatal() << "connect to custom dbus must init this object by custom dbus address";
|
||||||
}
|
}
|
||||||
m_connection.emplace(
|
m_serverConnection.emplace(QDBusConnection::connectToBus(m_serverBusAddress, ApplicationManagerServerDBusName));
|
||||||
QDBusConnection::connectToBus(static_cast<QDBusConnection::BusType>(m_type), ApplicationManagerDBusName));
|
if (!m_serverConnection->isConnected()) {
|
||||||
if (!m_connection->isConnected()) {
|
qFatal() << m_serverConnection->lastError();
|
||||||
qFatal() << m_connection->lastError();
|
|
||||||
}
|
}
|
||||||
return m_connection.value();
|
return m_serverConnection.value();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Q_UNREACHABLE();
|
Q_UNREACHABLE();
|
||||||
}
|
}
|
||||||
static ApplicationManager1DBus &instance()
|
static ApplicationManager1DBus &instance()
|
||||||
@ -106,13 +98,52 @@ public:
|
|||||||
return dbus;
|
return dbus;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDBusConnection &globalDestBus()
|
||||||
|
{
|
||||||
|
if (!m_destConnection) {
|
||||||
|
qFatal() << "please set which bus should application manager to use to invoke other D-Bus service's method.";
|
||||||
|
}
|
||||||
|
return m_destConnection.value();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setDestBus(const QString &destAddress)
|
||||||
|
{
|
||||||
|
if (m_destConnection) {
|
||||||
|
m_destConnection->disconnectFromBus(ApplicationManagerDestDBusName);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_destBusAddress = destAddress;
|
||||||
|
|
||||||
|
if (m_destBusAddress.isEmpty()) {
|
||||||
|
m_destConnection.emplace(
|
||||||
|
QDBusConnection::connectToBus(QDBusConnection::BusType::SessionBus, ApplicationManagerDestDBusName));
|
||||||
|
if (!m_destConnection->isConnected()) {
|
||||||
|
qFatal() << m_destConnection->lastError();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
if (m_destBusAddress.isEmpty()) {
|
||||||
|
qFatal() << "connect to custom dbus must init this object by custom dbus address";
|
||||||
|
}
|
||||||
|
m_destConnection.emplace(QDBusConnection::connectToBus(m_destBusAddress, ApplicationManagerDestDBusName));
|
||||||
|
if (!m_destConnection->isConnected()) {
|
||||||
|
qFatal() << m_destConnection->lastError();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Q_UNREACHABLE();
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
ApplicationManager1DBus() = default;
|
ApplicationManager1DBus() = default;
|
||||||
~ApplicationManager1DBus() = default;
|
~ApplicationManager1DBus() = default;
|
||||||
bool m_initFlag;
|
bool m_initFlag;
|
||||||
DBusType m_type;
|
DBusType m_serverType;
|
||||||
QString m_busAddress;
|
QString m_serverBusAddress;
|
||||||
std::optional<QDBusConnection> m_connection{std::nullopt};
|
QString m_destBusAddress;
|
||||||
|
std::optional<QDBusConnection> m_destConnection{std::nullopt};
|
||||||
|
std::optional<QDBusConnection> m_serverConnection{std::nullopt};
|
||||||
};
|
};
|
||||||
|
|
||||||
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface);
|
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface);
|
||||||
|
50
src/systemdsignaldispatcher.cpp
Normal file
50
src/systemdsignaldispatcher.cpp
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#include "systemdsignaldispatcher.h"
|
||||||
|
|
||||||
|
bool SystemdSignalDispatcher::connectToSignals() noexcept
|
||||||
|
{
|
||||||
|
auto &con = ApplicationManager1DBus::instance().globalDestBus();
|
||||||
|
|
||||||
|
if (!con.connect(SystemdService,
|
||||||
|
SystemdObjectPath,
|
||||||
|
SystemdInterfaceName,
|
||||||
|
"UnitNew",
|
||||||
|
this,
|
||||||
|
SLOT(onUnitNew(QString, QDBusObjectPath)))) {
|
||||||
|
qCritical() << "can't connect to UnitNew signal of systemd service.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!con.connect(SystemdService,
|
||||||
|
SystemdObjectPath,
|
||||||
|
SystemdInterfaceName,
|
||||||
|
"UnitRemoved",
|
||||||
|
this,
|
||||||
|
SLOT(onUnitRemoved(QString, QDBusObjectPath)))) {
|
||||||
|
qCritical() << "can't connect to UnitRemoved signal of systemd service.";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemdSignalDispatcher::onUnitNew(QString serviceName, QDBusObjectPath systemdUnitPath)
|
||||||
|
{
|
||||||
|
if (!serviceName.startsWith("app-")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit SystemdUnitNew(serviceName.sliced(4), systemdUnitPath); // remove "app-"
|
||||||
|
}
|
||||||
|
|
||||||
|
void SystemdSignalDispatcher::onUnitRemoved(QString serviceName, QDBusObjectPath systemdUnitPath)
|
||||||
|
{
|
||||||
|
if (!serviceName.startsWith("app-")) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit SystemdUnitRemoved(serviceName.sliced(4), systemdUnitPath);
|
||||||
|
}
|
39
src/systemdsignaldispatcher.h
Normal file
39
src/systemdsignaldispatcher.h
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
|
||||||
|
//
|
||||||
|
// SPDX-License-Identifier: LGPL-3.0-or-later
|
||||||
|
|
||||||
|
#ifndef SYSTEMDSIGNALDISPATCHER_H
|
||||||
|
#define SYSTEMDSIGNALDISPATCHER_H
|
||||||
|
|
||||||
|
#include "global.h"
|
||||||
|
|
||||||
|
class SystemdSignalDispatcher : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
~SystemdSignalDispatcher() = default;
|
||||||
|
static SystemdSignalDispatcher &instance()
|
||||||
|
{
|
||||||
|
static SystemdSignalDispatcher dispatcher;
|
||||||
|
return dispatcher;
|
||||||
|
}
|
||||||
|
Q_SIGNALS:
|
||||||
|
void SystemdUnitNew(QString serviceName, QDBusObjectPath systemdUnitPath);
|
||||||
|
void SystemdUnitRemoved(QString serviceName, QDBusObjectPath systemdUnitPath);
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void onUnitNew(QString serviceName, QDBusObjectPath systemdUnitPath);
|
||||||
|
void onUnitRemoved(QString serviceName, QDBusObjectPath systemdUnitPath);
|
||||||
|
|
||||||
|
private:
|
||||||
|
explicit SystemdSignalDispatcher(QObject *parent = nullptr)
|
||||||
|
: QObject(parent)
|
||||||
|
{
|
||||||
|
if (!connectToSignals()) {
|
||||||
|
std::terminate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool connectToSignals() noexcept;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user