diff options
-rw-r--r-- | qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes | 5 | ||||
-rw-r--r-- | src/dbus-lib/applicationmanagerdbuscontextadaptor.cpp | 6 | ||||
-rw-r--r-- | src/dbus-lib/dbuspolicy.cpp | 6 | ||||
-rw-r--r-- | src/dbus-lib/io.qt.applicationmanager.xml | 4 | ||||
-rw-r--r-- | src/manager-lib/applicationmanager.cpp | 39 | ||||
-rw-r--r-- | src/manager-lib/applicationmanager.h | 3 | ||||
-rw-r--r-- | src/window-lib/waylandcompositor.cpp | 9 | ||||
-rw-r--r-- | src/window-lib/waylandcompositor.h | 1 | ||||
-rw-r--r-- | src/window-lib/windowmanager.cpp | 20 |
9 files changed, 83 insertions, 10 deletions
diff --git a/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes b/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes index 5b7ce6ce..f9b4460c 100644 --- a/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes +++ b/qmltypes/QtApplicationManager/SystemUI/plugins.qmltypes @@ -1124,6 +1124,11 @@ Module { Parameter { name: "pid"; type: "int"; } } Method { + name: "identifyAllApplications" + type: "QStringList" + Parameter { name: "pid"; type: "int"; } + } + Method { name: "applicationRunState" type: "RunState" Parameter { name: "id"; type: "string"; } diff --git a/src/dbus-lib/applicationmanagerdbuscontextadaptor.cpp b/src/dbus-lib/applicationmanagerdbuscontextadaptor.cpp index c12ae788..5ad54940 100644 --- a/src/dbus-lib/applicationmanagerdbuscontextadaptor.cpp +++ b/src/dbus-lib/applicationmanagerdbuscontextadaptor.cpp @@ -206,6 +206,12 @@ QString ApplicationManagerAdaptor::identifyApplication(qlonglong pid) return ApplicationManager::instance()->identifyApplication(pid); } +QStringList ApplicationManagerAdaptor::identifyAllApplications(qlonglong pid) +{ + AM_AUTHENTICATE_DBUS(QStringList) + return ApplicationManager::instance()->identifyAllApplications(pid); +} + bool ApplicationManagerAdaptor::openUrl(const QString &url) { AM_AUTHENTICATE_DBUS(bool) diff --git a/src/dbus-lib/dbuspolicy.cpp b/src/dbus-lib/dbuspolicy.cpp index ef6214f6..43ed01b0 100644 --- a/src/dbus-lib/dbuspolicy.cpp +++ b/src/dbus-lib/dbuspolicy.cpp @@ -140,7 +140,11 @@ bool DBusPolicy::check(QDBusAbstractAdaptor *dbusAdaptor, const QByteArray &func if (!ip->m_capabilities.isEmpty()) { pid = dbusContext->connection().interface()->servicePid(dbusContext->message().service()); - QStringList appCaps = ApplicationManager::instance()->capabilities(ApplicationManager::instance()->identifyApplication(pid)); + const auto apps = ApplicationManager::instance()->identifyAllApplications(pid); + if (apps.size() > 1) + throw "multiple apps per pid are not supported"; + const QString appId = !apps.isEmpty() ? apps.constFirst() : QString(); + QStringList appCaps = ApplicationManager::instance()->capabilities(appId); bool match = false; for (const QString &cap : ip->m_capabilities) match = match && std::binary_search(appCaps.cbegin(), appCaps.cend(), cap); diff --git a/src/dbus-lib/io.qt.applicationmanager.xml b/src/dbus-lib/io.qt.applicationmanager.xml index 70ca1111..74294862 100644 --- a/src/dbus-lib/io.qt.applicationmanager.xml +++ b/src/dbus-lib/io.qt.applicationmanager.xml @@ -95,6 +95,10 @@ <arg type="s" direction="out"/> <arg name="pid" type="x" direction="in"/> </method> + <method name="identifyAllApplications"> + <arg type="as" direction="out"/> + <arg name="pid" type="x" direction="in"/> + </method> <method name="applicationRunState"> <arg type="u" direction="out"/> <arg name="id" type="s" direction="in"/> diff --git a/src/manager-lib/applicationmanager.cpp b/src/manager-lib/applicationmanager.cpp index 58da711f..938333bb 100644 --- a/src/manager-lib/applicationmanager.cpp +++ b/src/manager-lib/applicationmanager.cpp @@ -515,19 +515,23 @@ Application *ApplicationManager::fromId(const QString &id) const return nullptr; } -Application *ApplicationManager::fromProcessId(qint64 pid) const +QVector<Application *> ApplicationManager::fromProcessId(qint64 pid) const { + QVector<Application *> apps; + // pid could be an indirect child (e.g. when started via gdbserver) qint64 appmanPid = QCoreApplication::applicationPid(); while ((pid > 1) && (pid != appmanPid)) { for (Application *app : d->apps) { + if (apps.contains(app)) + continue; if (app->currentRuntime() && (app->currentRuntime()->applicationProcessId() == pid)) - return app; + apps.append(app); } pid = getParentPid(pid); } - return nullptr; + return apps; } Application *ApplicationManager::fromSecurityToken(const QByteArray &securityToken) const @@ -1119,12 +1123,37 @@ QStringList ApplicationManager::capabilities(const QString &id) const Validates the process running with process-identifier \a pid as a process started by the application manager. + \note If multiple applications are running within the same container process, this function + will return only the first matching application. See identifyAllApplications() for + a way to retrieve all application ids. + Returns the application's \c id on success, or an empty string on failure. */ QString ApplicationManager::identifyApplication(qint64 pid) const { - Application *app = fromProcessId(pid); - return app ? app->id() : QString(); + const auto apps = fromProcessId(pid); + return !apps.isEmpty() ? apps.constFirst()->id() : QString(); +} + +/*! + \qmlmethod list<string> ApplicationManager::identifyAllApplications(int pid) + + Validates the process running with process-identifier \a pid as a process started by the + application manager. + + If multiple applications are running within the same container process, this function will + return all those application ids. + + Returns a list with the applications' \c ids on success, or an empty list on failure. +*/ +QStringList ApplicationManager::identifyAllApplications(qint64 pid) const +{ + const auto apps = fromProcessId(pid); + QStringList result; + result.reserve(apps.size()); + for (const auto &app : apps) + result << app->id(); + return result; } void ApplicationManager::shutDown() diff --git a/src/manager-lib/applicationmanager.h b/src/manager-lib/applicationmanager.h index d7d8f0fa..498f2ba5 100644 --- a/src/manager-lib/applicationmanager.h +++ b/src/manager-lib/applicationmanager.h @@ -102,7 +102,7 @@ public: QVector<Application *> applications() const; Application *fromId(const QString &id) const; - Application *fromProcessId(qint64 pid) const; + QVector<Application *> fromProcessId(qint64 pid) const; Application *fromSecurityToken(const QByteArray &securityToken) const; QVector<Application *> schemeHandlers(const QString &scheme) const; QVector<Application *> mimeTypeHandlers(const QString &mimeType) const; @@ -151,6 +151,7 @@ public: Q_SCRIPTABLE bool openUrl(const QString &url); Q_SCRIPTABLE QStringList capabilities(const QString &id) const; Q_SCRIPTABLE QString identifyApplication(qint64 pid) const; + Q_SCRIPTABLE QStringList identifyAllApplications(qint64 pid) const; Q_SCRIPTABLE QT_PREPEND_NAMESPACE_AM(Am::RunState) applicationRunState(const QString &id) const; ApplicationManagerInternalSignals internalSignals; diff --git a/src/window-lib/waylandcompositor.cpp b/src/window-lib/waylandcompositor.cpp index 45b2cbb7..8854089d 100644 --- a/src/window-lib/waylandcompositor.cpp +++ b/src/window-lib/waylandcompositor.cpp @@ -94,6 +94,13 @@ WaylandCompositor *WindowSurface::compositor() const return m_compositor; } +QString WindowSurface::applicationId() const +{ + if (m_xdgSurface && m_xdgSurface->toplevel()) + return m_xdgSurface->toplevel()->appId(); + return { }; +} + bool WindowSurface::isPopup() const { return m_popup; @@ -167,7 +174,7 @@ WaylandCompositor::WaylandCompositor(QQuickWindow *window, const QString &waylan auto wmext = new QWaylandQtWindowManager(this); connect(wmext, &QWaylandQtWindowManager::openUrl, this, [](QWaylandClient *client, const QUrl &url) { - if (ApplicationManager::instance()->fromProcessId(client->processId())) + if (!ApplicationManager::instance()->fromProcessId(client->processId()).isEmpty()) ApplicationManager::instance()->openUrl(url.toString()); }); diff --git a/src/window-lib/waylandcompositor.h b/src/window-lib/waylandcompositor.h index ddf0ab97..fdb8add9 100644 --- a/src/window-lib/waylandcompositor.h +++ b/src/window-lib/waylandcompositor.h @@ -90,6 +90,7 @@ public: QWaylandWlShellSurface *shellSurface() const; WaylandCompositor *compositor() const; + QString applicationId() const; bool isPopup() const; QRect popupGeometry() const; void sendResizing(const QSize &size); diff --git a/src/window-lib/windowmanager.cpp b/src/window-lib/windowmanager.cpp index 0d8c7e9c..69201f01 100644 --- a/src/window-lib/windowmanager.cpp +++ b/src/window-lib/windowmanager.cpp @@ -808,11 +808,27 @@ void WindowManager::waylandSurfaceCreated(QWaylandSurface *surface) void WindowManager::waylandSurfaceMapped(WindowSurface *surface) { qint64 processId = surface->processId(); - Application *app = ApplicationManager::instance()->fromProcessId(processId); + const auto apps = ApplicationManager::instance()->fromProcessId(processId); + Application *app = nullptr; + + if (apps.size() == 1) { + app = apps.constFirst(); + } else if (apps.size() > 1) { + // if there is more than one app within the same process, check the XDG surface appId + const QString xdgAppId = surface->applicationId(); + if (!xdgAppId.isEmpty()) { + for (const auto &checkApp : apps) { + if (checkApp->id() == xdgAppId) { + app = checkApp; + break; + } + } + } + } if (!app && ApplicationManager::instance()->securityChecksEnabled()) { qCCritical(LogGraphics) << "SECURITY ALERT: an unknown application with pid" << processId - << "tried to map a Wayland surface!"; + << "tried to map a Wayland surface!"; return; } |