File indexing completed on 2024-05-12 05:33:53

0001 /*
0002  * SPDX-FileCopyrightText: 2014 Daniel Vratil <dvratil@redhat.com>
0003  *
0004  * SPDX-License-Identifier: LGPL-2.1-or-later
0005  *
0006  */
0007 
0008 #include "backendloader.h"
0009 #include "abstractbackend.h"
0010 #include "backenddbuswrapper.h"
0011 #include "backendloaderadaptor.h"
0012 #include "backendmanager_p.h"
0013 #include "kscreen_backendLauncher_debug.h"
0014 
0015 #include <QCoreApplication>
0016 #include <QDBusConnectionInterface>
0017 #include <QDir>
0018 #include <QPluginLoader>
0019 
0020 #include <memory>
0021 
0022 #include <QDBusConnection>
0023 #include <QDBusInterface>
0024 
0025 void pluginDeleter(QPluginLoader *p)
0026 {
0027     if (p) {
0028         qCDebug(KSCREEN_BACKEND_LAUNCHER) << "Unloading" << p->fileName();
0029         p->unload();
0030         delete p;
0031     }
0032 }
0033 
0034 BackendLoader::BackendLoader()
0035     : QObject()
0036     , QDBusContext()
0037     , mLoader(nullptr)
0038     , mBackend(nullptr)
0039 {
0040 }
0041 
0042 BackendLoader::~BackendLoader()
0043 {
0044     delete mBackend;
0045     pluginDeleter(mLoader);
0046     qCDebug(KSCREEN_BACKEND_LAUNCHER) << "Backend loader destroyed";
0047 }
0048 
0049 bool BackendLoader::init()
0050 {
0051     QDBusConnection dbus = QDBusConnection::sessionBus();
0052     new BackendLoaderAdaptor(this);
0053     if (!dbus.registerObject(QStringLiteral("/"), this, QDBusConnection::ExportAdaptors)) {
0054         qCWarning(KSCREEN_BACKEND_LAUNCHER) << "Failed to export backend to DBus: another launcher already running?";
0055         qCWarning(KSCREEN_BACKEND_LAUNCHER) << dbus.lastError().message();
0056         return false;
0057     }
0058 
0059     return true;
0060 }
0061 
0062 QString BackendLoader::backend() const
0063 {
0064     if (mBackend) {
0065         return mBackend->backend()->name();
0066     }
0067 
0068     return QString();
0069 }
0070 
0071 bool BackendLoader::requestBackend(const QString &backendName, const QVariantMap &arguments)
0072 {
0073     if (mBackend) {
0074         // If an backend is already loaded, but it's not the same as the one
0075         // requested, then it's an error
0076         if (!backendName.isEmpty() && mBackend->backend()->name() != backendName) {
0077             sendErrorReply(QDBusError::Failed, QStringLiteral("Another backend is already active"));
0078             return false;
0079         } else {
0080             // If caller requested the same one as already loaded, or did not
0081             // request a specific backend, hapilly reuse the existing one
0082             return true;
0083         }
0084     }
0085 
0086     KScreen::AbstractBackend *backend = loadBackend(backendName, arguments);
0087     if (!backend) {
0088         return false;
0089     }
0090 
0091     mBackend = new BackendDBusWrapper(backend);
0092     if (!mBackend->init()) {
0093         delete mBackend;
0094         mBackend = nullptr;
0095         pluginDeleter(mLoader);
0096         mLoader = nullptr;
0097         return false;
0098     }
0099     return true;
0100 }
0101 
0102 KScreen::AbstractBackend *BackendLoader::loadBackend(const QString &name, const QVariantMap &arguments)
0103 {
0104     if (mLoader == nullptr) {
0105         std::unique_ptr<QPluginLoader, void (*)(QPluginLoader *)> loader(new QPluginLoader(), pluginDeleter);
0106         mLoader = loader.release();
0107     }
0108     return KScreen::BackendManager::loadBackendPlugin(mLoader, name, arguments);
0109 }
0110 
0111 void BackendLoader::quit()
0112 {
0113     qApp->quit();
0114 }
0115 
0116 #include "moc_backendloader.cpp"