From 33df48f957eafef356f0a6912c6541feada1db98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?M=C3=A5rten=20Nordheim?= Date: Mon, 25 Oct 2021 20:23:24 +0200 Subject: QNI: networkmanager support for the isMetered API Task-number: QTBUG-91024 Change-Id: I25ac05adbcbfa92a98fe1e9db9ac931e5c340fcd Reviewed-by: Marc Mutz Reviewed-by: Edward Welbourne --- .../qnetworkmanagernetworkinformationbackend.cpp | 23 ++++++++- .../networkmanager/qnetworkmanagerservice.cpp | 59 +++++++++++++++++----- .../networkmanager/qnetworkmanagerservice.h | 12 +++++ 3 files changed, 79 insertions(+), 15 deletions(-) (limited to 'src/plugins/networkinformation') diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp index 5e2f4b61e6..ac16ad4b8d 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagernetworkinformationbackend.cpp @@ -118,7 +118,22 @@ transportMediumFromDeviceType(QNetworkManagerInterface::NMDeviceType type) // entries added in NetworkManager that isn't listed here return QNetworkInformation::TransportMedium::Unknown; } + +bool isMeteredFromNMMetered(QNetworkManagerInterface::NMMetered metered) +{ + switch (metered) { + case QNetworkManagerInterface::NM_METERED_YES: + case QNetworkManagerInterface::NM_METERED_GUESS_YES: + return true; + case QNetworkManagerInterface::NM_METERED_NO: + case QNetworkManagerInterface::NM_METERED_GUESS_NO: + case QNetworkManagerInterface::NM_METERED_UNKNOWN: + return false; + } + Q_UNREACHABLE(); + return false; } +} // unnamed namespace static QString backendName() { @@ -145,7 +160,7 @@ public: { using Feature = QNetworkInformation::Feature; return QNetworkInformation::Features(Feature::Reachability | Feature::CaptivePortal - | Feature::TransportMedium); + | Feature::TransportMedium | Feature::Metered); } bool isValid() const { return iface.isValid(); } @@ -215,6 +230,12 @@ QNetworkManagerNetworkInformationBackend::QNetworkManagerNetworkInformationBacke [this](NMDeviceType newDevice) { setTransportMedium(transportMediumFromDeviceType(newDevice)); }); + + auto updateMetered = [this](QNetworkManagerInterface::NMMetered metered) { + setMetered(isMeteredFromNMMetered(metered)); + }; + updateMetered(iface.meteredState()); + connect(&iface, &QNetworkManagerInterface::meteredChanged, this, std::move(updateMetered)); } QT_END_NAMESPACE diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp index 82a797ab87..dfc09b4637 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.cpp @@ -119,7 +119,23 @@ QNetworkManagerInterface::NMConnectivityState QNetworkManagerInterface::connecti return QNetworkManagerInterface::NM_CONNECTIVITY_UNKNOWN; } -QNetworkManagerInterface::NMDeviceType QNetworkManagerInterface::deviceType() const +static QDBusInterface getPrimaryDevice(const QDBusObjectPath &devicePath) +{ + const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(), + NM_CONNECTION_DBUS_INTERFACE, QDBusConnection::systemBus()); + if (!connection.isValid()) + return QDBusInterface({}, {}); + + const auto devicePaths = connection.property("Devices").value>(); + if (devicePaths.isEmpty()) + return QDBusInterface({}, {}); + + const QDBusObjectPath primaryDevicePath = devicePaths.front(); + return QDBusInterface(NM_DBUS_SERVICE, primaryDevicePath.path(), NM_DEVICE_DBUS_INTERFACE, + QDBusConnection::systemBus()); +} + +auto QNetworkManagerInterface::deviceType() const -> NMDeviceType { auto it = propertyMap.constFind("PrimaryConnection"); if (it != propertyMap.cend()) @@ -127,26 +143,37 @@ QNetworkManagerInterface::NMDeviceType QNetworkManagerInterface::deviceType() co return NM_DEVICE_TYPE_UNKNOWN; } -auto QNetworkManagerInterface::extractDeviceType(QDBusObjectPath devicePath) const -> NMDeviceType +auto QNetworkManagerInterface::meteredState() const -> NMMetered { - const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(), - NM_CONNECTION_DBUS_INTERFACE, QDBusConnection::systemBus()); - if (!connection.isValid()) - return NM_DEVICE_TYPE_UNKNOWN; + auto it = propertyMap.constFind(u"PrimaryConnection"_qs); + if (it != propertyMap.cend()) + return extractDeviceMetered(it->value()); + return NM_METERED_UNKNOWN; +} - const auto devicePaths = connection.property("Devices").value>(); - if (devicePaths.isEmpty()) +auto QNetworkManagerInterface::extractDeviceType(QDBusObjectPath devicePath) const -> NMDeviceType +{ + QDBusInterface primaryDevice = getPrimaryDevice(devicePath); + if (!primaryDevice.isValid()) return NM_DEVICE_TYPE_UNKNOWN; - - const QDBusObjectPath primaryDevicePath = devicePaths.front(); - const QDBusInterface device(NM_DBUS_SERVICE, primaryDevicePath.path(), NM_DEVICE_DBUS_INTERFACE, - QDBusConnection::systemBus()); - const QVariant deviceType = device.property("DeviceType"); + const QVariant deviceType = primaryDevice.property("DeviceType"); if (!deviceType.isValid()) return NM_DEVICE_TYPE_UNKNOWN; return static_cast(deviceType.toUInt()); } +auto QNetworkManagerInterface::extractDeviceMetered(const QDBusObjectPath &devicePath) const + -> NMMetered +{ + QDBusInterface primaryDevice = getPrimaryDevice(devicePath); + if (!primaryDevice.isValid()) + return NM_METERED_UNKNOWN; + const QVariant metered = primaryDevice.property("Metered"); + if (!metered.isValid()) + return NM_METERED_UNKNOWN; + return static_cast(metered.toUInt()); +} + void QNetworkManagerInterface::setProperties(const QString &interfaceName, const QMap &map, const QStringList &invalidatedProperties) @@ -173,7 +200,11 @@ void QNetworkManagerInterface::setProperties(const QString &interfaceName, quint32 state = i.value().toUInt(); Q_EMIT connectivityChanged(static_cast(state)); } else if (i.key() == QLatin1String("PrimaryConnection")) { - Q_EMIT deviceTypeChanged(extractDeviceType(i->value())); + const QDBusObjectPath devicePath = i->value(); + Q_EMIT deviceTypeChanged(extractDeviceType(devicePath)); + Q_EMIT meteredChanged(extractDeviceMetered(devicePath)); + } else if (i.key() == QLatin1String("Metered")) { + Q_EMIT meteredChanged(static_cast(i->toUInt())); } } } diff --git a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h index 93fa23870f..48073fd1a5 100644 --- a/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h +++ b/src/plugins/networkinformation/networkmanager/qnetworkmanagerservice.h @@ -150,6 +150,15 @@ public: NM_DEVICE_TYPE_WIFI_P2P = 30, NM_DEVICE_TYPE_VRF = 31, }; + // Matches 'NMMetered' from + // https://developer-old.gnome.org/NetworkManager/stable/nm-dbus-types.html#NMMetered + enum NMMetered { + NM_METERED_UNKNOWN, + NM_METERED_YES, + NM_METERED_NO, + NM_METERED_GUESS_YES, + NM_METERED_GUESS_NO, + }; QNetworkManagerInterface(QObject *parent = nullptr); ~QNetworkManagerInterface(); @@ -157,11 +166,13 @@ public: 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); private Q_SLOTS: void setProperties(const QString &interfaceName, const QMap &map, @@ -171,6 +182,7 @@ private: Q_DISABLE_COPY_MOVE(QNetworkManagerInterface) NMDeviceType extractDeviceType(QDBusObjectPath devicePath) const; + NMMetered extractDeviceMetered(const QDBusObjectPath &devicePath) const; QVariantMap propertyMap; }; -- cgit v1.2.3