diff options
Diffstat (limited to 'src/plugins/networkinformation/networkmanager')
5 files changed, 176 insertions, 102 deletions
diff --git a/src/plugins/networkinformation/networkmanager/CMakeLists.txt b/src/plugins/networkinformation/networkmanager/CMakeLists.txt index 5fc69f2d55..9d76dbe7b4 100644 --- a/src/plugins/networkinformation/networkmanager/CMakeLists.txt +++ b/src/plugins/networkinformation/networkmanager/CMakeLists.txt @@ -1,9 +1,13 @@ +# Copyright (C) 2022 The Qt Company Ltd. +# SPDX-License-Identifier: BSD-3-Clause + qt_internal_add_plugin(QNetworkManagerNetworkInformationPlugin OUTPUT_NAME qnetworkmanager CLASS_NAME QNetworkManagerNetworkInformationBackendFactory PLUGIN_TYPE networkinformation DEFAULT_IF LINUX SOURCES + qnetworkmanagernetworkinformationbackend.h qnetworkmanagernetworkinformationbackend.cpp qnetworkmanagerservice.h qnetworkmanagerservice.cpp diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp index 67129af2de..f583d1dcf6 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp @@ -1,9 +1,7 @@ // 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 <QtNetwork/private/qnetworkinformation_p.h> - -#include "qnetworkmanagerservice.h" +#include "qnetworkmanagernetworkinformationbackend.h" #include <QtCore/qglobal.h> #include <QtCore/private/qobject_p.h> @@ -94,46 +92,20 @@ bool isMeteredFromNMMetered(QNetworkManagerInterface::NMMetered metered) case QNetworkManagerInterface::NM_METERED_UNKNOWN: return false; } - Q_UNREACHABLE(); - return false; + Q_UNREACHABLE_RETURN(false); } } // unnamed namespace static QString backendName() { - return QString::fromUtf16(QNetworkInformationBackend::PluginNames - [QNetworkInformationBackend::PluginNamesLinuxIndex]); + return QStringView(QNetworkInformationBackend::PluginNames + [QNetworkInformationBackend::PluginNamesLinuxIndex]).toString(); } -class QNetworkManagerNetworkInformationBackend : public QNetworkInformationBackend +QString QNetworkManagerNetworkInformationBackend::name() const { - Q_OBJECT -public: - QNetworkManagerNetworkInformationBackend(); - ~QNetworkManagerNetworkInformationBackend() = default; - - QString name() const override { return backendName(); } - QNetworkInformation::Features featuresSupported() const override - { - if (!isValid()) - return {}; - return featuresSupportedStatic(); - } - - static QNetworkInformation::Features featuresSupportedStatic() - { - using Feature = QNetworkInformation::Feature; - return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal - | Feature::TransportMedium | Feature::Metered); - } - - bool isValid() const { return iface.isValid(); } - -private: - Q_DISABLE_COPY_MOVE(QNetworkManagerNetworkInformationBackend) - - QNetworkManagerInterface iface; -}; + return backendName(); +} class QNetworkManagerNetworkInformationBackendFactory : public QNetworkInformationBackendFactory { @@ -168,34 +140,42 @@ private: QNetworkManagerNetworkInformationBackend::QNetworkManagerNetworkInformationBackend() { - auto updateReachability = [this](QNetworkManagerInterface::NMState newState) { - setReachability(reachabilityFromNMState(newState)); - }; - updateReachability(iface.state()); - connect(&iface, &QNetworkManagerInterface::stateChanged, this, std::move(updateReachability)); - - auto updateBehindCaptivePortal = [this](QNetworkManagerInterface::NMConnectivityState state) { - const bool behindPortal = (state == QNetworkManagerInterface::NM_CONNECTIVITY_PORTAL); - setBehindCaptivePortal(behindPortal); - }; - updateBehindCaptivePortal(iface.connectivityState()); - connect(&iface, &QNetworkManagerInterface::connectivityChanged, this, - std::move(updateBehindCaptivePortal)); - - auto updateTransportMedium = [this](QNetworkManagerInterface::NMDeviceType newDevice) { - setTransportMedium(transportMediumFromDeviceType(newDevice)); - }; - updateTransportMedium(iface.deviceType()); - connect(&iface, &QNetworkManagerInterface::deviceTypeChanged, this, - std::move(updateTransportMedium)); - - auto updateMetered = [this](QNetworkManagerInterface::NMMetered metered) { - setMetered(isMeteredFromNMMetered(metered)); - }; - updateMetered(iface.meteredState()); - connect(&iface, &QNetworkManagerInterface::meteredChanged, this, std::move(updateMetered)); + if (!iface.isValid()) + return; + iface.setBackend(this); + onStateChanged(iface.state()); + onConnectivityChanged(iface.connectivityState()); + onDeviceTypeChanged(iface.deviceType()); + onMeteredChanged(iface.meteredState()); +} + +void QNetworkManagerNetworkInformationBackend::onStateChanged( + QNetworkManagerInterface::NMState newState) +{ + setReachability(reachabilityFromNMState(newState)); } +void QNetworkManagerNetworkInformationBackend::onConnectivityChanged( + QNetworkManagerInterface::NMConnectivityState connectivityState) +{ + const bool behindPortal = + (connectivityState == QNetworkManagerInterface::NM_CONNECTIVITY_PORTAL); + setBehindCaptivePortal(behindPortal); +} + +void QNetworkManagerNetworkInformationBackend::onDeviceTypeChanged( + QNetworkManagerInterface::NMDeviceType newDevice) +{ + setTransportMedium(transportMediumFromDeviceType(newDevice)); +} + +void QNetworkManagerNetworkInformationBackend::onMeteredChanged( + QNetworkManagerInterface::NMMetered metered) +{ + setMetered(isMeteredFromNMMetered(metered)); +}; + QT_END_NAMESPACE #include "qnetworkmanagernetworkinformationbackend.moc" +#include "moc_qnetworkmanagernetworkinformationbackend.cpp" diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h new file mode 100644 index 0000000000..3b60f0949c --- /dev/null +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.h @@ -0,0 +1,60 @@ +// 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 + +#ifndef QNETWORKMANAGERINFORMATIONBACKEND_H +#define QNETWORKMANAGERINFORMATIONBACKEND_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtNetwork/private/qnetworkinformation_p.h> +#include "qnetworkmanagerservice.h" + +QT_BEGIN_NAMESPACE + +class QNetworkManagerNetworkInformationBackend : public QNetworkInformationBackend +{ + Q_OBJECT +public: + QNetworkManagerNetworkInformationBackend(); + ~QNetworkManagerNetworkInformationBackend() = default; + + QString name() const override; + QNetworkInformation::Features featuresSupported() const override + { + if (!isValid()) + return {}; + return featuresSupportedStatic(); + } + + static QNetworkInformation::Features featuresSupportedStatic() + { + using Feature = QNetworkInformation::Feature; + return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal + | Feature::TransportMedium | Feature::Metered); + } + + bool isValid() const { return iface.isValid(); } + + void onStateChanged(QNetworkManagerInterface::NMState state); + void onConnectivityChanged(QNetworkManagerInterface::NMConnectivityState connectivityState); + void onDeviceTypeChanged(QNetworkManagerInterface::NMDeviceType deviceType); + void onMeteredChanged(QNetworkManagerInterface::NMMetered metered); + +private: + Q_DISABLE_COPY_MOVE(QNetworkManagerNetworkInformationBackend) + + QNetworkManagerInterface iface; +}; + +QT_END_NAMESPACE + +#endif diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp index 3a64c1892c..c055555cac 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp @@ -2,6 +2,7 @@ // 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> @@ -14,21 +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_SERVICE "org.freedesktop.NetworkManager" +#define NM_DBUS_INTERFACE "org.freedesktop.NetworkManager" +#define NM_DBUS_SERVICE NM_DBUS_INTERFACE ""_L1 -#define NM_DBUS_PATH "/org/freedesktop/NetworkManager" -#define NM_DBUS_INTERFACE NM_DBUS_SERVICE -#define NM_CONNECTION_DBUS_INTERFACE NM_DBUS_SERVICE ".Connection.Active" -#define NM_DEVICE_DBUS_INTERFACE NM_DBUS_SERVICE ".Device" +#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(NM_DBUS_SERVICE ""_L1, NM_DBUS_PATH ""_L1, + : QDBusAbstractInterface(NM_DBUS_SERVICE, NM_DBUS_PATH, NM_DBUS_INTERFACE, QDBusConnection::systemBus(), parent) { } @@ -41,45 +61,49 @@ bool QNetworkManagerInterfaceBase::networkManagerAvailable() QNetworkManagerInterface::QNetworkManagerInterface(QObject *parent) : QNetworkManagerInterfaceBase(parent) { - if (!isValid()) + if (!QDBusAbstractInterface::isValid()) return; PropertiesDBusInterface managerPropertiesInterface( - NM_DBUS_SERVICE ""_L1, NM_DBUS_PATH ""_L1, DBUS_PROPERTIES_INTERFACE, + NM_DBUS_SERVICE, NM_DBUS_PATH, DBUS_PROPERTIES_INTERFACE, QDBusConnection::systemBus()); QList<QVariant> argumentList; - argumentList << NM_DBUS_INTERFACE ""_L1; + argumentList << NM_DBUS_SERVICE; QDBusPendingReply<QVariantMap> propsReply = managerPropertiesInterface.callWithArgumentList( QDBus::Block, "GetAll"_L1, argumentList); - if (!propsReply.isError()) { - propertyMap = propsReply.value(); - } else { - qWarning() << "propsReply" << propsReply.error().message(); + 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(NM_DBUS_SERVICE ""_L1, NM_DBUS_PATH ""_L1, - DBUS_PROPERTIES_INTERFACE""_L1, "PropertiesChanged"_L1, this, - SLOT(setProperties(QString, QMap<QString, QVariant>, QList<QString>))); + 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(NM_DBUS_SERVICE ""_L1, NM_DBUS_PATH ""_L1, - DBUS_PROPERTIES_INTERFACE ""_L1, "PropertiesChanged"_L1, this, - SLOT(setProperties(QString, QMap<QString, QVariant>, QList<QString>))); + 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; } @@ -102,7 +126,7 @@ static std::optional<QDBusInterface> getPrimaryDevice(const QDBusObjectPath &dev std::optional<QDBusObjectPath> QNetworkManagerInterface::primaryConnectionDevicePath() const { - auto it = propertyMap.constFind(u"PrimaryConnection"_s); + auto it = propertyMap.constFind(primaryConnectionKey()); if (it != propertyMap.cend()) return it->value<QDBusObjectPath>(); return std::nullopt; @@ -150,6 +174,11 @@ auto QNetworkManagerInterface::extractDeviceMetered(const QDBusObjectPath &devic 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) @@ -169,18 +198,18 @@ void QNetworkManagerInterface::setProperties(const QString &interfaceName, } if (valueChanged) { - if (i.key() == "State"_L1) { + if (i.key() == stateKey()) { quint32 state = i.value().toUInt(); - Q_EMIT stateChanged(static_cast<NMState>(state)); - } else if (i.key() == "Connectivity"_L1) { + backend->onStateChanged(static_cast<NMState>(state)); + } else if (i.key() == connectivityKey()) { quint32 state = i.value().toUInt(); - Q_EMIT connectivityChanged(static_cast<NMConnectivityState>(state)); - } else if (i.key() == "PrimaryConnection"_L1) { + backend->onConnectivityChanged(static_cast<NMConnectivityState>(state)); + } else if (i.key() == primaryConnectionKey()) { const QDBusObjectPath devicePath = i->value<QDBusObjectPath>(); - Q_EMIT deviceTypeChanged(extractDeviceType(devicePath)); - Q_EMIT meteredChanged(extractDeviceMetered(devicePath)); + backend->onDeviceTypeChanged(extractDeviceType(devicePath)); + backend->onMeteredChanged(extractDeviceMetered(devicePath)); } else if (i.key() == "Metered"_L1) { - Q_EMIT meteredChanged(static_cast<NMMetered>(i->toUInt())); + backend->onMeteredChanged(static_cast<NMMetered>(i->toUInt())); } } } diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h index 30e7945d28..5201e8485b 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h @@ -39,6 +39,7 @@ enum NMDeviceState { QT_BEGIN_NAMESPACE class QDBusObjectPath; +class QNetworkManagerNetworkInformationBackend; // This tiny class exists for the purpose of seeing if NetworkManager is available without // initializing everything the derived/full class needs. @@ -46,7 +47,7 @@ class QNetworkManagerInterfaceBase : public QDBusAbstractInterface { Q_OBJECT public: - QNetworkManagerInterfaceBase(QObject *parent = nullptr); + explicit QNetworkManagerInterfaceBase(QObject *parent = nullptr); ~QNetworkManagerInterfaceBase() = default; static bool networkManagerAvailable(); @@ -128,19 +129,17 @@ public: NM_METERED_GUESS_NO, }; - QNetworkManagerInterface(QObject *parent = nullptr); + explicit QNetworkManagerInterface(QObject *parent = nullptr); ~QNetworkManagerInterface(); + void setBackend(QNetworkManagerNetworkInformationBackend *ourBackend); + NMState state() const; NMConnectivityState connectivityState() const; NMDeviceType deviceType() const; NMMetered meteredState() const; -Q_SIGNALS: - void stateChanged(NMState); - void connectivityChanged(NMConnectivityState); - void deviceTypeChanged(NMDeviceType); - void meteredChanged(NMMetered); + bool isValid() const { return QDBusAbstractInterface::isValid() && validDBusConnection; } private Q_SLOTS: void setProperties(const QString &interfaceName, const QMap<QString, QVariant> &map, @@ -155,13 +154,15 @@ private: std::optional<QDBusObjectPath> primaryConnectionDevicePath() const; QVariantMap propertyMap; + QNetworkManagerNetworkInformationBackend *backend = nullptr; + bool validDBusConnection = true; }; class PropertiesDBusInterface : public QDBusAbstractInterface { public: PropertiesDBusInterface(const QString &service, const QString &path, const QString &interface, - const QDBusConnection &connection, QObject *parent = 0) + const QDBusConnection &connection, QObject *parent = nullptr) : QDBusAbstractInterface(service, path, interface.toLatin1().data(), connection, parent) { } |