diff options
author | Mårten Nordheim <marten.nordheim@qt.io> | 2021-05-25 15:42:10 +0200 |
---|---|---|
committer | Mårten Nordheim <marten.nordheim@qt.io> | 2021-06-08 14:54:15 +0200 |
commit | 2a60c4b99f0929341aa3b5a15373f6e675ff7ad4 (patch) | |
tree | d87e34fab30cd0de7a7f0d754824467d57860b11 /src/plugins/networkinformationbackends | |
parent | c8cb2409477bdc3bc41d6bbdfc5055441cda084f (diff) |
QNetworkInformation: Captive portal support for Windows
Task-number: QTBUG-93848
Change-Id: Ic1ca895a73c98772aba900bbc3be18ba62be6c0f
Reviewed-by: Alex Blasche <alexander.blasche@qt.io>
Reviewed-by: Edward Welbourne <edward.welbourne@qt.io>
Diffstat (limited to 'src/plugins/networkinformationbackends')
-rw-r--r-- | src/plugins/networkinformationbackends/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp | 56 |
1 files changed, 55 insertions, 1 deletions
diff --git a/src/plugins/networkinformationbackends/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp b/src/plugins/networkinformationbackends/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp index c6b0a6e79b..ffed43aac7 100644 --- a/src/plugins/networkinformationbackends/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp +++ b/src/plugins/networkinformationbackends/networklistmanager/qnetworklistmanagernetworkinformationbackend.cpp @@ -41,6 +41,7 @@ #include <QtCore/qglobal.h> #include <QtCore/private/qobject_p.h> +#include <QtCore/qscopeguard.h> #include <objbase.h> #include <netlistmgr.h> @@ -120,7 +121,8 @@ public: static QNetworkInformation::Features featuresSupportedStatic() { - return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability); + return QNetworkInformation::Features(QNetworkInformation::Feature::Reachability + | QNetworkInformation::Feature::CaptivePortal); } [[nodiscard]] bool start(); @@ -131,6 +133,7 @@ private: bool event(QEvent *event) override; void setConnectivity(NLM_CONNECTIVITY newConnectivity); + void checkCaptivePortal(); ComPtr<QNetworkListManagerEvents> managerEvents; @@ -193,6 +196,8 @@ public: [[nodiscard]] bool start(); bool stop(); + [[nodiscard]] bool checkBehindCaptivePortal(); + signals: void connectivityChanged(NLM_CONNECTIVITY); @@ -288,6 +293,44 @@ bool QNetworkListManagerEvents::stop() return true; } +bool QNetworkListManagerEvents::checkBehindCaptivePortal() +{ + if (!networkListManager) + return false; + ComPtr<IEnumNetworks> networks; + HRESULT hr = + networkListManager->GetNetworks(NLM_ENUM_NETWORK_CONNECTED, networks.GetAddressOf()); + if (FAILED(hr) || networks == nullptr) + return false; + + // @note: This checks all connected networks, but that might not be necessary + ComPtr<INetwork> network; + hr = networks->Next(1, network.GetAddressOf(), nullptr); + while (SUCCEEDED(hr) && network != nullptr) { + ComPtr<IPropertyBag> propertyBag; + hr = network.As(&propertyBag); + if (SUCCEEDED(hr) && propertyBag != nullptr) { + VARIANT variant; + VariantInit(&variant); + const auto scopedVariantClear = qScopeGuard([&variant]() { VariantClear(&variant); }); + + const wchar_t *versions[] = { NA_InternetConnectivityV6, NA_InternetConnectivityV4 }; + for (const auto version : versions) { + hr = propertyBag->Read(version, &variant, nullptr); + if (SUCCEEDED(hr) + && (V_UINT(&variant) & NLM_INTERNET_CONNECTIVITY_WEBHIJACK) + == NLM_INTERNET_CONNECTIVITY_WEBHIJACK) { + return true; + } + } + } + + hr = networks->Next(1, network.GetAddressOf(), nullptr); + } + + return false; +} + QNetworkListManagerNetworkInformationBackend::QNetworkListManagerNetworkInformationBackend() { auto hr = CoInitialize(nullptr); @@ -314,9 +357,20 @@ void QNetworkListManagerNetworkInformationBackend::setConnectivity(NLM_CONNECTIV != reachabilityFromNLM_CONNECTIVITY(newConnectivity)) { connectivity = newConnectivity; setReachability(reachabilityFromNLM_CONNECTIVITY(newConnectivity)); + + // @future: only check if signal is connected + checkCaptivePortal(); } } +void QNetworkListManagerNetworkInformationBackend::checkCaptivePortal() +{ + const bool behindPortal = managerEvents->checkBehindCaptivePortal(); + using TriState = QNetworkInformation::TriState; + const auto triState = behindPortal ? TriState::True : TriState::False; + setBehindCaptivePortal(triState); +} + bool QNetworkListManagerNetworkInformationBackend::event(QEvent *event) { if (event->type() == QEvent::ThreadChange && monitoring) { |