From 0302bfdc2207f9b5482fb07aa6052e7f6cb237ca Mon Sep 17 00:00:00 2001 From: Vaxry Date: Sun, 27 Apr 2025 00:03:32 +0100 Subject: async: add Promise and use it for AsyncDialogBox --- src/managers/ANRManager.cpp | 9 +++++- .../permissions/DynamicPermissionManager.cpp | 36 +++++++++++++++++++++- .../permissions/DynamicPermissionManager.hpp | 27 ++++++++++------ 3 files changed, 60 insertions(+), 12 deletions(-) (limited to 'src/managers') diff --git a/src/managers/ANRManager.cpp b/src/managers/ANRManager.cpp index 69d127a7..48b9a6db 100644 --- a/src/managers/ANRManager.cpp +++ b/src/managers/ANRManager.cpp @@ -169,7 +169,14 @@ void CANRManager::SANRData::runDialog(const std::string& title, const std::strin appClass.empty() ? "unknown" : appClass), std::vector{"Terminate", "Wait"}); - dialogBox->open([dialogWmPID, this](std::string result) { + dialogBox->open()->then([dialogWmPID, this](SP> r) { + if (r->hasError()) { + Debug::log(ERR, "CANRManager::SANRData::runDialog: error spawning dialog"); + return; + } + + const auto& result = r->result(); + if (result.starts_with("Terminate")) ::kill(dialogWmPID, SIGKILL); else if (result.starts_with("Wait")) diff --git a/src/managers/permissions/DynamicPermissionManager.cpp b/src/managers/permissions/DynamicPermissionManager.cpp index cf1fd1a0..c23f1fdb 100644 --- a/src/managers/permissions/DynamicPermissionManager.cpp +++ b/src/managers/permissions/DynamicPermissionManager.cpp @@ -48,6 +48,7 @@ static const char* permissionToString(eDynamicPermissionType type) { switch (type) { case PERMISSION_TYPE_UNKNOWN: return "PERMISSION_TYPE_UNKNOWN"; case PERMISSION_TYPE_SCREENCOPY: return "PERMISSION_TYPE_SCREENCOPY"; + case PERMISSION_TYPE_PLUGIN: return "PERMISSION_TYPE_PLUGIN"; } return "error"; @@ -57,6 +58,7 @@ static const char* permissionToHumanString(eDynamicPermissionType type) { switch (type) { case PERMISSION_TYPE_UNKNOWN: return "requesting an unknown permission"; case PERMISSION_TYPE_SCREENCOPY: return "trying to capture your screen"; + case PERMISSION_TYPE_PLUGIN: return "trying to load a plugin"; } return "error"; @@ -210,10 +212,22 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s return; } - rule->m_dialogBox->open([r = WP(rule), binaryPath](std::string result) { + rule->m_promise = rule->m_dialogBox->open(); + rule->m_promise->then([r = WP(rule), binaryPath](SP> pr) { if (!r) return; + if (pr->hasError()) { + // not reachable for now + Debug::log(TRACE, "CDynamicPermissionRule: error spawning dialog box"); + if (r->m_promiseResolverForExternal) + r->m_promiseResolverForExternal->reject("error spawning dialog box"); + r->m_promiseResolverForExternal.reset(); + return; + } + + const std::string& result = pr->result(); + Debug::log(TRACE, "CDynamicPermissionRule: user returned {}", result); if (result.starts_with("Allow once")) @@ -226,9 +240,29 @@ void CDynamicPermissionManager::askForPermission(wl_client* client, const std::s r->m_binaryPath = binaryPath; } else if (result.starts_with("Allow")) r->m_allowMode = PERMISSION_RULE_ALLOW_MODE_ALLOW; + + if (r->m_promiseResolverForExternal) + r->m_promiseResolverForExternal->resolve(r->m_allowMode); + + r->m_promise.reset(); + r->m_promiseResolverForExternal.reset(); }); } +SP> CDynamicPermissionManager::promiseFor(wl_client* client, eDynamicPermissionType permission) { + auto rule = std::ranges::find_if(m_rules, [client, permission](const auto& e) { return e->m_client == client && e->m_type == permission; }); + if (rule == m_rules.end()) + return nullptr; + + if (!(*rule)->m_promise) + return nullptr; + + if ((*rule)->m_promiseResolverForExternal) + return nullptr; + + return CPromise::make([rule](SP> r) { (*rule)->m_promiseResolverForExternal = r; }); +} + void CDynamicPermissionManager::removeRulesForClient(wl_client* client) { std::erase_if(m_rules, [client](const auto& e) { return e->m_client == client; }); } diff --git a/src/managers/permissions/DynamicPermissionManager.hpp b/src/managers/permissions/DynamicPermissionManager.hpp index 681cbc1c..79dc56a6 100644 --- a/src/managers/permissions/DynamicPermissionManager.hpp +++ b/src/managers/permissions/DynamicPermissionManager.hpp @@ -5,7 +5,7 @@ #include "../../helpers/AsyncDialogBox.hpp" #include #include -#include +#include "../../helpers/defer/Promise.hpp" // NOLINTNEXTLINE namespace re2 { @@ -15,6 +15,7 @@ namespace re2 { enum eDynamicPermissionType : uint8_t { PERMISSION_TYPE_UNKNOWN = 0, PERMISSION_TYPE_SCREENCOPY, + PERMISSION_TYPE_PLUGIN, }; enum eDynamicPermissionRuleSource : uint8_t { @@ -50,16 +51,18 @@ class CDynamicPermissionRule { // user rule CDynamicPermissionRule(wl_client* const client, eDynamicPermissionType type, eDynamicPermissionAllowMode defaultAllowMode = PERMISSION_RULE_ALLOW_MODE_ASK); - const eDynamicPermissionType m_type = PERMISSION_TYPE_UNKNOWN; - const eDynamicPermissionRuleSource m_source = PERMISSION_RULE_SOURCE_UNKNOWN; - wl_client* const m_client = nullptr; - std::string m_binaryPath = ""; - UP m_binaryRegex; + const eDynamicPermissionType m_type = PERMISSION_TYPE_UNKNOWN; + const eDynamicPermissionRuleSource m_source = PERMISSION_RULE_SOURCE_UNKNOWN; + wl_client* const m_client = nullptr; + std::string m_binaryPath = ""; + UP m_binaryRegex; - eDynamicPermissionAllowMode m_allowMode = PERMISSION_RULE_ALLOW_MODE_ASK; - SP m_dialogBox; // for pending + eDynamicPermissionAllowMode m_allowMode = PERMISSION_RULE_ALLOW_MODE_ASK; + SP m_dialogBox; // for pending + SP> m_promise; // for pending + SP> m_promiseResolverForExternal; // for external promise - SDynamicPermissionRuleDestroyWrapper m_destroyWrapper; + SDynamicPermissionRuleDestroyWrapper m_destroyWrapper; friend class CDynamicPermissionManager; }; @@ -73,7 +76,11 @@ class CDynamicPermissionManager { // (will continue returning false if the user does not agree, of course.) eDynamicPermissionAllowMode clientPermissionMode(wl_client* client, eDynamicPermissionType permission); - void removeRulesForClient(wl_client* client); + // get a promise for the result. Returns null if there already was one requested for the client. + // Returns null if state is not pending + SP> promiseFor(wl_client* client, eDynamicPermissionType permission); + + void removeRulesForClient(wl_client* client); private: void askForPermission(wl_client* client, const std::string& binaryName, eDynamicPermissionType type); -- cgit v1.2.3