Fix failing asserts when trying to work with invalid plugin

Errors in the plugin itself should be handled gracefully, instead of causing failing asserts in MuseScore.
This commit is contained in:
Casper Jeukendrup 2022-08-31 14:45:06 +02:00
parent 4f517396ed
commit 5a5ec4cb02
No known key found for this signature in database
GPG key ID: 6C571BEF59E722DD
5 changed files with 43 additions and 19 deletions

View file

@ -107,7 +107,11 @@ PluginInfoMap PluginsService::readPlugins() const
for (const io::path_t& pluginPath: pluginsPaths) {
QUrl url = QUrl::fromLocalFile(pluginPath.toQString());
PluginView view(url);
PluginView view;
if (!view.load(url)) {
continue;
}
PluginInfo info;
info.codeKey = io::basename(pluginPath).toQString();
@ -249,7 +253,13 @@ mu::Ret PluginsService::run(const CodeKey& codeKey)
return make_ret(Err::PluginNotFound);
}
PluginView* view = new PluginView(info.url);
PluginView* view = new PluginView();
Ret ret = view->load(info.url);
if (!ret) {
return ret;
}
view->run();
QObject::connect(view, &PluginView::finished, view, &QObject::deleteLater);

View file

@ -31,7 +31,8 @@ enum class Err {
NoError = int(Ret::Code::Ok),
UnknownError = int(Ret::Code::PluginsFirst),
PluginNotFound
PluginNotFound,
PluginLoadError
};
inline Ret make_ret(Err e)
@ -43,6 +44,7 @@ inline Ret make_ret(Err e)
case Err::NoError: return Ret(retCode);
case Err::UnknownError: return Ret(retCode);
case Err::PluginNotFound: return Ret(retCode, trc("plugins", "Plugin not found"));
case Err::PluginLoadError: return Ret(retCode, trc("plugins", "Could not load plugin"));
}
return Ret(static_cast<int>(e));

View file

@ -32,7 +32,6 @@
#include "internal/pluginsactioncontroller.h"
#include "view/pluginsmodel.h"
#include "view/pluginview.h"
#include "api/qmlpluginapi.h"
#include "ui/iuiactionsregister.h"

View file

@ -24,23 +24,17 @@
#include <QQmlComponent>
#include "pluginserrors.h"
#include "api/qmlplugin.h"
#include "log.h"
using namespace mu::plugins;
PluginView::PluginView(const QUrl& url, QObject* parent)
PluginView::PluginView(QObject* parent)
: QObject(parent)
{
m_component = new QQmlComponent(engine(), url);
m_qmlPlugin = qobject_cast<mu::engraving::QmlPlugin*>(m_component->create());
connect(m_qmlPlugin, &mu::engraving::QmlPlugin::closeRequested, [this]() {
if (m_view && m_view->isVisible()) {
m_view->close();
}
});
}
PluginView::~PluginView()
@ -49,6 +43,25 @@ PluginView::~PluginView()
delete m_component;
}
mu::Ret PluginView::load(const QUrl& url)
{
m_component = new QQmlComponent(engine(), url);
m_qmlPlugin = qobject_cast<mu::engraving::QmlPlugin*>(m_component->create());
if (!m_qmlPlugin) {
LOGE() << "Failed to load QML plugin from " << url;
return make_ret(Err::PluginLoadError);
}
connect(m_qmlPlugin, &mu::engraving::QmlPlugin::closeRequested, [this]() {
if (m_view && m_view->isVisible()) {
m_view->close();
}
});
return make_ok();
}
void PluginView::destroyView()
{
if (m_view) {

View file

@ -25,21 +25,19 @@
#include <QQuickView>
#include "io/path.h"
#include "types/ret.h"
#include "modularity/ioc.h"
#include "framework/ui/iuiengine.h"
#include "ipluginsconfiguration.h"
#include "plugins/pluginstypes.h"
class QQmlComponent;
class QQuickView;
namespace mu::engraving {
class QmlPlugin;
}
class QQuickView;
class QQmlComponent;
namespace mu::plugins {
class PluginView : public QObject
{
@ -49,9 +47,11 @@ class PluginView : public QObject
INJECT(plugins, IPluginsConfiguration, configuration)
public:
PluginView(const QUrl& url, QObject* parent = nullptr);
PluginView(QObject* parent = nullptr);
~PluginView();
Ret load(const QUrl& url);
QString name() const;
QString description() const;
QVersionNumber version() const;