File indexing completed on 2024-04-21 03:55:30

0001 /*
0002     This file is part of the KDE libraries
0003     SPDX-FileCopyrightText: 2015 David Faure <faure@kde.org>
0004 
0005     SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0006 */
0007 
0008 #include <QApplication>
0009 #include <QDBusConnectionInterface>
0010 #include <QDBusMessage>
0011 #include <QHash>
0012 
0013 #include <KDBusService>
0014 #include <KDEDModule>
0015 #include <KPluginFactory>
0016 #include <KPluginMetaData>
0017 
0018 #include <QLoggingCategory>
0019 Q_DECLARE_LOGGING_CATEGORY(KIOD_CATEGORY)
0020 Q_LOGGING_CATEGORY(KIOD_CATEGORY, "kf.kio.kiod")
0021 
0022 class KIOD : public QObject
0023 {
0024     Q_OBJECT
0025 public:
0026     ~KIOD() override;
0027 
0028 public Q_SLOTS:
0029     void loadModule(const QString &name);
0030 
0031 private:
0032     QHash<QString, KDEDModule *> m_modules;
0033 };
0034 
0035 void KIOD::loadModule(const QString &name)
0036 {
0037     // Make sure this method is only called with valid module names.
0038     Q_ASSERT(name.indexOf(QLatin1Char('/')) == -1);
0039 
0040     KDEDModule *module = m_modules.value(name, nullptr);
0041     if (module) {
0042         return;
0043     }
0044 
0045     qCDebug(KIOD_CATEGORY) << "loadModule" << name;
0046     auto result = KPluginFactory::instantiatePlugin<KDEDModule>(KPluginMetaData(QStringLiteral("kf6/kiod/") + name));
0047     if (result) {
0048         module = result.plugin;
0049         module->setModuleName(name); // makes it register to DBus
0050         m_modules.insert(name, module);
0051     } else {
0052         qCWarning(KIOD_CATEGORY) << "Error loading plugin:" << result.errorText;
0053     }
0054 }
0055 
0056 KIOD::~KIOD()
0057 {
0058     qDeleteAll(m_modules);
0059 }
0060 
0061 Q_GLOBAL_STATIC(KIOD, self)
0062 
0063 // on-demand module loading
0064 // this function is called by the D-Bus message processing function before
0065 // calls are delivered to objects
0066 static void messageFilter(const QDBusMessage &message)
0067 {
0068     const QString name = KDEDModule::moduleForMessage(message);
0069     if (name.isEmpty()) {
0070         return;
0071     }
0072 
0073     self()->loadModule(name);
0074 }
0075 
0076 extern Q_DBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage &));
0077 
0078 int main(int argc, char *argv[])
0079 {
0080 #ifdef Q_OS_MACOS
0081     // do the "early" step to make this an "agent" application:
0082     // set the LSUIElement InfoDict key programmatically.
0083     extern void makeAgentApplication();
0084     makeAgentApplication();
0085 #endif
0086     qunsetenv("SESSION_MANAGER"); // disable session management
0087 
0088     QApplication app(argc, argv); // GUI needed for kpasswdserver's dialogs
0089     app.setApplicationName(QStringLiteral("kiod6"));
0090     app.setOrganizationDomain(QStringLiteral("kde.org"));
0091     app.setQuitOnLastWindowClosed(false);
0092     KDBusService service(KDBusService::Unique);
0093 
0094     QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface();
0095     // Also register as all the names we should respond to (org.kde.kssld, org.kde.kcookiejar, etc.)
0096     // so that the calling code is independent from the physical "location" of the service.
0097     const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/kiod"));
0098     for (const KPluginMetaData &metaData : plugins) {
0099         const QString serviceName = metaData.value(QStringLiteral("X-KDE-DBus-ServiceName"));
0100         if (serviceName.isEmpty()) {
0101             qCWarning(KIOD_CATEGORY) << "No X-KDE-DBus-ServiceName found in" << metaData.fileName();
0102             continue;
0103         }
0104         if (!bus->registerService(serviceName)) {
0105             qCWarning(KIOD_CATEGORY) << "Couldn't register name" << serviceName << "with DBUS - another process owns it already!";
0106         }
0107     }
0108 
0109     self(); // create it in this thread
0110     qDBusAddSpyHook(messageFilter);
0111 
0112 #ifdef Q_OS_MACOS
0113     // In the case of kiod6 we need to confirm the agent nature,
0114     // possibly because of how things have been set up after creating
0115     // the QApplication instance. Failure to do this will disable
0116     // text input into dialogs we may post.
0117     extern void setAgentActivationPolicy();
0118     setAgentActivationPolicy();
0119 #endif
0120     return app.exec();
0121 }
0122 
0123 #include "kiod_main.moc"