summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMårten Nordheim <[email protected]>2021-10-25 20:23:24 +0200
committerMårten Nordheim <[email protected]>2021-11-04 12:02:25 +0100
commitbd52c1bba6f5a0b7e820596e566146b5cf8a4ee7 (patch)
tree728aa2010288daee21336992428d57e306f22282
parent2148e1f0e6026ad7a87c7eec0362d1250c1f09e9 (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]>
-rw-r--r--src/network/kernel/qnetworkinformation.cpp23
-rw-r--r--src/network/kernel/qnetworkinformation.h5
-rw-r--r--src/network/kernel/qnetworkinformation_p.h11
-rw-r--r--tests/auto/network/kernel/qnetworkinformation/tst_qnetworkinformation.cpp36
-rw-r--r--tests/manual/qnetworkinformation/mainwindow.h12
-rw-r--r--tests/manual/qnetworkinformation/tst_qnetworkinformation.cpp8
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();
}