LCOV - code coverage report
Current view: top level - src/plugin - jamipluginmanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 204 299 68.2 %
Date: 2024-04-25 08:05:53 Functions: 26 32 81.2 %

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

Generated by: LCOV version 1.14