QNI: networkmanager support for the isMetered API

Task-number: QTBUG-91024
Change-Id: I25ac05adbcbfa92a98fe1e9db9ac931e5c340fcd
Reviewed-by: Marc Mutz <marc.mutz@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
bb10
Mårten Nordheim 2021-10-25 20:23:24 +02:00
parent 58b37f5908
commit 33df48f957
3 changed files with 79 additions and 15 deletions

View File

@ -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

View File

@ -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<QList<QDBusObjectPath>>();
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::meteredState() const -> NMMetered
{
auto it = propertyMap.constFind(u"PrimaryConnection"_qs);
if (it != propertyMap.cend())
return extractDeviceMetered(it->value<QDBusObjectPath>());
return NM_METERED_UNKNOWN;
}
auto QNetworkManagerInterface::extractDeviceType(QDBusObjectPath devicePath) const -> NMDeviceType
{
const QDBusInterface connection(NM_DBUS_SERVICE, devicePath.path(),
NM_CONNECTION_DBUS_INTERFACE, QDBusConnection::systemBus());
if (!connection.isValid())
QDBusInterface primaryDevice = getPrimaryDevice(devicePath);
if (!primaryDevice.isValid())
return NM_DEVICE_TYPE_UNKNOWN;
const auto devicePaths = connection.property("Devices").value<QList<QDBusObjectPath>>();
if (devicePaths.isEmpty())
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<NMDeviceType>(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<NMMetered>(metered.toUInt());
}
void QNetworkManagerInterface::setProperties(const QString &interfaceName,
const QMap<QString, QVariant> &map,
const QStringList &invalidatedProperties)
@ -173,7 +200,11 @@ void QNetworkManagerInterface::setProperties(const QString &interfaceName,
quint32 state = i.value().toUInt();
Q_EMIT connectivityChanged(static_cast<NMConnectivityState>(state));
} else if (i.key() == QLatin1String("PrimaryConnection")) {
Q_EMIT deviceTypeChanged(extractDeviceType(i->value<QDBusObjectPath>()));
const QDBusObjectPath devicePath = i->value<QDBusObjectPath>();
Q_EMIT deviceTypeChanged(extractDeviceType(devicePath));
Q_EMIT meteredChanged(extractDeviceMetered(devicePath));
} else if (i.key() == QLatin1String("Metered")) {
Q_EMIT meteredChanged(static_cast<NMMetered>(i->toUInt()));
}
}
}

View File

@ -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<QString, QVariant> &map,
@ -171,6 +182,7 @@ private:
Q_DISABLE_COPY_MOVE(QNetworkManagerInterface)
NMDeviceType extractDeviceType(QDBusObjectPath devicePath) const;
NMMetered extractDeviceMetered(const QDBusObjectPath &devicePath) const;
QVariantMap propertyMap;
};