LCOV - code coverage report
Current view: top level - src/plugin - jamipluginmanager.cpp (source / functions) Coverage Total Hit
Test: jami-coverage-filtered.info Lines: 10.9 % 303 33
Test Date: 2026-06-13 09:18:46 Functions: 13.0 % 54 7

            Line data    Source code
       1              : /*
       2              :  *  Copyright (C) 2004-2026 Savoir-faire Linux Inc.
       3              :  *
       4              :  *  This program is free software: you can redistribute it and/or modify
       5              :  *  it under the terms of the GNU General Public License as published by
       6              :  *  the Free Software Foundation, either version 3 of the License, or
       7              :  *  (at your option) any later version.
       8              :  *
       9              :  *  This program is distributed in the hope that it will be useful,
      10              :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
      12              :  *  GNU General Public License for more details.
      13              :  *
      14              :  *  You should have received a copy of the GNU General Public License
      15              :  *  along with this program. If not, see <https://www.gnu.org/licenses/>.
      16              :  */
      17              : 
      18              : #include "jamipluginmanager.h"
      19              : #include "pluginsutils.h"
      20              : #include "fileutils.h"
      21              : #include "archiver.h"
      22              : #include "logger.h"
      23              : #include "manager.h"
      24              : #include "jami/plugin_manager_interface.h"
      25              : // NOLINTNEXTLINE
      26              : #include "store_ca_crt.cpp"
      27              : 
      28              : #include <fstream>
      29              : #include <msgpack.hpp>
      30              : 
      31              : #define FAILURE                         -1
      32              : #define SUCCESS                         0
      33              : #define PLUGIN_ALREADY_INSTALLED        100 /* Plugin already installed with the same version */
      34              : #define PLUGIN_OLD_VERSION              200 /* Plugin already installed with a newer version */
      35              : #define SIGNATURE_VERIFICATION_FAILED   300
      36              : #define CERTIFICATE_VERIFICATION_FAILED 400
      37              : #define INVALID_PLUGIN                  500
      38              : 
      39              : #ifdef WIN32
      40              : #define LIB_TYPE   ".dll"
      41              : #define LIB_PREFIX ""
      42              : #else
      43              : #ifdef __APPLE__
      44              : #define LIB_TYPE   ".dylib"
      45              : #define LIB_PREFIX "lib"
      46              : #else
      47              : #define LIB_TYPE   ".so"
      48              : #define LIB_PREFIX "lib"
      49              : #endif
      50              : #endif
      51              : 
      52              : namespace jami {
      53              : 
      54           32 : JamiPluginManager::JamiPluginManager()
      55           32 :     : callsm_ {pm_}
      56           32 :     , chatsm_ {pm_}
      57           32 :     , webviewsm_ {pm_}
      58           64 :     , preferencesm_ {pm_}
      59              : {
      60           32 :     registerServices();
      61           32 : }
      62              : 
      63              : std::string
      64            0 : JamiPluginManager::getPluginAuthor(const std::string& rootPath, const std::string& pluginId)
      65              : {
      66            0 :     auto cert = PluginUtils::readPluginCertificate(rootPath, pluginId);
      67            0 :     if (!cert) {
      68            0 :         JAMI_ERROR("Unable to read plugin certificate");
      69            0 :         return {};
      70              :     }
      71            0 :     return cert->getIssuerName();
      72            0 : }
      73              : 
      74              : std::map<std::string, std::string>
      75            8 : JamiPluginManager::getPluginDetails(const std::string& rootPath, bool reset)
      76              : {
      77            8 :     auto detailsIt = pluginDetailsMap_.find(rootPath);
      78            8 :     if (detailsIt != pluginDetailsMap_.end()) {
      79            0 :         if (!reset)
      80            0 :             return detailsIt->second;
      81            0 :         pluginDetailsMap_.erase(detailsIt);
      82              :     }
      83              : 
      84           16 :     std::map<std::string, std::string> details = PluginUtils::parseManifestFile(PluginUtils::manifestPath(rootPath),
      85            8 :                                                                                 rootPath);
      86            8 :     if (!details.empty()) {
      87            0 :         auto itIcon = details.find("iconPath");
      88            0 :         itIcon->second.insert(0, rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH);
      89              : 
      90            0 :         auto itImage = details.find("backgroundPath");
      91            0 :         itImage->second.insert(0, rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH);
      92              : 
      93            0 :         details["soPath"] = rootPath + DIR_SEPARATOR_CH + LIB_PREFIX + details["id"] + LIB_TYPE;
      94            0 :         details["author"] = getPluginAuthor(rootPath, details["id"]);
      95            0 :         detailsIt = pluginDetailsMap_.emplace(rootPath, std::move(details)).first;
      96            0 :         return detailsIt->second;
      97              :     }
      98            8 :     return {};
      99            8 : }
     100              : 
     101              : std::vector<std::string>
     102            0 : JamiPluginManager::getInstalledPlugins()
     103              : {
     104              :     // Gets all plugins in standard path
     105            0 :     auto pluginsPath = fileutils::get_data_dir() / "plugins";
     106            0 :     std::vector<std::string> pluginsPaths;
     107            0 :     std::error_code ec;
     108            0 :     for (const auto& entry : std::filesystem::directory_iterator(pluginsPath, ec)) {
     109            0 :         const auto& p = entry.path();
     110            0 :         if (PluginUtils::checkPluginValidity(p))
     111            0 :             pluginsPaths.emplace_back(p.string());
     112            0 :     }
     113              : 
     114              :     // Gets plugins installed in non standard path
     115            0 :     std::vector<std::string> nonStandardInstalls = jami::Manager::instance().pluginPreferences.getInstalledPlugins();
     116            0 :     for (auto& path : nonStandardInstalls) {
     117            0 :         if (PluginUtils::checkPluginValidity(path))
     118            0 :             pluginsPaths.emplace_back(path);
     119              :     }
     120              : 
     121            0 :     return pluginsPaths;
     122            0 : }
     123              : 
     124              : bool
     125            0 : JamiPluginManager::checkPluginCertificatePublicKey(const std::string& oldJplPath, const std::string& newJplPath)
     126              : {
     127            0 :     std::map<std::string, std::string> oldDetails = PluginUtils::parseManifestFile(PluginUtils::manifestPath(oldJplPath),
     128            0 :                                                                                    oldJplPath);
     129            0 :     std::error_code ec;
     130            0 :     if (oldDetails.empty()
     131            0 :         || !std::filesystem::is_regular_file(oldJplPath + DIR_SEPARATOR_CH + oldDetails["id"] + ".crt", ec)
     132            0 :         || !std::filesystem::is_regular_file(newJplPath, ec))
     133            0 :         return false;
     134              :     try {
     135            0 :         auto oldCert = PluginUtils::readPluginCertificate(oldJplPath, oldDetails["id"]);
     136            0 :         auto newCert = PluginUtils::readPluginCertificateFromArchive(newJplPath);
     137            0 :         if (!oldCert || !newCert) {
     138            0 :             return false;
     139              :         }
     140            0 :         return oldCert->getPublicKey() == newCert->getPublicKey();
     141            0 :     } catch (const std::exception& e) {
     142            0 :         JAMI_ERROR("{}", e.what());
     143            0 :         return false;
     144            0 :     }
     145              :     return true;
     146            0 : }
     147              : 
     148              : bool
     149            0 : JamiPluginManager::checkPluginCertificateValidity(dht::crypto::Certificate* cert)
     150              : {
     151            0 :     if (!cert || !*cert)
     152            0 :         return false;
     153            0 :     trust_.add(crypto::Certificate(store_ca_crt, sizeof(store_ca_crt)));
     154            0 :     auto result = trust_.verify(*cert);
     155            0 :     if (!result) {
     156            0 :         JAMI_ERROR("Certificate verification failed: {}", result.toString());
     157              :     }
     158            0 :     return (bool) result;
     159              : }
     160              : 
     161              : std::map<std::string, std::string>
     162            0 : JamiPluginManager::getPlatformInfo()
     163              : {
     164            0 :     return PluginUtils::getPlatformInfo();
     165              : }
     166              : 
     167              : bool
     168            0 : JamiPluginManager::checkPluginSignatureFile(const std::string& jplPath)
     169              : {
     170              :     // check if the file exists
     171            0 :     std::error_code ec;
     172            0 :     if (!std::filesystem::is_regular_file(jplPath, ec)) {
     173            0 :         return false;
     174              :     }
     175              :     try {
     176            0 :         auto signatures = PluginUtils::readPluginSignatureFromArchive(jplPath);
     177            0 :         auto manifest = PluginUtils::readPluginManifestFromArchive(jplPath);
     178            0 :         const std::string& name = manifest["id"];
     179            0 :         auto filesPath = archiver::listFilesFromArchive(jplPath);
     180            0 :         for (const auto& file : filesPath) {
     181              :             // we skip the signatures and signatures.sig file
     182            0 :             if (file == "signatures" || file == "signatures.sig")
     183            0 :                 continue;
     184              :             // we also skip the plugin certificate
     185            0 :             if (file == name + ".crt")
     186            0 :                 continue;
     187              : 
     188            0 :             if (signatures.count(file) == 0) {
     189            0 :                 return false;
     190              :             }
     191              :         }
     192            0 :     } catch (const std::exception& e) {
     193            0 :         return false;
     194            0 :     }
     195            0 :     return true;
     196              : }
     197              : 
     198              : bool
     199            0 : JamiPluginManager::checkPluginSignatureValidity(const std::string& jplPath, dht::crypto::Certificate* cert)
     200              : {
     201            0 :     if (!std::filesystem::is_regular_file(jplPath))
     202            0 :         return false;
     203              :     try {
     204            0 :         const auto& pk = cert->getPublicKey();
     205            0 :         auto signaturesData = archiver::readFileFromArchive(jplPath, "signatures");
     206            0 :         auto signatureFile = PluginUtils::readSignatureFileFromArchive(jplPath);
     207            0 :         if (!pk.checkSignature(signaturesData, signatureFile))
     208            0 :             return false;
     209            0 :         auto signatures = PluginUtils::readPluginSignatureFromArchive(jplPath);
     210            0 :         for (const auto& signature : signatures) {
     211            0 :             auto file = archiver::readFileFromArchive(jplPath, signature.first);
     212            0 :             if (!pk.checkSignature(file, signature.second)) {
     213            0 :                 JAMI_ERROR("{} not correctly signed", signature.first);
     214            0 :                 return false;
     215              :             }
     216            0 :         }
     217            0 :     } catch (const std::exception& e) {
     218            0 :         return false;
     219            0 :     }
     220              : 
     221            0 :     return true;
     222              : }
     223              : 
     224              : bool
     225            0 : JamiPluginManager::checkPluginSignature(const std::string& jplPath, dht::crypto::Certificate* cert)
     226              : {
     227            0 :     if (!std::filesystem::is_regular_file(jplPath) || !cert || !*cert)
     228            0 :         return false;
     229              :     try {
     230            0 :         return checkPluginSignatureValidity(jplPath, cert) && checkPluginSignatureFile(jplPath);
     231            0 :     } catch (const std::exception& e) {
     232            0 :         return false;
     233            0 :     }
     234              : }
     235              : 
     236              : std::unique_ptr<dht::crypto::Certificate>
     237            0 : JamiPluginManager::checkPluginCertificate(const std::string& jplPath, bool force)
     238              : {
     239            0 :     if (!std::filesystem::is_regular_file(jplPath))
     240            0 :         return {};
     241              :     try {
     242            0 :         auto cert = PluginUtils::readPluginCertificateFromArchive(jplPath);
     243            0 :         if (checkPluginCertificateValidity(cert.get()) || force) {
     244            0 :             return cert;
     245              :         }
     246            0 :         return {};
     247            0 :     } catch (const std::exception& e) {
     248            0 :         return {};
     249            0 :     }
     250              : }
     251              : 
     252              : int
     253            0 : JamiPluginManager::installPlugin(const std::string& jplPath, bool force)
     254              : {
     255            0 :     int r {SUCCESS};
     256            0 :     std::error_code ec;
     257            0 :     if (std::filesystem::is_regular_file(jplPath, ec)) {
     258              :         try {
     259            0 :             auto manifestMap = PluginUtils::readPluginManifestFromArchive(jplPath);
     260            0 :             const std::string& name = manifestMap["id"];
     261            0 :             if (name.empty())
     262            0 :                 return INVALID_PLUGIN;
     263            0 :             auto cert = checkPluginCertificate(jplPath, force);
     264            0 :             if (!cert)
     265            0 :                 return CERTIFICATE_VERIFICATION_FAILED;
     266            0 :             if (!checkPluginSignature(jplPath, cert.get()))
     267            0 :                 return SIGNATURE_VERIFICATION_FAILED;
     268            0 :             const std::string& version = manifestMap["version"];
     269            0 :             auto destinationDir = (fileutils::get_data_dir() / "plugins" / name).string();
     270              :             // Find if there is an existing version of this plugin
     271            0 :             const auto alreadyInstalledManifestMap = PluginUtils::parseManifestFile(PluginUtils::manifestPath(
     272              :                                                                                         destinationDir),
     273            0 :                                                                                     destinationDir);
     274              : 
     275            0 :             if (!alreadyInstalledManifestMap.empty()) {
     276            0 :                 if (force) {
     277            0 :                     r = uninstallPlugin(destinationDir);
     278            0 :                     if (r == SUCCESS) {
     279            0 :                         archiver::uncompressArchive(jplPath, destinationDir, PluginUtils::uncompressJplFunction);
     280              :                     }
     281              :                 } else {
     282            0 :                     std::string installedVersion = alreadyInstalledManifestMap.at("version");
     283            0 :                     if (version > installedVersion) {
     284            0 :                         if (!checkPluginCertificatePublicKey(destinationDir, jplPath))
     285            0 :                             return CERTIFICATE_VERIFICATION_FAILED;
     286            0 :                         r = uninstallPlugin(destinationDir);
     287            0 :                         if (r == SUCCESS) {
     288            0 :                             archiver::uncompressArchive(jplPath, destinationDir, PluginUtils::uncompressJplFunction);
     289              :                         }
     290            0 :                     } else if (version == installedVersion) {
     291            0 :                         r = PLUGIN_ALREADY_INSTALLED;
     292              :                     } else {
     293            0 :                         r = PLUGIN_OLD_VERSION;
     294              :                     }
     295            0 :                 }
     296              :             } else {
     297            0 :                 archiver::uncompressArchive(jplPath, destinationDir, PluginUtils::uncompressJplFunction);
     298              :             }
     299            0 :             if (!libjami::getPluginsEnabled()) {
     300            0 :                 libjami::setPluginsEnabled(true);
     301            0 :                 Manager::instance().saveConfig();
     302            0 :                 loadPlugins();
     303            0 :                 return r;
     304              :             }
     305            0 :             libjami::loadPlugin(destinationDir);
     306            0 :         } catch (const std::exception& e) {
     307            0 :             JAMI_ERROR("{}", e.what());
     308            0 :         }
     309              :     }
     310            0 :     return r;
     311              : }
     312              : 
     313              : int
     314            0 : JamiPluginManager::uninstallPlugin(const std::string& rootPath)
     315              : {
     316            0 :     std::error_code ec;
     317            0 :     if (PluginUtils::checkPluginValidity(rootPath)) {
     318            0 :         auto detailsIt = pluginDetailsMap_.find(rootPath);
     319            0 :         if (detailsIt != pluginDetailsMap_.end()) {
     320            0 :             bool loaded = pm_.checkLoadedPlugin(rootPath);
     321            0 :             if (loaded) {
     322            0 :                 JAMI_LOG("PLUGIN: unloading before uninstall.");
     323            0 :                 bool status = libjami::unloadPlugin(rootPath);
     324            0 :                 if (!status) {
     325            0 :                     JAMI_LOG("PLUGIN: unable to unload, not performing uninstall.");
     326            0 :                     return FAILURE;
     327              :                 }
     328              :             }
     329            0 :             for (const auto& accId : jami::Manager::instance().getAccountList())
     330            0 :                 std::filesystem::remove_all(fileutils::get_data_dir() / accId / "plugins" / detailsIt->second.at("id"),
     331            0 :                                             ec);
     332            0 :             pluginDetailsMap_.erase(detailsIt);
     333              :         }
     334            0 :         return std::filesystem::remove_all(rootPath, ec) ? SUCCESS : FAILURE;
     335              :     } else {
     336            0 :         JAMI_LOG("PLUGIN: not installed.");
     337            0 :         return FAILURE;
     338              :     }
     339              : }
     340              : 
     341              : bool
     342            8 : JamiPluginManager::loadPlugin(const std::string& rootPath)
     343              : {
     344              : #ifdef ENABLE_PLUGIN
     345              :     try {
     346           32 :         bool status = pm_.load(getPluginDetails(rootPath).at("soPath"));
     347            0 :         JAMI_LOG("PLUGIN: load status - {}", status);
     348              : 
     349            0 :         return status;
     350              : 
     351            8 :     } catch (const std::exception& e) {
     352           32 :         JAMI_ERROR("{}", e.what());
     353            8 :         return false;
     354            8 :     }
     355              : #endif
     356              :     return false;
     357              : }
     358              : 
     359              : bool
     360            8 : JamiPluginManager::loadPlugins()
     361              : {
     362              : #ifdef ENABLE_PLUGIN
     363            8 :     bool status = true;
     364            8 :     auto loadedPlugins = jami::Manager::instance().pluginPreferences.getLoadedPlugins();
     365           16 :     for (const auto& pluginPath : loadedPlugins) {
     366            8 :         status &= loadPlugin(pluginPath);
     367              :     }
     368            8 :     return status;
     369              : #endif
     370              :     return false;
     371            8 : }
     372              : 
     373              : bool
     374            0 : JamiPluginManager::unloadPlugin(const std::string& rootPath)
     375              : {
     376              : #ifdef ENABLE_PLUGIN
     377              :     try {
     378            0 :         bool status = pm_.unload(getPluginDetails(rootPath).at("soPath"));
     379            0 :         JAMI_LOG("PLUGIN: unload status - {}", status);
     380              : 
     381            0 :         return status;
     382            0 :     } catch (const std::exception& e) {
     383            0 :         JAMI_ERROR("{}", e.what());
     384            0 :         return false;
     385            0 :     }
     386              : #endif
     387              :     return false;
     388              : }
     389              : 
     390              : std::vector<std::string>
     391            0 : JamiPluginManager::getLoadedPlugins() const
     392              : {
     393            0 :     std::vector<std::string> loadedSoPlugins = pm_.getLoadedPlugins();
     394            0 :     std::vector<std::string> loadedPlugins {};
     395            0 :     loadedPlugins.reserve(loadedSoPlugins.size());
     396            0 :     std::transform(loadedSoPlugins.begin(),
     397              :                    loadedSoPlugins.end(),
     398              :                    std::back_inserter(loadedPlugins),
     399            0 :                    [](const std::string& soPath) { return PluginUtils::getRootPathFromSoPath(soPath).string(); });
     400            0 :     return loadedPlugins;
     401            0 : }
     402              : 
     403              : std::vector<std::map<std::string, std::string>>
     404            0 : JamiPluginManager::getPluginPreferences(const std::string& rootPath, const std::string& accountId)
     405              : {
     406            0 :     return PluginPreferencesUtils::getPreferences(rootPath, accountId);
     407              : }
     408              : 
     409              : bool
     410            0 : JamiPluginManager::setPluginPreference(const std::filesystem::path& rootPath,
     411              :                                        const std::string& accountId,
     412              :                                        const std::string& key,
     413              :                                        const std::string& value)
     414              : {
     415            0 :     std::string acc = accountId;
     416              : 
     417              :     // If we try to change a preference value linked to an account
     418              :     // but that preference is global, we must ignore accountId and
     419              :     // change the preference for every account
     420            0 :     if (!accountId.empty()) {
     421              :         // Get global preferences
     422            0 :         auto preferences = PluginPreferencesUtils::getPreferences(rootPath, "");
     423              :         // Check if the preference we want to change is global
     424            0 :         auto it = std::find_if(preferences.cbegin(),
     425              :                                preferences.cend(),
     426            0 :                                [key](const std::map<std::string, std::string>& preference) {
     427            0 :                                    return preference.at("key") == key;
     428              :                                });
     429              :         // Ignore accountId if global preference
     430            0 :         if (it != preferences.cend())
     431            0 :             acc.clear();
     432            0 :     }
     433              : 
     434              :     std::map<std::string, std::string> pluginUserPreferencesMap
     435            0 :         = PluginPreferencesUtils::getUserPreferencesValuesMap(rootPath, acc);
     436              :     std::map<std::string, std::string> pluginPreferencesMap = PluginPreferencesUtils::getPreferencesValuesMap(rootPath,
     437            0 :                                                                                                               acc);
     438              : 
     439              :     // If any plugin handler is active we may have to reload it
     440            0 :     bool force {pm_.checkLoadedPlugin(rootPath.string())};
     441              : 
     442              :     // We check if the preference is modified without having to reload plugin
     443            0 :     force &= preferencesm_.setPreference(key, value, rootPath.string(), acc);
     444            0 :     force &= callsm_.setPreference(key, value, rootPath.string());
     445            0 :     force &= chatsm_.setPreference(key, value, rootPath.string());
     446              : 
     447            0 :     if (force)
     448            0 :         unloadPlugin(rootPath.string());
     449              : 
     450              :     // Save preferences.msgpack with modified preferences values
     451            0 :     auto find = pluginPreferencesMap.find(key);
     452            0 :     if (find != pluginPreferencesMap.end()) {
     453            0 :         pluginUserPreferencesMap[key] = value;
     454            0 :         auto preferencesValuesFilePath = PluginPreferencesUtils::valuesFilePath(rootPath, acc);
     455            0 :         std::lock_guard guard(dhtnet::fileutils::getFileLock(preferencesValuesFilePath));
     456            0 :         std::ofstream fs(preferencesValuesFilePath, std::ios::binary);
     457            0 :         if (!fs.good()) {
     458            0 :             if (force) {
     459            0 :                 loadPlugin(rootPath.string());
     460              :             }
     461            0 :             return false;
     462              :         }
     463              :         try {
     464            0 :             msgpack::pack(fs, pluginUserPreferencesMap);
     465            0 :         } catch (const std::exception& e) {
     466            0 :             JAMI_ERROR("{}", e.what());
     467            0 :             if (force) {
     468            0 :                 loadPlugin(rootPath.string());
     469              :             }
     470            0 :             return false;
     471            0 :         }
     472            0 :     }
     473            0 :     if (force) {
     474            0 :         loadPlugin(rootPath.string());
     475              :     }
     476            0 :     return true;
     477            0 : }
     478              : 
     479              : std::map<std::string, std::string>
     480            0 : JamiPluginManager::getPluginPreferencesValuesMap(const std::string& rootPath, const std::string& accountId)
     481              : {
     482            0 :     return PluginPreferencesUtils::getPreferencesValuesMap(rootPath, accountId);
     483              : }
     484              : 
     485              : bool
     486            0 : JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath, const std::string& accountId)
     487              : {
     488            0 :     bool acc {accountId.empty()};
     489            0 :     bool loaded {pm_.checkLoadedPlugin(rootPath)};
     490            0 :     if (loaded && acc)
     491            0 :         unloadPlugin(rootPath);
     492            0 :     auto status = PluginPreferencesUtils::resetPreferencesValuesMap(rootPath, accountId);
     493            0 :     preferencesm_.resetPreferences(rootPath, accountId);
     494            0 :     if (loaded && acc) {
     495            0 :         loadPlugin(rootPath);
     496              :     }
     497            0 :     return status;
     498              : }
     499              : 
     500              : void
     501           32 : JamiPluginManager::registerServices()
     502              : {
     503              :     // Register getPluginPreferences so that plugin's can receive it's preferences
     504           96 :     pm_.registerService("getPluginPreferences", [](const DLPlugin* plugin, void* data) {
     505            0 :         auto* ppp = static_cast<std::map<std::string, std::string>*>(data);
     506            0 :         *ppp = PluginPreferencesUtils::getPreferencesValuesMap(PluginUtils::getRootPathFromSoPath(plugin->getPath()));
     507            0 :         return SUCCESS;
     508              :     });
     509              : 
     510              :     // Register getPluginDataPath so that plugin's can receive the path to it's data folder
     511           96 :     pm_.registerService("getPluginDataPath", [](const DLPlugin* plugin, void* data) {
     512            0 :         auto* dataPath = static_cast<std::string*>(data);
     513            0 :         dataPath->assign(PluginUtils::dataPath(plugin->getPath()).string());
     514            0 :         return SUCCESS;
     515              :     });
     516              : 
     517              :     // getPluginAccPreferences is a service that allows plugins to load saved per account preferences.
     518            0 :     auto getPluginAccPreferences = [](const DLPlugin* plugin, void* data) {
     519            0 :         const auto path = PluginUtils::getRootPathFromSoPath(plugin->getPath());
     520            0 :         auto* preferencesPtr {(static_cast<PreferencesMap*>(data))};
     521            0 :         if (!preferencesPtr)
     522            0 :             return FAILURE;
     523              : 
     524            0 :         preferencesPtr->emplace("default", PluginPreferencesUtils::getPreferencesValuesMap(path, "default"));
     525              : 
     526            0 :         for (const auto& accId : jami::Manager::instance().getAccountList())
     527            0 :             preferencesPtr->emplace(accId, PluginPreferencesUtils::getPreferencesValuesMap(path, accId));
     528            0 :         return SUCCESS;
     529            0 :     };
     530              : 
     531           96 :     pm_.registerService("getPluginAccPreferences", getPluginAccPreferences);
     532           32 : }
     533              : 
     534              : #ifdef LIBJAMI_TEST
     535              : void
     536            0 : JamiPluginManager::addPluginAuthority(const dht::crypto::Certificate& cert)
     537              : {
     538            0 :     trust_.add(cert);
     539            0 : }
     540              : #endif
     541              : 
     542              : } // namespace jami
        

Generated by: LCOV version 2.0-1