diff --git a/CHANGES b/CHANGES index 4b8fcfd55..a57b48956 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,11 @@ This release contains contributions from (alphabetically by first name): - *networkcfg* now translates the "live user" on an ISO to the regular user on the installed system, so that network configuration changes made in the live system are automatically used after installation. + - *welcome* can now check multiple URLs to determine if internet connectivity + is available. It is still recommended to check the distro home-page or + some special "ping" page of the distro, although that has some privacy + implications; using example.com or google.com may work as well. Listing + multiple URLs will ping each of them in turn until one succeeds. # 3.2.41.1 (2021-08-05) # diff --git a/src/libcalamares/Settings.cpp b/src/libcalamares/Settings.cpp index 9453075b6..2620b8563 100644 --- a/src/libcalamares/Settings.cpp +++ b/src/libcalamares/Settings.cpp @@ -104,6 +104,10 @@ Settings* Settings::s_instance = nullptr; Settings* Settings::instance() { + if ( !s_instance ) + { + cWarning() << "Getting nullptr Settings instance."; + } return s_instance; } @@ -238,6 +242,9 @@ Settings::Settings( bool debugMode ) , m_disableCancel( false ) , m_disableCancelDuringExec( false ) { + cWarning() << "Using bogus Calamares settings in" + << ( debugMode ? QStringLiteral( "debug" ) : QStringLiteral( "regular" ) ) << "mode"; + s_instance = this; } Settings::Settings( const QString& settingsFilePath, bool debugMode ) diff --git a/src/libcalamares/network/Manager.cpp b/src/libcalamares/network/Manager.cpp index 79db1a587..cceff477e 100644 --- a/src/libcalamares/network/Manager.cpp +++ b/src/libcalamares/network/Manager.cpp @@ -20,6 +20,8 @@ #include #include +#include + namespace CalamaresUtils { namespace Network @@ -27,7 +29,7 @@ namespace Network void RequestOptions::applyToRequest( QNetworkRequest* request ) const { -#if QT_VERSION < QT_VERSION_CHECK(5, 15, 0) +#if QT_VERSION < QT_VERSION_CHECK( 5, 15, 0 ) constexpr const auto RedirectPolicyAttribute = QNetworkRequest::FollowRedirectsAttribute; #else constexpr const auto RedirectPolicyAttribute = QNetworkRequest::RedirectPolicyAttribute; @@ -60,8 +62,9 @@ public slots: void cleanupNam(); public: - QUrl m_hasInternetUrl; - bool m_hasInternet; + QVector< QUrl > m_hasInternetUrls; + bool m_hasInternet = false; + int m_lastCheckedUrlIndex = -1; Private(); @@ -155,8 +158,33 @@ Manager::hasInternet() bool Manager::checkHasInternet() { + if ( d->m_hasInternetUrls.empty() ) + { + return false; + } + if ( d->m_lastCheckedUrlIndex < 0 ) + { + d->m_lastCheckedUrlIndex = 0; + } + int attempts = 0; + do + { + // Start by pinging the same one as last time + d->m_hasInternet = synchronousPing( d->m_hasInternetUrls.at( d->m_lastCheckedUrlIndex ) ); + // if it's not responding, **then** move on to the next one, + // and wrap around if needed + if ( !d->m_hasInternet ) + { + if ( ++( d->m_lastCheckedUrlIndex ) >= d->m_hasInternetUrls.size() ) + { + d->m_lastCheckedUrlIndex = 0; + } + } + // keep track of how often we've tried, because there's no point in + // going around more than once. + attempts++; + } while ( !d->m_hasInternet && ( attempts < d->m_hasInternetUrls.size() ) ); - d->m_hasInternet = synchronousPing( d->m_hasInternetUrl ); // For earlier Qt versions (< 5.15.0), set the accessibility flag to // NotAccessible if synchronous ping has failed, so that any module @@ -177,7 +205,40 @@ Manager::checkHasInternet() void Manager::setCheckHasInternetUrl( const QUrl& url ) { - d->m_hasInternetUrl = url; + d->m_lastCheckedUrlIndex = -1; + d->m_hasInternetUrls.clear(); + if ( url.isValid() ) + { + d->m_hasInternetUrls.append( url ); + } +} + +void +Manager::setCheckHasInternetUrl( const QVector< QUrl >& urls ) +{ + d->m_lastCheckedUrlIndex = -1; + d->m_hasInternetUrls = urls; + auto it = std::remove_if( + d->m_hasInternetUrls.begin(), d->m_hasInternetUrls.end(), []( const QUrl& u ) { return !u.isValid(); } ); + if ( it != d->m_hasInternetUrls.end() ) + { + d->m_hasInternetUrls.erase( it, d->m_hasInternetUrls.end() ); + } +} + +void +Manager::addCheckHasInternetUrl( const QUrl& url ) +{ + if ( url.isValid() ) + { + d->m_hasInternetUrls.append( url ); + } +} + +QVector< QUrl > +Manager::getCheckInternetUrls() const +{ + return d->m_hasInternetUrls; } /** @brief Does a request asynchronously, returns the (pending) reply diff --git a/src/libcalamares/network/Manager.h b/src/libcalamares/network/Manager.h index a038dceae..6a906c883 100644 --- a/src/libcalamares/network/Manager.h +++ b/src/libcalamares/network/Manager.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -89,6 +90,7 @@ class DLLEXPORT Manager : public QObject { Q_OBJECT Q_PROPERTY( bool hasInternet READ hasInternet NOTIFY hasInternetChanged FINAL ) + Q_PROPERTY( QVector< QUrl > checkInternetUrls READ getCheckInternetUrls WRITE setCheckHasInternetUrl ) Manager(); @@ -122,6 +124,15 @@ public: /// @brief Set the URL which is used for the general "is there internet" check. void setCheckHasInternetUrl( const QUrl& url ); + /// @brief Adds an (extra) URL to check + void addCheckHasInternetUrl( const QUrl& url ); + + /// @brief Set a collection of URLs used for the general "is there internet" check. + void setCheckHasInternetUrl( const QVector< QUrl >& urls ); + + /// @brief What URLs are used to check for internet connectivity? + QVector< QUrl > getCheckInternetUrls() const; + /** @brief Do a network request asynchronously. * * Returns a pointer to the reply-from-the-request. diff --git a/src/libcalamares/network/Tests.cpp b/src/libcalamares/network/Tests.cpp index d42a74115..e5bd34c23 100644 --- a/src/libcalamares/network/Tests.cpp +++ b/src/libcalamares/network/Tests.cpp @@ -30,6 +30,7 @@ NetworkTests::testInstance() { auto& nam = CalamaresUtils::Network::Manager::instance(); QVERIFY( !nam.hasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 0 ); } void @@ -60,3 +61,87 @@ NetworkTests::testPing() QVERIFY( canPing_www_kde_org ); } } + +void +NetworkTests::testCheckUrl() +{ + using namespace CalamaresUtils::Network; + Logger::setupLogLevel( Logger::LOGVERBOSE ); + auto& nam = Manager::instance(); + + { + QUrl u( "http://example.com" ); + QVERIFY( u.isValid() ); + nam.setCheckHasInternetUrl( u ); + QVERIFY( nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 1 ); // Valid URL + } + { + QUrl u( "http://nonexistent.example.com" ); + QVERIFY( u.isValid() ); + nam.setCheckHasInternetUrl( u ); + QVERIFY( !nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 1 ); // Valid URL even if it doesn't resolve + } + { + QUrl u; + QVERIFY( !u.isValid() ); + nam.setCheckHasInternetUrl( u ); + QVERIFY( !nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 0 ); // Invalid URL tried + } +} + +void +NetworkTests::testCheckMultiUrl() +{ + using namespace CalamaresUtils::Network; + Logger::setupLogLevel( Logger::LOGVERBOSE ); + auto& nam = Manager::instance(); + + { + QUrl u0( "http://example.com" ); + QUrl u1( "https://kde.org" ); + QVERIFY( u0.isValid() ); + QVERIFY( u1.isValid() ); + nam.setCheckHasInternetUrl( { u0, u1 } ); + QVERIFY( nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 2 ); + } + { + QUrl u0( "http://nonexistent.example.com" ); + QUrl u1( "http://bogus.example.com" ); + QVERIFY( u0.isValid() ); + QVERIFY( u1.isValid() ); + nam.setCheckHasInternetUrl( { u0, u1 } ); + QVERIFY( !nam.checkHasInternet() ); + QVERIFY( !nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 2 ); // Both are valid URLs + nam.addCheckHasInternetUrl( QUrl( "http://example.com" ) ); + QVERIFY( nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 3 ); + } + { + QUrl u0( "http://nonexistent.example.com" ); + QUrl u1; + QVERIFY( u0.isValid() ); + QVERIFY( !u1.isValid() ); + nam.setCheckHasInternetUrl( { u0, u1 } ); + QVERIFY( !nam.checkHasInternet() ); + QVERIFY( !nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 1 ); // Only valid URL added + nam.addCheckHasInternetUrl( QUrl( "http://example.com" ) ); + QVERIFY( nam.checkHasInternet() ); + QCOMPARE( nam.getCheckInternetUrls().count(), 2 ); + } + { + QUrl u0( "http://nonexistent.example.com" ); + QUrl u1; + QVERIFY( u0.isValid() ); + QVERIFY( !u1.isValid() ); + nam.setCheckHasInternetUrl( { u1, u1, u1, u1 } ); + QCOMPARE( nam.getCheckInternetUrls().count(), 0 ); + nam.setCheckHasInternetUrl( { u1, u1, u0, u1 } ); + QCOMPARE( nam.getCheckInternetUrls().count(), 1 ); + } +} diff --git a/src/libcalamares/network/Tests.h b/src/libcalamares/network/Tests.h index 6000e227a..d72da574a 100644 --- a/src/libcalamares/network/Tests.h +++ b/src/libcalamares/network/Tests.h @@ -24,6 +24,9 @@ private Q_SLOTS: void testInstance(); void testPing(); + + void testCheckUrl(); + void testCheckMultiUrl(); }; #endif diff --git a/src/libcalamares/utils/CalamaresUtilsSystem.cpp b/src/libcalamares/utils/CalamaresUtilsSystem.cpp index 29f743743..df578a862 100644 --- a/src/libcalamares/utils/CalamaresUtilsSystem.cpp +++ b/src/libcalamares/utils/CalamaresUtilsSystem.cpp @@ -102,7 +102,7 @@ System::instance() if ( !s_instance ) { cError() << "No Calamares system-object has been created."; - cError() << Logger::SubEntry << "using a bogus instance instead."; + cDebug() << Logger::SubEntry << "using a bogus instance instead."; return new System( true, nullptr ); } return s_instance; diff --git a/src/libcalamares/utils/Variant.h b/src/libcalamares/utils/Variant.h index ab9e73f90..d0d893dc3 100644 --- a/src/libcalamares/utils/Variant.h +++ b/src/libcalamares/utils/Variant.h @@ -34,7 +34,7 @@ DLLEXPORT QString getString( const QVariantMap& map, const QString& key, const Q /** @brief Get a string list from a mapping with a given key; returns @p d if no value. * - * This is slightly more lenient that getString(), and a single-string value will + * This is slightly more lenient than getString(), and a single-string value will * be returned as a 1-item list. */ DLLEXPORT QStringList getStringList( const QVariantMap& map, const QString& key, const QStringList& d = QStringList() ); diff --git a/src/libcalamaresui/Branding.cpp b/src/libcalamaresui/Branding.cpp index b9445ba83..5894c723d 100644 --- a/src/libcalamaresui/Branding.cpp +++ b/src/libcalamaresui/Branding.cpp @@ -49,6 +49,10 @@ Branding* Branding::s_instance = nullptr; Branding* Branding::instance() { + if ( !s_instance ) + { + cWarning() << "No Branding instance created yet."; + } return s_instance; } diff --git a/src/modules/welcome/CMakeLists.txt b/src/modules/welcome/CMakeLists.txt index 924062652..01a89703a 100644 --- a/src/modules/welcome/CMakeLists.txt +++ b/src/modules/welcome/CMakeLists.txt @@ -8,26 +8,22 @@ find_package( Qt5 ${QT_VERSION} CONFIG REQUIRED DBus Network ) find_package( LIBPARTED ) if ( LIBPARTED_FOUND ) set( PARTMAN_SRC checker/partman_devices.c ) - set( CHECKER_LINK_LIBRARIES ${LIBPARTED_LIBRARY} ) + set( PARTMAN_LIB ${LIBPARTED_LIBRARY} ) else() set( PARTMAN_SRC ) - set( CHECKER_LINK_LIBRARIES ) + set( PARTMAN_LIB ) add_definitions( -DWITHOUT_LIBPARTED ) endif() -set( CHECKER_SOURCES - checker/CheckerContainer.cpp - checker/GeneralRequirements.cpp - checker/ResultWidget.cpp - checker/ResultsListWidget.cpp - ${PARTMAN_SRC} -) - calamares_add_plugin( welcome TYPE viewmodule EXPORT_MACRO PLUGINDLLEXPORT_PRO SOURCES - ${CHECKER_SOURCES} + checker/CheckerContainer.cpp + checker/GeneralRequirements.cpp + checker/ResultWidget.cpp + checker/ResultsListWidget.cpp + ${PARTMAN_SRC} WelcomeViewStep.cpp Config.cpp Config.h @@ -37,8 +33,23 @@ calamares_add_plugin( welcome RESOURCES welcome.qrc LINK_PRIVATE_LIBRARIES - ${CHECKER_LINK_LIBRARIES} + ${PARTMAN_LIB} Qt5::DBus Qt5::Network SHARED_LIB ) + +calamares_add_test( + welcometest + SOURCES + checker/GeneralRequirements.cpp + ${PARTMAN_SRC} + Config.cpp + Tests.cpp + LIBRARIES + ${PARTMAN_LIB} + Qt5::DBus + Qt5::Network + Qt5::Widgets + Calamares::calamaresui +) diff --git a/src/modules/welcome/Config.cpp b/src/modules/welcome/Config.cpp index 48e92e628..b2a49552b 100644 --- a/src/modules/welcome/Config.cpp +++ b/src/modules/welcome/Config.cpp @@ -27,6 +27,7 @@ Config::Config( QObject* parent ) : QObject( parent ) , m_languages( CalamaresUtils::Locale::availableTranslations() ) , m_filtermodel( std::make_unique< QSortFilterProxyModel >() ) + , m_requirementsChecker( std::make_unique< GeneralRequirements >( this ) ) { initLanguages(); @@ -38,14 +39,16 @@ Config::Config( QObject* parent ) void Config::retranslate() { - m_genericWelcomeMessage = genericWelcomeMessage().arg( Calamares::Branding::instance()->versionedName() ); + const auto* branding = Calamares::Branding::instance(); + const auto* settings = Calamares::Settings::instance(); + m_genericWelcomeMessage = genericWelcomeMessage().arg( branding ? branding->versionedName() : QString() ); emit genericWelcomeMessageChanged( m_genericWelcomeMessage ); const auto* r = requirementsModel(); - if ( !r->satisfiedRequirements() ) + if ( r && !r->satisfiedRequirements() ) { QString message; - const bool setup = Calamares::Settings::instance()->isSetupMode(); + const bool setup = settings ? settings->isSetupMode() : false; if ( !r->satisfiedMandatory() ) { @@ -70,13 +73,13 @@ Config::retranslate() "might be disabled." ); } - m_warningMessage = message.arg( Calamares::Branding::instance()->shortVersionedName() ); + m_warningMessage = message.arg( branding ? branding->shortVersionedName() : QString() ); } else { m_warningMessage = tr( "This program will ask you some questions and " "set up %2 on your computer." ) - .arg( Calamares::Branding::instance()->productName() ); + .arg( branding ? branding->productName() : QString() ); } emit warningMessageChanged( m_warningMessage ); @@ -91,7 +94,8 @@ Config::languagesModel() const Calamares::RequirementsModel* Config::requirementsModel() const { - return Calamares::ModuleManager::instance()->requirementsModel(); + auto* manager = Calamares::ModuleManager::instance(); + return manager ? manager->requirementsModel() : nullptr; } QAbstractItemModel* @@ -150,8 +154,6 @@ Config::initLanguages() { QString name = m_languages->locale( matchedLocaleIndex ).name(); cDebug() << Logger::SubEntry << "Matched with index" << matchedLocaleIndex << name; - - CalamaresUtils::installTranslator( name, Calamares::Branding::instance()->translationsDirectory() ); setLocaleIndex( matchedLocaleIndex ); } else @@ -190,7 +192,8 @@ Config::setLocaleIndex( int index ) cDebug() << "Index" << index << "Selected locale" << selectedLocale; QLocale::setDefault( selectedLocale ); - CalamaresUtils::installTranslator( selectedLocale, Calamares::Branding::instance()->translationsDirectory() ); + const auto* branding = Calamares::Branding::instance(); + CalamaresUtils::installTranslator( selectedLocale, branding ? branding->translationsDirectory() : QString() ); if ( Calamares::JobQueue::instance() && Calamares::JobQueue::instance()->globalStorage() ) { CalamaresUtils::Locale::insertGS( *Calamares::JobQueue::instance()->globalStorage(), @@ -240,17 +243,19 @@ Config::genericWelcomeMessage() const { QString message; - if ( Calamares::Settings::instance()->isSetupMode() ) + const auto* settings = Calamares::Settings::instance(); + const auto* branding = Calamares::Branding::instance(); + const bool welcomeStyle = branding ? branding->welcomeStyleCalamares() : true; + + if ( settings ? settings->isSetupMode() : false ) { - message = Calamares::Branding::instance()->welcomeStyleCalamares() - ? tr( "

Welcome to the Calamares setup program for %1

" ) - : tr( "

Welcome to %1 setup

" ); + message = welcomeStyle ? tr( "

Welcome to the Calamares setup program for %1

" ) + : tr( "

Welcome to %1 setup

" ); } else { - message = Calamares::Branding::instance()->welcomeStyleCalamares() - ? tr( "

Welcome to the Calamares installer for %1

" ) - : tr( "

Welcome to the %1 installer

" ); + message = welcomeStyle ? tr( "

Welcome to the Calamares installer for %1

" ) + : tr( "

Welcome to the %1 installer

" ); } return message; @@ -393,4 +398,15 @@ Config::setConfigurationMap( const QVariantMap& configurationMap ) ::setLanguageIcon( this, configurationMap ); ::setGeoIP( this, configurationMap ); + + if ( configurationMap.contains( "requirements" ) + && configurationMap.value( "requirements" ).type() == QVariant::Map ) + { + m_requirementsChecker->setConfigurationMap( configurationMap.value( "requirements" ).toMap() ); + } + else + { + cWarning() << "no valid requirements map found in welcome " + "module configuration."; + } } diff --git a/src/modules/welcome/Config.h b/src/modules/welcome/Config.h index a3f1276a6..6cce75f22 100644 --- a/src/modules/welcome/Config.h +++ b/src/modules/welcome/Config.h @@ -10,6 +10,8 @@ #ifndef WELCOME_CONFIG_H #define WELCOME_CONFIG_H +#include "checker/GeneralRequirements.h" + #include "locale/LabelModel.h" #include "modulesystem/RequirementsModel.h" @@ -100,6 +102,9 @@ public slots: QAbstractItemModel* unsatisfiedRequirements() const; + /// @brief Check the general requirements + Calamares::RequirementsList checkRequirements() const { return m_requirementsChecker->checkRequirements(); } + signals: void countryCodeChanged( QString countryCode ); void localeIndexChanged( int localeIndex ); @@ -118,6 +123,7 @@ private: CalamaresUtils::Locale::LabelModel* m_languages = nullptr; std::unique_ptr< QSortFilterProxyModel > m_filtermodel; + std::unique_ptr< GeneralRequirements > m_requirementsChecker; QString m_languageIcon; QString m_countryCode; diff --git a/src/modules/welcome/Tests.cpp b/src/modules/welcome/Tests.cpp new file mode 100644 index 000000000..0445433e9 --- /dev/null +++ b/src/modules/welcome/Tests.cpp @@ -0,0 +1,116 @@ +/* === This file is part of Calamares - === + * + * SPDX-FileCopyrightText: 2021 Adriaan de Groot + * SPDX-License-Identifier: GPL-3.0-or-later + * + * Calamares is Free Software: see the License-Identifier above. + * + */ + +#include "Config.h" + +#include "Branding.h" +#include "Settings.h" +#include "network/Manager.h" +#include "utils/CalamaresUtilsSystem.h" +#include "utils/Logger.h" +#include "utils/Yaml.h" + +#include + +class WelcomeTests : public QObject +{ + Q_OBJECT +public: + WelcomeTests(); + ~WelcomeTests() override {} + +private Q_SLOTS: + void initTestCase(); + + void testOneUrl(); + void testUrls_data(); + void testUrls(); +}; + +WelcomeTests::WelcomeTests() {} + +void +WelcomeTests::initTestCase() +{ + Logger::setupLogLevel( Logger::LOGDEBUG ); + cDebug() << "Welcome test started."; + + // Ensure we have a system object, expect it to be a "bogus" one + CalamaresUtils::System* system = CalamaresUtils::System::instance(); + QVERIFY( system ); + cDebug() << Logger::SubEntry << "System @" << Logger::Pointer( system ); + + const auto* settings = Calamares::Settings::instance(); + if ( !settings ) + { + (void)new Calamares::Settings( true ); + } +} + +void +WelcomeTests::testOneUrl() +{ + Config c; + + // BUILD_AS_TEST is the source-directory path + QString filename = QStringLiteral( "1a-checkinternet.conf" ); + QFile fi( QString( "%1/tests/%2" ).arg( BUILD_AS_TEST, filename ) ); + QVERIFY( fi.exists() ); + + bool ok = false; + const auto map = CalamaresUtils::loadYaml( fi, &ok ); + QVERIFY( ok ); + QVERIFY( map.count() > 0 ); + QVERIFY( map.contains( "requirements" ) ); + + c.setConfigurationMap( map ); + QCOMPARE( CalamaresUtils::Network::Manager::instance().getCheckInternetUrls().count(), 1 ); +} + +void +WelcomeTests::testUrls_data() +{ + QTest::addColumn< QString >( "filename" ); + QTest::addColumn< int >( "result" ); + + QTest::newRow( "one " ) << QString( "1a-checkinternet.conf" ) << 1; + QTest::newRow( "none " ) << QString( "1b-checkinternet.conf" ) << 0; + QTest::newRow( "blank" ) << QString( "1c-checkinternet.conf" ) << 0; + QTest::newRow( "bogus" ) << QString( "1d-checkinternet.conf" ) << 0; + QTest::newRow( "[] " ) << QString( "1e-checkinternet.conf" ) << 0; + QTest::newRow( "-3 " ) << QString( "1f-checkinternet.conf" ) << 3; + QTest::newRow( "[3] " ) << QString( "1g-checkinternet.conf" ) << 3; + QTest::newRow( "some " ) << QString( "1h-checkinternet.conf" ) << 3; +} + +void +WelcomeTests::testUrls() +{ + QFETCH( QString, filename ); + QFETCH( int, result ); + + Config c; + + // BUILD_AS_TEST is the source-directory path + QFile fi( QString( "%1/tests/%2" ).arg( BUILD_AS_TEST, filename ) ); + QVERIFY( fi.exists() ); + + bool ok = false; + const auto map = CalamaresUtils::loadYaml( fi, &ok ); + QVERIFY( ok ); + + c.setConfigurationMap( map ); + QCOMPARE( CalamaresUtils::Network::Manager::instance().getCheckInternetUrls().count(), result ); +} + +QTEST_GUILESS_MAIN( WelcomeTests ) + +#include "utils/moc-warnings.h" + +#include "Tests.moc" diff --git a/src/modules/welcome/WelcomeViewStep.cpp b/src/modules/welcome/WelcomeViewStep.cpp index 2a0d57bc4..df42271fc 100644 --- a/src/modules/welcome/WelcomeViewStep.cpp +++ b/src/modules/welcome/WelcomeViewStep.cpp @@ -12,7 +12,6 @@ #include "Config.h" #include "WelcomePage.h" -#include "checker/GeneralRequirements.h" #include "Branding.h" #include "modulesystem/ModuleManager.h" @@ -25,7 +24,6 @@ WelcomeViewStep::WelcomeViewStep( QObject* parent ) : Calamares::ViewStep( parent ) , m_conf( new Config( this ) ) , m_widget( new WelcomePage( m_conf ) ) - , m_requirementsChecker( new GeneralRequirements( this ) ) { connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, @@ -96,17 +94,6 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_conf->setConfigurationMap( configurationMap ); - if ( configurationMap.contains( "requirements" ) - && configurationMap.value( "requirements" ).type() == QVariant::Map ) - { - m_requirementsChecker->setConfigurationMap( configurationMap.value( "requirements" ).toMap() ); - } - else - { - cWarning() << "no valid requirements map found in welcome " - "module configuration."; - } - //here init the qml or qwidgets needed bits m_widget->init(); } @@ -114,5 +101,5 @@ WelcomeViewStep::setConfigurationMap( const QVariantMap& configurationMap ) Calamares::RequirementsList WelcomeViewStep::checkRequirements() { - return m_requirementsChecker->checkRequirements(); + return m_conf->checkRequirements(); } diff --git a/src/modules/welcome/WelcomeViewStep.h b/src/modules/welcome/WelcomeViewStep.h index 57632f7ac..dfc6f1169 100644 --- a/src/modules/welcome/WelcomeViewStep.h +++ b/src/modules/welcome/WelcomeViewStep.h @@ -66,7 +66,6 @@ public: private: Config* m_conf; WelcomePage* m_widget; - GeneralRequirements* m_requirementsChecker; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( WelcomeViewStepFactory ) diff --git a/src/modules/welcome/checker/GeneralRequirements.cpp b/src/modules/welcome/checker/GeneralRequirements.cpp index 07c352946..2528cbd9f 100644 --- a/src/modules/welcome/checker/GeneralRequirements.cpp +++ b/src/modules/welcome/checker/GeneralRequirements.cpp @@ -215,6 +215,57 @@ GeneralRequirements::checkRequirements() return checkEntries; } +/** @brief Loads the check-internel URLs + * + * There may be zero or one or more URLs specified; returns + * @c true if the configuration is incomplete or damaged in some way. + */ +static bool +getCheckInternetUrls( const QVariantMap& configurationMap ) +{ + const QString exampleUrl = QStringLiteral( "http://example.com" ); + + bool incomplete = false; + QStringList checkInternetSetting = CalamaresUtils::getStringList( configurationMap, "internetCheckUrl" ); + if ( !checkInternetSetting.isEmpty() ) + { + QVector< QUrl > urls; + for ( const auto& urlString : qAsConst( checkInternetSetting ) ) + { + QUrl url( urlString.trimmed() ); + if ( url.isValid() ) + { + urls.append( url ); + } + else + { + cWarning() << "GeneralRequirements entry 'internetCheckUrl' in welcome.conf contains invalid" + << urlString; + } + } + + if ( urls.empty() ) + { + cWarning() << "GeneralRequirements entry 'internetCheckUrl' contains no valid URLs," + << "reverting to default (http://example.com)."; + CalamaresUtils::Network::Manager::instance().setCheckHasInternetUrl( QUrl( exampleUrl ) ); + incomplete = true; + } + else + { + CalamaresUtils::Network::Manager::instance().setCheckHasInternetUrl( urls ); + } + } + else + { + cWarning() << "GeneralRequirements entry 'internetCheckUrl' is undefined in welcome.conf," + "reverting to default (http://example.com)."; + CalamaresUtils::Network::Manager::instance().setCheckHasInternetUrl( QUrl( exampleUrl ) ); + incomplete = true; + } + return incomplete; +} + void GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) @@ -302,30 +353,7 @@ GeneralRequirements::setConfigurationMap( const QVariantMap& configurationMap ) incompleteConfiguration = true; } - QUrl checkInternetUrl; - QString checkInternetSetting = CalamaresUtils::getString( configurationMap, "internetCheckUrl" ); - if ( !checkInternetSetting.isEmpty() ) - { - checkInternetUrl = QUrl( checkInternetSetting.trimmed() ); - if ( !checkInternetUrl.isValid() ) - { - cWarning() << "GeneralRequirements entry 'internetCheckUrl' is invalid in welcome.conf" - << checkInternetSetting << "reverting to default (http://example.com)."; - checkInternetUrl = QUrl( "http://example.com" ); - incompleteConfiguration = true; - } - } - else - { - cWarning() << "GeneralRequirements entry 'internetCheckUrl' is undefined in welcome.conf," - "reverting to default (http://example.com)."; - checkInternetUrl = "http://example.com"; - incompleteConfiguration = true; - } - if ( checkInternetUrl.isValid() ) - { - CalamaresUtils::Network::Manager::instance().setCheckHasInternetUrl( checkInternetUrl ); - } + incompleteConfiguration |= getCheckInternetUrls( configurationMap ); if ( incompleteConfiguration ) { diff --git a/src/modules/welcome/tests/1a-checkinternet.conf b/src/modules/welcome/tests/1a-checkinternet.conf new file mode 100644 index 000000000..d2140f201 --- /dev/null +++ b/src/modules/welcome/tests/1a-checkinternet.conf @@ -0,0 +1,3 @@ +--- +requirements: + internetCheckUrl: http://example.com diff --git a/src/modules/welcome/tests/1b-checkinternet.conf b/src/modules/welcome/tests/1b-checkinternet.conf new file mode 100644 index 000000000..a1e656985 --- /dev/null +++ b/src/modules/welcome/tests/1b-checkinternet.conf @@ -0,0 +1,3 @@ +# Nothing at all +--- +bogus: 1 diff --git a/src/modules/welcome/tests/1c-checkinternet.conf b/src/modules/welcome/tests/1c-checkinternet.conf new file mode 100644 index 000000000..845e253c0 --- /dev/null +++ b/src/modules/welcome/tests/1c-checkinternet.conf @@ -0,0 +1,4 @@ +# Set to blank +--- +requirements: + internetCheckUrl: "" diff --git a/src/modules/welcome/tests/1d-checkinternet.conf b/src/modules/welcome/tests/1d-checkinternet.conf new file mode 100644 index 000000000..9a44d7c93 --- /dev/null +++ b/src/modules/welcome/tests/1d-checkinternet.conf @@ -0,0 +1,4 @@ +# Set to something broken +--- +requirements: + internetCheckUrl: false diff --git a/src/modules/welcome/tests/1e-checkinternet.conf b/src/modules/welcome/tests/1e-checkinternet.conf new file mode 100644 index 000000000..579414a79 --- /dev/null +++ b/src/modules/welcome/tests/1e-checkinternet.conf @@ -0,0 +1,4 @@ +# Empty list +--- +requirements: + internetCheckUrl: [] diff --git a/src/modules/welcome/tests/1f-checkinternet.conf b/src/modules/welcome/tests/1f-checkinternet.conf new file mode 100644 index 000000000..660760381 --- /dev/null +++ b/src/modules/welcome/tests/1f-checkinternet.conf @@ -0,0 +1,6 @@ +--- +requirements: + internetCheckUrl: + - http://example.com + - http://bogus.example.com + - http://nonexistent.example.com diff --git a/src/modules/welcome/tests/1g-checkinternet.conf b/src/modules/welcome/tests/1g-checkinternet.conf new file mode 100644 index 000000000..dd3ddae0c --- /dev/null +++ b/src/modules/welcome/tests/1g-checkinternet.conf @@ -0,0 +1,3 @@ +--- +requirements: + internetCheckUrl: [ http://example.com, http://bogus.example.com, http://nonexistent.example.com ] diff --git a/src/modules/welcome/tests/1h-checkinternet.conf b/src/modules/welcome/tests/1h-checkinternet.conf new file mode 100644 index 000000000..928360c20 --- /dev/null +++ b/src/modules/welcome/tests/1h-checkinternet.conf @@ -0,0 +1,8 @@ +# "0" is a valid URL (?) but "" is not +--- +requirements: + internetCheckUrl: + - http://example.com + - 0 + - "" + - http://nonexistent.example.com diff --git a/src/modules/welcome/welcome.conf b/src/modules/welcome/welcome.conf index b3da8d366..6e11817bf 100644 --- a/src/modules/welcome/welcome.conf +++ b/src/modules/welcome/welcome.conf @@ -43,6 +43,21 @@ requirements: # # The URL is only used if "internet" is in the *check* list below. internetCheckUrl: http://example.com + # + # This may be a single URL, or a list or URLs, in which case the + # URLs will be checked one-by-one; if any of them returns data, + # internet is assumed to be OK. This can be used to check via + # a number of places, where some domains may be down or blocked. + # + # To use a list of URLs, just use YAML list syntax (e.g. + # + # internetCheckUrl: + # - http://www.kde.org + # - http://www.freebsd.org + # + # or short-form + # + # internetCheckUrl: [ http://www.kde.org, http://www.freebsd.org ] # List conditions to check. Each listed condition will be # probed in some way, and yields true or false according to diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.cpp b/src/modules/welcomeq/WelcomeQmlViewStep.cpp index af32f2992..914ea4f3a 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.cpp +++ b/src/modules/welcomeq/WelcomeQmlViewStep.cpp @@ -26,7 +26,6 @@ CALAMARES_PLUGIN_FACTORY_DEFINITION( WelcomeQmlViewStepFactory, registerPlugin< WelcomeQmlViewStep::WelcomeQmlViewStep( QObject* parent ) : Calamares::QmlViewStep( parent ) , m_config( new Config( this ) ) - , m_requirementsChecker( new GeneralRequirements( this ) ) { connect( Calamares::ModuleManager::instance(), &Calamares::ModuleManager::requirementsComplete, @@ -58,7 +57,6 @@ WelcomeQmlViewStep::isBackEnabled() const bool WelcomeQmlViewStep::isAtBeginning() const { - // TODO: adjust to "pages" in the QML return true; } @@ -66,7 +64,6 @@ WelcomeQmlViewStep::isAtBeginning() const bool WelcomeQmlViewStep::isAtEnd() const { - // TODO: adjust to "pages" in the QML return true; } @@ -81,26 +78,13 @@ void WelcomeQmlViewStep::setConfigurationMap( const QVariantMap& configurationMap ) { m_config->setConfigurationMap( configurationMap ); - - if ( configurationMap.contains( "requirements" ) - && configurationMap.value( "requirements" ).type() == QVariant::Map ) - { - m_requirementsChecker->setConfigurationMap( configurationMap.value( "requirements" ).toMap() ); - } - else - { - cWarning() << "no valid requirements map found in welcomeq " - "module configuration."; - } - Calamares::QmlViewStep::setConfigurationMap( configurationMap ); // call parent implementation last - setContextProperty( "Welcome", m_config ); } Calamares::RequirementsList WelcomeQmlViewStep::checkRequirements() { - return m_requirementsChecker->checkRequirements(); + return m_config->checkRequirements(); } QObject* diff --git a/src/modules/welcomeq/WelcomeQmlViewStep.h b/src/modules/welcomeq/WelcomeQmlViewStep.h index 4c68ea2ae..1ed90ce05 100644 --- a/src/modules/welcomeq/WelcomeQmlViewStep.h +++ b/src/modules/welcomeq/WelcomeQmlViewStep.h @@ -29,9 +29,7 @@ class Handler; } } // namespace CalamaresUtils -class GeneralRequirements; -// TODO: Needs a generic Calamares::QmlViewStep as base class // TODO: refactor and move what makes sense to base class class PLUGINDLLEXPORT WelcomeQmlViewStep : public Calamares::QmlViewStep { @@ -65,7 +63,6 @@ public: private: Config* m_config; - GeneralRequirements* m_requirementsChecker; }; CALAMARES_PLUGIN_FACTORY_DECLARATION( WelcomeQmlViewStepFactory )