QNetworkInformation: Behind captive portal

This patch adds the API, with no supporting backends

Task-number: QTBUG-93848
Change-Id: I50454717f928819e1b990df91872675e842f9987
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Reviewed-by: Timur Pocheptsov <timur.pocheptsov@qt.io>
This commit is contained in:
Mårten Nordheim 2021-05-21 16:36:57 +02:00
parent 69982182a3
commit da955aadf5
5 changed files with 103 additions and 2 deletions

View File

@ -470,6 +470,21 @@ QNetworkInformationBackendFactory::~QNetworkInformationBackendFactory()
\sa QNetworkInformation::reachability
*/
/*!
\enum QNetworkInformation::TriState
\since 6.2
A bool with a 3rd, unknown, state.
\value False
Known to be \c{false}.
\value True
Known to be \c{true}.
\value Unknown
The state cannot be determined at present, either because the query is
not supported on this platform or because the OS lacks the information.
*/
/*!
\internal ctor
*/
@ -478,6 +493,9 @@ QNetworkInformation::QNetworkInformation(QNetworkInformationBackend *backend)
{
connect(backend, &QNetworkInformationBackend::reachabilityChanged, this,
[this]() { emit reachabilityChanged(d_func()->backend->reachability()); });
connect(backend, &QNetworkInformationBackend::behindCaptivePortalChanged, this, [this]() {
emit behindCaptivePortalChanged(d_func()->backend->behindCaptivePortal());
});
}
/*!
@ -504,6 +522,24 @@ QNetworkInformation::Reachability QNetworkInformation::reachability() const
return d_func()->backend->reachability();
}
/*!
\property QNetworkInformation::behindCaptivePortal
\brief Lets you know if the user's device is behind a captive portal.
\since 6.2
This property indicates if the user's device is currently behind a captive
portal. This functionality relies on the operating system's detection of
captive portals and is not supported on systems that don't report this.
On systems where this is not supported this will always return
TriState::Unknown.
\sa TriState
*/
QNetworkInformation::TriState QNetworkInformation::behindCaptivePortal() const
{
return d_func()->backend->behindCaptivePortal();
}
/*!
Returns the name of the currently loaded backend.
*/

View File

@ -55,6 +55,7 @@ class Q_NETWORK_EXPORT QNetworkInformation : public QObject
Q_OBJECT
Q_DECLARE_PRIVATE(QNetworkInformation)
Q_PROPERTY(Reachability reachability READ reachability NOTIFY reachabilityChanged)
Q_PROPERTY(TriState behindCaptivePortal READ behindCaptivePortal NOTIFY behindCaptivePortalChanged)
public:
enum class Reachability {
Unknown,
@ -65,14 +66,24 @@ public:
};
Q_ENUM(Reachability)
enum class TriState {
False,
True,
Unknown,
};
Q_ENUM(TriState)
enum class Feature {
Reachability = 0x1,
CaptivePortal = 0x2,
};
Q_DECLARE_FLAGS(Features, Feature)
Q_FLAG(Features)
Reachability reachability() const;
TriState behindCaptivePortal() const;
QString backendName() const;
bool supports(Features features) const;
@ -84,6 +95,7 @@ public:
Q_SIGNALS:
void reachabilityChanged(Reachability newReachability);
void behindCaptivePortalChanged(TriState state);
private:
friend struct QNetworkInformationDeleter;

View File

@ -70,9 +70,11 @@ public:
virtual QNetworkInformation::Features featuresSupported() const = 0;
QNetworkInformation::Reachability reachability() const { return m_reachability; }
QNetworkInformation::TriState behindCaptivePortal() const { return m_behindCaptivePortal; }
Q_SIGNALS:
void reachabilityChanged();
void behindCaptivePortalChanged();
protected:
void setReachability(QNetworkInformation::Reachability reachability)
@ -83,8 +85,18 @@ protected:
}
}
void setBehindCaptivePortal(QNetworkInformation::TriState behindPortal)
{
if (m_behindCaptivePortal != behindPortal) {
m_behindCaptivePortal = behindPortal;
emit behindCaptivePortalChanged();
}
}
private:
QNetworkInformation::Reachability m_reachability = QNetworkInformation::Reachability::Unknown;
QNetworkInformation::TriState m_behindCaptivePortal =
QNetworkInformation::TriState::Unknown;
Q_DISABLE_COPY_MOVE(QNetworkInformationBackend)
friend class QNetworkInformation;

View File

@ -40,6 +40,7 @@ class tst_QNetworkInformation : public QObject
private slots:
void initTestCase();
void reachability();
void behindCaptivePortal();
void cleanupTestCase();
private:
@ -56,6 +57,7 @@ public:
Q_ASSERT(!instance);
instance = this;
setReachability(QNetworkInformation::Reachability::Online);
setNewBehindCaptivePortal(QNetworkInformation::TriState::False);
}
~MockBackend() { instance = nullptr; }
@ -72,9 +74,16 @@ public:
instance->setReachability(value);
}
static void setNewBehindCaptivePortal(QNetworkInformation::TriState value)
{
Q_ASSERT(instance);
instance->setBehindCaptivePortal(value);
}
static QNetworkInformation::Features featuresSupportedStatic()
{
return { QNetworkInformation::Feature::Reachability };
return { QNetworkInformation::Feature::Reachability,
QNetworkInformation::Feature::CaptivePortal };
}
private:
@ -152,5 +161,31 @@ void tst_QNetworkInformation::reachability()
QCOMPARE(boundIsOnline, QNetworkInformation::Reachability::Site);
}
void tst_QNetworkInformation::behindCaptivePortal()
{
auto info = QNetworkInformation::instance();
QNetworkInformation::TriState behindPortal = QNetworkInformation::TriState::Unknown;
bool signalEmitted = false;
connect(info, &QNetworkInformation::behindCaptivePortalChanged, this,
[&, info](QNetworkInformation::TriState state) {
signalEmitted = true;
QCOMPARE(state, info->behindCaptivePortal());
behindPortal = info->behindCaptivePortal();
});
QCOMPARE(info->behindCaptivePortal(), QNetworkInformation::TriState::False);
MockBackend::setNewBehindCaptivePortal(QNetworkInformation::TriState::True);
QCoreApplication::processEvents();
QVERIFY(signalEmitted);
QCOMPARE(info->behindCaptivePortal(), QNetworkInformation::TriState::True);
QCOMPARE(behindPortal, QNetworkInformation::TriState::True);
// Set the same value again, signal should not be emitted again
signalEmitted = false;
MockBackend::setNewBehindCaptivePortal(QNetworkInformation::TriState::True);
QCoreApplication::processEvents();
QVERIFY(!signalEmitted);
}
QTEST_MAIN(tst_QNetworkInformation);
#include "tst_qnetworkinformation.moc"

View File

@ -48,7 +48,13 @@ int main(int argc, char **argv)
qDebug() << "Updated:" << newStatus;
});
qDebug() << "Initial:" << info->reachability();
QObject::connect(info, &QNetworkInformation::behindCaptivePortalChanged,
[](QNetworkInformation::TriState status) {
qDebug() << "Updated, behind captive portal:" << status;
});
qDebug() << "Initial reachability:" << info->reachability();
qDebug() << "Behind captive portal:" << info->behindCaptivePortal();
return app.exec();
}