diff --git a/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml b/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml
index a502daa..bfb7d66 100644
--- a/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml
+++ b/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml
@@ -4,9 +4,12 @@
diff --git a/api/dbus/org.desktopspec.ApplicationManager1.xml b/api/dbus/org.desktopspec.ApplicationManager1.xml
index 7b700f3..12f933e 100644
--- a/api/dbus/org.desktopspec.ApplicationManager1.xml
+++ b/api/dbus/org.desktopspec.ApplicationManager1.xml
@@ -30,6 +30,5 @@
1. You should use pidfd_open(2) to get a pidfd."
/>
-
diff --git a/api/dbus/org.desktopspec.ObjectManager1.xml b/api/dbus/org.desktopspec.ObjectManager1.xml
new file mode 100644
index 0000000..c1fbe2a
--- /dev/null
+++ b/api/dbus/org.desktopspec.ObjectManager1.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/dde-application-manager/src/main.cpp b/apps/dde-application-manager/src/main.cpp
index d25aeba..16882bb 100644
--- a/apps/dde-application-manager/src/main.cpp
+++ b/apps/dde-application-manager/src/main.cpp
@@ -15,6 +15,7 @@ void registerComplexDbusType()
qDBusRegisterMetaType>();
qDBusRegisterMetaType>>();
qDBusRegisterMetaType();
+ qDBusRegisterMetaType();
}
} // namespace
diff --git a/src/dbus/CMakeLists.txt b/src/dbus/CMakeLists.txt
index ae56a0b..afbfd82 100644
--- a/src/dbus/CMakeLists.txt
+++ b/src/dbus/CMakeLists.txt
@@ -11,7 +11,8 @@ qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.deskto
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ApplicationManager1.Instance.xml dbus/instanceservice.h InstanceService)
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.JobManager1.xml dbus/jobmanager1service.h JobManager1Service)
qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.JobManager1.Job.xml dbus/jobservice.h JobService)
-
+qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ObjectManager1.xml dbus/applicationmanager1service.h ApplicationManager1Service AMobjectmanager1adaptor AMObjectManagerAdaptor)
+qt_add_dbus_adaptor(dde_am_dbus_SOURCE ${PROJECT_SOURCE_DIR}/api/dbus/org.desktopspec.ObjectManager1.xml dbus/applicationservice.h ApplicationService APPobjectmanager1adaptor APPObjectManagerAdaptor)
target_sources(dde_am_dbus PRIVATE
${dde_am_dbus_SOURCE}
diff --git a/src/dbus/applicationmanager1service.cpp b/src/dbus/applicationmanager1service.cpp
index 19ef5d3..ad06dee 100644
--- a/src/dbus/applicationmanager1service.cpp
+++ b/src/dbus/applicationmanager1service.cpp
@@ -1,8 +1,9 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: LGPL-3.0-or-later
-#include "dbus/applicationmanager1service.h"
+
#include "dbus/applicationmanager1adaptor.h"
+#include "dbus/AMobjectmanager1adaptor.h"
#include "systemdsignaldispatcher.h"
#include
#include
@@ -17,8 +18,14 @@ ApplicationManager1Service::ApplicationManager1Service(std::unique_ptr())) {
+ if (tmp == nullptr) {
+ std::terminate();
+ }
+
+ if (!registerObjectToDBus(
+ this, DDEApplicationManager1ObjectPath, getDBusInterface(QMetaType::fromType()))) {
std::terminate();
}
@@ -98,6 +105,7 @@ QList ApplicationManager1Service::list() const
void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &application)
{
if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) {
+ emit InterfacesRemoved(application, getInterfacesListFromObject(it->data()));
unregisterObjectFromDBus(application.path());
m_applicationList.remove(application);
}
@@ -207,3 +215,15 @@ void ApplicationManager1Service::UpdateApplicationInfo(const QStringList &appIdL
addApplication(std::move(file).value());
}
}
+
+ObjectMap ApplicationManager1Service::GetManagedObjects() const
+{
+ ObjectMap objs;
+
+ for (const auto &[key, value] : m_applicationList.asKeyValueRange()) {
+ auto interfaces = getInterfacesListFromObject(value.data());
+ objs.insert(key, interfaces);
+ }
+
+ return objs;
+}
diff --git a/src/dbus/applicationmanager1service.h b/src/dbus/applicationmanager1service.h
index d798d85..b9add4b 100644
--- a/src/dbus/applicationmanager1service.h
+++ b/src/dbus/applicationmanager1service.h
@@ -13,7 +13,7 @@
#include
#include
#include "dbus/jobmanager1service.h"
-#include "dbus/applicationservice.h"
+#include "dbus/APPobjectmanager1adaptor.h"
#include "dbus/applicationadaptor.h"
#include "identifier.h"
@@ -39,13 +39,25 @@ public:
return false;
}
+ if (m_applicationList.constFind(application->m_applicationPath) != m_applicationList.cend()) {
+ auto info = qInfo();
+ info << "this application already exists.";
+ if (application->m_isPersistence) {
+ info << "desktop source:" << application->m_desktopSource.m_file.filePath();
+ }
+ return false;
+ }
+
auto *ptr = application.data();
new ApplicationAdaptor{ptr};
- if (!registerObjectToDBus(ptr, application->m_applicationPath.path(), getDBusInterface())) {
+ if (!registerObjectToDBus(
+ ptr, application->m_applicationPath.path(), getDBusInterface(QMetaType::fromType()))) {
return false;
}
m_applicationList.insert(application->m_applicationPath, application);
+ emit InterfacesAdded(application->m_applicationPath, getInterfacesListFromObject(ptr));
+
return true;
}
void removeOneApplication(const QDBusObjectPath &application);
@@ -58,6 +70,11 @@ public:
public Q_SLOTS:
QString Identify(const QDBusUnixFileDescriptor &pidfd, QDBusObjectPath &application, QDBusObjectPath &application_instance);
void UpdateApplicationInfo(const QStringList &appIdList);
+ [[nodiscard]] ObjectMap GetManagedObjects() const;
+
+Q_SIGNALS:
+ void InterfacesAdded(const QDBusObjectPath &object_path, const QStringList &interfaces);
+ void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
private:
std::unique_ptr m_identifier;
@@ -65,4 +82,58 @@ private:
QMap> m_applicationList;
};
+template
+QSharedPointer makeApplication(T &&source, ApplicationManager1Service *parent)
+{
+ static_assert(std::is_same_v or std::is_same_v, "param type must be QString or DesktopFile.");
+ QString objectPath;
+ QTextStream sourceStream;
+ QFile sourceFile;
+ QSharedPointer app{nullptr};
+
+ if constexpr (std::is_same_v) {
+ DesktopFile in{std::forward(source)};
+ objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + escapeToObjectPath(in.desktopId());
+ sourceFile.setFileName(in.filePath());
+
+ if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
+ qCritical() << "desktop file can't open:" << in.filePath() << sourceFile.errorString();
+ return nullptr;
+ }
+
+ app.reset(new ApplicationService{std::move(in)});
+ sourceStream.setDevice(&sourceFile);
+ } else if (std::is_same_v) {
+ QString in{std::forward(source)};
+ objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + QUuid::createUuid().toString(QUuid::Id128);
+
+ app.reset(new ApplicationService{std::move(in)});
+ sourceStream.setString(&in, QTextStream::ReadOnly | QTextStream::Text);
+ }
+
+ std::unique_ptr entry{std::make_unique()};
+ auto error = entry->parse(sourceStream);
+
+ if (error != DesktopErrorCode::NoError) {
+ if (error != DesktopErrorCode::EntryKeyInvalid) {
+ return nullptr;
+ }
+ }
+
+ if (auto val = entry->value(DesktopFileEntryKey, "Hidden"); val.has_value()) {
+ bool ok{false};
+ if (auto hidden = val.value().toBoolean(ok); ok and hidden) {
+ return nullptr;
+ }
+ }
+
+ app->m_parent = parent;
+ app->m_entry.reset(entry.release());
+ app->m_applicationPath = QDBusObjectPath{std::move(objectPath)};
+
+ // TODO: icon lookup
+ new APPObjectManagerAdaptor{app.data()};
+ return app;
+}
+
#endif
diff --git a/src/dbus/applicationservice.cpp b/src/dbus/applicationservice.cpp
index 52f61e1..7b73744 100644
--- a/src/dbus/applicationservice.cpp
+++ b/src/dbus/applicationservice.cpp
@@ -206,6 +206,18 @@ QStringList ApplicationService::actions() const noexcept
return actionList;
}
+ObjectMap ApplicationService::GetManagedObjects() const
+{
+ ObjectMap objs;
+
+ for (const auto &[key, value] : m_Instances.asKeyValueRange()) {
+ auto interfaces = getInterfacesListFromObject(value.data());
+ objs.insert(key, interfaces);
+ }
+
+ return objs;
+}
+
QString ApplicationService::id() const noexcept
{
if (m_isPersistence) {
@@ -292,10 +304,11 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
auto adaptor = new InstanceAdaptor(service);
QString objectPath{m_applicationPath.path() + "/" + instanceId};
- if (registerObjectToDBus(service, objectPath, getDBusInterface())) {
+ if (registerObjectToDBus(service, objectPath, getDBusInterface(QMetaType::fromType()))) {
m_Instances.insert(QDBusObjectPath{objectPath}, QSharedPointer{service});
service->moveToThread(this->thread());
adaptor->moveToThread(this->thread());
+ emit InterfacesAdded(QDBusObjectPath{objectPath}, getInterfacesListFromObject(service));
return true;
}
@@ -306,8 +319,11 @@ bool ApplicationService::addOneInstance(const QString &instanceId, const QString
void ApplicationService::removeOneInstance(const QDBusObjectPath &instance)
{
- unregisterObjectFromDBus(instance.path());
- m_Instances.remove(instance);
+ if (auto it = m_Instances.find(instance); it != m_Instances.cend()) {
+ emit InterfacesRemoved(instance, getInterfacesListFromObject(it->data()));
+ unregisterObjectFromDBus(instance.path());
+ m_Instances.remove(instance);
+ }
}
void ApplicationService::removeAllInstance()
diff --git a/src/dbus/applicationservice.h b/src/dbus/applicationservice.h
index 1cccf57..5eb5128 100644
--- a/src/dbus/applicationservice.h
+++ b/src/dbus/applicationservice.h
@@ -67,6 +67,11 @@ public:
public Q_SLOTS:
QString GetActionName(const QString &identifier, const QStringList &env);
QDBusObjectPath Launch(QString action, QStringList fields, QVariantMap options);
+ [[nodiscard]] ObjectMap GetManagedObjects() const;
+
+Q_SIGNALS:
+ void InterfacesAdded(const QDBusObjectPath &object_path, const QStringList &interfaces);
+ void InterfacesRemoved(const QDBusObjectPath &object_path, const QStringList &interfaces);
private:
friend class ApplicationManager1Service;
@@ -118,58 +123,4 @@ private:
[[nodiscard]] LaunchTask unescapeExec(const QString &str, const QStringList &fields);
};
-template
-QSharedPointer makeApplication(T &&source, ApplicationManager1Service *parent)
-{
- static_assert(std::is_same_v or std::is_same_v, "param type must be QString or DesktopFile.");
- QString objectPath;
- QTextStream sourceStream;
- QFile sourceFile;
- QSharedPointer app{nullptr};
-
- if constexpr (std::is_same_v) {
- DesktopFile in{std::forward(source)};
- objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + escapeToObjectPath(in.desktopId());
- sourceFile.setFileName(in.filePath());
-
- if (!sourceFile.open(QFile::ExistingOnly | QFile::ReadOnly | QFile::Text)) {
- qCritical() << "desktop file can't open:" << in.filePath() << sourceFile.errorString();
- return nullptr;
- }
-
- app.reset(new ApplicationService{std::move(in)});
- sourceStream.setDevice(&sourceFile);
- } else if (std::is_same_v) {
- QString in{std::forward(source)};
- objectPath = QString{DDEApplicationManager1ObjectPath} + "/" + QUuid::createUuid().toString(QUuid::Id128);
-
- app.reset(new ApplicationService{std::move(in)});
- sourceStream.setString(&in, QTextStream::ReadOnly | QTextStream::Text);
- }
-
- std::unique_ptr entry{std::make_unique()};
- auto error = entry->parse(sourceStream);
-
- if (error != DesktopErrorCode::NoError) {
- if (error != DesktopErrorCode::EntryKeyInvalid) {
- return nullptr;
- }
- }
-
- if (auto val = entry->value(DesktopFileEntryKey, "Hidden"); val.has_value()) {
- bool ok{false};
- if (auto hidden = val.value().toBoolean(ok); ok and hidden) {
- return nullptr;
- }
- }
-
- app->m_parent = parent;
- app->m_entry.reset(entry.release());
- app->m_applicationPath = QDBusObjectPath{std::move(objectPath)};
-
- // TODO: icon lookup
-
- return app;
-}
-
#endif
diff --git a/src/dbus/jobmanager1service.cpp b/src/dbus/jobmanager1service.cpp
index 2d7e72f..33a1533 100644
--- a/src/dbus/jobmanager1service.cpp
+++ b/src/dbus/jobmanager1service.cpp
@@ -9,7 +9,8 @@ JobManager1Service::JobManager1Service(ApplicationManager1Service *parent)
: m_parent(parent)
{
new JobManager1Adaptor{this};
- if (!registerObjectToDBus(this, DDEApplicationManager1JobManagerObjectPath, getDBusInterface())) {
+ if (!registerObjectToDBus(
+ this, DDEApplicationManager1JobManagerObjectPath, getDBusInterface(QMetaType::fromType()))) {
std::terminate();
}
qRegisterMetaType();
diff --git a/src/dbus/jobmanager1service.h b/src/dbus/jobmanager1service.h
index 23801aa..47e004d 100644
--- a/src/dbus/jobmanager1service.h
+++ b/src/dbus/jobmanager1service.h
@@ -61,7 +61,7 @@ public:
auto *ptr = job.data();
new JobAdaptor(ptr);
- if (!registerObjectToDBus(ptr, objectPath, getDBusInterface())) {
+ if (!registerObjectToDBus(ptr, objectPath, getDBusInterface(QMetaType::fromType()))) {
qCritical() << "can't register job to dbus.";
future.cancel();
return {};
diff --git a/src/global.h b/src/global.h
index 49b65a9..4271cb6 100644
--- a/src/global.h
+++ b/src/global.h
@@ -23,6 +23,7 @@
#include "config.h"
using IconMap = QMap>>;
+using ObjectMap = QMap;
inline QString getApplicationLauncherBinary()
{
@@ -185,11 +186,9 @@ private:
bool registerObjectToDBus(QObject *o, const QString &path, const QString &interface);
void unregisterObjectFromDBus(const QString &path);
-template
-QString getDBusInterface()
+inline QString getDBusInterface(const QMetaType &meta)
{
- auto meta = QMetaType::fromType();
- auto infoObject = meta.metaObject();
+ const auto *infoObject = meta.metaObject();
if (auto infoIndex = infoObject->indexOfClassInfo("D-Bus Interface"); infoIndex != -1) {
return infoObject->classInfo(infoIndex).value();
}
@@ -197,6 +196,19 @@ QString getDBusInterface()
return {};
}
+inline QStringList getInterfacesListFromObject(QObject *o)
+{
+ auto childs = o->children();
+ QStringList interfaces;
+ std::for_each(childs.cbegin(), childs.cend(), [&interfaces](QObject *app) {
+ if (app->inherits("QDBusAbstractAdaptor")) {
+ interfaces.emplace_back(getDBusInterface(app->metaObject()->metaType()));
+ }
+ });
+
+ return interfaces;
+}
+
inline uid_t getCurrentUID()
{
return getuid(); // current use linux getuid