File indexing completed on 2024-11-10 04:57:32

0001 /*
0002     SPDX-FileCopyrightText: 2023 David Edmundson <davidedmundson@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 #include "securitycontext_v1.h"
0007 #include "display.h"
0008 #include "utils/filedescriptor.h"
0009 #include "wayland/display_p.h"
0010 
0011 #include <qwayland-server-security-context-v1.h>
0012 
0013 #include <QDebug>
0014 
0015 class QSocketNotifier;
0016 
0017 namespace KWin
0018 {
0019 static const quint32 s_version = 1;
0020 
0021 class SecurityContextManagerV1InterfacePrivate : public QtWaylandServer::wp_security_context_manager_v1
0022 {
0023 public:
0024     SecurityContextManagerV1InterfacePrivate(Display *display);
0025 
0026 protected:
0027     void wp_security_context_manager_v1_destroy(Resource *resource) override;
0028     void wp_security_context_manager_v1_create_listener(Resource *resource, uint32_t id, int32_t listen_fd, int32_t close_fd) override;
0029 
0030 private:
0031     Display *m_display;
0032 };
0033 
0034 class SecurityContextV1Interface : public QtWaylandServer::wp_security_context_v1
0035 {
0036 public:
0037     SecurityContextV1Interface(Display *display, int listenFd, int closeFd, wl_resource *resource);
0038 
0039 protected:
0040     void wp_security_context_v1_set_sandbox_engine(Resource *resource, const QString &name) override;
0041     void wp_security_context_v1_set_app_id(Resource *resource, const QString &app_id) override;
0042     void wp_security_context_v1_set_instance_id(Resource *resource, const QString &instance_id) override;
0043     void wp_security_context_v1_commit(Resource *resource) override;
0044     void wp_security_context_v1_destroy_resource(Resource *resource) override;
0045     void wp_security_context_v1_destroy(Resource *resource) override;
0046 
0047 private:
0048     Display *m_display;
0049     FileDescriptor m_listenFd;
0050     FileDescriptor m_closeFd;
0051     bool m_committed = false;
0052     QString m_sandboxEngine;
0053     QString m_appId;
0054     QString m_instanceId;
0055 };
0056 
0057 SecurityContextManagerV1Interface::SecurityContextManagerV1Interface(Display *display, QObject *parent)
0058     : QObject(parent)
0059     , d(new SecurityContextManagerV1InterfacePrivate(display))
0060 {
0061 }
0062 
0063 SecurityContextManagerV1Interface::~SecurityContextManagerV1Interface()
0064 {
0065 }
0066 
0067 SecurityContextManagerV1InterfacePrivate::SecurityContextManagerV1InterfacePrivate(Display *display)
0068     : QtWaylandServer::wp_security_context_manager_v1(*display, s_version)
0069     , m_display(display)
0070 {
0071 }
0072 
0073 void SecurityContextManagerV1InterfacePrivate::wp_security_context_manager_v1_destroy(Resource *resource)
0074 {
0075     wl_resource_destroy(resource->handle);
0076 }
0077 
0078 void SecurityContextManagerV1InterfacePrivate::wp_security_context_manager_v1_create_listener(Resource *resource, uint32_t id, int32_t listen_fd, int32_t close_fd)
0079 {
0080     auto *securityContextResource = wl_resource_create(resource->client(), &wp_security_context_v1_interface, resource->version(), id);
0081     if (!securityContextResource) {
0082         wl_resource_post_no_memory(resource->handle);
0083         return;
0084     }
0085     new SecurityContextV1Interface(m_display, listen_fd, close_fd, securityContextResource);
0086 }
0087 
0088 SecurityContextV1Interface::SecurityContextV1Interface(Display *display, int listenFd, int closeFd, wl_resource *resource)
0089     : QtWaylandServer::wp_security_context_v1(resource)
0090     , m_display(display)
0091     , m_listenFd(listenFd)
0092     , m_closeFd(closeFd)
0093 {
0094 }
0095 
0096 void SecurityContextV1Interface::wp_security_context_v1_set_sandbox_engine(Resource *resource, const QString &name)
0097 {
0098     if (m_committed) {
0099         wl_resource_post_error(resource->handle, error_already_used, "Already committed");
0100         return;
0101     }
0102     m_sandboxEngine = name;
0103 }
0104 
0105 void SecurityContextV1Interface::wp_security_context_v1_set_app_id(Resource *resource, const QString &app_id)
0106 {
0107     if (m_committed) {
0108         wl_resource_post_error(resource->handle, error_already_used, "Already committed");
0109         return;
0110     }
0111     if (app_id.isEmpty()) {
0112         wl_resource_post_error(resource->handle, error_invalid_metadata, "App ID cannot be empty");
0113         return;
0114     }
0115     m_appId = app_id;
0116 }
0117 
0118 void SecurityContextV1Interface::wp_security_context_v1_set_instance_id(Resource *resource, const QString &instance_id)
0119 {
0120     if (m_committed) {
0121         wl_resource_post_error(resource->handle, error_already_used, "Already committed");
0122         return;
0123     }
0124     m_instanceId = instance_id;
0125 }
0126 
0127 void SecurityContextV1Interface::wp_security_context_v1_commit(Resource *resource)
0128 {
0129     if (m_committed) {
0130         wl_resource_post_error(resource->handle, error_already_used, "Already committed");
0131         return;
0132     }
0133     if (m_appId.isEmpty()) {
0134         wl_resource_post_error(resource->handle, error_invalid_metadata, "App ID cannot be empty");
0135         return;
0136     }
0137     if (m_sandboxEngine.isEmpty()) {
0138         wl_resource_post_error(resource->handle, error_invalid_metadata, "Sandbox engine cannot be empty");
0139         return;
0140     }
0141 
0142     m_committed = true;
0143 
0144     // lifespan is managed by the closeFD's state
0145     new SecurityContext(m_display, std::move(m_listenFd), std::move(m_closeFd), m_appId);
0146 }
0147 
0148 void SecurityContextV1Interface::wp_security_context_v1_destroy_resource(Resource *resource)
0149 {
0150     delete this;
0151 }
0152 
0153 void SecurityContextV1Interface::wp_security_context_v1_destroy(Resource *resource)
0154 {
0155     wl_resource_destroy(resource->handle);
0156 }
0157 
0158 }