LCOV - code coverage report
Current view: top level - src/plugin - jamipluginmanager.cpp (source / functions) Hit Total Coverage
Test: jami-coverage-filtered.info Lines: 207 304 68.1 %
Date: 2024-12-21 08:56:24 Functions: 26 34 76.5 %

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

Generated by: LCOV version 1.14