File indexing completed on 2024-04-28 16:54:38

0001 /*
0002     SPDX-FileCopyrightText: 2018 Kai Uwe Broulik <kde@privat.broulik.de>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "serverinfo.h"
0008 
0009 #include "server_p.h" // for notificationServiceName
0010 
0011 #include "debug.h"
0012 
0013 #include <QDBusConnection>
0014 #include <QDBusConnectionInterface>
0015 #include <QDBusPendingCallWatcher>
0016 #include <QDBusServiceWatcher>
0017 #include <QDebug>
0018 
0019 using namespace NotificationManager;
0020 
0021 class Q_DECL_HIDDEN ServerInfo::Private
0022 {
0023 public:
0024     Private(ServerInfo *q);
0025     ~Private();
0026 
0027     void setStatus(ServerInfo::Status status);
0028     void setServerInformation(const QString &vendor, const QString &name, const QString &version, const QString &specVersion);
0029 
0030     void updateServerInformation();
0031 
0032     ServerInfo *q;
0033 
0034     ServerInfo::Status status = ServerInfo::Status::Unknown;
0035 
0036     QString vendor;
0037     QString name;
0038     QString version;
0039     QString specVersion;
0040 };
0041 
0042 ServerInfo::Private::Private(ServerInfo *q)
0043     : q(q)
0044 {
0045 }
0046 
0047 ServerInfo::Private::~Private() = default;
0048 
0049 void ServerInfo::Private::setStatus(ServerInfo::Status status)
0050 {
0051     if (this->status != status) {
0052         this->status = status;
0053         Q_EMIT q->statusChanged(status);
0054     }
0055 }
0056 
0057 void ServerInfo::Private::setServerInformation(const QString &vendor, const QString &name, const QString &version, const QString &specVersion)
0058 {
0059     if (this->vendor != vendor) {
0060         this->vendor = vendor;
0061         Q_EMIT q->vendorChanged(vendor);
0062     }
0063     if (this->name != name) {
0064         this->name = name;
0065         Q_EMIT q->nameChanged(name);
0066     }
0067     if (this->version != version) {
0068         this->version = version;
0069         Q_EMIT q->versionChanged(version);
0070     }
0071     if (this->specVersion != specVersion) {
0072         this->specVersion = specVersion;
0073         Q_EMIT q->specVersionChanged(specVersion);
0074     }
0075 }
0076 
0077 void ServerInfo::Private::updateServerInformation()
0078 {
0079     // Check whether the service is running to avoid DBus-activating plasma_waitforname and getting stuck there.
0080     if (!QDBusConnection::sessionBus().interface()->isServiceRegistered(ServerPrivate::notificationServiceName())) {
0081         setStatus(ServerInfo::Status::NotRunning);
0082         setServerInformation({}, {}, {}, {});
0083         return;
0084     }
0085 
0086     QDBusMessage msg = QDBusMessage::createMethodCall(ServerPrivate::notificationServiceName(),
0087                                                       QStringLiteral("/org/freedesktop/Notifications"),
0088                                                       QStringLiteral("org.freedesktop.Notifications"),
0089                                                       QStringLiteral("GetServerInformation"));
0090     auto call = QDBusConnection::sessionBus().asyncCall(msg);
0091 
0092     auto *watcher = new QDBusPendingCallWatcher(call, q);
0093     QObject::connect(watcher, &QDBusPendingCallWatcher::finished, q, [this](QDBusPendingCallWatcher *watcher) {
0094         QDBusPendingReply<QString, QString, QString, QString> reply = *watcher;
0095         watcher->deleteLater();
0096 
0097         if (reply.isError()) {
0098             qCWarning(NOTIFICATIONMANAGER) << "Failed to determine notification server information" << reply.error().message();
0099             // Should this still be "Running" as technically it is?
0100             // But if it is not even responding to this properly, who knows what it'll to with an actual notification
0101             setStatus(Status::Unknown);
0102             setServerInformation({}, {}, {}, {});
0103             return;
0104         }
0105 
0106         const QString name = reply.argumentAt(0).toString();
0107         const QString vendor = reply.argumentAt(1).toString();
0108         const QString version = reply.argumentAt(2).toString();
0109         const QString specVersion = reply.argumentAt(3).toString();
0110 
0111         setServerInformation(vendor, name, version, specVersion);
0112         setStatus(ServerInfo::Status::Running);
0113     });
0114 }
0115 
0116 ServerInfo::ServerInfo(QObject *parent)
0117     : QObject(parent)
0118     , d(new Private(this))
0119 {
0120     auto *watcher =
0121         new QDBusServiceWatcher(ServerPrivate::notificationServiceName(), QDBusConnection::sessionBus(), QDBusServiceWatcher::WatchForOwnerChange, this);
0122     connect(watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, [this]() {
0123         d->updateServerInformation();
0124     });
0125 
0126     d->updateServerInformation();
0127 }
0128 
0129 ServerInfo::~ServerInfo() = default;
0130 
0131 ServerInfo::Status ServerInfo::status() const
0132 {
0133     return d->status;
0134 }
0135 
0136 QString ServerInfo::vendor() const
0137 {
0138     return d->vendor;
0139 }
0140 
0141 QString ServerInfo::name() const
0142 {
0143     return d->name;
0144 }
0145 
0146 QString ServerInfo::version() const
0147 {
0148     return d->version;
0149 }
0150 
0151 QString ServerInfo::specVersion() const
0152 {
0153     return d->specVersion;
0154 }