diff options
Diffstat (limited to 'src/network/kernel/qnetworkinformation.cpp')
-rw-r--r-- | src/network/kernel/qnetworkinformation.cpp | 95 |
1 files changed, 74 insertions, 21 deletions
diff --git a/src/network/kernel/qnetworkinformation.cpp b/src/network/kernel/qnetworkinformation.cpp index a2f00fadb4..10d6b89e2c 100644 --- a/src/network/kernel/qnetworkinformation.cpp +++ b/src/network/kernel/qnetworkinformation.cpp @@ -26,7 +26,7 @@ struct QNetworkInformationDeleter void operator()(QNetworkInformation *information) { delete information; } }; -Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, loader, +Q_GLOBAL_STATIC_WITH_ARGS(QFactoryLoader, qniLoader, (QNetworkInformationBackendFactory_iid, QStringLiteral("/networkinformation"))) @@ -47,14 +47,21 @@ static void networkInfoCleanup() if (!instance) return; - auto needsReinvoke = instance->thread() && instance->thread() != QThread::currentThread(); - if (needsReinvoke) { - QMetaObject::invokeMethod(dataHolder->instanceHolder.get(), []() { networkInfoCleanup(); }); - return; - } dataHolder->instanceHolder.reset(); } +using namespace Qt::Literals::StringLiterals; + +class QNetworkInformationDummyBackend : public QNetworkInformationBackend { + Q_OBJECT +public: + QString name() const override { return u"dummy"_s; } + QNetworkInformation::Features featuresSupported() const override + { + return {}; + } +}; + class QNetworkInformationPrivate : public QObjectPrivate { Q_DECLARE_PUBLIC(QNetworkInformation) @@ -65,6 +72,7 @@ public: static QNetworkInformation *create(QNetworkInformation::Features features); static QNetworkInformation *create(QStringView name); + static QNetworkInformation *createDummy(); static QNetworkInformation *instance() { if (!dataHolder()) @@ -84,7 +92,7 @@ private: bool QNetworkInformationPrivate::initializeList() { - if (!loader()) + if (!qniLoader()) return false; if (!dataHolder()) return false; @@ -92,11 +100,11 @@ bool QNetworkInformationPrivate::initializeList() QMutexLocker initLocker(&mutex); #if QT_CONFIG(library) - loader->update(); + qniLoader->update(); #endif // Instantiates the plugins (and registers the factories) int index = 0; - while (loader->instance(index)) + while (qniLoader->instance(index)) ++index; initLocker.unlock(); @@ -187,8 +195,8 @@ QNetworkInformation *QNetworkInformationPrivate::create(QStringView name) } else { QString listNames; listNames.reserve(8 * dataHolder->factories.count()); - for (const auto *factory : qAsConst(dataHolder->factories)) - listNames += factory->name() + QStringLiteral(", "); + for (const auto *factory : std::as_const(dataHolder->factories)) + listNames += factory->name() + ", "_L1; listNames.chop(2); qDebug().nospace() << "Couldn't find " << name << " in list with names: { " << listNames << " }"; @@ -230,7 +238,7 @@ QNetworkInformation *QNetworkInformationPrivate::create(QNetworkInformation::Fea return dataHolder->instanceHolder.get(); const auto supportsRequestedFeatures = [features](QNetworkInformationBackendFactory *factory) { - return factory && (factory->featuresSupported() & features) == features; + return factory && factory->featuresSupported().testFlags(features); }; for (auto it = dataHolder->factories.cbegin(), end = dataHolder->factories.cend(); it != end; @@ -243,7 +251,7 @@ QNetworkInformation *QNetworkInformationPrivate::create(QNetworkInformation::Fea } else { QStringList names; names.reserve(dataHolder->factories.count()); - for (const auto *factory : qAsConst(dataHolder->factories)) + for (const auto *factory : std::as_const(dataHolder->factories)) names += factory->name(); qDebug() << "None of the following backends has all the requested features:" << names << features; @@ -271,6 +279,20 @@ QNetworkInformation *QNetworkInformationPrivate::create(QNetworkInformation::Fea return nullptr; } +QNetworkInformation *QNetworkInformationPrivate::createDummy() +{ + if (!dataHolder()) + return nullptr; + + QMutexLocker locker(&dataHolder->instanceMutex); + if (dataHolder->instanceHolder) + return dataHolder->instanceHolder.get(); + + QNetworkInformationBackend *backend = new QNetworkInformationDummyBackend; + dataHolder->instanceHolder.reset(new QNetworkInformation(backend)); + return dataHolder->instanceHolder.get(); +} + /*! \class QNetworkInformationBackend \internal (Semi-private) @@ -492,6 +514,14 @@ QNetworkInformation::QNetworkInformation(QNetworkInformationBackend *backend) &QNetworkInformation::transportMediumChanged); connect(backend, &QNetworkInformationBackend::isMeteredChanged, this, &QNetworkInformation::isMeteredChanged); + + QThread *main = nullptr; + + if (QCoreApplication::instance()) + main = QCoreApplication::instance()->thread(); + + if (main && thread() != main) + moveToThread(main); } /*! @@ -599,6 +629,12 @@ QNetworkInformation::Features QNetworkInformation::supportedFeatures() const Attempts to load the platform-default backend. + \note Starting with 6.7 this tries to load any backend that supports + \l{QNetworkInformation::Feature::Reachability}{Reachability} if the + platform-default backend is not available or fails to load. + If this also fails it will fall back to a backend that only returns + the default values for all properties. + This platform-to-plugin mapping is as follows: \table @@ -619,12 +655,14 @@ QNetworkInformation::Features QNetworkInformation::supportedFeatures() const \li networkmanager \endtable - This function is provided for convenience where the default for a given - platform is good enough. If you are not using the default plugins you must - use one of the other load() overloads. + This function is provided for convenience where the logic earlier + is good enough. If you require a specific plugin then you should call + loadBackendByName() or loadBackendByFeatures() directly instead. - Returns \c true if it managed to load the backend or if it was already - loaded. Returns \c false otherwise. + Determines a suitable backend to load and returns \c true if this backend + is already loaded or on successful loading of it. Returns \c false if any + other backend has already been loaded, or if loading of the selected + backend fails. \sa instance(), load() */ @@ -640,9 +678,15 @@ bool QNetworkInformation::loadDefaultBackend() #elif defined(Q_OS_LINUX) index = QNetworkInformationBackend::PluginNamesLinuxIndex; #endif - if (index == -1) - return false; - return loadBackendByName(QNetworkInformationBackend::PluginNames[index]); + if (index != -1 && loadBackendByName(QNetworkInformationBackend::PluginNames[index])) + return true; + // We assume reachability is the most commonly wanted feature, and try to + // load the backend that advertises the most features including that: + if (loadBackendByFeatures(Feature::Reachability)) + return true; + + // Fall back to the dummy backend + return loadBackendByName(u"dummy"); } /*! @@ -658,10 +702,14 @@ bool QNetworkInformation::loadDefaultBackend() */ bool QNetworkInformation::loadBackendByName(QStringView backend) { + if (backend == u"dummy") + return QNetworkInformationPrivate::createDummy() != nullptr; + auto loadedBackend = QNetworkInformationPrivate::create(backend); return loadedBackend && loadedBackend->backendName().compare(backend, Qt::CaseInsensitive) == 0; } +#if QT_DEPRECATED_SINCE(6,4) /*! \deprecated [6.4] Use loadBackendByName() instead. @@ -671,8 +719,10 @@ bool QNetworkInformation::load(QStringView backend) { return loadBackendByName(backend); } +#endif // QT_DEPRECATED_SINCE(6,4) /*! + \since 6.4 Load a backend which supports \a features. Returns \c true if it managed to load the requested backend or @@ -686,6 +736,7 @@ bool QNetworkInformation::loadBackendByFeatures(Features features) return loadedBackend && loadedBackend->supports(features); } +#if QT_DEPRECATED_SINCE(6,4) /*! \deprecated [6.4] Use loadBackendByFeatures() instead. @@ -695,6 +746,7 @@ bool QNetworkInformation::load(Features features) { return loadBackendByFeatures(features); } +#endif // QT_DEPRECATED_SINCE(6,4) /*! Returns a list of the names of all currently available backends. @@ -719,3 +771,4 @@ QT_END_NAMESPACE #include "moc_qnetworkinformation.cpp" #include "moc_qnetworkinformation_p.cpp" +#include "qnetworkinformation.moc" |