From 5856cf5a8f024e21a9cf3830b0c8256d6cd3a948 Mon Sep 17 00:00:00 2001 From: agsantos <aline.gondimsantos@savoirfairelinux.com> Date: Thu, 9 Dec 2021 09:37:09 -0500 Subject: [PATCH] plugins: add support to preferences per account bump Plugin api version bump Jami version GitLab: #631 Change-Id: I8b8a9bbb05b3dd461bfafc02940441fda92b25c4 --- .../cx.ring.Ring.PluginManagerInterface.xml | 10 +- bin/dbus/dbuspluginmanagerinterface.cpp | 18 ++- bin/dbus/dbuspluginmanagerinterface.h | 9 +- bin/jni/plugin_manager_interface.i | 8 +- src/client/plugin_manager_interface.cpp | 25 ++-- src/conference.cpp | 12 +- src/jami/plugin_manager_interface.h | 9 +- src/manager.cpp | 16 ++- src/meson.build | 1 + src/plugin/CMakeLists.txt | 3 + src/plugin/Makefile.am | 5 +- src/plugin/callservicesmanager.cpp | 3 +- src/plugin/chatservicesmanager.cpp | 3 +- src/plugin/jamiplugin.h | 4 +- src/plugin/jamipluginmanager.cpp | 95 +++++++++---- src/plugin/jamipluginmanager.h | 20 ++- src/plugin/pluginmanager.cpp | 1 + src/plugin/pluginpreferencesutils.cpp | 97 +++++++++---- src/plugin/pluginpreferencesutils.h | 25 +++- src/plugin/preferencehandler.h | 82 +++++++++++ src/plugin/preferenceservicesmanager.cpp | 130 ++++++++++++++++++ src/plugin/preferenceservicesmanager.h | 102 ++++++++++++++ src/plugin/streamdata.h | 13 +- src/sip/sipcall.cpp | 8 +- 24 files changed, 588 insertions(+), 111 deletions(-) create mode 100644 src/plugin/preferencehandler.h create mode 100644 src/plugin/preferenceservicesmanager.cpp create mode 100644 src/plugin/preferenceservicesmanager.h diff --git a/bin/dbus/cx.ring.Ring.PluginManagerInterface.xml b/bin/dbus/cx.ring.Ring.PluginManagerInterface.xml index 2e6e32be13..ce9861241a 100644 --- a/bin/dbus/cx.ring.Ring.PluginManagerInterface.xml +++ b/bin/dbus/cx.ring.Ring.PluginManagerInterface.xml @@ -31,9 +31,11 @@ <method name="getPluginPreferences" tp:name-for-bindings="getPluginPreferences"> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> - <tp:added version="9.2.0"/> + <tp:added version="11.1.0"/> <arg type="s" name="path" direction="in"> </arg> + <arg type="s" name="accountId" direction="in"> + </arg> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="VectorMapStringString"/> <arg type="aa{ss}" name="PluginPreferences" direction="out" tp:type="String_String_Map"> </arg> @@ -43,6 +45,8 @@ <tp:added version="9.2.0"/> <arg type="s" name="path" direction="in"> </arg> + <arg type="s" name="accountId" direction="in"> + </arg> <arg type="s" name="key" direction="in"> </arg> <arg type="s" name="value" direction="in"> @@ -56,6 +60,8 @@ <tp:added version="9.2.0"/> <arg type="s" name="path" direction="in"> </arg> + <arg type="s" name="accountId" direction="in"> + </arg> <annotation name="org.qtproject.QtDBus.QtTypeName.Out0" value="MapStringString"/> <arg type="a{ss}" name="preferencesValues" direction="out" tp:type="String_String_Map"> </arg> @@ -65,6 +71,8 @@ <tp:added version="9.2.0"/> <arg type="s" name="path" direction="in"> </arg> + <arg type="s" name="accountId" direction="in"> + </arg> <arg type="b" name="reset" direction="out"> </arg> </method> diff --git a/bin/dbus/dbuspluginmanagerinterface.cpp b/bin/dbus/dbuspluginmanagerinterface.cpp index 46371c8c5c..3fd3b02114 100644 --- a/bin/dbus/dbuspluginmanagerinterface.cpp +++ b/bin/dbus/dbuspluginmanagerinterface.cpp @@ -44,29 +44,33 @@ DBusPluginManagerInterface::getPluginDetails(const std::string& path) } std::vector<std::map<std::string, std::string>> -DBusPluginManagerInterface::getPluginPreferences(const std::string& path) +DBusPluginManagerInterface::getPluginPreferences(const std::string& path, + const std::string& accountId) { - return DRing::getPluginPreferences(path); + return DRing::getPluginPreferences(path, accountId); } bool DBusPluginManagerInterface::setPluginPreference(const std::string& path, + const std::string& accountId, const std::string& key, const std::string& value) { - return DRing::setPluginPreference(path, key, value); + return DRing::setPluginPreference(path, accountId, key, value); } std::map<std::string, std::string> -DBusPluginManagerInterface::getPluginPreferencesValues(const std::string& path) +DBusPluginManagerInterface::getPluginPreferencesValues(const std::string& path, + const std::string& accountId) { - return DRing::getPluginPreferencesValues(path); + return DRing::getPluginPreferencesValues(path, accountId); } bool -DBusPluginManagerInterface::resetPluginPreferencesValues(const std::string& path) +DBusPluginManagerInterface::resetPluginPreferencesValues(const std::string& path, + const std::string& accountId) { - return DRing::resetPluginPreferencesValues(path); + return DRing::resetPluginPreferencesValues(path, accountId); } auto diff --git a/bin/dbus/dbuspluginmanagerinterface.h b/bin/dbus/dbuspluginmanagerinterface.h index 9b3855ad1a..4fc3ce6fe4 100644 --- a/bin/dbus/dbuspluginmanagerinterface.h +++ b/bin/dbus/dbuspluginmanagerinterface.h @@ -55,12 +55,15 @@ public: bool loadPlugin(const std::string& path); bool unloadPlugin(const std::string& path); std::map<std::string, std::string> getPluginDetails(const std::string& path); - std::vector<std::map<std::string, std::string>> getPluginPreferences(const std::string& path); + std::vector<std::map<std::string, std::string>> getPluginPreferences( + const std::string& path, const std::string& accountId); bool setPluginPreference(const std::string& path, + const std::string& accountId, const std::string& key, const std::string& value); - std::map<std::string, std::string> getPluginPreferencesValues(const std::string& path); - bool resetPluginPreferencesValues(const std::string& path); + std::map<std::string, std::string> getPluginPreferencesValues(const std::string& path, + const std::string& accountId); + bool resetPluginPreferencesValues(const std::string& path, const std::string& accountId); std::vector<std::string> getInstalledPlugins(); std::vector<std::string> getLoadedPlugins(); int installPlugin(const std::string& jplPath, const bool& force); diff --git a/bin/jni/plugin_manager_interface.i b/bin/jni/plugin_manager_interface.i index 0f5e226da2..dfcc01ca32 100644 --- a/bin/jni/plugin_manager_interface.i +++ b/bin/jni/plugin_manager_interface.i @@ -27,10 +27,10 @@ namespace DRing { bool loadPlugin(const std::string& path); bool unloadPlugin(const std::string& path); std::map<std::string,std::string> getPluginDetails(const std::string& path); -std::vector<std::map<std::string,std::string>> getPluginPreferences(const std::string& path); -bool setPluginPreference(const std::string& path, const std::string& key, const std::string& value); -std::map<std::string,std::string> getPluginPreferencesValues(const std::string& path); -bool resetPluginPreferencesValues(const std::string& path); +std::vector<std::map<std::string,std::string>> getPluginPreferences(const std::string& path, const std::string& accountId); +bool setPluginPreference(const std::string& path, const std::string& accountId, const std::string& key, const std::string& value); +std::map<std::string,std::string> getPluginPreferencesValues(const std::string& path, const std::string& accountId); +bool resetPluginPreferencesValues(const std::string& path, const std::string& accountId); std::vector<std::string> getInstalledPlugins(); std::vector<std::string> getLoadedPlugins(); int installPlugin(const std::string& jplPath, bool force); diff --git a/src/client/plugin_manager_interface.cpp b/src/client/plugin_manager_interface.cpp index fc41f7a21f..0a0115a846 100644 --- a/src/client/plugin_manager_interface.cpp +++ b/src/client/plugin_manager_interface.cpp @@ -52,26 +52,35 @@ getPluginDetails(const std::string& path) } std::vector<std::map<std::string, std::string>> -getPluginPreferences(const std::string& path) +getPluginPreferences(const std::string& path, const std::string& accountId) { - return jami::Manager::instance().getJamiPluginManager().getPluginPreferences(path); + return jami::Manager::instance().getJamiPluginManager().getPluginPreferences(path, accountId); } bool -setPluginPreference(const std::string& path, const std::string& key, const std::string& value) +setPluginPreference(const std::string& path, + const std::string& accountId, + const std::string& key, + const std::string& value) { - return jami::Manager::instance().getJamiPluginManager().setPluginPreference(path, key, value); + return jami::Manager::instance().getJamiPluginManager().setPluginPreference(path, + accountId, + key, + value); } std::map<std::string, std::string> -getPluginPreferencesValues(const std::string& path) +getPluginPreferencesValues(const std::string& path, const std::string& accountId) { - return jami::Manager::instance().getJamiPluginManager().getPluginPreferencesValuesMap(path); + return jami::Manager::instance().getJamiPluginManager().getPluginPreferencesValuesMap(path, + accountId); } bool -resetPluginPreferencesValues(const std::string& path) +resetPluginPreferencesValues(const std::string& path, const std::string& accountId) { - return jami::Manager::instance().getJamiPluginManager().resetPluginPreferencesValuesMap(path); + return jami::Manager::instance() + .getJamiPluginManager() + .resetPluginPreferencesValuesMap(path, accountId); } std::vector<std::string> diff --git a/src/conference.cpp b/src/conference.cpp index be023394b9..9ea5af27ec 100644 --- a/src/conference.cpp +++ b/src/conference.cpp @@ -310,6 +310,8 @@ Conference::setLocalHostDefaultMediaSource() void Conference::createConfAVStreams() { + std::string accountId = getAccountId(); + auto audioMap = [](const std::shared_ptr<jami::MediaFrame>& m) -> AVFrame* { return std::static_pointer_cast<AudioFrame>(m)->pointer(); }; @@ -317,9 +319,9 @@ Conference::createConfAVStreams() // Preview and Received if ((audioMixer_ = jami::getAudioInput(getConfId()))) { auto audioSubject = std::make_shared<MediaStreamSubject>(audioMap); - StreamData previewStreamData {getConfId(), false, StreamType::audio, getConfId()}; + StreamData previewStreamData {getConfId(), false, StreamType::audio, getConfId(), accountId}; createConfAVStream(previewStreamData, *audioMixer_, audioSubject); - StreamData receivedStreamData {getConfId(), true, StreamType::audio, getConfId()}; + StreamData receivedStreamData {getConfId(), true, StreamType::audio, getConfId(), accountId}; createConfAVStream(receivedStreamData, *audioMixer_, audioSubject); } @@ -328,13 +330,13 @@ Conference::createConfAVStreams() if (videoMixer_) { // Review auto receiveSubject = std::make_shared<MediaStreamSubject>(pluginVideoMap_); - StreamData receiveStreamData {getConfId(), true, StreamType::video, getConfId()}; + StreamData receiveStreamData {getConfId(), true, StreamType::video, getConfId(), accountId}; createConfAVStream(receiveStreamData, *videoMixer_, receiveSubject); // Preview if (auto& videoPreview = videoMixer_->getVideoLocal()) { auto previewSubject = std::make_shared<MediaStreamSubject>(pluginVideoMap_); - StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId()}; + StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId(), accountId}; createConfAVStream(previewStreamData, *videoPreview, previewSubject); } } @@ -1024,7 +1026,7 @@ Conference::switchInput(const std::string& input) // Preview if (auto& videoPreview = mixer->getVideoLocal()) { auto previewSubject = std::make_shared<MediaStreamSubject>(pluginVideoMap_); - StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId()}; + StreamData previewStreamData {getConfId(), false, StreamType::video, getConfId(), getAccountId()}; createConfAVStream(previewStreamData, *videoPreview, previewSubject, true); } #endif diff --git a/src/jami/plugin_manager_interface.h b/src/jami/plugin_manager_interface.h index e1f4aee9f8..f35a05a119 100644 --- a/src/jami/plugin_manager_interface.h +++ b/src/jami/plugin_manager_interface.h @@ -38,12 +38,15 @@ DRING_PUBLIC bool loadPlugin(const std::string& path); DRING_PUBLIC bool unloadPlugin(const std::string& path); DRING_PUBLIC std::map<std::string, std::string> getPluginDetails(const std::string& path); DRING_PUBLIC std::vector<std::map<std::string, std::string>> getPluginPreferences( - const std::string& path); + const std::string& path, const std::string& accountId); DRING_PUBLIC bool setPluginPreference(const std::string& path, + const std::string& accountId, const std::string& key, const std::string& value); -DRING_PUBLIC std::map<std::string, std::string> getPluginPreferencesValues(const std::string& path); -DRING_PUBLIC bool resetPluginPreferencesValues(const std::string& path); +DRING_PUBLIC std::map<std::string, std::string> getPluginPreferencesValues( + const std::string& path, const std::string& accountId); +DRING_PUBLIC bool resetPluginPreferencesValues(const std::string& path, + const std::string& accountId); DRING_PUBLIC std::vector<std::string> getInstalledPlugins(); DRING_PUBLIC std::vector<std::string> getLoadedPlugins(); DRING_PUBLIC int installPlugin(const std::string& jplPath, bool force); diff --git a/src/manager.cpp b/src/manager.cpp index 4ce503fa2e..70cc9e2352 100644 --- a/src/manager.cpp +++ b/src/manager.cpp @@ -2789,13 +2789,6 @@ Manager::loadAccountMap(const YAML::Node& node) #endif #ifdef ENABLE_PLUGIN pluginPreferences.unserialize(node); - - if (pluginPreferences.getPluginsEnabled()) { - std::vector<std::string> loadedPlugins = pluginPreferences.getLoadedPlugins(); - for (const std::string& plugin : loadedPlugins) { - jami::Manager::instance().getJamiPluginManager().loadPlugin(plugin); - } - } #endif } catch (const YAML::Exception& e) { JAMI_ERR("%s: Preferences node unserialize error: ", e.what()); @@ -2849,6 +2842,15 @@ Manager::loadAccountMap(const YAML::Node& node) } cv.wait(l, [&remaining] { return remaining == 0; }); +#ifdef ENABLE_PLUGIN + if (pluginPreferences.getPluginsEnabled()) { + std::vector<std::string> loadedPlugins = pluginPreferences.getLoadedPlugins(); + for (const std::string& plugin : loadedPlugins) { + jami::Manager::instance().getJamiPluginManager().loadPlugin(plugin); + } + } +#endif + return errorCount; } diff --git a/src/meson.build b/src/meson.build index 5171da766b..7a53e38dd4 100644 --- a/src/meson.build +++ b/src/meson.build @@ -292,6 +292,7 @@ endif if conf.get('ENABLE_PLUGIN') libjami_sources += files( 'client/plugin_manager_interface.cpp', + 'plugin/preferenceservicesmanager.cpp', 'plugin/callservicesmanager.cpp', 'plugin/chatservicesmanager.cpp', 'plugin/jamipluginmanager.cpp', diff --git a/src/plugin/CMakeLists.txt b/src/plugin/CMakeLists.txt index e79748986b..968e154de7 100644 --- a/src/plugin/CMakeLists.txt +++ b/src/plugin/CMakeLists.txt @@ -7,10 +7,13 @@ list (APPEND Source_Files__plugin "${CMAKE_CURRENT_SOURCE_DIR}/pluginmanager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/pluginpreferencesutils.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/pluginsutils.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/preferenceservicesmanager.h" + "${CMAKE_CURRENT_SOURCE_DIR}/preferenceservicesmanager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/callservicesmanager.h" "${CMAKE_CURRENT_SOURCE_DIR}/callservicesmanager.cpp" "${CMAKE_CURRENT_SOURCE_DIR}/chatservicesmanager.h" "${CMAKE_CURRENT_SOURCE_DIR}/chatservicesmanager.cpp" + "${CMAKE_CURRENT_SOURCE_DIR}/preferencehandler.h" "${CMAKE_CURRENT_SOURCE_DIR}/chathandler.h" "${CMAKE_CURRENT_SOURCE_DIR}/jamiplugin.h" "${CMAKE_CURRENT_SOURCE_DIR}/jamipluginmanager.h" diff --git a/src/plugin/Makefile.am b/src/plugin/Makefile.am index 4ce81f7579..02b6b728fb 100644 --- a/src/plugin/Makefile.am +++ b/src/plugin/Makefile.am @@ -3,7 +3,9 @@ if ENABLE_PLUGIN noinst_LTLIBRARIES += libplugin.la noinst_HEADERS += \ + ./plugin/preferenceservicesmanager.h \ ./plugin/callservicesmanager.h \ + ./plugin/preferencehandler.h \ ./plugin/chathandler.h \ ./plugin/chatservicesmanager.h \ ./plugin/jamiplugin.h \ @@ -22,7 +24,8 @@ libplugin_la_SOURCES = \ ./plugin/pluginpreferencesutils.cpp \ ./plugin/pluginsutils.cpp \ ./plugin/chatservicesmanager.cpp \ - ./plugin/callservicesmanager.cpp + ./plugin/callservicesmanager.cpp \ + ./plugin/preferenceservicesmanager.cpp libring_la_LIBADD += libplugin.la diff --git a/src/plugin/callservicesmanager.cpp b/src/plugin/callservicesmanager.cpp index 294c1e1f9b..79aec3bd82 100644 --- a/src/plugin/callservicesmanager.cpp +++ b/src/plugin/callservicesmanager.cpp @@ -61,7 +61,8 @@ CallServicesManager::createAVSubject(const StreamData& data, AVSubjectSPtr subje // toggle is true if we should automatically activate the MediaHandler. bool toggle = PluginPreferencesUtils::getAlwaysPreference( callMediaHandler->id().substr(0, found), - callMediaHandler->getCallMediaHandlerDetails().at("name")); + callMediaHandler->getCallMediaHandlerDetails().at("name"), + data.source); // toggle may be overwritten if the MediaHandler was previously activated/deactivated // for the given call. for (const auto& toggledMediaHandlerPair : mediaHandlerToggled_[data.id]) { diff --git a/src/plugin/chatservicesmanager.cpp b/src/plugin/chatservicesmanager.cpp index a406017e92..723c2dd1cd 100644 --- a/src/plugin/chatservicesmanager.cpp +++ b/src/plugin/chatservicesmanager.cpp @@ -147,7 +147,8 @@ ChatServicesManager::publishMessage(pluginMessagePtr message) std::size_t found = chatHandler->id().find_last_of(DIR_SEPARATOR_CH); // toggle is true if we should automatically activate the ChatHandler. bool toggle = PluginPreferencesUtils::getAlwaysPreference(chatHandler->id().substr(0, found), - chatHandlerName); + chatHandlerName, + message->accountId); // toggle is overwritten if we have previously activated/deactivated the ChatHandler // for the given conversation. auto allowedIt = chatAllowDenySet.find(chatHandlerName); diff --git a/src/plugin/jamiplugin.h b/src/plugin/jamiplugin.h index b7510445fd..92043524bd 100644 --- a/src/plugin/jamiplugin.h +++ b/src/plugin/jamiplugin.h @@ -38,8 +38,8 @@ #define JAMI_PLUGIN_ABI_VERSION 1 // 0 doesn't exist, considered as error // JAMI_PLUGIN_API_VERSION reflects changes in Services Managers -// (CallServicesManager and ChatServicesMangers) and in JAMI_PluginAPI. -#define JAMI_PLUGIN_API_VERSION 1 // 0 doesn't exist, considered as error +// (CallServicesManager, ChatServicesMansge, and PreferenceServicesManagers) and in JAMI_PluginAPI. +#define JAMI_PLUGIN_API_VERSION 2 // 0 doesn't exist, considered as error C_INTERFACE_START; diff --git a/src/plugin/jamipluginmanager.cpp b/src/plugin/jamipluginmanager.cpp index a8cde173ef..5c078b5cfa 100644 --- a/src/plugin/jamipluginmanager.cpp +++ b/src/plugin/jamipluginmanager.cpp @@ -79,9 +79,11 @@ JamiPluginManager::getInstalledPlugins() std::for_each(pluginsPaths.begin(), pluginsPaths.end(), [&pluginsPath](std::string& x) { x = pluginsPath + DIR_SEPARATOR_CH + x; }); - auto returnIterator = std::remove_if(pluginsPaths.begin(), pluginsPaths.end(), [](const std::string& path) { - return !PluginUtils::checkPluginValidity(path); - }); + auto returnIterator = std::remove_if(pluginsPaths.begin(), + pluginsPaths.end(), + [](const std::string& path) { + return !PluginUtils::checkPluginValidity(path); + }); pluginsPaths.erase(returnIterator, std::end(pluginsPaths)); // Gets plugins installed in non standard path @@ -106,8 +108,8 @@ JamiPluginManager::installPlugin(const std::string& jplPath, bool force) if (name.empty()) return 0; const std::string& version = manifestMap["version"]; - std::string destinationDir {fileutils::get_data_dir() + DIR_SEPARATOR_CH - + "plugins" + DIR_SEPARATOR_CH + name}; + std::string destinationDir {fileutils::get_data_dir() + DIR_SEPARATOR_CH + "plugins" + + DIR_SEPARATOR_CH + name}; // Find if there is an existing version of this plugin const auto alreadyInstalledManifestMap = PluginUtils::parseManifestFile( PluginUtils::manifestPath(destinationDir)); @@ -163,6 +165,10 @@ JamiPluginManager::uninstallPlugin(const std::string& rootPath) return -1; } } + for (const auto& accId : jami::Manager::instance().getAccountList()) + fileutils::removeAll(fileutils::get_data_dir() + DIR_SEPARATOR_CH + accId + + DIR_SEPARATOR_CH + "plugins" + DIR_SEPARATOR_CH + + detailsIt->second.at("name")); pluginDetailsMap_.erase(detailsIt); } return fileutils::removeAll(rootPath); @@ -223,34 +229,49 @@ JamiPluginManager::getLoadedPlugins() const } std::vector<std::map<std::string, std::string>> -JamiPluginManager::getPluginPreferences(const std::string& rootPath) +JamiPluginManager::getPluginPreferences(const std::string& rootPath, const std::string& accountId) { - return PluginPreferencesUtils::getPreferences(rootPath); + return PluginPreferencesUtils::getPreferences(rootPath, accountId); } bool JamiPluginManager::setPluginPreference(const std::string& rootPath, + const std::string& accountId, const std::string& key, const std::string& value) { + std::string acc = accountId; + + // If we try to change a preference value linked to an account + // but that preference is global, we must ignore accountId and + // change the preference for every account + if (!accountId.empty()) { + // Get global preferences + auto preferences = PluginPreferencesUtils::getPreferences(rootPath, ""); + // Check if the preference we want to change is global + auto it = std::find_if(preferences.cbegin(), + preferences.cend(), + [key](const std::map<std::string, std::string>& preference) { + return preference.at("key") == key; + }); + // Ignore accountId if global preference + if (it != preferences.cend()) + acc.clear(); + } + std::map<std::string, std::string> pluginUserPreferencesMap - = PluginPreferencesUtils::getUserPreferencesValuesMap(rootPath); + = PluginPreferencesUtils::getUserPreferencesValuesMap(rootPath, acc); std::map<std::string, std::string> pluginPreferencesMap - = PluginPreferencesUtils::getPreferencesValuesMap(rootPath); + = PluginPreferencesUtils::getPreferencesValuesMap(rootPath, acc); - std::vector<std::map<std::string, std::string>> preferences - = PluginPreferencesUtils::getPreferences(rootPath); // If any plugin handler is active we may have to reload it bool force {pm_.checkLoadedPlugin(rootPath)}; // We check if the preference is modified without having to reload plugin - for (auto& preference : preferences) { - if (!preference["key"].compare(key)) { - force &= callsm_.setPreference(key, value, rootPath); - force &= chatsm_.setPreference(key, value, rootPath); - break; - } - } + force &= preferencesm_.setPreference(key, value, rootPath, acc); + force &= callsm_.setPreference(key, value, rootPath); + force &= chatsm_.setPreference(key, value, rootPath); + if (force) unloadPlugin(rootPath); @@ -258,8 +279,8 @@ JamiPluginManager::setPluginPreference(const std::string& rootPath, auto find = pluginPreferencesMap.find(key); if (find != pluginPreferencesMap.end()) { pluginUserPreferencesMap[key] = value; - const std::string preferencesValuesFilePath = PluginPreferencesUtils::valuesFilePath( - rootPath); + const std::string preferencesValuesFilePath + = PluginPreferencesUtils::valuesFilePath(rootPath, acc); std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferencesValuesFilePath)); std::ofstream fs(preferencesValuesFilePath, std::ios::binary); if (!fs.good()) { @@ -285,19 +306,23 @@ JamiPluginManager::setPluginPreference(const std::string& rootPath, } std::map<std::string, std::string> -JamiPluginManager::getPluginPreferencesValuesMap(const std::string& rootPath) +JamiPluginManager::getPluginPreferencesValuesMap(const std::string& rootPath, + const std::string& accountId) { - return PluginPreferencesUtils::getPreferencesValuesMap(rootPath); + return PluginPreferencesUtils::getPreferencesValuesMap(rootPath, accountId); } bool -JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath) +JamiPluginManager::resetPluginPreferencesValuesMap(const std::string& rootPath, + const std::string& accountId) { + bool acc {accountId.empty()}; bool loaded {pm_.checkLoadedPlugin(rootPath)}; - if (loaded) + if (loaded && acc) unloadPlugin(rootPath); - auto status = PluginPreferencesUtils::resetPreferencesValuesMap(rootPath); - if (loaded) { + auto status = PluginPreferencesUtils::resetPreferencesValuesMap(rootPath, accountId); + preferencesm_.resetPreferences(rootPath, accountId); + if (loaded && acc) { loadPlugin(rootPath); } return status; @@ -320,5 +345,23 @@ JamiPluginManager::registerServices() dataPath->assign(PluginUtils::dataPath(plugin->getPath())); return 0; }); + + // getPluginAccPreferences is a service that allows plugins to load saved per account preferences. + auto getPluginAccPreferences = [](const DLPlugin* plugin, void* data) { + const auto path = PluginUtils::getRootPathFromSoPath(plugin->getPath()); + auto preferencesPtr {(static_cast<PreferencesMap*>(data))}; + if (!preferencesPtr) + return -1; + + preferencesPtr->emplace("default", + PluginPreferencesUtils::getPreferencesValuesMap(path, "default")); + + for (const auto& accId : jami::Manager::instance().getAccountList()) + preferencesPtr->emplace(accId, + PluginPreferencesUtils::getPreferencesValuesMap(path, accId)); + return 0; + }; + + pm_.registerService("getPluginAccPreferences", getPluginAccPreferences); } } // namespace jami diff --git a/src/plugin/jamipluginmanager.h b/src/plugin/jamipluginmanager.h index b33ea39c1b..974ae216c5 100644 --- a/src/plugin/jamipluginmanager.h +++ b/src/plugin/jamipluginmanager.h @@ -26,6 +26,7 @@ #include "callservicesmanager.h" #include "chatservicesmanager.h" +#include "preferenceservicesmanager.h" #include <vector> #include <map> @@ -34,6 +35,8 @@ namespace jami { +using PreferencesMap = std::map<std::string, std::map<std::string, std::string>>; + /** * @class JamiPluginManager * @brief This class provides an interface to functions exposed to the @@ -45,6 +48,7 @@ public: JamiPluginManager() : callsm_ {pm_} , chatsm_ {pm_} + , preferencesm_ {pm_} { registerServices(); } @@ -102,39 +106,48 @@ public: /** * @brief Returns contents of plugin's preferences.json file * @param rootPath + * @param accountId */ - std::vector<std::map<std::string, std::string>> getPluginPreferences(const std::string& rootPath); + std::vector<std::map<std::string, std::string>> getPluginPreferences( + const std::string& rootPath, const std::string& accountId); /** * @brief Returns a Map with preferences keys and values. * @param rootPath + * @param accountId */ - std::map<std::string, std::string> getPluginPreferencesValuesMap(const std::string& rootPath); + std::map<std::string, std::string> getPluginPreferencesValuesMap(const std::string& rootPath, + const std::string& accountId); /** * @brief Modifies a preference value by saving it to a preferences.msgpack. * Plugin is reloaded only if the preference cannot take effect immediately. * In other words, if we have to reload plugin so that preference may take effect. * @param rootPath + * @param accountId * @param key * @param value * @return True if success */ bool setPluginPreference(const std::string& rootPath, + const std::string& accountId, const std::string& key, const std::string& value); /** * @brief Reset plugin's preferences values to their defaultValues * @param rootPath + * @param accountId * @return True if success. */ - bool resetPluginPreferencesValuesMap(const std::string& rootPath); + bool resetPluginPreferencesValuesMap(const std::string& rootPath, const std::string& accountId); CallServicesManager& getCallServicesManager() { return callsm_; } ChatServicesManager& getChatServicesManager() { return chatsm_; } + PreferenceServicesManager& getPreferenceServicesManager() { return preferencesm_; } + private: NON_COPYABLE(JamiPluginManager); @@ -152,5 +165,6 @@ private: // Services instances CallServicesManager callsm_; ChatServicesManager chatsm_; + PreferenceServicesManager preferencesm_; }; } // namespace jami diff --git a/src/plugin/pluginmanager.cpp b/src/plugin/pluginmanager.cpp index 51b02a6a31..8c30afb930 100644 --- a/src/plugin/pluginmanager.cpp +++ b/src/plugin/pluginmanager.cpp @@ -150,6 +150,7 @@ PluginManager::callPluginInitFunction(const std::string& path) if (!exitFunc) { JAMI_ERR() << "Plugin: init failed"; + // emit signal with error message to let user know that jamid could not load plugin returnValue = false; } else { returnValue = true; diff --git a/src/plugin/pluginpreferencesutils.cpp b/src/plugin/pluginpreferencesutils.cpp index 07f2c4c552..16754c981b 100644 --- a/src/plugin/pluginpreferencesutils.cpp +++ b/src/plugin/pluginpreferencesutils.cpp @@ -30,15 +30,25 @@ namespace jami { std::string -PluginPreferencesUtils::getPreferencesConfigFilePath(const std::string& rootPath) +PluginPreferencesUtils::getPreferencesConfigFilePath(const std::string& rootPath, + const std::string& accountId) { - return rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH + "preferences.json"; + if (accountId.empty()) + return rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH + "preferences.json"; + else + return rootPath + DIR_SEPARATOR_CH + "data" + DIR_SEPARATOR_CH + "accountpreferences.json"; } std::string -PluginPreferencesUtils::valuesFilePath(const std::string& rootPath) +PluginPreferencesUtils::valuesFilePath(const std::string& rootPath, const std::string& accountId) { - return rootPath + DIR_SEPARATOR_CH + "preferences.msgpack"; + if (accountId.empty() || accountId == "default") + return rootPath + DIR_SEPARATOR_CH + "preferences.msgpack"; + auto pluginName = rootPath.substr(rootPath.find_last_of(DIR_SEPARATOR_CH) + 1); + auto dir = fileutils::get_data_dir() + DIR_SEPARATOR_CH + accountId + DIR_SEPARATOR_CH + + "plugins" + DIR_SEPARATOR_CH + pluginName; + fileutils::check_dir(dir.c_str()); + return dir + DIR_SEPARATOR_CH + "preferences.msgpack"; } std::string @@ -89,9 +99,9 @@ PluginPreferencesUtils::parsePreferenceConfig(const Json::Value& jsonPreference) } std::vector<std::map<std::string, std::string>> -PluginPreferencesUtils::getPreferences(const std::string& rootPath) +PluginPreferencesUtils::getPreferences(const std::string& rootPath, const std::string& accountId) { - std::string preferenceFilePath = getPreferencesConfigFilePath(rootPath); + std::string preferenceFilePath = getPreferencesConfigFilePath(rootPath, accountId); std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferenceFilePath)); std::ifstream file(preferenceFilePath); Json::Value root; @@ -142,9 +152,10 @@ PluginPreferencesUtils::getPreferences(const std::string& rootPath) } std::map<std::string, std::string> -PluginPreferencesUtils::getUserPreferencesValuesMap(const std::string& rootPath) +PluginPreferencesUtils::getUserPreferencesValuesMap(const std::string& rootPath, + const std::string& accountId) { - const std::string preferencesValuesFilePath = valuesFilePath(rootPath); + const std::string preferencesValuesFilePath = valuesFilePath(rootPath, accountId); std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferencesValuesFilePath)); std::ifstream file(preferencesValuesFilePath, std::ios::binary); std::map<std::string, std::string> rmap; @@ -177,12 +188,17 @@ PluginPreferencesUtils::getUserPreferencesValuesMap(const std::string& rootPath) } std::map<std::string, std::string> -PluginPreferencesUtils::getPreferencesValuesMap(const std::string& rootPath) +PluginPreferencesUtils::getPreferencesValuesMap(const std::string& rootPath, + const std::string& accountId) { std::map<std::string, std::string> rmap; // Read all preferences values std::vector<std::map<std::string, std::string>> preferences = getPreferences(rootPath); + auto accPrefs = getPreferences(rootPath, accountId); + for (const auto& item : accPrefs) { + preferences.push_back(item); + } for (auto& preference : preferences) { rmap[preference["key"]] = preference["defaultValue"]; } @@ -192,16 +208,24 @@ PluginPreferencesUtils::getPreferencesValuesMap(const std::string& rootPath) rmap[pair.first] = pair.second; } + if (!accountId.empty()) { + // If any of these preferences were modified, its value is changed before return + for (const auto& pair : getUserPreferencesValuesMap(rootPath, accountId)) { + rmap[pair.first] = pair.second; + } + } + return rmap; } bool -PluginPreferencesUtils::resetPreferencesValuesMap(const std::string& rootPath) +PluginPreferencesUtils::resetPreferencesValuesMap(const std::string& rootPath, + const std::string& accountId) { bool returnValue = true; std::map<std::string, std::string> pluginPreferencesMap {}; - const std::string preferencesValuesFilePath = valuesFilePath(rootPath); + const std::string preferencesValuesFilePath = valuesFilePath(rootPath, accountId); std::lock_guard<std::mutex> guard(fileutils::getFileLock(preferencesValuesFilePath)); std::ofstream fs(preferencesValuesFilePath, std::ios::binary); if (!fs.good()) { @@ -270,7 +294,28 @@ void PluginPreferencesUtils::addAlwaysHandlerPreference(const std::string& handlerName, const std::string& rootPath) { - std::string filePath = getPreferencesConfigFilePath(rootPath); + { + std::string filePath = getPreferencesConfigFilePath(rootPath); + Json::Value root; + + std::lock_guard<std::mutex> guard(fileutils::getFileLock(filePath)); + std::ifstream file(filePath); + Json::CharReaderBuilder rbuilder; + Json::Value preference; + rbuilder["collectComments"] = false; + std::string errs; + if (file) { + bool ok = Json::parseFromStream(rbuilder, file, &root, &errs); + if (ok && root.isArray()) { + // Return if preference already exists + for (const auto& child : root) + if (child.get("key", "None").asString() == handlerName + "Always") + return; + } + } + } + + std::string filePath = getPreferencesConfigFilePath(rootPath, "acc"); Json::Value root; { std::lock_guard<std::mutex> guard(fileutils::getFileLock(filePath)); @@ -279,8 +324,6 @@ PluginPreferencesUtils::addAlwaysHandlerPreference(const std::string& handlerNam Json::Value preference; rbuilder["collectComments"] = false; std::string errs; - std::set<std::string> keys; - std::vector<std::map<std::string, std::string>> preferences; if (file) { bool ok = Json::parseFromStream(rbuilder, file, &root, &errs); if (ok && root.isArray()) { @@ -289,15 +332,15 @@ PluginPreferencesUtils::addAlwaysHandlerPreference(const std::string& handlerNam if (child.get("key", "None").asString() == handlerName + "Always") return; } - // Create preference structure otherwise - preference["key"] = handlerName + "Always"; - preference["type"] = "Switch"; - preference["defaultValue"] = "0"; - preference["title"] = "Automatically turn " + handlerName + " on"; - preference["summary"] = handlerName + " will take effect immediately"; - root.append(preference); - file.close(); } + // Create preference structure otherwise + preference["key"] = handlerName + "Always"; + preference["type"] = "Switch"; + preference["defaultValue"] = "0"; + preference["title"] = "Automatically turn " + handlerName + " on"; + preference["summary"] = handlerName + " will take effect immediately"; + preference["scope"] = "accountId"; + root.append(preference); } std::lock_guard<std::mutex> guard(fileutils::getFileLock(filePath)); std::ofstream outFile(filePath); @@ -309,10 +352,16 @@ PluginPreferencesUtils::addAlwaysHandlerPreference(const std::string& handlerNam } bool -PluginPreferencesUtils::getAlwaysPreference(const std::string& rootPath, std::string& handlerName) +PluginPreferencesUtils::getAlwaysPreference(const std::string& rootPath, + const std::string& handlerName, + const std::string& accountId) { auto preferences = getPreferences(rootPath); - auto preferencesValues = getPreferencesValuesMap(rootPath); + auto accPrefs = getPreferences(rootPath, accountId); + for (const auto& item : accPrefs) { + preferences.push_back(item); + } + auto preferencesValues = getPreferencesValuesMap(rootPath, accountId); for (const auto& preference : preferences) { auto key = preference.at("key"); diff --git a/src/plugin/pluginpreferencesutils.h b/src/plugin/pluginpreferencesutils.h index e52e2caa92..b034d169c9 100644 --- a/src/plugin/pluginpreferencesutils.h +++ b/src/plugin/pluginpreferencesutils.h @@ -43,7 +43,8 @@ public: * @param rootPath * @return preference.json file path. */ - static std::string getPreferencesConfigFilePath(const std::string& rootPath); + static std::string getPreferencesConfigFilePath(const std::string& rootPath, + const std::string& accountId = ""); /** * @brief Given a plugin installation path, returns the path to the @@ -51,9 +52,11 @@ public: * The preference.msgpack file saves the actuall preferences values * if they were modified. * @param rootPath + * @param accountId * @return preference.msgpack file path. */ - static std::string valuesFilePath(const std::string& rootPath); + static std::string valuesFilePath(const std::string& rootPath, + const std::string& accountId = ""); /** * @brief Returns the path to allowdeny.msgpack file. @@ -81,33 +84,38 @@ public: /** * @brief Reads a preference.json file from the plugin installed in rootPath. * @param rootPath + * @param accountId * @return std::vector<std::map<std::string, std::string>> with preferences.json content */ static std::vector<std::map<std::string, std::string>> getPreferences( - const std::string& rootPath); + const std::string& rootPath, const std::string& accountId = ""); /** * @brief Reads preferences values which were modified from defaultValue * @param rootPath + * @param accountId * @return Map with preference keys and actuall values. */ static std::map<std::string, std::string> getUserPreferencesValuesMap( - const std::string& rootPath); + const std::string& rootPath, const std::string& accountId = ""); /** * @brief Reads preferences values * @param rootPath + * @param accountId * @return Map with preference keys and actuall values. */ - static std::map<std::string, std::string> getPreferencesValuesMap(const std::string& rootPath); + static std::map<std::string, std::string> getPreferencesValuesMap( + const std::string& rootPath, const std::string& accountId = ""); /** * @brief Resets all preferences values to their defaultValues * by erasing all data saved in preferences.msgpack. * @param rootPath + * @param accountId * @return True if preferences were reset. */ - static bool resetPreferencesValuesMap(const std::string& rootPath); + static bool resetPreferencesValuesMap(const std::string& rootPath, const std::string& accountId); /** * @brief Saves ChantHandlers status provided by list. @@ -136,9 +144,12 @@ public: * "always" preference is True or False. * @param rootPath * @param handlerName + * @param accountId * @return True if the handler should be automatically toggled */ - static bool getAlwaysPreference(const std::string& rootPath, std::string& handlerName); + static bool getAlwaysPreference(const std::string& rootPath, + const std::string& handlerName, + const std::string& accountId); private: PluginPreferencesUtils() {} diff --git a/src/plugin/preferencehandler.h b/src/plugin/preferencehandler.h new file mode 100644 index 0000000000..b094c10519 --- /dev/null +++ b/src/plugin/preferencehandler.h @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include <string> +#include <map> + +namespace jami { + +/** + * @brief This abstract class is an API we need to implement from plugin side. + * In other words, a plugin functionality that handles preferences per account + * must start from the implementation of this class. + */ +class PreferenceHandler +{ +public: + virtual ~PreferenceHandler() {} + + /** + * @brief Returns a map with handler's name, iconPath, and pluginId. + */ + virtual std::map<std::string, std::string> getHandlerDetails() = 0; + + /** + * @brief If a preference can have different values depending on accountId, those values should + * be stored in the plugin through this function. + * @param accountId + * @param key + * @param value + */ + virtual void setPreferenceAttribute(const std::string& accountId, + const std::string& key, + const std::string& value) + = 0; + + /** + * @brief If a preference can be stored as per accountId, this function should return True. + * @param key + * @return True if preference can be changed through setPreferenceAttribute method. + */ + virtual bool preferenceMapHasKey(const std::string& key) = 0; + + /** + * @brief Reset stored preferences for given accountId. + * @param accountId + */ + virtual void resetPreferenceAttributes(const std::string& accountId) = 0; + + /** + * @brief Returns the dataPath of the plugin that created this PreferenceHandler. + */ + std::string id() const { return id_; } + + /** + * @brief Should be called by the PreferenceHandler creator to set the plugins id_ variable. + */ + virtual void setId(const std::string& id) final { id_ = id; } + +private: + // Is the dataPath of the plugin that created this ChatHandler. + std::string id_; +}; +} // namespace jami diff --git a/src/plugin/preferenceservicesmanager.cpp b/src/plugin/preferenceservicesmanager.cpp new file mode 100644 index 0000000000..b5bff51bf8 --- /dev/null +++ b/src/plugin/preferenceservicesmanager.cpp @@ -0,0 +1,130 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#include "preferenceservicesmanager.h" + +#include "pluginmanager.h" +#include "pluginpreferencesutils.h" + +#include "manager.h" +#include "sip/sipcall.h" +#include "fileutils.h" +#include "logger.h" + +namespace jami { + +PreferenceServicesManager::PreferenceServicesManager(PluginManager& pluginManager) +{ + registerComponentsLifeCycleManagers(pluginManager); +} + +PreferenceServicesManager::~PreferenceServicesManager() +{ + handlers_.clear(); +} + +std::vector<std::string> +PreferenceServicesManager::getHandlers() const +{ + std::vector<std::string> res; + res.reserve(handlers_.size()); + for (const auto& preferenceHandler : handlers_) { + res.emplace_back(std::to_string((uintptr_t) preferenceHandler.get())); + } + return res; +} + +std::map<std::string, std::string> +PreferenceServicesManager::getHandlerDetails(const std::string& preferenceHandlerIdStr) const +{ + auto preferenceHandlerId = std::stoull(preferenceHandlerIdStr); + for (auto& preferenceHandler : handlers_) { + if ((uintptr_t) preferenceHandler.get() == preferenceHandlerId) { + return preferenceHandler->getHandlerDetails(); + } + } + return {}; +} + +bool +PreferenceServicesManager::setPreference(const std::string& key, + const std::string& value, + const std::string& rootPath, + const std::string& accountId) +{ + bool status {true}; + for (auto& preferenceHandler : handlers_) { + if (preferenceHandler->id().find(rootPath) != std::string::npos) { + if (preferenceHandler->preferenceMapHasKey(key)) { + preferenceHandler->setPreferenceAttribute(accountId, key, value); + // We can return here since we expect plugins to have a single preferencehandler + return false; + } + } + } + return status; +} + +void +PreferenceServicesManager::resetPreferences(const std::string& rootPath, + const std::string& accountId) +{ + for (auto& preferenceHandler : handlers_) { + if (preferenceHandler->id().find(rootPath) != std::string::npos) { + preferenceHandler->resetPreferenceAttributes(accountId); + } + } +} + +void +PreferenceServicesManager::registerComponentsLifeCycleManagers(PluginManager& pluginManager) +{ + // registerHandler may be called by the PluginManager upon loading a plugin. + auto registerHandler = [this](void* data, std::mutex& pmMtx_) { + std::lock_guard<std::mutex> lk(pmMtx_); + PreferenceHandlerPtr ptr {(static_cast<PreferenceHandler*>(data))}; + + if (!ptr) + return -1; + handlers_.emplace_back(std::move(ptr)); + return 0; + }; + + // unregisterHandler may be called by the PluginManager while unloading. + auto unregisterHandler = [this](void* data, std::mutex& pmMtx_) { + std::lock_guard<std::mutex> lk(pmMtx_); + auto handlerIt = std::find_if(handlers_.begin(), + handlers_.end(), + [data](PreferenceHandlerPtr& handler) { + return (handler.get() == data); + }); + + if (handlerIt != handlers_.end()) { + handlers_.erase(handlerIt); + } + return true; + }; + + // Services are registered to the PluginManager. + pluginManager.registerComponentManager("PreferenceHandlerManager", + registerHandler, + unregisterHandler); +} +} // namespace jami diff --git a/src/plugin/preferenceservicesmanager.h b/src/plugin/preferenceservicesmanager.h new file mode 100644 index 0000000000..7e03dd0863 --- /dev/null +++ b/src/plugin/preferenceservicesmanager.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2021 Savoir-faire Linux Inc. + * + * Author: Aline Gondim Santos <aline.gondimsantos@savoirfairelinux.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + */ + +#pragma once + +#include "preferencehandler.h" + +#include "noncopyable.h" + +#include <list> +#include <map> +#include <tuple> +#include <memory> +#include <vector> + +namespace jami { + +class PluginManager; + +using PreferenceHandlerPtr = std::unique_ptr<PreferenceHandler>; + +/** + * @brief This class provides the interface between PreferenceHandlers + * and per account preferences. Besides, it stores pointers to all loaded PreferenceHandlers; + */ +class PreferenceServicesManager +{ +public: + /** + * @brief Constructor registers PreferenceHandler API services to the PluginManager + * instance. These services will store PreferenceHandler pointers or clean them + * from the Plugin System once a plugin is loaded or unloaded. + * @param pluginManager + */ + PreferenceServicesManager(PluginManager& pluginManager); + + ~PreferenceServicesManager(); + + NON_COPYABLE(PreferenceServicesManager); + + /** + * @brief List all PreferenceHandlers available. + * @return Vector with stored PreferenceHandlers pointers. + */ + std::vector<std::string> getHandlers() const; + + /** + * @brief Returns details Map from s implementation. + * @param preferenceHandlerIdStr + * @return Details map from the PreferenceHandler implementation + */ + std::map<std::string, std::string> getHandlerDetails( + const std::string& preferenceHandlerIdStr) const; + + /** + * @brief Sets a preference. + * @param key + * @param value + * @param rootPath + * @param accountId + * @return False if preference was changed. + */ + bool setPreference(const std::string& key, + const std::string& value, + const std::string& rootPath, + const std::string& accountId); + + /** + * @brief Resets acc preferences to default values. + * @param rootPath + * @param accountId + */ + void resetPreferences(const std::string& rootPath, const std::string& accountId); + +private: + /** + * @brief Exposes PreferenceHandlers' life cycle managers services to the main API. + * @param pluginManager + */ + void registerComponentsLifeCycleManagers(PluginManager& pluginManager); + + // Components that a plugin can register through registerPreferenceHandler service. + std::list<PreferenceHandlerPtr> handlers_; +}; +} // namespace jami diff --git a/src/plugin/streamdata.h b/src/plugin/streamdata.h index b2be704521..40706c0fdc 100644 --- a/src/plugin/streamdata.h +++ b/src/plugin/streamdata.h @@ -34,16 +34,19 @@ struct StreamData * @param callId * @param isReceived False if local audio/video streams * @param mediaType - * @param peerId + * @param conversationId + * @param accountId */ StreamData(const std::string& callId, bool isReceived, const StreamType& mediaType, - const std::string& peerId) + const std::string& conversationId, + const std::string& accountId) : id {std::move(callId)} , direction {isReceived} , type {mediaType} - , source {std::move(peerId)} + , conversation {std::move(conversationId)} + , source {std::move(accountId)} {} // callId const std::string id; @@ -51,8 +54,10 @@ struct StreamData const bool direction; // StreamType -> audio or video. const StreamType type; - // peerId + // accountId const std::string source; + // conversationId + const std::string conversation; }; /** diff --git a/src/sip/sipcall.cpp b/src/sip/sipcall.cpp index a12f98f623..ba52bd4bf9 100644 --- a/src/sip/sipcall.cpp +++ b/src/sip/sipcall.cpp @@ -283,14 +283,14 @@ SIPCall::createCallAVStreams() // Preview if (auto& localAudio = audioRtp->getAudioLocal()) { auto previewSubject = std::make_shared<MediaStreamSubject>(audioMap); - StreamData microStreamData {baseId, false, StreamType::audio, getPeerNumber()}; + StreamData microStreamData {baseId, false, StreamType::audio, getPeerNumber(), getAccountId()}; createCallAVStream(microStreamData, *localAudio, previewSubject); } // Receive if (auto& audioReceive = audioRtp->getAudioReceive()) { auto receiveSubject = std::make_shared<MediaStreamSubject>(audioMap); - StreamData phoneStreamData {baseId, true, StreamType::audio, getPeerNumber()}; + StreamData phoneStreamData {baseId, true, StreamType::audio, getPeerNumber(), getAccountId()}; createCallAVStream(phoneStreamData, (AVMediaStream&) *audioReceive, receiveSubject); } #ifdef ENABLE_VIDEO @@ -306,14 +306,14 @@ SIPCall::createCallAVStreams() // Preview if (auto& videoPreview = videoRtp->getVideoLocal()) { auto previewSubject = std::make_shared<MediaStreamSubject>(map); - StreamData previewStreamData {getCallId(), false, StreamType::video, getPeerNumber()}; + StreamData previewStreamData {getCallId(), false, StreamType::video, getPeerNumber(), getAccountId()}; createCallAVStream(previewStreamData, *videoPreview, previewSubject); } // Receive if (auto& videoReceive = videoRtp->getVideoReceive()) { auto receiveSubject = std::make_shared<MediaStreamSubject>(map); - StreamData receiveStreamData {getCallId(), true, StreamType::video, getPeerNumber()}; + StreamData receiveStreamData {getCallId(), true, StreamType::video, getPeerNumber(), getAccountId()}; createCallAVStream(receiveStreamData, *videoReceive, receiveSubject); } } -- GitLab