LCOV - code coverage report
Current view: top level - foo/src/plugin - jamipluginmanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 209 307 68.1 %
Date: 2025-08-24 09:11:10 Functions: 26 34 76.5 %

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

Generated by: LCOV version 1.14