File indexing completed on 2023-10-01 08:41:45

0001 /*
0002     Copyright (C) 2011 Collabora Ltd. <info@collabora.com>
0003       @author George Kiagiadakis <george.kiagiadakis@collabora.com>
0004 
0005     This library is free software; you can redistribute it and/or modify
0006     it under the terms of the GNU Lesser General Public License as published
0007     by the Free Software Foundation; either version 2.1 of the License, or
0008     (at your option) any later version.
0009 
0010     This program is distributed in the hope that it will be useful,
0011     but WITHOUT ANY WARRANTY; without even the implied warranty of
0012     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0013     GNU General Public License for more details.
0014 
0015     You should have received a copy of the GNU Lesser General Public License
0016     along with this program.  If not, see <http://www.gnu.org/licenses/>.
0017 */
0018 #include "service-availability-checker.h"
0019 
0020 #include <QtDBus/QDBusConnectionInterface>
0021 #include <QtDBus/QDBusServiceWatcher>
0022 #include <QtDBus/QDBusPendingCall>
0023 #include <QtDBus/QDBusReply>
0024 
0025 #include "ktp-debug.h"
0026 
0027 namespace KTp
0028 {
0029 
0030 struct ServiceAvailabilityChecker::Private
0031 {
0032     QString serviceName;
0033     bool serviceAvailable;
0034     bool serviceActivatable;
0035 };
0036 
0037 ServiceAvailabilityChecker::ServiceAvailabilityChecker(const QString & serviceName, QObject *parent)
0038     : QObject(parent), d(new Private)
0039 {
0040     d->serviceName = serviceName;
0041     d->serviceAvailable = false;
0042     d->serviceActivatable = false;
0043 
0044     QDBusServiceWatcher *serviceWatcher = new QDBusServiceWatcher(serviceName,
0045             QDBusConnection::sessionBus(),
0046             QDBusServiceWatcher::WatchForRegistration | QDBusServiceWatcher::WatchForUnregistration,
0047             this);
0048     connect(serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
0049             this, SLOT(onServiceOwnerChanged(QString,QString,QString)));
0050 
0051     introspect();
0052 }
0053 
0054 ServiceAvailabilityChecker::~ServiceAvailabilityChecker()
0055 {
0056     delete d;
0057 }
0058 
0059 bool ServiceAvailabilityChecker::isAvailable() const
0060 {
0061     return d->serviceAvailable || d->serviceActivatable;
0062 }
0063 
0064 void ServiceAvailabilityChecker::introspect()
0065 {
0066     QDBusConnectionInterface *dbusIface = QDBusConnection::sessionBus().interface();
0067 
0068     QDBusPendingCall call = dbusIface->asyncCall(QLatin1String("ListActivatableNames"));
0069     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(call, this);
0070     connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
0071             this, SLOT(onCallFinished(QDBusPendingCallWatcher*)));
0072     watcher->setObjectName(QLatin1String("ListActivatableNamesWatcher"));
0073 
0074     call = dbusIface->asyncCall(QLatin1String("ListNames"));
0075     watcher = new QDBusPendingCallWatcher(call, this);
0076     connect(watcher, SIGNAL(finished(QDBusPendingCallWatcher*)),
0077             this, SLOT(onCallFinished(QDBusPendingCallWatcher*)));
0078 }
0079 
0080 void ServiceAvailabilityChecker::onCallFinished(QDBusPendingCallWatcher *watcher)
0081 {
0082     QDBusReply<QStringList> reply = *watcher;
0083     if (!reply.isValid()) {
0084         qCDebug(KTP_COMMONINTERNALS) << "Got error while introspecting service availability:" << reply.error();
0085     } else {
0086         if (watcher->objectName() == QLatin1String("ListActivatableNamesWatcher")) {
0087             d->serviceActivatable = reply.value().contains(d->serviceName);
0088         } else {
0089             if (!d->serviceAvailable) {
0090                 d->serviceAvailable = reply.value().contains(d->serviceName);
0091             }
0092             //else onServiceOwnerChanged() has been emitted before the introspection finished
0093             //so the reply we got here may be incorrect, claiming that the service is not available
0094         }
0095     }
0096 
0097     watcher->deleteLater();
0098 }
0099 
0100 void ServiceAvailabilityChecker::onServiceOwnerChanged(const QString & service,
0101         const QString & oldOwner, const QString & newOwner)
0102 {
0103     Q_UNUSED(oldOwner);
0104 
0105     if (service == d->serviceName) {
0106         d->serviceAvailable = !newOwner.isEmpty();
0107     }
0108 }
0109 
0110 }