diff --git a/api/dbus/org.desktopspec.ApplicationManager1.xml b/api/dbus/org.desktopspec.ApplicationManager1.xml index a2d757d..2e31463 100644 --- a/api/dbus/org.desktopspec.ApplicationManager1.xml +++ b/api/dbus/org.desktopspec.ApplicationManager1.xml @@ -15,8 +15,9 @@ - - + + + resize(0)) { qCritical() << "failed to clear file:" << m_file->errorString(); - return; + return false; } auto content = QJsonDocument{m_data}.toJson(QJsonDocument::Compact); @@ -77,28 +77,32 @@ void ApplicationManager1Storage::writeToFile() const noexcept } if (!m_file->flush()) { - qCritical() << "io error."; + qCritical() << "io error, write failed."; + return false; } + + return true; } -void ApplicationManager1Storage::setVersion(uint8_t version) noexcept +bool ApplicationManager1Storage::setVersion(uint8_t version) noexcept { m_data["version"] = version; - writeToFile(); + return writeToFile(); } uint8_t ApplicationManager1Storage::version() const noexcept { - return m_data["version"].toInt(0); + return m_data["version"].toInt(-1); } -void ApplicationManager1Storage::createApplicationValue(const QString &appId, +bool ApplicationManager1Storage::createApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey, const QVariant &value) noexcept { if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) { - return; + qWarning() << "unexpected empty string"; + return false; } QJsonObject appObj; @@ -112,94 +116,137 @@ void ApplicationManager1Storage::createApplicationValue(const QString &appId, } if (groupObj.contains(valueKey)) { - return; + qInfo() << "value" << valueKey << value << "is already exists."; + return true; } groupObj.insert(valueKey, value.toJsonValue()); appObj.insert(groupName, groupObj); m_data.insert(appId, appObj); - writeToFile(); + return writeToFile(); } -void ApplicationManager1Storage::updateApplicationValue(const QString &appId, +bool ApplicationManager1Storage::updateApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey, const QVariant &value) noexcept { if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) { - return; + qWarning() << "unexpected empty string"; + return false; } if (!m_data.contains(appId)) { - return; + qInfo() << "app" << appId << "doesn't exists."; + return false; } auto appObj = m_data[appId].toObject(); if (!appObj.contains(groupName)) { - return; + qInfo() << "group" << groupName << "doesn't exists."; + return false; } auto groupObj = appObj[groupName].toObject(); if (!groupObj.contains(valueKey)) { - return; + qInfo() << "value" << valueKey << "doesn't exists."; + return false; } groupObj.insert(valueKey, value.toJsonValue()); appObj.insert(groupName, groupObj); m_data.insert(appId, appObj); - writeToFile(); + return writeToFile(); } QVariant ApplicationManager1Storage::readApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) const noexcept { - return m_data[appId][groupName][valueKey].toVariant(); + auto app = m_data.constFind(appId)->toObject(); + if (app.isEmpty()) { + return {}; + } + + auto group = app.constFind(groupName)->toObject(); + if (group.isEmpty()) { + return {}; + } + + auto val = group.constFind(valueKey); + if (val->isNull()) { + return {}; + } + + return val->toVariant(); } -void ApplicationManager1Storage::deleteApplicationValue(const QString &appId, +bool ApplicationManager1Storage::deleteApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) noexcept { - if (appId.isEmpty()) { - auto empty = QJsonObject{}; - m_data.swap(empty); - return; + if (appId.isEmpty() or groupName.isEmpty() or valueKey.isEmpty()) { + qWarning() << "unexpected empty string"; + return false; } auto app = m_data.find(appId).value(); if (app.isNull()) { - return; + return true; } auto appObj = app.toObject(); - if (groupName.isEmpty()) { - m_data.remove(appId); - return; - } - auto group = appObj.find(groupName).value(); if (group.isNull()) { - return; + return true; } auto groupObj = group.toObject(); - if (valueKey.isEmpty()) { - appObj.remove(groupName); - m_data.insert(appId, appObj); - return; - } - auto val = groupObj.find(valueKey).value(); if (val.isNull()) { - return; + return true; } groupObj.remove(valueKey); appObj.insert(groupName, groupObj); m_data.insert(appId, appObj); - writeToFile(); + return writeToFile(); +} + +bool ApplicationManager1Storage::clearData() noexcept +{ + QJsonObject obj; + m_data.swap(obj); + return setVersion(STORAGE_VERSION); +} + +bool ApplicationManager1Storage::deleteApplication(const QString &appId) noexcept +{ + if (appId.isEmpty()) { + qWarning() << "unexpected empty string."; + return false; + } + + m_data.remove(appId); + return writeToFile(); +} + +bool ApplicationManager1Storage::deleteGroup(const QString &appId, const QString &groupName) noexcept +{ + if (appId.isEmpty() or groupName.isEmpty()) { + qWarning() << "unexpected empty string."; + return false; + } + + auto app = m_data.find(appId).value().toObject(); + if (app.isEmpty()) { + return true; + } + + app.remove(groupName); + m_data.insert(appId, app); + return writeToFile(); } diff --git a/src/applicationmanagerstorage.h b/src/applicationmanagerstorage.h index 9f6b188..702c183 100644 --- a/src/applicationmanagerstorage.h +++ b/src/applicationmanagerstorage.h @@ -20,25 +20,28 @@ public: ApplicationManager1Storage &operator=(ApplicationManager1Storage &&) = default; ~ApplicationManager1Storage() = default; - void createApplicationValue(const QString &appId, + bool createApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey, const QVariant &value) noexcept; - void updateApplicationValue(const QString &appId, + bool updateApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey, const QVariant &value) noexcept; [[nodiscard]] QVariant readApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) const noexcept; - void deleteApplicationValue(const QString &appId = "", const QString &groupName = "", const QString &valueKey = "") noexcept; + bool deleteApplicationValue(const QString &appId, const QString &groupName, const QString &valueKey) noexcept; + bool clearData() noexcept; + bool deleteApplication(const QString &appId) noexcept; + bool deleteGroup(const QString &appId, const QString &groupName) noexcept; - void setVersion(uint8_t version) noexcept; + bool setVersion(uint8_t version) noexcept; [[nodiscard]] uint8_t version() const noexcept; static std::shared_ptr createApplicationManager1Storage(const QString &storageDir) noexcept; private: - void writeToFile() const noexcept; + [[nodiscard]] bool writeToFile() const noexcept; explicit ApplicationManager1Storage(const QString &storagePath); std::unique_ptr m_file; QJsonObject m_data; diff --git a/src/constant.h b/src/constant.h index 5e52656..9c70113 100644 --- a/src/constant.h +++ b/src/constant.h @@ -47,7 +47,7 @@ constexpr auto systemdOption = u8"systemd"; constexpr auto splitOption = u8"split"; constexpr auto AppExecOption = u8"appExec"; -constexpr auto STORAGE_VERSION = 1; +constexpr auto STORAGE_VERSION = 0; constexpr auto ApplicationPropertiesGroup = u8"Application Properties"; constexpr auto LastLaunchedTime = u8"LastLaunchedTime"; diff --git a/src/dbus/applicationmanager1service.cpp b/src/dbus/applicationmanager1service.cpp index ede24c5..d9a00cc 100644 --- a/src/dbus/applicationmanager1service.cpp +++ b/src/dbus/applicationmanager1service.cpp @@ -124,16 +124,7 @@ void ApplicationManager1Service::addInstanceToApplication(const QString &unitNam return; } - if (sender() != nullptr) { // activate by signal - auto timestamp = QDateTime::currentMSecsSinceEpoch(); - - if (auto ptr = m_storage.lock(); ptr) { - ptr->updateApplicationValue((*appIt)->m_desktopSource.desktopId(), - ApplicationPropertiesGroup, - LastLaunchedTime, - QVariant::fromValue(timestamp)); - } - } + (*appIt)->updateAfterLaunch(sender() != nullptr); // activate by signal const auto &applicationPath = (*appIt)->applicationPath().path(); @@ -278,17 +269,6 @@ bool ApplicationManager1Service::addApplication(DesktopFile desktopFileSource) n } m_applicationList.insert(application->applicationPath(), application); - if (auto storagePtr = m_storage.lock(); storagePtr) { - auto appId = ptr->id(); - auto value = storagePtr->readApplicationValue(appId, ApplicationPropertiesGroup, LastLaunchedTime); - if (value.isNull()) { - storagePtr->createApplicationValue( - appId, ApplicationPropertiesGroup, LastLaunchedTime, QVariant::fromValue(0)); - } else { - ptr->m_lastLaunch = value.toInt(); - } - } - emit listChanged(); emit InterfacesAdded(application->applicationPath(), getChildInterfacesAndPropertiesFromObject(ptr)); @@ -300,7 +280,7 @@ void ApplicationManager1Service::removeOneApplication(const QDBusObjectPath &app if (auto it = m_applicationList.find(application); it != m_applicationList.cend()) { emit InterfacesRemoved(application, getChildInterfacesFromObject(it->data())); if (auto ptr = m_storage.lock(); ptr) { - ptr->deleteApplicationValue((*it)->id()); + ptr->deleteApplication((*it)->id()); } unregisterObjectFromDBus(application.path()); m_applicationList.remove(application); @@ -317,7 +297,8 @@ void ApplicationManager1Service::removeAllApplication() noexcept } QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidfd, - ObjectMap &application_instance_info) const noexcept + QDBusObjectPath &instance, + ObjectInterfaceMap &application_instance_info) const noexcept { if (!pidfd.isValid()) { qWarning() << "pidfd isn't a valid unix file descriptor"; @@ -369,17 +350,16 @@ QString ApplicationManager1Service::Identify(const QDBusUnixFileDescriptor &pidf return {}; } - auto instance = (*app)->findInstance(ret.InstanceId); + auto instancePath = (*app)->findInstance(ret.InstanceId); - if (auto path = instance.path(); path.isEmpty()) { + if (auto path = instancePath.path(); path.isEmpty()) { qWarning() << "can't find instance:" << path; return {}; } + instance = instancePath; auto instanceObj = (*app)->m_Instances.constFind(instance); - auto map = getChildInterfacesAndPropertiesFromObject(instanceObj->get()); - - application_instance_info.insert(instance, map); + application_instance_info = getChildInterfacesAndPropertiesFromObject(instanceObj->get()); return ret.ApplicationId; } @@ -407,6 +387,7 @@ void ApplicationManager1Service::updateApplication(const QSharedPointerm_entry != newEntry) { destApp->resetEntry(newEntry); destApp->m_desktopSource = std::move(desktopFile); + destApp->detachAllInstance(); } } diff --git a/src/dbus/applicationmanager1service.h b/src/dbus/applicationmanager1service.h index 4ef8823..8021943 100644 --- a/src/dbus/applicationmanager1service.h +++ b/src/dbus/applicationmanager1service.h @@ -44,7 +44,9 @@ public: JobManager1Service &jobManager() noexcept { return *m_jobManager; } public Q_SLOTS: - QString Identify(const QDBusUnixFileDescriptor &pidfd, ObjectMap &application_instance_info) const noexcept; + QString Identify(const QDBusUnixFileDescriptor &pidfd, + QDBusObjectPath &instance, + ObjectInterfaceMap &application_instance_info) const noexcept; void ReloadApplications(); [[nodiscard]] ObjectMap GetManagedObjects() const; diff --git a/src/dbus/applicationservice.cpp b/src/dbus/applicationservice.cpp index bad298d..9a004c8 100644 --- a/src/dbus/applicationservice.cpp +++ b/src/dbus/applicationservice.cpp @@ -29,14 +29,28 @@ ApplicationService::ApplicationService(DesktopFile source, , m_storage(std::move(storage)) , m_desktopSource(std::move(source)) { + auto storagePtr = m_storage.lock(); + if (!storagePtr) { + m_lastLaunch = -1; + return; + } + + auto appId = id(); + auto value = storagePtr->readApplicationValue(appId, ApplicationPropertiesGroup, LastLaunchedTime); + if (value.isNull()) { + if (!storagePtr->createApplicationValue( + appId, ApplicationPropertiesGroup, LastLaunchedTime, QVariant::fromValue(0))) { + m_lastLaunch = -1; + } + return; + } + + m_lastLaunch = value.toInt(); } ApplicationService::~ApplicationService() { - for (auto &instance : m_Instances.values()) { - orphanedInstances->append(instance); - instance->m_orphaned = true; - } + detachAllInstance(); } QSharedPointer ApplicationService::createApplicationService( @@ -93,12 +107,6 @@ QSharedPointer ApplicationService::createApplicationService( return nullptr; } - auto ptr = app->m_storage.lock(); - if (!ptr) { - qWarning() << "runtime storage doesn't exists."; - return app; - } - return app; } @@ -501,6 +509,16 @@ void ApplicationService::removeAllInstance() noexcept } } +void ApplicationService::detachAllInstance() noexcept +{ + for (auto &instance : m_Instances.values()) { + orphanedInstances->append(instance); + instance->m_orphaned = true; + } + + m_Instances.clear(); +} + QDBusObjectPath ApplicationService::findInstance(const QString &instanceId) const { for (auto it = m_Instances.constKeyValueBegin(); it != m_Instances.constKeyValueEnd(); ++it) { @@ -715,6 +733,20 @@ QVariant ApplicationService::findEntryValue(const QString &group, return ret; } +void ApplicationService::updateAfterLaunch(bool isLaunch) noexcept +{ + if (!isLaunch) { + return; + } + + auto timestamp = QDateTime::currentMSecsSinceEpoch(); + + if (auto ptr = m_storage.lock(); ptr) { + ptr->updateApplicationValue( + m_desktopSource.desktopId(), ApplicationPropertiesGroup, ::LastLaunchedTime, QVariant::fromValue(timestamp)); + } +} + QString getDeepinWineScaleFactor(const QString &appId) noexcept { qCritical() << "Don't using env to control the window scale factor, this function" diff --git a/src/dbus/applicationservice.h b/src/dbus/applicationservice.h index 98239ac..d5a8acc 100644 --- a/src/dbus/applicationservice.h +++ b/src/dbus/applicationservice.h @@ -100,6 +100,7 @@ public: return m_Instances; } void resetEntry(DesktopEntry *newEntry) noexcept; + void detachAllInstance() noexcept; public Q_SLOTS: QDBusObjectPath Launch(const QString &action, const QStringList &fields, const QVariantMap &options); @@ -131,6 +132,7 @@ private: const QString &valueKey, EntryValueType type, const QLocale &locale = getUserLocale()) const noexcept; + void updateAfterLaunch(bool isLaunch) noexcept; static bool shouldBeShown(const std::unique_ptr &entry) noexcept; static bool autostartCheck(const QString &linkPath) noexcept; }; diff --git a/tests/ut_applicationmanager.cpp b/tests/ut_applicationmanager.cpp index 1437cac..3dfacb6 100644 --- a/tests/ut_applicationmanager.cpp +++ b/tests/ut_applicationmanager.cpp @@ -97,12 +97,12 @@ TEST_F(TestApplicationManager, identifyService) auto pidfd = pidfd_open(fakePid, 0); ASSERT_TRUE(pidfd > 0) << std::strerror(errno); - ObjectMap instanceInfo; - auto appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, instanceInfo); + ObjectInterfaceMap instanceInfo; + QDBusObjectPath path; + auto appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, path, instanceInfo); EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString()); - auto instance = instanceInfo.constFind(InstancePath); - if (instance == instanceInfo.cend()) { + if (path.path().isEmpty()) { GTEST_SKIP_("couldn't find instance and skip."); } @@ -111,7 +111,7 @@ TEST_F(TestApplicationManager, identifyService) {QString{"SystemdUnitPath"}, QDBusObjectPath{"/"}}, {QString{"Launcher"}, QString{"DDE"}}, {QString{"Orphaned"}, false}}}}; - EXPECT_EQ(instance.value(), map); + EXPECT_EQ(instanceInfo, map); close(pidfd); @@ -148,16 +148,16 @@ TEST_F(TestApplicationManager, identifyService) ASSERT_TRUE(pidfd > 0) << std::strerror(errno); instanceInfo.clear(); + path.setPath("/"); - appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, instanceInfo); + appId = m_am->Identify(QDBusUnixFileDescriptor{pidfd}, path, instanceInfo); EXPECT_EQ(appId.toStdString(), QString{"test-Application"}.toStdString()); - instance = instanceInfo.constFind(InstancePath); - if (instance == instanceInfo.cend()) { + if (path.path().isEmpty()) { GTEST_SKIP_("couldn't find instance and skip."); } - EXPECT_EQ(instance.value(), map); + EXPECT_EQ(instanceInfo, map); close(pidfd);