diff options
author | Mårten Nordheim <[email protected]> | 2021-10-25 20:23:24 +0200 |
---|---|---|
committer | Mårten Nordheim <[email protected]> | 2021-11-04 12:02:25 +0100 |
commit | bd52c1bba6f5a0b7e820596e566146b5cf8a4ee7 (patch) | |
tree | 728aa2010288daee21336992428d57e306f22282 | |
parent | 2148e1f0e6026ad7a87c7eec0362d1250c1f09e9 (diff) |
QNI: Add API to check if connection is metered
This may be a useful factor in deciding whether or not you should
perform communications over the network which are not purely essential.
For example, if you have a logging mechanism you can delay uploading
them until you are no longer on a metered network.
Task-number: QTBUG-91024
Change-Id: I19d32f031a3893512dc440914133678004987fb1
Reviewed-by: Paul Wicking <[email protected]>
Reviewed-by: Marc Mutz <[email protected]>
Reviewed-by: Edward Welbourne <[email protected]>
6 files changed, 89 insertions, 6 deletions
diff --git a/src/network/kernel/qnetworkinformation.cpp b/src/network/kernel/qnetworkinformation.cpp index 5d889ac574d..034a277b3cf 100644 --- a/src/network/kernel/qnetworkinformation.cpp +++ b/src/network/kernel/qnetworkinformation.cpp @@ -457,6 +457,11 @@ QNetworkInformationBackendFactory::~QNetworkInformationBackendFactory() property will provide useful results. Otherwise it will always return \c{TransportMedium::Unknown}. See also QNetworkInformation::TransportMedium. + + \value Metered + If the plugin supports this feature then the \c isMetered + property will provide useful results. Otherwise it will always return + \c{false}. */ /*! @@ -520,6 +525,8 @@ QNetworkInformation::QNetworkInformation(QNetworkInformationBackend *backend) &QNetworkInformation::isBehindCaptivePortalChanged); connect(backend, &QNetworkInformationBackend::transportMediumChanged, this, &QNetworkInformation::transportMediumChanged); + connect(backend, &QNetworkInformationBackend::isMeteredChanged, this, + &QNetworkInformation::isMeteredChanged); } /*! @@ -580,6 +587,22 @@ QNetworkInformation::TransportMedium QNetworkInformation::transportMedium() cons } /*! + \property QNetworkInformation::isMetered + \brief Check if the current connection is metered + \since 6.3 + + This property returns whether the current connection is (known to be) + metered or not. You can use this as a guiding factor to decide whether your + application should perform certain network requests or uploads. + For instance, you may not want to upload logs or diagnostics while this + property is \c true. +*/ +bool QNetworkInformation::isMetered() const +{ + return d_func()->backend->isMetered(); +} + +/*! Returns the name of the currently loaded backend. */ QString QNetworkInformation::backendName() const diff --git a/src/network/kernel/qnetworkinformation.h b/src/network/kernel/qnetworkinformation.h index e280894feff..9b09fcee982 100644 --- a/src/network/kernel/qnetworkinformation.h +++ b/src/network/kernel/qnetworkinformation.h @@ -58,6 +58,7 @@ class Q_NETWORK_EXPORT QNetworkInformation : public QObject Q_PROPERTY(bool isBehindCaptivePortal READ isBehindCaptivePortal NOTIFY isBehindCaptivePortalChanged) Q_PROPERTY(TransportMedium transportMedium READ transportMedium NOTIFY transportMediumChanged) + Q_PROPERTY(bool isMetered READ isMetered NOTIFY isMeteredChanged) public: enum class Reachability { Unknown, @@ -81,6 +82,7 @@ public: Reachability = 0x1, CaptivePortal = 0x2, TransportMedium = 0x4, + Metered = 0x8, }; Q_DECLARE_FLAGS(Features, Feature) Q_FLAG(Features) @@ -91,6 +93,8 @@ public: TransportMedium transportMedium() const; + bool isMetered() const; + QString backendName() const; bool supports(Features features) const; @@ -106,6 +110,7 @@ Q_SIGNALS: void reachabilityChanged(Reachability newReachability); void isBehindCaptivePortalChanged(bool state); void transportMediumChanged(TransportMedium current); + void isMeteredChanged(bool isMetered); private: friend struct QNetworkInformationDeleter; diff --git a/src/network/kernel/qnetworkinformation_p.h b/src/network/kernel/qnetworkinformation_p.h index 3493de3b440..36084b8e44f 100644 --- a/src/network/kernel/qnetworkinformation_p.h +++ b/src/network/kernel/qnetworkinformation_p.h @@ -87,11 +87,13 @@ public: Reachability reachability() const { return m_reachability; } bool behindCaptivePortal() const { return m_behindCaptivePortal; } TransportMedium transportMedium() const { return m_transportMedium; } + bool isMetered() const { return m_metered; } Q_SIGNALS: void reachabilityChanged(Reachability reachability); void behindCaptivePortalChanged(bool behindPortal); void transportMediumChanged(TransportMedium medium); + void isMeteredChanged(bool isMetered); protected: void setReachability(QNetworkInformation::Reachability reachability) @@ -118,10 +120,19 @@ protected: } } + void setMetered(bool isMetered) + { + if (m_metered != isMetered) { + m_metered = isMetered; + emit isMeteredChanged(isMetered); + } + } + private: Reachability m_reachability = Reachability::Unknown; TransportMedium m_transportMedium = TransportMedium::Unknown; bool m_behindCaptivePortal = false; + bool m_metered = false; Q_DISABLE_COPY_MOVE(QNetworkInformationBackend) friend class QNetworkInformation; diff --git a/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp b/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp index b78983ae401..e37db514e3e 100644 --- a/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp +++ b/tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp @@ -29,6 +29,7 @@ #include <QtNetwork/private/qnetworkinformation_p.h> #include <QtNetwork/qnetworkinformation.h> #include <QtTest/qtest.h> +#include <QtTest/qsignalspy.h> #include <limits> #include <memory> @@ -43,6 +44,7 @@ private slots: void reachability(); void behindCaptivePortal(); void transportMedium(); + void isMetered(); void cleanupTestCase(); private: @@ -88,11 +90,18 @@ public: instance->setTransportMedium(medium); } + static void setNewMetered(bool metered) + { + Q_ASSERT(instance); + instance->setMetered(metered); + } + static QNetworkInformation::Features featuresSupportedStatic() { return { QNetworkInformation::Feature::Reachability | QNetworkInformation::Feature::CaptivePortal - | QNetworkInformation::Feature::TransportMedium }; + | QNetworkInformation::Feature::TransportMedium + | QNetworkInformation::Feature::Metered }; } private: @@ -144,9 +153,10 @@ void tst_QNetworkInformation::supportedFeatures() { auto info = QNetworkInformation::instance(); - auto allFeatures = QNetworkInformation::Features( - QNetworkInformation::Feature::CaptivePortal | QNetworkInformation::Feature::Reachability - | QNetworkInformation::Feature::TransportMedium); + auto allFeatures = QNetworkInformation::Features(QNetworkInformation::Feature::CaptivePortal + | QNetworkInformation::Feature::Reachability + | QNetworkInformation::Feature::TransportMedium + | QNetworkInformation::Feature::Metered); QCOMPARE(info->supportedFeatures(), allFeatures); @@ -154,6 +164,7 @@ void tst_QNetworkInformation::supportedFeatures() QVERIFY(info->supports(QNetworkInformation::Feature::CaptivePortal)); QVERIFY(info->supports(QNetworkInformation::Feature::Reachability)); QVERIFY(info->supports(QNetworkInformation::Feature::TransportMedium)); + QVERIFY(info->supports(QNetworkInformation::Feature::Metered)); } void tst_QNetworkInformation::reachability() @@ -248,5 +259,22 @@ void tst_QNetworkInformation::transportMedium() QVERIFY(!signalEmitted); } +void tst_QNetworkInformation::isMetered() +{ + auto info = QNetworkInformation::instance(); + + QSignalSpy spy(info, &QNetworkInformation::isMeteredChanged); + QVERIFY(!info->isMetered()); + MockBackend::setNewMetered(true); + QCOMPARE(spy.count(), 1); + QVERIFY(info->isMetered()); + QVERIFY(spy[0][0].toBool()); + spy.clear(); + + // Set the same value again, signal should not be emitted again + MockBackend::setNewMetered(true); + QCOMPARE(spy.count(), 0); +} + QTEST_MAIN(tst_QNetworkInformation); #include "tst_qnetworkinformation.moc" diff --git a/tests/manual/qnetworkinformation/mainwindow.h b/tests/manual/qnetworkinformation/mainwindow.h index 4ecc721b817..0426bc37142 100644 --- a/tests/manual/qnetworkinformation/mainwindow.h +++ b/tests/manual/qnetworkinformation/mainwindow.h @@ -74,13 +74,20 @@ public slots: updateText(); } + void updateMetered(bool newValue) + { + metered = newValue; + updateText(); + } + private: void updateText() { QString str = - QLatin1String("Reachability: %1\nBehind captive portal: %2\nTransport medium: %3") + QLatin1String("Reachability: %1\nBehind captive portal: %2\nTransport medium: %3" + "\nMetered: %4") .arg(enumToString(reachability), QStringView(captive ? u"true" : u"false"), - enumToString(transportMedium)); + enumToString(transportMedium), metered ? u"true" : u"false"); label->setText(str); } @@ -88,6 +95,7 @@ private: Reachability reachability = Reachability::Unknown; TransportMedium transportMedium = TransportMedium::Unknown; bool captive = false; + bool metered = false; }; #endif diff --git a/tests/manual/qnetworkinformation/tst_qnetworkinformation.cpp b/tests/manual/qnetworkinformation/tst_qnetworkinformation.cpp index 8cac9408749..fc34a36c3cd 100644 --- a/tests/manual/qnetworkinformation/tst_qnetworkinformation.cpp +++ b/tests/manual/qnetworkinformation/tst_qnetworkinformation.cpp @@ -70,6 +70,11 @@ int main(int argc, char **argv) qDebug() << "Updated, current transport medium:" << newMedium; }); + QObject::connect(info, &QNetworkInformation::isMeteredChanged, + [](bool metered) { + qDebug() << "Updated, metered:" << metered; + }); + #ifdef MOBILE // Some extra connections to update the window if we're on mobile QObject::connect(info, &QNetworkInformation::reachabilityChanged, &window, @@ -78,11 +83,14 @@ int main(int argc, char **argv) &MainWindow::updateCaptiveState); QObject::connect(info, &QNetworkInformation::transportMediumChanged, &window, &MainWindow::updateTransportMedium); + QObject::connect(info, &QNetworkInformation::isMeteredChanged, &window, + &MainWindow::updateMetered); #endif qDebug() << "Initial reachability:" << info->reachability(); qDebug() << "Behind captive portal:" << info->isBehindCaptivePortal(); qDebug() << "Transport medium:" << info->transportMedium(); + qDebug() << "Is metered:" << info->isMetered(); return app.exec(); } |