/* SPDX-FileCopyrightText: 2010-2016 Ivan Cukic SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL */ #include "manager_p.h" #include #include #include #include #include #include #include "debug_p.h" #include "mainthreadexecutor_p.h" #include "common/dbus/common.h" #include "utils/continue_with.h" #include "utils/dbusfuture_p.h" #include "version.h" namespace KActivities { Manager *Manager::s_instance = nullptr; Manager::Manager() : QObject() , m_watcher(KAMD_DBUS_SERVICE, QDBusConnection::sessionBus()) , m_service(new KAMD_DBUS_CLASS_INTERFACE("/", Application, this)) , m_activities(new KAMD_DBUS_CLASS_INTERFACE("Activities", Activities, this)) , m_resources(new KAMD_DBUS_CLASS_INTERFACE("Resources", Resources, this)) , m_resourcesLinking(new KAMD_DBUS_CLASS_INTERFACE("Resources/Linking", ResourcesLinking, this)) , m_features(new KAMD_DBUS_CLASS_INTERFACE("Features", Features, this)) , m_serviceStatus(Manager::NotRunning) { connect(&m_watcher, &QDBusServiceWatcher::serviceOwnerChanged, this, &Manager::serviceOwnerChanged); if (serviceStatus()) { serviceOwnerChanged(KAMD_DBUS_SERVICE, QString(), KAMD_DBUS_SERVICE); } } Manager *Manager::self() { static std::mutex singleton; std::lock_guard singleton_lock(singleton); if (!s_instance) { runInMainThread([]() { // check if the activity manager is already running // creating a new instance of the class Manager::s_instance = new Manager(); if (QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE)) { // already running s_instance->m_serviceStatus = Running; } else { // not running bool disableAutolaunch = QCoreApplication::instance()->property("org.kde.KActivities.core.disableAutostart").toBool(); qCDebug(KAMD_CORELIB) << "Should we start the daemon?"; // start only if not disabled and we have a dbus connection at all if (!disableAutolaunch && QDBusConnection::sessionBus().interface()) { qCDebug(KAMD_CORELIB) << "Starting the activity manager daemon"; auto busInterface = QDBusConnection::sessionBus().interface(); auto pending = busInterface->asyncCall(QStringLiteral("StartServiceByName"), KAMD_DBUS_SERVICE, uint(0)); s_instance->m_serviceStatus = Manager::Starting; QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(pending, s_instance); connect(watcher, &QDBusPendingCallWatcher::finished, watcher, []() { const bool isRunning = QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE); s_instance->m_serviceStatus = isRunning ? Manager::Running : Manager::NotRunning; Q_EMIT s_instance->serviceStatusChanged(s_instance->m_serviceStatus); }); } } }); } return s_instance; } bool Manager::isServiceRunning() { return s_instance && s_instance->m_serviceStatus == Manager::Running; } Manager::ServiceStatus Manager::serviceStatus() { return s_instance ? s_instance->m_serviceStatus : NotRunning; } void Manager::serviceOwnerChanged(const QString &serviceName, const QString &oldOwner, const QString &newOwner) { Q_UNUSED(oldOwner); if (serviceName == KAMD_DBUS_SERVICE) { const bool isRunning = QDBusConnection::sessionBus().interface()->isServiceRegistered(KAMD_DBUS_SERVICE); m_serviceStatus = isRunning ? Manager::Running : Manager::NotRunning; Q_EMIT serviceStatusChanged(m_serviceStatus); if (isRunning) { using namespace kamd::utils; continue_with(DBusFuture::fromReply(m_service->serviceVersion()), [this](const std::optional &serviceVersion) { // Test whether the service is older than the library. // If it is, we need to end this if (!serviceVersion.has_value()) { qWarning() << "KActivities: FATAL ERROR: Failed to contact the activity manager daemon"; m_serviceStatus = NotRunning; return; } auto split = serviceVersion->split(QLatin1Char('.')); QList version; // We require kactivitymanagerd version to be at least the // one before the repository split const int requiredVersion[] = {6, 2, 0}; std::transform(split.cbegin(), split.cend(), std::back_inserter(version), [](const QString &component) { return component.toInt(); }); // if required version is greater than the current version if (std::lexicographical_compare(version.cbegin(), version.cend(), std::begin(requiredVersion), std::end(requiredVersion))) { QString libraryVersion = QString::number(requiredVersion[0]) + QLatin1Char('.') + QString::number(requiredVersion[1]) + QLatin1Char('.') + QString::number(requiredVersion[2]); qDebug() << "KActivities service version: " << serviceVersion.value(); qDebug() << "KActivities library version: " << libraryVersion; qFatal("KActivities: FATAL ERROR: The service is older than the library"); } }); } } } Service::Activities *Manager::activities() { return self()->m_activities; } Service::Resources *Manager::resources() { return self()->m_resources; } Service::ResourcesLinking *Manager::resourcesLinking() { return self()->m_resourcesLinking; } Service::Features *Manager::features() { return self()->m_features; } } // namespace KActivities #include "moc_manager_p.cpp"