LCOV - code coverage report
Current view: top level - muse/framework/extensions/internal - extensionsconfiguration.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 103 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2024 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : #include "extensionsconfiguration.h"
      23              : 
      24              : #include "global/settings.h"
      25              : #include "global/serialization/json.h"
      26              : #include "global/io/file.h"
      27              : #include "global/io/dir.h"
      28              : #include "multiwindows/resourcelockguard.h"
      29              : #include "legacy/extpluginsloader.h"
      30              : 
      31              : #include "log.h"
      32              : 
      33              : using namespace muse;
      34              : using namespace muse::extensions;
      35              : 
      36              : static const muse::Settings::Key USER_PLUGINS_PATH("plugins", "application/paths/myPlugins");
      37              : 
      38              : static const std::string EXTENSIONS_RESOURCE_NAME("EXTENSIONS");
      39              : 
      40            0 : void ExtensionsConfiguration::init()
      41              : {
      42            0 :     settings()->setDefaultValue(USER_PLUGINS_PATH, Val(globalConfiguration()->userDataPath() + "/Plugins"));
      43            0 :     settings()->valueChanged(USER_PLUGINS_PATH).onReceive(nullptr, [this](const Val& val) {
      44            0 :         m_pluginsUserPathChanged.send(val.toString());
      45            0 :     });
      46              : 
      47            0 :     if (!pluginsUserPath().empty()) {
      48            0 :         io::Dir::mkpath(pluginsUserPath());
      49              :     }
      50              : 
      51            0 :     io::Dir::mkpath(userPath());
      52            0 : }
      53              : 
      54            0 : io::path_t ExtensionsConfiguration::defaultPath() const
      55              : {
      56            0 :     return globalConfiguration()->appDataPath() + "/extensions";
      57              : }
      58              : 
      59            0 : io::path_t ExtensionsConfiguration::userPath() const
      60              : {
      61            0 :     return globalConfiguration()->userAppDataPath() + "/extensions";
      62              : }
      63              : 
      64            0 : io::path_t ExtensionsConfiguration::pluginsDefaultPath() const
      65              : {
      66            0 :     return globalConfiguration()->appDataPath() + "/plugins";
      67              : }
      68              : 
      69            0 : io::path_t ExtensionsConfiguration::pluginsUserPath() const
      70              : {
      71            0 :     return settings()->value(USER_PLUGINS_PATH).toPath();
      72              : }
      73              : 
      74            0 : void ExtensionsConfiguration::setUserPluginsPath(const io::path_t& path)
      75              : {
      76            0 :     settings()->setSharedValue(USER_PLUGINS_PATH, Val(path));
      77            0 : }
      78              : 
      79            0 : async::Channel<io::path_t> ExtensionsConfiguration::pluginsUserPathChanged() const
      80              : {
      81            0 :     return m_pluginsUserPathChanged;
      82              : }
      83              : 
      84            0 : Ret ExtensionsConfiguration::setExtensionConfigs(const std::map<Uri, ExtensionConfig>& configs)
      85              : {
      86            0 :     JsonArray arr;
      87            0 :     for (const auto& p : configs) {
      88            0 :         JsonObject obj;
      89            0 :         obj["uri"] = p.first.toString();
      90              : 
      91            0 :         const ExtensionConfig& c = p.second;
      92            0 :         obj["enabled"] = c.enabled;
      93              : 
      94            0 :         arr.append(obj);
      95            0 :     }
      96              : 
      97            0 :     Ret ret;
      98            0 :     ByteArray data = JsonDocument(arr).toJson();
      99              :     {
     100            0 :         mi::WriteResourceLockGuard lock_guard(multiwindowsProvider.get(), EXTENSIONS_RESOURCE_NAME);
     101            0 :         ret = io::File::writeFile(userPath() + "/config.json", data);
     102            0 :     }
     103              : 
     104            0 :     if (!ret) {
     105            0 :         LOGE() << "failed write config data, err: " << ret.toString();
     106              :     }
     107              : 
     108            0 :     return ret;
     109            0 : }
     110              : 
     111            0 : std::map<muse::Uri, ExtensionConfig> ExtensionsConfiguration::extensionConfigs() const
     112              : {
     113            0 :     const io::path_t configPath = userPath() + "/config.json";
     114            0 :     const io::path_t oldPluginsConfigPath = globalConfiguration()->userAppDataPath() + "/plugins/plugins.json";
     115              : 
     116              :     //! NOTE Load current config
     117            0 :     if (io::File::exists(configPath)) {
     118            0 :         ByteArray data;
     119              :         {
     120            0 :             mi::ReadResourceLockGuard lock_guard(multiwindowsProvider.get(), EXTENSIONS_RESOURCE_NAME);
     121            0 :             Ret ret = io::File::readFile(configPath, data);
     122            0 :             if (!ret) {
     123            0 :                 LOGE() << "failed read config data, err: " << ret.toString() << ", file: " << configPath;
     124            0 :                 return {};
     125              :             }
     126            0 :         }
     127              : 
     128            0 :         std::string err;
     129            0 :         JsonDocument doc = JsonDocument::fromJson(data, &err);
     130            0 :         if (!err.empty()) {
     131            0 :             LOGE() << "failed parse json, err: " << err;
     132            0 :             return {};
     133              :         }
     134              : 
     135            0 :         if (!doc.isArray()) {
     136            0 :             LOGE() << "bad format of config file";
     137            0 :             return {};
     138              :         }
     139              : 
     140            0 :         std::map<Uri, ExtensionConfig> result;
     141            0 :         JsonArray arr = doc.rootArray();
     142            0 :         for (size_t i = 0; i < arr.size(); ++i) {
     143            0 :             JsonObject obj = arr.at(i).toObject();
     144              : 
     145            0 :             Uri uri = Uri(obj.value("uri").toStdString());
     146              : 
     147            0 :             ExtensionConfig c;
     148            0 :             c.enabled = obj.value("enabled").toBool();
     149              : 
     150            0 :             result.insert({ uri, c });
     151            0 :         }
     152              : 
     153            0 :         return result;
     154            0 :     }
     155              :     //! NOTE Load old plugins config
     156              :     else {
     157            0 :         ByteArray data;
     158              : 
     159              :         {
     160            0 :             mi::ReadResourceLockGuard lock_guard(multiwindowsProvider.get(), EXTENSIONS_RESOURCE_NAME);
     161            0 :             Ret ret = io::File::readFile(oldPluginsConfigPath, data);
     162            0 :             if (!ret) {
     163            0 :                 LOGE() << "failed read config data, err: " << ret.toString() << ", file: " << oldPluginsConfigPath;
     164            0 :                 return {};
     165              :             }
     166            0 :         }
     167              : 
     168            0 :         std::string err;
     169            0 :         JsonDocument doc = JsonDocument::fromJson(data, &err);
     170            0 :         if (!err.empty()) {
     171            0 :             LOGE() << "failed parse json, err: " << err;
     172            0 :             return {};
     173              :         }
     174              : 
     175            0 :         if (!doc.isArray()) {
     176            0 :             LOGE() << "bad format of config file";
     177            0 :             return {};
     178              :         }
     179              : 
     180            0 :         std::map<std::string /*codeKey*/, Uri> uris;
     181              :         {
     182              :             legacy::ExtPluginsLoader pluginsLoader;
     183            0 :             uris = pluginsLoader.loadCodekeyUriMap(pluginsDefaultPath(), pluginsUserPath());
     184              :         }
     185              : 
     186            0 :         std::map<Uri, ExtensionConfig> result;
     187            0 :         JsonArray arr = doc.rootArray();
     188            0 :         for (size_t i = 0; i < arr.size(); ++i) {
     189            0 :             JsonObject obj = arr.at(i).toObject();
     190              : 
     191            0 :             std::string codeKey = obj.value("codeKey").toStdString();
     192            0 :             Uri uri = muse::value(uris, codeKey);
     193            0 :             if (!uri.isValid()) {
     194            0 :                 LOGW() << "not found plugin with codeKey: " << codeKey;
     195            0 :                 continue;
     196              :             }
     197              : 
     198            0 :             ExtensionConfig c;
     199            0 :             c.enabled = obj.value("enabled").toBool();
     200              : 
     201            0 :             result.insert({ uri, c });
     202            0 :         }
     203              : 
     204            0 :         return result;
     205            0 :     }
     206            0 : }
        

Generated by: LCOV version 2.0-1