1/*
2 This file is part of the KDE libraries
3 SPDX-FileCopyrightText: 2015 David Faure <faure@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6*/
7
8#include <QApplication>
9#include <QDBusConnectionInterface>
10#include <QDBusMessage>
11#include <QHash>
12
13#include <KDBusService>
14#include <KDEDModule>
15#include <KPluginFactory>
16#include <KPluginMetaData>
17
18#include <QLoggingCategory>
19Q_DECLARE_LOGGING_CATEGORY(KIOD_CATEGORY)
20Q_LOGGING_CATEGORY(KIOD_CATEGORY, "kf.kio.kiod")
21
22class KIOD : public QObject
23{
24 Q_OBJECT
25public:
26 ~KIOD() override;
27
28public Q_SLOTS:
29 void loadModule(const QString &name);
30
31private:
32 QHash<QString, KDEDModule *> m_modules;
33};
34
35void KIOD::loadModule(const QString &name)
36{
37 // Make sure this method is only called with valid module names.
38 Q_ASSERT(name.indexOf(QLatin1Char('/')) == -1);
39
40 KDEDModule *module = m_modules.value(key: name, defaultValue: nullptr);
41 if (module) {
42 return;
43 }
44
45 qCDebug(KIOD_CATEGORY) << "loadModule" << name;
46 auto result = KPluginFactory::instantiatePlugin<KDEDModule>(data: KPluginMetaData(QStringLiteral("kf6/kiod/") + name));
47 if (result) {
48 module = result.plugin;
49 module->setModuleName(name); // makes it register to DBus
50 m_modules.insert(key: name, value: module);
51 } else {
52 qCWarning(KIOD_CATEGORY) << "Error loading plugin:" << result.errorText;
53 }
54}
55
56KIOD::~KIOD()
57{
58 qDeleteAll(c: m_modules);
59}
60
61Q_GLOBAL_STATIC(KIOD, self)
62
63// on-demand module loading
64// this function is called by the D-Bus message processing function before
65// calls are delivered to objects
66static void messageFilter(const QDBusMessage &message)
67{
68 const QString name = KDEDModule::moduleForMessage(message);
69 if (name.isEmpty()) {
70 return;
71 }
72
73 self()->loadModule(name);
74}
75
76extern Q_DBUS_EXPORT void qDBusAddSpyHook(void (*)(const QDBusMessage &));
77
78int main(int argc, char *argv[])
79{
80#ifdef Q_OS_MACOS
81 // do the "early" step to make this an "agent" application:
82 // set the LSUIElement InfoDict key programmatically.
83 extern void makeAgentApplication();
84 makeAgentApplication();
85#endif
86 qunsetenv(varName: "SESSION_MANAGER"); // disable session management
87
88 QApplication app(argc, argv); // GUI needed for kpasswdserver's dialogs
89 app.setApplicationName(QStringLiteral("kiod6"));
90 app.setOrganizationDomain(QStringLiteral("kde.org"));
91 app.setQuitOnLastWindowClosed(false);
92 KDBusService service(KDBusService::Unique);
93
94 QDBusConnectionInterface *bus = QDBusConnection::sessionBus().interface();
95 // Also register as all the names we should respond to (org.kde.kssld, org.kde.kcookiejar, etc.)
96 // so that the calling code is independent from the physical "location" of the service.
97 const QList<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("kf6/kiod"));
98 for (const KPluginMetaData &metaData : plugins) {
99 const QString serviceName = metaData.value(QStringLiteral("X-KDE-DBus-ServiceName"));
100 if (serviceName.isEmpty()) {
101 qCWarning(KIOD_CATEGORY) << "No X-KDE-DBus-ServiceName found in" << metaData.fileName();
102 continue;
103 }
104 if (!bus->registerService(serviceName)) {
105 qCWarning(KIOD_CATEGORY) << "Couldn't register name" << serviceName << "with DBUS - another process owns it already!";
106 }
107 }
108
109 self(); // create it in this thread
110 qDBusAddSpyHook(messageFilter);
111
112#ifdef Q_OS_MACOS
113 // In the case of kiod6 we need to confirm the agent nature,
114 // possibly because of how things have been set up after creating
115 // the QApplication instance. Failure to do this will disable
116 // text input into dialogs we may post.
117 extern void setAgentActivationPolicy();
118 setAgentActivationPolicy();
119#endif
120 return app.exec();
121}
122
123#include "kiod_main.moc"
124

source code of kio/src/kiod/kiod_main.cpp