File indexing completed on 2024-04-28 16:51:33
0001 /* 0002 SPDX-FileCopyrightText: 2019 Kai Uwe Broulik <kde@privat.broulik.de> 0003 0004 SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "pluginmanager.h" 0008 0009 #include <QJsonObject> 0010 0011 #include "abstractbrowserplugin.h" 0012 #include "connection.h" 0013 0014 PluginManager::PluginManager() 0015 : QObject(nullptr) 0016 { 0017 connect(Connection::self(), &Connection::dataReceived, this, &PluginManager::onDataReceived); 0018 } 0019 0020 PluginManager::~PluginManager() = default; 0021 0022 PluginManager &PluginManager::self() 0023 { 0024 static PluginManager s_self; 0025 return s_self; 0026 } 0027 0028 AbstractBrowserPlugin *PluginManager::pluginForSubsystem(const QString &subsystem) const 0029 { 0030 return m_plugins.value(subsystem); 0031 } 0032 0033 void PluginManager::addPlugin(AbstractBrowserPlugin *plugin) 0034 { 0035 m_plugins.insert(plugin->m_subsystem, plugin); 0036 } 0037 0038 bool PluginManager::loadPlugin(AbstractBrowserPlugin *plugin) 0039 { 0040 return setPluginLoaded(plugin, true); 0041 } 0042 0043 bool PluginManager::unloadPlugin(AbstractBrowserPlugin *plugin) 0044 { 0045 return setPluginLoaded(plugin, false); 0046 } 0047 0048 bool PluginManager::setPluginLoaded(AbstractBrowserPlugin *plugin, bool loaded) 0049 { 0050 if (!plugin) { 0051 return false; 0052 } 0053 0054 if (plugin->isLoaded() == loaded) { 0055 return true; 0056 } 0057 0058 bool ok = false; 0059 if (loaded && !plugin->isLoaded()) { 0060 ok = plugin->onLoad(); 0061 } else if (!loaded && plugin->isLoaded()) { 0062 ok = plugin->onUnload(); 0063 } 0064 0065 if (!ok) { 0066 qDebug() << "plugin" << plugin->subsystem() << "refused to" << (loaded ? "load" : "unload"); 0067 return false; 0068 } 0069 0070 plugin->setLoaded(loaded); 0071 0072 if (loaded) { 0073 Q_EMIT pluginLoaded(plugin); 0074 } else { 0075 Q_EMIT pluginUnloaded(plugin); 0076 } 0077 0078 return true; 0079 } 0080 0081 void PluginManager::settingsChanged(AbstractBrowserPlugin *plugin, const QJsonObject &settings) 0082 { 0083 plugin->onSettingsChanged(settings); 0084 } 0085 0086 QStringList PluginManager::knownPluginSubsystems() const 0087 { 0088 return m_plugins.keys(); 0089 } 0090 0091 QStringList PluginManager::loadedPluginSubsystems() const 0092 { 0093 QStringList plugins; 0094 for (auto it = m_plugins.constBegin(), end = m_plugins.constEnd(); it != end; ++it) { 0095 if (it.value()->isLoaded()) { 0096 plugins << it.key(); 0097 } 0098 } 0099 return plugins; 0100 } 0101 0102 void PluginManager::onDataReceived(const QJsonObject &json) 0103 { 0104 const QString subsystem = json.value(QStringLiteral("subsystem")).toString(); 0105 0106 AbstractBrowserPlugin *plugin = m_plugins.value(subsystem); 0107 if (!plugin) { 0108 return; 0109 } 0110 0111 if (!plugin->isLoaded()) { 0112 return; 0113 } 0114 0115 const QString event = json.value(QStringLiteral("event")).toString(); 0116 if (event.isEmpty()) { 0117 return; 0118 } 0119 0120 const QJsonValue requestSerialVariant = json.value(QStringLiteral("serial")); 0121 if (!requestSerialVariant.isUndefined()) { 0122 const int requestSerial = requestSerialVariant.toInt(); 0123 0124 const auto reply = plugin->handleData(requestSerial, event, json); 0125 if (!reply.isEmpty()) { 0126 plugin->sendReply(requestSerial, reply); 0127 } 0128 } else { 0129 // design question, should we have a JSON of subsystem, event, payload, or have all data at the root level? 0130 plugin->handleData(event, json); 0131 } 0132 }