diff options
author | saturneric <[email protected]> | 2023-10-17 15:45:10 +0000 |
---|---|---|
committer | saturneric <[email protected]> | 2023-10-17 15:45:10 +0000 |
commit | 459cd3d0e512a1166b3a09233c22b7357b514760 (patch) | |
tree | 9ab0484a6d17ca7971f54f46a9d74b1c971f8b28 /src/core/module | |
parent | fix: slove compile issues (diff) | |
download | GpgFrontend-459cd3d0e512a1166b3a09233c22b7357b514760.tar.gz GpgFrontend-459cd3d0e512a1166b3a09233c22b7357b514760.zip |
refactor: move module system to core and make it work
Diffstat (limited to 'src/core/module')
-rw-r--r-- | src/core/module/Event.cpp | 108 | ||||
-rw-r--r-- | src/core/module/Event.h | 88 | ||||
-rw-r--r-- | src/core/module/GlobalModuleContext.cpp | 341 | ||||
-rw-r--r-- | src/core/module/GlobalModuleContext.h | 83 | ||||
-rw-r--r-- | src/core/module/GpgFrontendModuleSystem.h | 34 | ||||
-rw-r--r-- | src/core/module/Module.cpp | 107 | ||||
-rw-r--r-- | src/core/module/Module.h | 87 | ||||
-rw-r--r-- | src/core/module/ModuleManager.cpp | 111 | ||||
-rw-r--r-- | src/core/module/ModuleManager.h | 104 |
9 files changed, 1063 insertions, 0 deletions
diff --git a/src/core/module/Event.cpp b/src/core/module/Event.cpp new file mode 100644 index 00000000..3e27e26d --- /dev/null +++ b/src/core/module/Event.cpp @@ -0,0 +1,108 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "Event.h" + +#include <memory> + +namespace GpgFrontend::Module { + +class Event::Impl { + public: + Impl(const std::string& event_dientifier, + std::initializer_list<ParameterInitializer> params_init_list = {}) + : event_identifier_(event_dientifier) { + for (const auto& param : params_init_list) { + AddParameter(param); + } + } + + std::optional<ParameterValue> operator[](const std::string& key) const { + auto it = data_.find(key); + if (it != data_.end()) { + return it->second; + } + return std::nullopt; + } + + bool operator==(const Event& other) const { + return event_identifier_ == other.p_->event_identifier_; + } + + bool operator!=(const Event& other) const { return !(*this == other); } + + bool operator<(const Event& other) const { + return this->event_identifier_ < other.p_->event_identifier_; + } + + operator std::string() const { return event_identifier_; } + + EventIdentifier GetIdentifier() { return event_identifier_; } + + void AddParameter(const std::string& key, const ParameterValue& value) { + data_[key] = value; + } + + void AddParameter(ParameterInitializer param) { + AddParameter(param.key, param.value); + } + + private: + EventIdentifier event_identifier_; + std::map<std::string, ParameterValue> data_; +}; + +Event::Event(const std::string& event_dientifier, + std::initializer_list<ParameterInitializer> params_init_list) + : p_(std::make_unique<Impl>(event_dientifier, params_init_list)) {} + +Event::~Event() = default; + +bool Event::Event::operator==(const Event& other) const { + return this->p_ == other.p_; +} + +bool Event::Event::operator!=(const Event& other) const { + return this->p_ != other.p_; +} + +bool Event::Event::operator<(const Event& other) const { + return this->p_ < other.p_; +} + +Event::Event::operator std::string() const { + return static_cast<std::string>(*p_); +} + +EventIdentifier Event::Event::GetIdentifier() { return p_->GetIdentifier(); } + +void Event::AddParameter(const std::string& key, const ParameterValue& value) { + p_->AddParameter(key, value); +} + +} // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/Event.h b/src/core/module/Event.h new file mode 100644 index 00000000..8703b159 --- /dev/null +++ b/src/core/module/Event.h @@ -0,0 +1,88 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef GPGFRONTEND_EVENT_H +#define GPGFRONTEND_EVENT_H + +#include <memory> + +#include "core/GpgFrontendCoreExport.h" + +namespace GpgFrontend::Module { + +class Event; + +using EventRefrernce = std::shared_ptr<Event>; +using EventIdentifier = std::string; +using Evnets = std::vector<Event>; + +class GPGFRONTEND_CORE_EXPORT Event { + public: + using ParameterValue = std::any; + using EventIdentifier = std::string; + struct ParameterInitializer { + std::string key; + ParameterValue value; + }; + + Event(const std::string& event_dientifier, + std::initializer_list<ParameterInitializer> params_init_list = {}); + + ~Event(); + + std::optional<ParameterValue> operator[](const std::string& key) const; + + bool operator==(const Event& other) const; + + bool operator!=(const Event& other) const; + + bool operator<(const Event& other) const; + + bool operator<=(const Event& other) const; + + operator std::string() const; + + EventIdentifier GetIdentifier(); + + void AddParameter(const std::string& key, const ParameterValue& value); + + private: + class Impl; + std::unique_ptr<Impl> p_; +}; + +template <typename... Args> +Event MakeEvent(const std::string& eventIdentifier, Args&&... args) { + std::initializer_list<Event::ParameterInitializer> params = { + Event::ParameterInitializer{std::forward<Args>(args)}...}; + return Event(eventIdentifier, params); +} + +} // namespace GpgFrontend::Module + +#endif // GPGFRONTEND_EVENT_H
\ No newline at end of file diff --git a/src/core/module/GlobalModuleContext.cpp b/src/core/module/GlobalModuleContext.cpp new file mode 100644 index 00000000..df58c211 --- /dev/null +++ b/src/core/module/GlobalModuleContext.cpp @@ -0,0 +1,341 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "GlobalModuleContext.h" + +#include <boost/random/mersenne_twister.hpp> +#include <boost/random/uniform_int_distribution.hpp> +#include <memory> +#include <optional> +#include <string> +#include <unordered_map> +#include <unordered_set> + +#include "core/module/Event.h" +#include "core/module/Module.h" +#include "core/thread/Task.h" + +namespace GpgFrontend::Module { + +class GlobalModuleContext::Impl { + public: + Impl(TaskRunnerPtr task_runner) + : default_task_runner_(task_runner), + random_gen_( + (boost::posix_time::microsec_clock::universal_time() - + boost::posix_time::ptime(boost::gregorian::date(1970, 1, 1))) + .total_milliseconds()) { + // Initialize acquired channels with default values. + acquired_channel_.insert(GPGFRONTEND_DEFAULT_CHANNEL); + acquired_channel_.insert(GPGFRONTEND_NON_ASCII_CHANNEL); + } + + int GetChannel(ModulePtr module) { + // Search for the module in the register table. + auto module_info_opt = + search_module_register_table(module->GetModuleIdentifier()); + if (!module_info_opt.has_value()) { + SPDLOG_ERROR( + "cannot find module id {} at register table, fallbacking to " + "default " + "channel", + module->GetModuleIdentifier()); + return GetDefaultChannel(module); + } + + auto module_info = module_info_opt.value(); + return module_info->channel; + } + + int GetDefaultChannel(ModulePtr) { return GPGFRONTEND_DEFAULT_CHANNEL; } + + std::optional<TaskRunnerPtr> GetTaskRunner(ModulePtr module) { + auto opt = search_module_register_table(module->GetModuleIdentifier()); + if (!opt.has_value()) { + return std::nullopt; + } + return opt.value()->task_runner; + } + + std::optional<TaskRunnerPtr> GetTaskRunner(ModuleIdentifier module_id) { + // Search for the module in the register table. + auto module_info_opt = search_module_register_table(module_id); + if (!module_info_opt.has_value()) { + SPDLOG_ERROR("cannot find module id {} at register table", module_id); + return std::nullopt; + } + return module_info_opt.value()->task_runner; + } + + std::optional<TaskRunnerPtr> GetGlobalTaskRunner() { + return default_task_runner_; + } + + bool RegisterModule(ModulePtr module) { + SPDLOG_DEBUG("attempting to register module: {}", + module->GetModuleIdentifier()); + // Check if the module is null or already registered. + if (module == nullptr || + module_register_table_.find(module->GetModuleIdentifier()) != + module_register_table_.end()) { + SPDLOG_ERROR("module is null or have already registered this module"); + return false; + } + + if (!module->Register()) { + SPDLOG_ERROR("register module {} failed", module->GetModuleIdentifier()); + return false; + } + + ModuleRegisterInfo register_info; + register_info.module = module; + register_info.channel = acquire_new_unique_channel(); + register_info.task_runner = std::make_shared<Thread::TaskRunner>(); + + // Register the module with its identifier. + module_register_table_[module->GetModuleIdentifier()] = + std::make_shared<ModuleRegisterInfo>(std::move(register_info)); + + SPDLOG_DEBUG("successfully registered module: {}", + module->GetModuleIdentifier()); + return true; + } + + bool ActiveModule(ModuleIdentifier module_id) { + SPDLOG_DEBUG("attempting to activate module: {}", module_id); + + // Search for the module in the register table. + auto module_info_opt = search_module_register_table(module_id); + if (!module_info_opt.has_value()) { + SPDLOG_ERROR("cannot find module id {} at register table", module_id); + return false; + } + + auto module_info = module_info_opt.value(); + // Activate the module if it is not already active. + if (module_info->activate && module_info->module->Active()) { + module_info->activate = true; + } + + SPDLOG_DEBUG("module activation status: {}", module_info->activate); + return module_info->activate; + } + + bool ListenEvent(ModuleIdentifier module_id, EventIdentifier event) { + SPDLOG_DEBUG("module: {} is attempting to listen to event {}", module_id, + event); + // Check if the event exists, if not, create it. + auto it = module_events_table_.find(event); + if (it == module_events_table_.end()) { + module_events_table_[event] = std::unordered_set<ModuleIdentifier>(); + it = module_events_table_.find(event); + SPDLOG_INFO("new event {} of module system created", event); + } + + auto& listeners_set = it->second; + // Add the listener (module) to the event. + auto listener_it = + std::find(listeners_set.begin(), listeners_set.end(), module_id); + if (listener_it == listeners_set.end()) { + listeners_set.insert(module_id); + } + return true; + } + + bool DeactivateModule(ModuleIdentifier module_id) { + // Search for the module in the register table. + auto module_info_opt = search_module_register_table(module_id); + if (!module_info_opt.has_value()) { + SPDLOG_ERROR("cannot find module id {} at register table", module_id); + return false; + } + + auto module_info = module_info_opt.value(); + // Activate the module if it is not already deactive. + if (!module_info->activate && module_info->module->Deactive()) { + module_info->activate = false; + } + + return !module_info->activate; + } + + bool TriggerEvent(EventRefrernce event) { + SPDLOG_DEBUG("attempting to trigger event: {}", event->GetIdentifier()); + + // Find the set of listeners associated with the given event in the table + auto it = module_events_table_.find(event->GetIdentifier()); + if (it == module_events_table_.end()) { + // Log a warning if the event is not registered and nobody is listening + SPDLOG_WARN( + "event {} is not listening by anyone and not registered as well", + event->GetIdentifier()); + return false; + } + + // Retrieve the set of listeners for this event + auto& listeners_set = it->second; + + // Check if the set of listeners is empty + if (listeners_set.empty()) { + // Log a warning if nobody is listening to this event + SPDLOG_WARN("event {} is not listening by anyone", + event->GetIdentifier()); + return false; + } + + // Log the number of listeners for this event + SPDLOG_DEBUG("event {}'s current listeners size: {}", + event->GetIdentifier(), listeners_set.size()); + + // Iterate through each listener and execute the corresponding module + for (auto& listener_module_id : listeners_set) { + // Search for the module's information in the registration table + auto module_info_opt = search_module_register_table(listener_module_id); + + // Log an error if the module is not found in the registration table + if (!module_info_opt.has_value()) { + SPDLOG_ERROR("cannot find module id {} at register table", + listener_module_id); + } + + // Retrieve the module's information + auto module_info = module_info_opt.value(); + + // Check if the module is activated + if (!module_info->activate) continue; + + // Execute the module and check if it fails + if (module_info->module->Exec(event)) { + // Log an error if the module execution fails + SPDLOG_ERROR("module {} executed failed", listener_module_id); + } + } + + // Return true to indicate successful execution of all modules + return true; + } + + private: + struct ModuleRegisterInfo { + int channel; + TaskRunnerPtr task_runner; + ModulePtr module; + bool activate; + }; + + using ModuleRegisterInfoPtr = std::shared_ptr<ModuleRegisterInfo>; + + std::unordered_map<ModuleIdentifier, ModuleRegisterInfoPtr> + module_register_table_; + std::map<EventIdentifier, std::unordered_set<ModuleIdentifier>> + module_events_table_; + + std::set<int> acquired_channel_; + boost::random::mt19937 random_gen_; + TaskRunnerPtr default_task_runner_; + + int acquire_new_unique_channel() { + boost::random::uniform_int_distribution<> dist(1, 65535); + + int random_channel = dist(random_gen_); + // Ensure the acquired channel is unique. + while (acquired_channel_.find(random_channel) != acquired_channel_.end()) { + random_channel = dist(random_gen_); + } + + // Add the acquired channel to the set. + acquired_channel_.insert(random_channel); + return random_channel; + } + + // Function to search for a module in the register table. + std::optional<ModuleRegisterInfoPtr> search_module_register_table( + ModuleIdentifier identifier) { + auto it = module_register_table_.find(identifier); + if (it == module_register_table_.end()) { + return std::nullopt; + } + return it->second; + } + + std::list<ModuleIdentifier>& search_module_events_table(ModuleIdentifier); +}; + +// Constructor for GlobalModuleContext, takes a TaskRunnerPtr as an argument. +GlobalModuleContext::GlobalModuleContext(TaskRunnerPtr task_runner) + : p_(std::make_unique<Impl>(task_runner)) {} + +GlobalModuleContext::~GlobalModuleContext() = default; + +// Function to get the task runner associated with a module. +std::optional<TaskRunnerPtr> GlobalModuleContext::GetTaskRunner( + ModulePtr module) { + return p_->GetTaskRunner(module); +} + +// Function to get the task runner associated with a module. +std::optional<TaskRunnerPtr> GlobalModuleContext::GetTaskRunner( + ModuleIdentifier module_id) { + return p_->GetTaskRunner(module_id); +} + +// Function to get the global task runner. +std::optional<TaskRunnerPtr> GlobalModuleContext::GetGlobalTaskRunner() { + return p_->GetGlobalTaskRunner(); +} + +bool GlobalModuleContext::RegisterModule(ModulePtr module) { + return p_->RegisterModule(module); +} + +bool GlobalModuleContext::ActiveModule(ModuleIdentifier module_id) { + return p_->ActiveModule(module_id); +} + +bool GlobalModuleContext::ListenEvent(ModuleIdentifier module_id, + EventIdentifier event) { + return p_->ListenEvent(module_id, event); +} + +bool GlobalModuleContext::DeactivateModule(ModuleIdentifier module_id) { + return p_->DeactivateModule(module_id); +} + +bool GlobalModuleContext::TriggerEvent(EventRefrernce event) { + return p_->TriggerEvent(event); +} + +int GlobalModuleContext::GetChannel(ModulePtr module) { + return p_->GetChannel(module); +} + +int GlobalModuleContext::GetDefaultChannel(ModulePtr _) { + return p_->GetDefaultChannel(_); +} + +} // namespace GpgFrontend::Module diff --git a/src/core/module/GlobalModuleContext.h b/src/core/module/GlobalModuleContext.h new file mode 100644 index 00000000..e4dcac2f --- /dev/null +++ b/src/core/module/GlobalModuleContext.h @@ -0,0 +1,83 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef GPGFRONTEND_GLOBALMODULECONTEXT_H +#define GPGFRONTEND_GLOBALMODULECONTEXT_H + +#include "core/GpgFrontendCore.h" +#include "core/module/Event.h" +#include "core/thread/TaskRunner.h" + +namespace GpgFrontend::Module { + +class GlobalModuleContext; + +class Module; +class ModuleManager; +using ModuleIdentifier = std::string; +using ModulePtr = std::shared_ptr<Module>; + +using GlobalModuleContextPtr = std::shared_ptr<GlobalModuleContext>; + +using TaskRunnerPtr = std::shared_ptr<Thread::TaskRunner>; + +class GPGFRONTEND_CORE_EXPORT GlobalModuleContext : public QObject { + Q_OBJECT + public: + GlobalModuleContext(TaskRunnerPtr); + + ~GlobalModuleContext(); + + int GetChannel(ModulePtr); + + int GetDefaultChannel(ModulePtr); + + std::optional<TaskRunnerPtr> GetTaskRunner(ModulePtr); + + std::optional<TaskRunnerPtr> GetTaskRunner(ModuleIdentifier); + + std::optional<TaskRunnerPtr> GetGlobalTaskRunner(); + + bool RegisterModule(ModulePtr); + + bool ActiveModule(ModuleIdentifier); + + bool DeactivateModule(ModuleIdentifier); + + bool ListenEvent(ModuleIdentifier, EventIdentifier); + + bool TriggerEvent(EventRefrernce); + + private: + class Impl; + std::unique_ptr<Impl> p_; +}; + +} // namespace GpgFrontend::Module + +#endif // GPGFRONTEND_GLOBALMODULECONTEXT_H
\ No newline at end of file diff --git a/src/core/module/GpgFrontendModuleSystem.h b/src/core/module/GpgFrontendModuleSystem.h new file mode 100644 index 00000000..903aec69 --- /dev/null +++ b/src/core/module/GpgFrontendModuleSystem.h @@ -0,0 +1,34 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#pragma once + +#include <core/GpgFrontendCore.h> +#include <core/module/Event.h> +#include <core/module/Module.h> +#include <core/module/ModuleManager.h>
\ No newline at end of file diff --git a/src/core/module/Module.cpp b/src/core/module/Module.cpp new file mode 100644 index 00000000..d84b74af --- /dev/null +++ b/src/core/module/Module.cpp @@ -0,0 +1,107 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "Module.h" + +#include <memory> + +#include "core/module/GlobalModuleContext.h" + +namespace GpgFrontend::Module { + +class Module::Impl { + public: + friend class GlobalModuleContext; + + Impl(ModuleIdentifier id, ModuleVersion version, ModuleMetaData meta_data) + : identifier_((boost::format("__module_%1%") % id).str()), + version_(version), + meta_data_(meta_data) {} + + int GetChannel() { + return get_global_module_context()->GetChannel(self_shared_ptr_); + } + + int GetDefaultChannel() { + return get_global_module_context()->GetDefaultChannel(self_shared_ptr_); + } + + std::optional<TaskRunnerPtr> GetTaskRunner() { + return get_global_module_context()->GetTaskRunner(self_shared_ptr_); + } + + bool ListenEvent(EventIdentifier event) { + return get_global_module_context()->ListenEvent(gpc_get_identifier(), + event); + } + + ModuleIdentifier GetModuleIdentifier() const { return identifier_; } + + void SetGPC(GlobalModuleContextPtr gpc) { gpc_ = gpc; } + + private: + GlobalModuleContextPtr gpc_; + const std::shared_ptr<Module> self_shared_ptr_; + const ModuleIdentifier identifier_; + const ModuleVersion version_; + const ModuleMetaData meta_data_; + + ModuleIdentifier gpc_get_identifier() { return identifier_; } + + const GlobalModuleContextPtr get_global_module_context() { + if (gpc_ == nullptr) { + throw std::runtime_error("module is not registered by module manager"); + } + return gpc_; + } +}; + +Module::Module(ModuleIdentifier id, ModuleVersion version, + ModuleMetaData meta_data) + : p_(std::make_unique<Impl>(id, version, meta_data)) {} + +Module::~Module() = default; + +int Module::getChannel() { return p_->GetChannel(); } + +int Module::getDefaultChannel() { return p_->GetDefaultChannel(); } + +TaskRunnerPtr Module::getTaskRunner() { + return p_->GetTaskRunner().value_or(nullptr); +} + +bool Module::listenEvent(EventIdentifier event) { + return p_->ListenEvent(event); +} + +ModuleIdentifier Module::GetModuleIdentifier() const { + return p_->GetModuleIdentifier(); +} + +void Module::SetGPC(GlobalModuleContextPtr gpc) { p_->SetGPC(gpc); } +} // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/Module.h b/src/core/module/Module.h new file mode 100644 index 00000000..bb7678ae --- /dev/null +++ b/src/core/module/Module.h @@ -0,0 +1,87 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef GPGFRONTEND_MODULE_H +#define GPGFRONTEND_MODULE_H + +#include <memory> + +#include "core/module/Event.h" +#include "core/thread/Task.h" +#include "core/thread/TaskRunner.h" + +namespace GpgFrontend::Module { + +class Module; +class GlobalModuleContext; +class ModuleManager; + +using ModuleIdentifier = std::string; +using ModuleVersion = std::string; +using ModuleMetaData = std::map<std::string, std::string>; +using ModulePtr = std::shared_ptr<Module>; +using GlobalModuleContextPtr = std::shared_ptr<GlobalModuleContext>; + +using TaskRunnerPtr = std::shared_ptr<Thread::TaskRunner>; + +class GPGFRONTEND_CORE_EXPORT Module : public QObject { + Q_OBJECT + public: + Module(ModuleIdentifier, ModuleVersion, ModuleMetaData); + + ~Module(); + + virtual bool Register() = 0; + + virtual bool Active() = 0; + + virtual int Exec(EventRefrernce) = 0; + + virtual bool Deactive() = 0; + + ModuleIdentifier GetModuleIdentifier() const; + + void SetGPC(GlobalModuleContextPtr); + + protected: + int getChannel(); + + int getDefaultChannel(); + + TaskRunnerPtr getTaskRunner(); + + bool listenEvent(EventIdentifier); + + private: + class Impl; + std::unique_ptr<Impl> p_; +}; + +} // namespace GpgFrontend::Module + +#endif // GPGFRONTEND_MODULE_H
\ No newline at end of file diff --git a/src/core/module/ModuleManager.cpp b/src/core/module/ModuleManager.cpp new file mode 100644 index 00000000..dc31072b --- /dev/null +++ b/src/core/module/ModuleManager.cpp @@ -0,0 +1,111 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#include "ModuleManager.h" + +#include "core/module/GlobalModuleContext.h" +#include "core/module/Module.h" +#include "core/thread/TaskRunner.h" + +namespace GpgFrontend::Module { + +ModuleMangerPtr ModuleManager::g_ = nullptr; + +class ModuleManager::Impl { + public: + Impl() + : task_runner_(std::make_shared<Thread::TaskRunner>()), + gpc_(std::make_shared<GlobalModuleContext>(task_runner_)) { + task_runner_->start(); + } + + void RegisterModule(ModulePtr module) { + task_runner_->PostTask(new Thread::Task( + std::move([=](GpgFrontend::Thread::DataObjectPtr) -> int { + module->SetGPC(gpc_); + gpc_->RegisterModule(module); + return 0; + }), + __func__, nullptr, true)); + } + + void TriggerEvent(EventRefrernce event) { + task_runner_->PostTask(new Thread::Task( + std::move([=](GpgFrontend::Thread::DataObjectPtr) -> int { + gpc_->TriggerEvent(event); + return 0; + }), + __func__, nullptr, true)); + } + + void ActiveModule(ModuleIdentifier identifier) { + task_runner_->PostTask(new Thread::Task( + std::move([=](GpgFrontend::Thread::DataObjectPtr) -> int { + gpc_->ActiveModule(identifier); + return 0; + }), + __func__, nullptr, true)); + } + + std::optional<TaskRunnerPtr> GetTaskRunner(ModuleIdentifier module_id) { + return gpc_->GetTaskRunner(module_id); + } + + private: + static ModuleMangerPtr global_module_manager_; + TaskRunnerPtr task_runner_; + GlobalModuleContextPtr gpc_; +}; + +ModuleManager::ModuleManager() : p_(std::make_unique<Impl>()) {} + +ModuleManager::~ModuleManager() = default; + +ModuleMangerPtr ModuleManager::GetInstance() { + if (g_ == nullptr) g_ = std::shared_ptr<ModuleManager>(new ModuleManager()); + return g_; +} + +void ModuleManager::RegisterModule(ModulePtr module) { + return p_->RegisterModule(module); +} + +void ModuleManager::TriggerEvent(EventRefrernce event) { + return p_->TriggerEvent(event); +} + +void ModuleManager::ActiveModule(ModuleIdentifier identifier) { + return p_->ActiveModule(identifier); +} + +std::optional<TaskRunnerPtr> ModuleManager::GetTaskRunner( + ModuleIdentifier module_id) { + return p_->GetTaskRunner(module_id); +} + +} // namespace GpgFrontend::Module
\ No newline at end of file diff --git a/src/core/module/ModuleManager.h b/src/core/module/ModuleManager.h new file mode 100644 index 00000000..bb201ebe --- /dev/null +++ b/src/core/module/ModuleManager.h @@ -0,0 +1,104 @@ +/** + * Copyright (C) 2021 Saturneric <[email protected]> + * + * This file is part of GpgFrontend. + * + * GpgFrontend is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * GpgFrontend is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with GpgFrontend. If not, see <https://www.gnu.org/licenses/>. + * + * The initial version of the source code is inherited from + * the gpg4usb project, which is under GPL-3.0-or-later. + * + * All the source code of GpgFrontend was modified and released by + * Saturneric <[email protected]> starting on May 12, 2021. + * + * SPDX-License-Identifier: GPL-3.0-or-later + * + */ + +#ifndef GPGFRONTEND_MODULEMANAGER_H +#define GPGFRONTEND_MODULEMANAGER_H + +#include <memory> +#include <string> + +#include "core/GpgFrontendCore.h" +#include "core/thread/Task.h" + +namespace GpgFrontend::Thread { +class TaskRunner; +} + +namespace GpgFrontend::Module { + +using TaskRunnerPtr = std::shared_ptr<Thread::TaskRunner>; + +class Event; +class Module; +class GlobalModuleContext; +class ModuleManager; + +using EventRefrernce = std::shared_ptr<Event>; +using ModuleIdentifier = std::string; +using ModulePtr = std::shared_ptr<Module>; +using ModuleMangerPtr = std::shared_ptr<ModuleManager>; +using GlobalModuleContextPtr = std::shared_ptr<GlobalModuleContext>; + +class GPGFRONTEND_CORE_EXPORT ModuleManager : public QObject { + Q_OBJECT + public: + ~ModuleManager(); + + static ModuleMangerPtr GetInstance(); + + void RegisterModule(ModulePtr); + + void TriggerEvent(EventRefrernce); + + void ActiveModule(ModuleIdentifier); + + void DeactiveModule(ModuleIdentifier); + + std::optional<TaskRunnerPtr> GetTaskRunner(ModuleIdentifier); + + private: + class Impl; + std::unique_ptr<Impl> p_; + static ModuleMangerPtr g_; + + ModuleManager(); +}; + +template <typename T, typename... Args> +void RegisterModule(Args&&... args) { + ModuleManager::GetInstance()->RegisterModule( + std::make_shared<T>(std::forward<Args>(args)...)); +} + +template <typename T, typename... Args> +void RegisterAndActivateModule(Args&&... args) { + auto manager = ModuleManager::GetInstance(); + auto module = std::make_shared<T>(std::forward<Args>(args)...); + manager->RegisterModule(module); + manager->ActiveModule(module->GetModuleIdentifier()); +} + +template <typename... Args> +void TriggerEvent(const std::string& eventIdentifier, Args&&... args) { + ModuleManager::GetInstance()->TriggerEvent(std::make_shared<Event>( + std::move(MakeEvent(eventIdentifier, std::forward<Args>(args)...)))); +} + +} // namespace GpgFrontend::Module + +#endif // GPGFRONTEND_MODULEMANAGER_H
\ No newline at end of file |