diff options
Diffstat (limited to 'src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp')
-rw-r--r-- | src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp | 224 |
1 files changed, 151 insertions, 73 deletions
diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp index 764507fd4b..c055555cac 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp @@ -1,43 +1,8 @@ -/**************************************************************************** -** -** Copyright (C) 2021 The Qt Company Ltd. -** Contact: https://www.qt.io/licensing/ -** -** This file is part of the plugins of the Qt Toolkit. -** -** $QT_BEGIN_LICENSE:LGPL$ -** Commercial License Usage -** Licensees holding valid commercial Qt licenses may use this file in -** accordance with the commercial license agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and The Qt Company. For licensing terms -** and conditions see https://www.qt.io/terms-conditions. For further -** information use the contact form at https://www.qt.io/contact-us. -** -** GNU Lesser General Public License Usage -** Alternatively, this file may be used under the terms of the GNU Lesser -** General Public License version 3 as published by the Free Software -** Foundation and appearing in the file LICENSE.LGPL3 included in the -** packaging of this file. Please review the following information to -** ensure the GNU Lesser General Public License version 3 requirements -** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. -** -** GNU General Public License Usage -** Alternatively, this file may be used under the terms of the GNU -** General Public License version 2.0 or (at your option) the GNU General -** Public license version 3 or any later version approved by the KDE Free -** Qt Foundation. The licenses are as published by the Free Software -** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 -** included in the packaging of this file. Please review the following -** information to ensure the GNU General Public License requirements will -** be met: https://www.gnu.org/licenses/gpl-2.0.html and -** https://www.gnu.org/licenses/gpl-3.0.html. -** -** $QT_END_LICENSE$ -** -****************************************************************************/ +// Copyright (C) 2021 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qnetworkmanagerservice.h" +#include "qnetworkmanagernetworkinformationbackend.h" #include <QObject> #include <QList> @@ -50,12 +15,40 @@ #include <QtDBus/QDBusObjectPath> #include <QtDBus/QDBusPendingCall> -#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties" +#define DBUS_PROPERTIES_INTERFACE "org.freedesktop.DBus.Properties"_L1 + +#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" +#define NM_DBUS_SERVICE NM_DBUS_INTERFACE ""_L1 + +#define NM_DBUS_PATH "/org/freedesktop/NetworkManager"_L1 +#define NM_CONNECTION_DBUS_INTERFACE NM_DBUS_SERVICE ".Connection.Active"_L1 +#define NM_DEVICE_DBUS_INTERFACE NM_DBUS_SERVICE ".Device"_L1 QT_BEGIN_NAMESPACE +using namespace Qt::StringLiterals; + +namespace { +constexpr QLatin1StringView propertiesChangedKey = "PropertiesChanged"_L1; +const QString &stateKey() +{ + static auto key = u"State"_s; + return key; +} +const QString &connectivityKey() +{ + static auto key = u"Connectivity"_s; + return key; +} +const QString &primaryConnectionKey() +{ + static auto key = u"PrimaryConnection"_s; + return key; +} +} + QNetworkManagerInterfaceBase::QNetworkManagerInterfaceBase(QObject *parent) - : QDBusAbstractInterface(QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), + : QDBusAbstractInterface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, QDBusConnection::systemBus(), parent) { } @@ -68,75 +61,160 @@ bool QNetworkManagerInterfaceBase::networkManagerAvailable() QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent) : QNetworkManagerInterfaceBase(parent) { - if (!isValid()) + if (!QDBusAbstractInterface::isValid()) return; PropertiesDBusInterface managerPropertiesInterface( - QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), DBUS_PROPERTIES_INTERFACE, + NM_DBUS_SERVICE, NM_DBUS_PATH, DBUS_PROPERTIES_INTERFACE, QDBusConnection::systemBus()); QList<QVariant> argumentList; - argumentList << QLatin1String(NM_DBUS_INTERFACE); + argumentList << NM_DBUS_SERVICE; QDBusPendingReply<QVariantMap> propsReply = managerPropertiesInterface.callWithArgumentList( - QDBus::Block, QLatin1String("GetAll"), argumentList); - if (!propsReply.isError()) { - propertyMap = propsReply.value(); - } else { - qWarning() << "propsReply" << propsReply.error().message(); + QDBus::Block, "GetAll"_L1, argumentList); + if (propsReply.isError()) { + validDBusConnection = false; + if (auto error = propsReply.error(); error.type() != QDBusError::AccessDenied) + qWarning() << "Failed to query NetworkManager properties:" << error.message(); + return; } + propertyMap = propsReply.value(); - QDBusConnection::systemBus().connect( - QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), - QLatin1String(NM_DBUS_INTERFACE), QLatin1String("PropertiesChanged"), this, - SLOT(setProperties(QMap<QString, QVariant>))); + validDBusConnection = QDBusConnection::systemBus().connect(NM_DBUS_SERVICE, NM_DBUS_PATH, + DBUS_PROPERTIES_INTERFACE, propertiesChangedKey, this, + SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>))); } QNetworkManagerInterface::~QNetworkManagerInterface() { - QDBusConnection::systemBus().disconnect( - QLatin1String(NM_DBUS_SERVICE), QLatin1String(NM_DBUS_PATH), - QLatin1String(NM_DBUS_INTERFACE), QLatin1String("PropertiesChanged"), this, - SLOT(setProperties(QMap<QString, QVariant>))); + QDBusConnection::systemBus().disconnect(NM_DBUS_SERVICE, NM_DBUS_PATH, + DBUS_PROPERTIES_INTERFACE, propertiesChangedKey, this, + SLOT(setProperties(QString,QMap<QString,QVariant>,QList<QString>))); } QNetworkManagerInterface::NMState QNetworkManagerInterface::state() const { - if (propertyMap.contains("State")) - return static_cast<QNetworkManagerInterface::NMState>(propertyMap.value("State").toUInt()); + auto it = propertyMap.constFind(stateKey()); + if (it != propertyMap.cend()) + return static_cast<QNetworkManagerInterface::NMState>(it->toUInt()); return QNetworkManagerInterface::NM_STATE_UNKNOWN; } QNetworkManagerInterface::NMConnectivityState QNetworkManagerInterface::connectivityState() const { - if (propertyMap.contains("Connectivity")) - return static_cast<NMConnectivityState>(propertyMap.value("Connectivity").toUInt()); + auto it = propertyMap.constFind(connectivityKey()); + if (it != propertyMap.cend()) + return static_cast<NMConnectivityState>(it->toUInt()); return QNetworkManagerInterface::NM_CONNECTIVITY_UNKNOWN; } -void QNetworkManagerInterface::setProperties(const QMap<QString, QVariant> &map) +static std::optional<QDBusInterface> getPrimaryDevice(const QDBusObjectPath &devicePath) +{ + const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(), + NM_CONNECTION_DBUS_INTERFACE, QDBusConnection::systemBus()); + if (!connection.isValid()) + return std::nullopt; + + const auto devicePaths = connection.property("Devices").value<QList<QDBusObjectPath>>(); + if (devicePaths.isEmpty()) + return std::nullopt; + + const QDBusObjectPath primaryDevicePath = devicePaths.front(); + return std::make_optional<QDBusInterface>(NM_DBUS_SERVICE, primaryDevicePath.path(), + NM_DEVICE_DBUS_INTERFACE, + QDBusConnection::systemBus()); +} + +std::optional<QDBusObjectPath> QNetworkManagerInterface::primaryConnectionDevicePath() const +{ + auto it = propertyMap.constFind(primaryConnectionKey()); + if (it != propertyMap.cend()) + return it->value<QDBusObjectPath>(); + return std::nullopt; +} + +auto QNetworkManagerInterface::deviceType() const -> NMDeviceType { + if (const auto path = primaryConnectionDevicePath()) + return extractDeviceType(*path); + return NM_DEVICE_TYPE_UNKNOWN; +} + +auto QNetworkManagerInterface::meteredState() const -> NMMetered +{ + if (const auto path = primaryConnectionDevicePath()) + return extractDeviceMetered(*path); + return NM_METERED_UNKNOWN; +} + +auto QNetworkManagerInterface::extractDeviceType(const QDBusObjectPath &devicePath) const + -> NMDeviceType +{ + const auto primaryDevice = getPrimaryDevice(devicePath); + if (!primaryDevice) + return NM_DEVICE_TYPE_UNKNOWN; + if (!primaryDevice->isValid()) + return NM_DEVICE_TYPE_UNKNOWN; + const QVariant deviceType = primaryDevice->property("DeviceType"); + if (!deviceType.isValid()) + return NM_DEVICE_TYPE_UNKNOWN; + return static_cast<NMDeviceType>(deviceType.toUInt()); +} + +auto QNetworkManagerInterface::extractDeviceMetered(const QDBusObjectPath &devicePath) const + -> NMMetered +{ + const auto primaryDevice = getPrimaryDevice(devicePath); + if (!primaryDevice) + return NM_METERED_UNKNOWN; + if (!primaryDevice->isValid()) + return NM_METERED_UNKNOWN; + const QVariant metered = primaryDevice->property("Metered"); + if (!metered.isValid()) + return NM_METERED_UNKNOWN; + return static_cast<NMMetered>(metered.toUInt()); +} + +void QNetworkManagerInterface::setBackend(QNetworkManagerNetworkInformationBackend *ourBackend) +{ + backend = ourBackend; +} + +void QNetworkManagerInterface::setProperties(const QString &interfaceName, + const QMap<QString, QVariant> &map, + const QStringList &invalidatedProperties) +{ + Q_UNUSED(interfaceName); + Q_UNUSED(invalidatedProperties); + for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) { - const bool isState = i.key() == QLatin1String("State"); - const bool isConnectivity = i.key() == QLatin1String("Connectivity"); - bool stateUpdate = isState; - bool connectivityUpdate = isConnectivity; + bool valueChanged = true; auto it = propertyMap.lowerBound(i.key()); if (it != propertyMap.end() && it.key() == i.key()) { - stateUpdate &= (it.value() != i.value()); - connectivityUpdate &= (it.value() != i.value()); + valueChanged = (it.value() != i.value()); *it = *i; } else { propertyMap.insert(it, i.key(), i.value()); } - if (stateUpdate) { - quint32 state = i.value().toUInt(); - Q_EMIT stateChanged(static_cast<NMState>(state)); - } else if (connectivityUpdate) { - quint32 state = i.value().toUInt(); - Q_EMIT connectivityChanged(static_cast<NMConnectivityState>(state)); + if (valueChanged) { + if (i.key() == stateKey()) { + quint32 state = i.value().toUInt(); + backend->onStateChanged(static_cast<NMState>(state)); + } else if (i.key() == connectivityKey()) { + quint32 state = i.value().toUInt(); + backend->onConnectivityChanged(static_cast<NMConnectivityState>(state)); + } else if (i.key() == primaryConnectionKey()) { + const QDBusObjectPath devicePath = i->value<QDBusObjectPath>(); + backend->onDeviceTypeChanged(extractDeviceType(devicePath)); + backend->onMeteredChanged(extractDeviceMetered(devicePath)); + } else if (i.key() == "Metered"_L1) { + backend->onMeteredChanged(static_cast<NMMetered>(i->toUInt())); + } } } } QT_END_NAMESPACE + +#include "moc_qnetworkmanagerservice.cpp" |