diff options
Diffstat (limited to 'src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp')
-rw-r--r-- | src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp | 65 |
1 files changed, 44 insertions, 21 deletions
diff --git a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp index 72023c6628..a4b1f23b9c 100644 --- a/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp +++ b/src/plugins/networkinformation/networklistmanager/qnetworklistmanagerevents.cpp @@ -3,15 +3,12 @@ #include "qnetworklistmanagerevents.h" +#include <QtCore/qpointer.h> + +#include <mutex> + #ifdef SUPPORTS_WINRT -#include <winrt/base.h> -// Workaround for Windows SDK bug. -// See https://github.com/microsoft/Windows.UI.Composition-Win32-Samples/issues/47 -namespace winrt::impl -{ - template <typename Async> - auto wait_for(Async const& async, Windows::Foundation::TimeSpan const& timeout); -} +#include <QtCore/private/qt_winrtbase_p.h> #include <winrt/Windows.Networking.Connectivity.h> #endif @@ -101,11 +98,16 @@ bool QNetworkListManagerEvents::start() #ifdef SUPPORTS_WINRT using namespace winrt::Windows::Networking::Connectivity; + using winrt::Windows::Foundation::IInspectable; // Register for changes in the network and store a token to unregister later: token = NetworkInformation::NetworkStatusChanged( - [this](const winrt::Windows::Foundation::IInspectable sender) { + [owner = QPointer(this)](const IInspectable sender) { Q_UNUSED(sender); - emitWinRTUpdates(); + if (owner) { + std::scoped_lock locker(owner->winrtLock); + if (owner->token) + owner->emitWinRTUpdates(); + } }); // Emit initial state emitWinRTUpdates(); @@ -114,24 +116,28 @@ bool QNetworkListManagerEvents::start() return true; } -bool QNetworkListManagerEvents::stop() +void QNetworkListManagerEvents::stop() { Q_ASSERT(connectionPoint); auto hr = connectionPoint->Unadvise(cookie); if (FAILED(hr)) { qCWarning(lcNetInfoNLM) << "Failed to unsubscribe from network connectivity events:" << errorStringFromHResult(hr); - return false; + } else { + cookie = 0; } - cookie = 0; + // Even if we fail we should still try to unregister from winrt events: #ifdef SUPPORTS_WINRT - using namespace winrt::Windows::Networking::Connectivity; - // Pass the token we stored earlier to unregister: - NetworkInformation::NetworkStatusChanged(token); - token = {}; + // Try to synchronize unregistering with potentially in-progress callbacks + std::scoped_lock locker(winrtLock); + if (token) { + using namespace winrt::Windows::Networking::Connectivity; + // Pass the token we stored earlier to unregister: + NetworkInformation::NetworkStatusChanged(token); + token = {}; + } #endif - return true; } bool QNetworkListManagerEvents::checkBehindCaptivePortal() @@ -185,7 +191,12 @@ QNetworkInformation::TransportMedium getTransportMedium(const ConnectionProfile if (profile.IsWlanConnectionProfile()) return QNetworkInformation::TransportMedium::WiFi; - NetworkAdapter adapter = profile.NetworkAdapter(); + NetworkAdapter adapter(nullptr); + try { + adapter = profile.NetworkAdapter(); + } catch (...) { + // pass, we will return Unknown anyway + } if (adapter == nullptr) return QNetworkInformation::TransportMedium::Unknown; @@ -208,7 +219,14 @@ QNetworkInformation::TransportMedium getTransportMedium(const ConnectionProfile [[nodiscard]] bool getMetered(const ConnectionProfile &profile) { - ConnectionCost cost = profile.GetConnectionCost(); + ConnectionCost cost(nullptr); + try { + cost = profile.GetConnectionCost(); + } catch (...) { + // pass, we return false if we get an empty object back anyway + } + if (cost == nullptr) + return false; NetworkCostType type = cost.NetworkCostType(); return type == NetworkCostType::Fixed || type == NetworkCostType::Variable; } @@ -217,7 +235,12 @@ QNetworkInformation::TransportMedium getTransportMedium(const ConnectionProfile void QNetworkListManagerEvents::emitWinRTUpdates() { using namespace winrt::Windows::Networking::Connectivity; - ConnectionProfile profile = NetworkInformation::GetInternetConnectionProfile(); + ConnectionProfile profile = nullptr; + try { + profile = NetworkInformation::GetInternetConnectionProfile(); + } catch (...) { + // pass, we would just return early if we get an empty object back anyway + } if (profile == nullptr) return; emit transportMediumChanged(getTransportMedium(profile)); |