aboutsummaryrefslogtreecommitdiffstats
path: root/src/core/module
diff options
context:
space:
mode:
authorsaturneric <[email protected]>2023-10-17 15:45:10 +0000
committersaturneric <[email protected]>2023-10-17 15:45:10 +0000
commit459cd3d0e512a1166b3a09233c22b7357b514760 (patch)
tree9ab0484a6d17ca7971f54f46a9d74b1c971f8b28 /src/core/module
parentfix: slove compile issues (diff)
downloadGpgFrontend-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.cpp108
-rw-r--r--src/core/module/Event.h88
-rw-r--r--src/core/module/GlobalModuleContext.cpp341
-rw-r--r--src/core/module/GlobalModuleContext.h83
-rw-r--r--src/core/module/GpgFrontendModuleSystem.h34
-rw-r--r--src/core/module/Module.cpp107
-rw-r--r--src/core/module/Module.h87
-rw-r--r--src/core/module/ModuleManager.cpp111
-rw-r--r--src/core/module/ModuleManager.h104
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