From a31642125c01e8bf4bfd48e14b40952506da46bb Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Fri, 5 Jul 2019 18:27:49 +0200 Subject: Fix headless compilation (backported from 5.13) Change-Id: I4eb3fae767066dcfb64f3f6fc126680768a10ecc Reviewed-by: Dominik Holland --- application-manager.pro | 8 ++++---- examples/applicationmanager/applicationmanager.pro | 4 ++++ qmake-features/am-config.prf | 4 ++++ src/main-lib/main.cpp | 6 ++++++ src/manager-lib/qmlinprocessruntime.h | 2 ++ src/manager-lib/systemreader.cpp | 2 +- src/monitor-lib/frametimer.h | 4 ++++ src/monitor-lib/gpustatus.h | 3 +++ src/monitor-lib/monitor-lib.pro | 13 +++++++++---- src/shared-main-lib/sharedmain.cpp | 11 +++++++++-- src/src.pro | 4 +++- src/tools/launcher-qml/launcher-qml.cpp | 10 ++++++++-- src/tools/testrunner/testrunner.pro | 2 ++ tests/qml/qml.pro | 4 ++++ 14 files changed, 63 insertions(+), 14 deletions(-) diff --git a/application-manager.pro b/application-manager.pro index 38694938..62771a35 100644 --- a/application-manager.pro +++ b/application-manager.pro @@ -22,10 +22,12 @@ else:contains(QT_BUILD_PARTS, "examples"):CONFIG += enable-examples load(configure) qtCompileTest(libarchive) qtCompileTest(libyaml) - !headless:qtCompileTest(touchemulation) + !headless:qtHaveModule(gui):qtCompileTest(touchemulation) } -qtHaveModule(waylandcompositor):CONFIG += am_compatible_compositor +qtHaveModule(waylandcompositor):qtHaveModule(quick):qtConfig(opengl):CONFIG += am_compatible_compositor + +load(am-config) force-single-process:force-multi-process:error("You cannot both specify force-single-process and force-multi-process") force-multi-process:!headless:!am_compatible_compositor:error("You forced multi-process mode, but the QtCompositor module is not available") @@ -34,8 +36,6 @@ if(linux|force-libcrypto) { !if(contains(QT_CONFIG,"openssl")|contains(QT_CONFIG,"openssl-linked")|contains(QT_CONFIG,"ssl")):error("Qt was built without OpenSSL support.") } -load(am-config) - !config_libyaml|no-system-libyaml { force-system-libyaml:error("Could not find a system installation for libyaml.") else:SUBDIRS += 3rdparty/libyaml/libyaml.pro diff --git a/examples/applicationmanager/applicationmanager.pro b/examples/applicationmanager/applicationmanager.pro index 8231c457..49cc2c82 100644 --- a/examples/applicationmanager/applicationmanager.pro +++ b/examples/applicationmanager/applicationmanager.pro @@ -1,3 +1,7 @@ +load(am-config) + +requires(!headless) + TEMPLATE = subdirs SUBDIRS = \ diff --git a/qmake-features/am-config.prf b/qmake-features/am-config.prf index 3ddfe8b2..d115eb63 100644 --- a/qmake-features/am-config.prf +++ b/qmake-features/am-config.prf @@ -5,6 +5,10 @@ CONFIG *= no_private_qt_headers_warning hide_symbols CONFIG -= app_bundle qml_debug CONFIG += exceptions +!qtHaveModule(gui)|!qtHaveModule(quick)|!qtConfig(opengl) { + CONFIG *= headless +} + DEFINES += QT_MESSAGELOGCONTEXT win32-msvc*:QMAKE_CXXFLAGS += /FS /wd4290 /DNOMINMAX /D_CRT_SECURE_NO_WARNINGS diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp index 11a85d83..8a4c9788 100644 --- a/src/main-lib/main.cpp +++ b/src/main-lib/main.cpp @@ -627,8 +627,10 @@ void Main::setupQmlEngine(const QStringList &importPaths, const QString &quickCo // monitor-lib qmlRegisterType("QtApplicationManager", 2, 0, "CpuStatus"); +#if !defined(AM_HEADLESS) qmlRegisterType("QtApplicationManager", 2, 0, "FrameTimer"); qmlRegisterType("QtApplicationManager", 2, 0, "GpuStatus"); +#endif qmlRegisterType("QtApplicationManager", 2, 0, "IoStatus"); qmlRegisterType("QtApplicationManager", 2, 0, "MemoryStatus"); qmlRegisterType("QtApplicationManager", 2, 0, "MonitorModel"); @@ -694,6 +696,9 @@ void Main::setupWindowManager(const QString &waylandSocketName, bool slowAnimati void Main::setupTouchEmulation(bool enableTouchEmulation) { +#if defined(AM_HEADLESS) + Q_UNUSED(enableTouchEmulation) +#else if (enableTouchEmulation) { if (TouchEmulation::isSupported()) { TouchEmulation::createInstance(); @@ -704,6 +709,7 @@ void Main::setupTouchEmulation(bool enableTouchEmulation) "build time or the platform does not support it."; } } +#endif } void Main::loadQml(bool loadDummyData) Q_DECL_NOEXCEPT_EXPR(false) diff --git a/src/manager-lib/qmlinprocessruntime.h b/src/manager-lib/qmlinprocessruntime.h index 8c0281dc..f2d57eb6 100644 --- a/src/manager-lib/qmlinprocessruntime.h +++ b/src/manager-lib/qmlinprocessruntime.h @@ -82,7 +82,9 @@ public: public slots: bool start() override; void stop(bool forceKill = false) override; +#if !defined(AM_HEADLESS) void stopIfNoVisibleSurfaces(); +#endif signals: void aboutToStop(); // used for the ApplicationInterface diff --git a/src/manager-lib/systemreader.cpp b/src/manager-lib/systemreader.cpp index cab1fa56..efd3fb94 100644 --- a/src/manager-lib/systemreader.cpp +++ b/src/manager-lib/systemreader.cpp @@ -71,11 +71,11 @@ QT_END_NAMESPACE_AM # include # include # include +# include # if !defined(AM_HEADLESS) # include # include # include -# include # endif # include diff --git a/src/monitor-lib/frametimer.h b/src/monitor-lib/frametimer.h index 65d1cee1..fe0ce2d3 100644 --- a/src/monitor-lib/frametimer.h +++ b/src/monitor-lib/frametimer.h @@ -42,6 +42,8 @@ #pragma once +#if !defined(AM_HEADLESS) + #include #include #include @@ -135,3 +137,5 @@ private: }; QT_END_NAMESPACE_AM + +#endif // !AM_HEADLESS diff --git a/src/monitor-lib/gpustatus.h b/src/monitor-lib/gpustatus.h index 16f95077..9f44ba82 100644 --- a/src/monitor-lib/gpustatus.h +++ b/src/monitor-lib/gpustatus.h @@ -42,6 +42,8 @@ #pragma once +#if !defined(AM_HEADLESS) + #include #include @@ -78,3 +80,4 @@ private: QT_END_NAMESPACE_AM +#endif // !AM_HEADLESS diff --git a/src/monitor-lib/monitor-lib.pro b/src/monitor-lib/monitor-lib.pro index 792c85de..dc55c715 100644 --- a/src/monitor-lib/monitor-lib.pro +++ b/src/monitor-lib/monitor-lib.pro @@ -16,8 +16,6 @@ CONFIG *= static internal_module HEADERS += \ cpustatus.h \ - frametimer.h \ - gpustatus.h \ iostatus.h \ memorystatus.h \ monitormodel.h \ @@ -26,12 +24,19 @@ HEADERS += \ SOURCES += \ cpustatus.cpp \ - frametimer.cpp \ - gpustatus.cpp \ iostatus.cpp \ memorystatus.cpp \ monitormodel.cpp \ processreader.cpp \ processstatus.cpp \ +!headless:HEADERS += \ + frametimer.h \ + gpustatus.h \ + +!headless:SOURCES += \ + frametimer.cpp \ + gpustatus.cpp \ + + load(qt_module) diff --git a/src/shared-main-lib/sharedmain.cpp b/src/shared-main-lib/sharedmain.cpp index 6e63e69b..6780efe5 100644 --- a/src/shared-main-lib/sharedmain.cpp +++ b/src/shared-main-lib/sharedmain.cpp @@ -49,7 +49,6 @@ #include #include #include -#include #include #include #include @@ -59,6 +58,7 @@ #if !defined(AM_HEADLESS) # include +# include # include #endif @@ -123,8 +123,13 @@ int &SharedMain::preConstructor(int &argc) void SharedMain::setupIconTheme(const QStringList &themeSearchPaths, const QString &themeName) { +#if defined(AM_HEADLESS) + Q_UNUSED(themeSearchPaths) + Q_UNUSED(themeName) +#else QIcon::setThemeSearchPaths(themeSearchPaths); QIcon::setThemeName(themeName); +#endif } void SharedMain::setupQmlDebugging(bool qmlDebugging) @@ -156,7 +161,9 @@ void SharedMain::setupLoggingRules(bool verbose, const QStringList &loggingRules void SharedMain::setupOpenGL(const QVariantMap &openGLConfiguration) { -#if !defined(AM_HEADLESS) +#if defined(AM_HEADLESS) + Q_UNUSED(openGLConfiguration) +#else QString profileName = openGLConfiguration.value(qSL("desktopProfile")).toString(); int majorVersion = openGLConfiguration.value(qSL("esMajorVersion"), -1).toInt(); int minorVersion = openGLConfiguration.value(qSL("esMinorVersion"), -1).toInt(); diff --git a/src/src.pro b/src/src.pro index 480a19ab..9b51de64 100644 --- a/src/src.pro +++ b/src/src.pro @@ -104,7 +104,9 @@ SUBDIRS = \ qtHaveModule(qml):qtHaveModule(dbus):SUBDIRS += \ launcher_lib \ - # This tool links against everything to extract the Qml type information + + # This tool links against everything to extract the Qml type information + qtHaveModule(qml):qtHaveModule(dbus):!headless:SUBDIRS += \ tools_dumpqmltypes \ multi-process:qtHaveModule(qml):qtHaveModule(dbus):SUBDIRS += \ diff --git a/src/tools/launcher-qml/launcher-qml.cpp b/src/tools/launcher-qml/launcher-qml.cpp index f5fcfbd0..ccaa78da 100644 --- a/src/tools/launcher-qml/launcher-qml.cpp +++ b/src/tools/launcher-qml/launcher-qml.cpp @@ -94,8 +94,10 @@ // monitor-lib #include "cpustatus.h" -#include "frametimer.h" -#include "gpustatus.h" +#if !defined(AM_HEADLESS) +# include "frametimer.h" +# include "gpustatus.h" +#endif #include "iostatus.h" #include "memorystatus.h" #include "monitormodel.h" @@ -185,8 +187,10 @@ Controller::Controller(LauncherMain *a, bool quickLaunched, const QString &direc // monitor-lib qmlRegisterType("QtApplicationManager", 2, 0, "CpuStatus"); +#if !defined(AM_HEADLESS) qmlRegisterType("QtApplicationManager", 2, 0, "FrameTimer"); qmlRegisterType("QtApplicationManager", 2, 0, "GpuStatus"); +#endif qmlRegisterType("QtApplicationManager", 2, 0, "IoStatus"); qmlRegisterType("QtApplicationManager", 2, 0, "MemoryStatus"); qmlRegisterType("QtApplicationManager", 2, 0, "MonitorModel"); @@ -361,6 +365,7 @@ void Controller::startApplication(const QString &baseDir, const QString &qmlFile LauncherMain::instance(), &LauncherMain::setSlowAnimations); } +#if !defined(AM_HEADLESS) // Going through the LauncherMain instance here is a bit weird, and should be refactored // sometime. Having the flag there makes sense though, because this class can also be used for // custom launchers. @@ -371,6 +376,7 @@ void Controller::startApplication(const QString &baseDir, const QString &qmlFile // we need to catch all show events to apply the slow-animations QCoreApplication::instance()->installEventFilter(this); +#endif QStringList startupPluginFiles = variantToStringList(m_configuration.value(qSL("plugins")).toMap().value(qSL("startup"))); auto startupPlugins = loadPlugins("startup", startupPluginFiles); diff --git a/src/tools/testrunner/testrunner.pro b/src/tools/testrunner/testrunner.pro index aa4817bd..c097dba8 100644 --- a/src/tools/testrunner/testrunner.pro +++ b/src/tools/testrunner/testrunner.pro @@ -1,5 +1,7 @@ include(../appman/appman.pro) +requires(!headless) + TARGET = appman-qmltestrunner DEFINES += AM_TESTRUNNER diff --git a/tests/qml/qml.pro b/tests/qml/qml.pro index 78ac75a5..ad01fcb8 100644 --- a/tests/qml/qml.pro +++ b/tests/qml/qml.pro @@ -1,3 +1,7 @@ +load(am-config) + +requires(!headless) + TEMPLATE = subdirs SUBDIRS = \ simple \ -- cgit v1.2.3 From 4433649ed79b409ce59eafab143aff69dca546ed Mon Sep 17 00:00:00 2001 From: Egor Nemtsev Date: Thu, 25 Apr 2019 11:41:43 +0300 Subject: [intents] add intents list to read/write of ApplicationInfo to stream Fixes reading/writing intents into applications db Cherry-picked from dev: 8174e3b Change-Id: Ibfe4354d154aa429462718a565b3340e579f6fa3 Reviewed-by: Robert Griebl --- src/application-lib/applicationinfo.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/application-lib/applicationinfo.cpp b/src/application-lib/applicationinfo.cpp index fd431fc6..f746f849 100644 --- a/src/application-lib/applicationinfo.cpp +++ b/src/application-lib/applicationinfo.cpp @@ -372,7 +372,8 @@ void ApplicationInfo::writeToDataStream(QDataStream &ds) const << m_manifestDir.absolutePath() << m_codeDir.absolutePath() << m_uid - << m_dlt; + << m_dlt + << m_intents; } bool ApplicationInfo::supportsApplicationInterface() const @@ -402,7 +403,8 @@ void ApplicationInfo::read(QDataStream &ds) >> manifestDir >> codeDir >> m_uid - >> m_dlt; + >> m_dlt + >> m_intents; m_capabilities.sort(); m_categories.sort(); @@ -436,6 +438,7 @@ void ApplicationInfo::toVariantMapHelper(QVariantMap &map) const : QString(); map[qSL("supportsApplicationInterface")] = m_supportsApplicationInterface; map[qSL("dlt")] = m_dlt; + map[qSL("intents")] = m_intents; } QT_END_NAMESPACE_AM -- cgit v1.2.3 From 1df51a44f4303410d255fa6b2aacc536fedd58ac Mon Sep 17 00:00:00 2001 From: Dominik Holland Date: Mon, 17 Jun 2019 12:02:55 +0200 Subject: Only calculate the hardwareId once If no other configuration was chosen appman calculates its hardwareId using the available network interfaces. Instead of iterating and sorting them every time the hardwareId is now saved once calculated. This is also a workaround for QTBUG-76408 on macOS which reports a wrong intereface type on the second run and cause the appman to stop without hardwareId. Cherry-picked from dev: c82f080 Task-number: AUTOSUITE-1019 Change-Id: I521245987486b09fce5c410918d0a35be37b1e10 Reviewed-by: Robert Griebl --- src/main-lib/main.cpp | 41 ++++++++++++++++++++++------------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp index 8a4c9788..84b48de7 100644 --- a/src/main-lib/main.cpp +++ b/src/main-lib/main.cpp @@ -1172,30 +1172,33 @@ QVector Main::scanForApplications(const QStringList & QString Main::hardwareId() const { + static QString hardwareId; + if (hardwareId.isEmpty()) { #if defined(AM_HARDWARE_ID) - return QString::fromLocal8Bit(AM_HARDWARE_ID); + hardwareId = QString::fromLocal8Bit(AM_HARDWARE_ID); #elif defined(AM_HARDWARE_ID_FROM_FILE) - QFile f(QString::fromLocal8Bit(AM_HARDWARE_ID_FROM_FILE)); - if (f.open(QFile::ReadOnly)) - return QString::fromLocal8Bit(f.readAll().trimmed()); + QFile f(QString::fromLocal8Bit(AM_HARDWARE_ID_FROM_FILE)); + if (f.open(QFile::ReadOnly)) + hardwareId = QString::fromLocal8Bit(f.readAll().trimmed()); #else - QVector candidateIfaces; - for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) { - if (iface.isValid() - && !(iface.flags() & (QNetworkInterface::IsPointToPoint | QNetworkInterface::IsLoopBack)) - && iface.type() > QNetworkInterface::Virtual - && !iface.hardwareAddress().isEmpty()) { - candidateIfaces << iface; + QVector candidateIfaces; + for (const QNetworkInterface &iface : QNetworkInterface::allInterfaces()) { + if (iface.isValid() + && !(iface.flags() & (QNetworkInterface::IsPointToPoint | QNetworkInterface::IsLoopBack)) + && iface.type() > QNetworkInterface::Virtual + && !iface.hardwareAddress().isEmpty()) { + candidateIfaces << iface; + } + } + if (!candidateIfaces.isEmpty()) { + std::sort(candidateIfaces.begin(), candidateIfaces.end(), [](const QNetworkInterface &first, const QNetworkInterface &second) { + return first.name().compare(second.name()) < 0; + }); + hardwareId = candidateIfaces.constFirst().hardwareAddress().replace(qL1C(':'), qL1S("-")); } - } - if (!candidateIfaces.isEmpty()) { - std::sort(candidateIfaces.begin(), candidateIfaces.end(), [](const QNetworkInterface &first, const QNetworkInterface &second) { - return first.name().compare(second.name()) < 0; - }); - return candidateIfaces.constFirst().hardwareAddress().replace(qL1C(':'), qL1S("-")); - } #endif - return QString(); + } + return hardwareId; } QT_END_NAMESPACE_AM -- cgit v1.2.3 From 93bc72664091403d3c1cbd64274faf3ef31cc902 Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Tue, 2 Jul 2019 16:06:50 +0200 Subject: Fix possibly crashing qml/simple tests Cherry-picked from dev: 6482d3d Change-Id: If5f52f8fcf6f06bb0a4b9820c48b2ae9123f1e90 Reviewed-by: Robert Griebl --- tests/qml/simple/tst_applicationmanager.qml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/qml/simple/tst_applicationmanager.qml b/tests/qml/simple/tst_applicationmanager.qml index 2581d66c..d5c3787e 100644 --- a/tests/qml/simple/tst_applicationmanager.qml +++ b/tests/qml/simple/tst_applicationmanager.qml @@ -127,7 +127,7 @@ TestCase { var id = simpleApplication.id; compare(simpleApplication.id, "tld.test.simple1") compare(simpleApplication.runtimeName, "qml") - compare(simpleApplication.icon, Qt.resolvedUrl("apps/tld.test.simple1/icon.png")) + compare(simpleApplication.icon.toString(), Qt.resolvedUrl("apps/tld.test.simple1/icon.png")) compare(simpleApplication.documentUrl, "") compare(simpleApplication.builtIn, true) compare(simpleApplication.alias, false) @@ -158,7 +158,7 @@ TestCase { compare(applicationAlias.alias, true) compare(applicationAlias.nonAliased, simpleApplication) //TODO this should be a Url instead, as this is what's used in QML usually - compare(applicationAlias.icon, Qt.resolvedUrl("apps/tld.test.simple1/icon2.png")) + compare(applicationAlias.icon.toString(), Qt.resolvedUrl("apps/tld.test.simple1/icon2.png")) compare(applicationAlias.documentUrl, "x-test:alias") compare(applicationAlias.runtimeName, simpleApplication.runtimeName) compare(applicationAlias.capabilities, simpleApplication.capabilities) @@ -193,7 +193,7 @@ TestCase { compare(listView.currentItem.modelData.application, simpleApplication) compare(listView.currentItem.modelData.applicationId, simpleApplication.id) compare(listView.currentItem.modelData.name, "Simple1") - compare(listView.currentItem.modelData.icon, Qt.resolvedUrl(simpleApplication.icon)) + compare(listView.currentItem.modelData.icon.toString(), Qt.resolvedUrl(simpleApplication.icon)) compare(listView.currentItem.modelData.runtimeName, "qml") compare(listView.currentItem.modelData.isRunning, false) compare(listView.currentItem.modelData.isStartingUp, false) @@ -273,7 +273,7 @@ TestCase { compare(appData.application, simpleApplication) compare(appData.applicationId, simpleApplication.id) compare(appData.name, "Simple1") - compare(appData.icon, Qt.resolvedUrl(simpleApplication.icon)) + compare(appData.icon.toString(), Qt.resolvedUrl(simpleApplication.icon)) compare(appData.runtimeName, "qml") compare(appData.isRunning, false) compare(appData.isStartingUp, false) -- cgit v1.2.3 From ef66fc9984a21cb5ef5d4f660172848c19603caf Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Tue, 2 Jul 2019 18:38:50 +0200 Subject: Make sure the app-db is flushed after writing Otherwise we might end up with a 0-byte app db, if the AM gets killed before the OS (notably Windows) has synced the data to disk. Cherry-picked from dev: 071799b Task-number: AUTOSUITE-1096 Change-Id: Ifacf4854ab3f2b454d098a7b503b3922f72f9742 Reviewed-by: Robert Griebl --- src/main-lib/main.cpp | 2 ++ src/manager-lib/applicationdatabase.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/main-lib/main.cpp b/src/main-lib/main.cpp index 84b48de7..22a4abf5 100644 --- a/src/main-lib/main.cpp +++ b/src/main-lib/main.cpp @@ -424,6 +424,8 @@ void Main::loadApplicationDatabase(const QString &databasePath, bool recreateDat if (singleApp.isEmpty()) { if (!QFile::exists(databasePath)) // make sure to create a database on the first run recreateDatabase = true; + if (QFileInfo(databasePath).size() == 0) // cope with Windows' 0-byte left-overs + recreateDatabase = true; if (recreateDatabase) { const QString dbDir = QFileInfo(databasePath).absolutePath(); diff --git a/src/manager-lib/applicationdatabase.cpp b/src/manager-lib/applicationdatabase.cpp index 1b336a9b..a6fb8ef3 100644 --- a/src/manager-lib/applicationdatabase.cpp +++ b/src/manager-lib/applicationdatabase.cpp @@ -167,6 +167,8 @@ void ApplicationDatabase::write(const QVector &apps) Q_DE if (ds.status() != QDataStream::Ok) throw Exception(*d->file, "could not write to application database"); + + d->file->flush(); } void ApplicationDatabase::invalidate() -- cgit v1.2.3 From ecf00cd214a771799717d9f2b24c300d8c50cccc Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Wed, 26 Jun 2019 15:32:11 +0200 Subject: Wait for apps to stop before actually uninstalling them Cherry-picked from dev: f6a895c Change-Id: Iaf4b3da0c622079ccb79886875134af58175bd43 Task-number: AUTOSUITE-1075 Reviewed-by: Robert Griebl --- src/installer-lib/deinstallationtask.cpp | 16 ++++++++++++++++ src/installer-lib/deinstallationtask.h | 5 +++++ src/window-lib/window.h | 4 ++-- 3 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/installer-lib/deinstallationtask.cpp b/src/installer-lib/deinstallationtask.cpp index fd8c56f7..cb03cb83 100644 --- a/src/installer-lib/deinstallationtask.cpp +++ b/src/installer-lib/deinstallationtask.cpp @@ -63,6 +63,13 @@ DeinstallationTask::DeinstallationTask(ApplicationInfo *app, const InstallationL m_applicationId = m_app->id(); // in base class } +bool DeinstallationTask::cancel() +{ + if (m_canBeCanceled) + m_canceled = true; + return m_canceled; +} + void DeinstallationTask::execute() { // these have been checked in ApplicationInstaller::removePackage() already @@ -84,6 +91,15 @@ void DeinstallationTask::execute() if (!managerApproval) throw Exception("ApplicationManager rejected the removal of app %1").arg(m_app->id()); + // if the app was running before, we now need to wait until is has actually stopped + while (!m_canceled && + (ApplicationManager::instance()->applicationRunState(m_app->id()) != Am::NotRunning)) { + QThread::msleep(30); + } + // there's a small race condition here, but not doing a planned cancellation isn't harmful + m_canBeCanceled = false; + if (m_canceled) + throw Exception(Error::Canceled, "canceled"); ScopedRenamer docDirRename; ScopedRenamer appDirRename; diff --git a/src/installer-lib/deinstallationtask.h b/src/installer-lib/deinstallationtask.h index 912a34a1..f990cee7 100644 --- a/src/installer-lib/deinstallationtask.h +++ b/src/installer-lib/deinstallationtask.h @@ -56,6 +56,9 @@ class DeinstallationTask : public AsynchronousTask public: DeinstallationTask(ApplicationInfo *app, const InstallationLocation &installationLocation, bool forceDeinstallation, bool keepDocuments, QObject *parent = nullptr); + + bool cancel() override; + protected: void execute() override; @@ -64,6 +67,8 @@ private: const InstallationLocation &m_installationLocation; bool m_forceDeinstallation; bool m_keepDocuments; + bool m_canBeCanceled = true; + bool m_canceled = false; }; QT_END_NAMESPACE_AM diff --git a/src/window-lib/window.h b/src/window-lib/window.h index a856b4d3..b9a7c69d 100644 --- a/src/window-lib/window.h +++ b/src/window-lib/window.h @@ -48,10 +48,10 @@ #include #include #include +#include QT_BEGIN_NAMESPACE_AM -class AbstractApplication; class WindowItem; // A Window object exists for every application window that is managed by the application-manager @@ -117,7 +117,7 @@ signals: void _windowDestroyed(); protected: - AbstractApplication *m_application; + QPointer m_application; QSet m_items; WindowItem *m_primaryItem{nullptr}; -- cgit v1.2.3 From 3adab135d7aa4c560d29d39964f3ba4afa5abf94 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Wed, 26 Jun 2019 13:44:25 +0200 Subject: Fix crashes when trying to start blocked apps Cherry-picked from dev: 6be19e2 Task-number: AUTOSUITE-1079 Change-Id: I11fb811af92d782815659ce41c50008f9b336a71 Reviewed-by: Robert Griebl --- src/manager-lib/applicationmanager.cpp | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp index 370b45e3..b2745ecb 100644 --- a/src/manager-lib/applicationmanager.cpp +++ b/src/manager-lib/applicationmanager.cpp @@ -1039,7 +1039,12 @@ bool ApplicationManager::openUrl(const QString &urlStr) if (!apps.isEmpty()) { if (!isSignalConnected(QMetaMethod::fromSignal(&ApplicationManager::openUrlRequested))) { // If the System-UI does not react to the signal, then just use the first match. - startApplicationInternal(apps.constFirst(), urlStr, mimeTypeName); + try { + startApplicationInternal(apps.constFirst(), urlStr, mimeTypeName); + } catch (const Exception &e) { + qCWarning(LogSystem) << "openUrl for" << urlStr << "requested app" << apps.constFirst()->id() + << "which could not be started:" << e.errorString(); + } } else { ApplicationManagerPrivate::OpenUrlRequest req { QUuid::createUuid().toString(), @@ -1096,7 +1101,12 @@ void ApplicationManager::acknowledgeOpenUrlRequest(const QString &requestId, con for (auto it = d->openUrlRequests.begin(); it != d->openUrlRequests.end(); ++it) { if (it->requestId == requestId) { if (it->possibleAppIds.contains(appId)) { - startApplicationInternal(application(appId), it->urlStr, it->mimeTypeName); + try { + startApplicationInternal(application(appId), it->urlStr, it->mimeTypeName); + } catch (const Exception &e) { + qCWarning(LogSystem) << "acknowledgeOpenUrlRequest for" << it->urlStr << "requested app" + << appId << "which could not be started:" << e.errorString(); + } } else { qCWarning(LogSystem) << "acknowledgeOpenUrlRequest for" << it->urlStr << "requested app" << appId << "which is not one of the registered possibilities:" @@ -1374,7 +1384,7 @@ void ApplicationManager::startSingleAppAndQuitWhenStopped() AbstractApplication *app = d->apps[0]; - if (!startApplicationInternal(app)) { + if (!startApplication(app->id())) { QMetaObject::invokeMethod(qApp, "shutDown", Qt::DirectConnection, Q_ARG(int, 1)); } else { connect(this, &ApplicationManager::applicationRunStateChanged, [app](const QString &id, Am::RunState runState) { @@ -1657,7 +1667,7 @@ void ApplicationManager::addApplication(AbstractApplication *app) connect (&app->requests, &ApplicationRequests::startRequested, this, [this, app](const QString &documentUrl) { - startApplicationInternal(app, documentUrl); + startApplication(app->id(), documentUrl); }); connect (&app->requests, &ApplicationRequests::debugRequested, -- cgit v1.2.3 From 0cb42db5bb3ff97f1549ef3053ef5685b8dc5e9c Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Fri, 17 May 2019 14:43:09 +0200 Subject: Fix broken Wayland socket name detection The algorithm for finding a free 'qtam-wayland-%d' Wayland socket was modelled after the code in libwayland-server, but due to a mixup between the socket filename and the lock filename it was not working correctly. Cherry-picked from dev: 4d01c85 Change-Id: Iac204c31fd0e6c239e44acefb5d65afe414461a8 Task-number: AUTOSUITE-857 Reviewed-by: Robert Griebl --- src/main-lib/defaultconfiguration.cpp | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/main-lib/defaultconfiguration.cpp b/src/main-lib/defaultconfiguration.cpp index 6ee6b2e0..2987a52a 100644 --- a/src/main-lib/defaultconfiguration.cpp +++ b/src/main-lib/defaultconfiguration.cpp @@ -45,6 +45,10 @@ #include #include +#if defined(Q_OS_LINUX) +# include +#endif + #include #include "defaultconfiguration.h" @@ -456,12 +460,24 @@ QString DefaultConfiguration::waylandSocketName() const if (qEnvironmentVariableIsSet(envName)) return qEnvironmentVariable(envName); - const QString lockPattern = qEnvironmentVariable("XDG_RUNTIME_DIR") + qSL("/qtam-wayland-%1.lock"); +#if defined(Q_OS_LINUX) + // modelled after wl_socket_lock() in wayland_server.c + const QString xdgDir = qEnvironmentVariable("XDG_RUNTIME_DIR") + qSL("/"); + const QString pattern = qSL("qtam-wayland-%1"); + const QString lockSuffix = qSL(".lock"); + for (int i = 0; i < 32; ++i) { - QFile lock(lockPattern.arg(i)); - if (lock.open(QIODevice::ReadWrite | QIODevice::NewOnly)) - return qSL("qtam-wayland-%1").arg(i); + const QString socketName = pattern.arg(i); + QFile lock(xdgDir + socketName + lockSuffix); + if (lock.open(QIODevice::ReadWrite)) { + if (::flock(lock.handle(), LOCK_EX | LOCK_NB) == 0) { + QFile socket(xdgDir + socketName); + if (!socket.exists() || socket.remove()) + return socketName; + } + } } +#endif return QString(); } -- cgit v1.2.3 From c5db47a7b53c5800a3af6a6f2f79925ba3a71c57 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Fri, 17 May 2019 12:56:21 +0200 Subject: Fix applications reusing a runtime object that is about to be destructed Cherry-picked from dev: d1ac8c9 Change-Id: I784772e66afe55434297b89669d2555318887dde Task-number: AUTOSUITE-925 Reviewed-by: Robert Griebl --- src/manager-lib/nativeruntime.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/manager-lib/nativeruntime.cpp b/src/manager-lib/nativeruntime.cpp index 3283a923..c5786ffd 100644 --- a/src/manager-lib/nativeruntime.cpp +++ b/src/manager-lib/nativeruntime.cpp @@ -234,8 +234,11 @@ void NativeRuntime::shutdown(int exitCode, Am::ExitStatus status) emit applicationDisconnectedFromPeerDBus(connection, application()); emit finished(exitCode, status); - setState(Am::NotRunning); + if (m_app) + m_app->setCurrentRuntime(nullptr); + + setState(Am::NotRunning); deleteLater(); } -- cgit v1.2.3 From 35046bc0913f7eda19716348eb1284351a4443ff Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Fri, 17 May 2019 12:42:59 +0200 Subject: Destroy QDBusServer instance when an application quits Cherry-picked from dev: 742f39b Change-Id: Id4e38169185e6a99a38294d7c5146efcf5db4716 Task-number: AUTOSUITE-951 Reviewed-by: Robert Griebl --- src/manager-lib/nativeruntime.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/manager-lib/nativeruntime.cpp b/src/manager-lib/nativeruntime.cpp index c5786ffd..ad7d5231 100644 --- a/src/manager-lib/nativeruntime.cpp +++ b/src/manager-lib/nativeruntime.cpp @@ -106,7 +106,7 @@ NativeRuntime::NativeRuntime(AbstractContainer *container, Application *app, Nat , m_startedViaLauncher(manager->identifier() != qL1S("native")) { QString dbusAddress = QUuid::createUuid().toString().mid(1,36); - m_applicationInterfaceServer = new QDBusServer(qSL("unix:path=/tmp/dbus-qtam-") + dbusAddress); + m_applicationInterfaceServer = new QDBusServer(qSL("unix:path=/tmp/dbus-qtam-") + dbusAddress, this); connect(m_applicationInterfaceServer, &QDBusServer::newConnection, this, [this](const QDBusConnection &connection) { -- cgit v1.2.3 From 6467ca84366d897ba4ed25ed74560296070b571d Mon Sep 17 00:00:00 2001 From: Bernd Weimer Date: Mon, 22 Jul 2019 16:43:49 +0200 Subject: Fix app start/stop in single-process mode If an app has been started and immediately stopped again, the next time the app is started the assert would fail, that checks that the app's root object is null. The stop signal would be handled before the InProcessWindow could be created and hence the app's window surface would never be released. The assert is in QmlInProcessRuntime::start(). Cherry-picked from dev: cada823 Change-Id: I0711416a0fa4582bdaaa0a7f9b0c081eb6539c01 Reviewed-by: Robert Griebl --- src/window-lib/windowmanager.cpp | 2 +- tests/qml/windowmapping/tst_windowmapping.qml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/window-lib/windowmanager.cpp b/src/window-lib/windowmanager.cpp index 096db273..97a3b68c 100644 --- a/src/window-lib/windowmanager.cpp +++ b/src/window-lib/windowmanager.cpp @@ -491,7 +491,7 @@ void WindowManager::setupInProcessRuntime(AbstractRuntime *runtime) runtime->setInProcessQmlEngine(d->qmlEngine); connect(runtime, &AbstractRuntime::inProcessSurfaceItemReady, - this, &WindowManager::inProcessSurfaceItemCreated, Qt::QueuedConnection); + this, &WindowManager::inProcessSurfaceItemCreated); } } diff --git a/tests/qml/windowmapping/tst_windowmapping.qml b/tests/qml/windowmapping/tst_windowmapping.qml index 5e5d0f45..00a6e582 100644 --- a/tests/qml/windowmapping/tst_windowmapping.qml +++ b/tests/qml/windowmapping/tst_windowmapping.qml @@ -292,6 +292,7 @@ TestCase { function test_window_properties() { var app = ApplicationManager.application("test.winmap.amwin"); + windowPropertyChangedSpy.clear(); app.start(); tryCompare(WindowManager, "count", 1); -- cgit v1.2.3 From e49107e72c12f931a3d2c20c67195fec6513a783 Mon Sep 17 00:00:00 2001 From: Robert Griebl Date: Thu, 1 Aug 2019 13:12:00 +0200 Subject: Bump version to 5.12.4 Change-Id: Ib1dfa2b4d80d5bbda9848be9870e4a02c14d7bab Reviewed-by: Dominik Holland --- .qmake.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.qmake.conf b/.qmake.conf index ba10eefc..d8b9ff65 100644 --- a/.qmake.conf +++ b/.qmake.conf @@ -1,6 +1,6 @@ load(qt_build_config) -MODULE_VERSION = 5.12.1 +MODULE_VERSION = 5.12.4 SOURCE_DIR=$$PWD BUILD_DIR=$$shadowed($$PWD) -- cgit v1.2.3