mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -05:00
add portal module again
This access module now only checks if the connection is comming from the portal and tags the ACCESS property with portal in that case. It will no longer do permission store checks, that's for the session manager.
This commit is contained in:
parent
9b00462561
commit
5731447357
2 changed files with 294 additions and 0 deletions
286
src/modules/module-portal.c
Normal file
286
src/modules/module-portal.c
Normal file
|
|
@ -0,0 +1,286 @@
|
|||
/* PipeWire
|
||||
* Copyright (C) 2016 Wim Taymans <wim.taymans@gmail.com>
|
||||
* Copyright (C) 2019 Red Hat Inc.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Library General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Library General Public
|
||||
* License along with this library; if not, write to the
|
||||
* Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
|
||||
* Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
#include <spa/support/dbus.h>
|
||||
|
||||
#include "pipewire/context.h"
|
||||
#include "pipewire/impl-client.h"
|
||||
#include "pipewire/log.h"
|
||||
#include "pipewire/module.h"
|
||||
#include "pipewire/utils.h"
|
||||
#include "pipewire/private.h"
|
||||
|
||||
#define NAME "portal"
|
||||
|
||||
struct impl {
|
||||
struct pw_context *context;
|
||||
struct pw_properties *properties;
|
||||
|
||||
struct spa_dbus_connection *conn;
|
||||
DBusConnection *bus;
|
||||
|
||||
struct spa_hook context_listener;
|
||||
struct spa_hook module_listener;
|
||||
|
||||
DBusPendingCall *portal_pid_pending;
|
||||
pid_t portal_pid;
|
||||
unsigned int first:1;
|
||||
};
|
||||
|
||||
static void
|
||||
context_check_access(void *data, struct pw_impl_client *client)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
const struct pw_properties *props;
|
||||
const char *str;
|
||||
struct pw_permission permissions[1];
|
||||
struct spa_dict_item items[1];
|
||||
pid_t pid;
|
||||
|
||||
if (impl->portal_pid == 0)
|
||||
return;
|
||||
|
||||
if ((props = pw_impl_client_get_properties(client)) == NULL)
|
||||
return;
|
||||
|
||||
if ((str = pw_properties_get(props, PW_KEY_SEC_PID)) == NULL)
|
||||
return;
|
||||
|
||||
pid = atoi(str);
|
||||
if (pid != impl->portal_pid)
|
||||
return;
|
||||
|
||||
items[0] = SPA_DICT_ITEM_INIT(PW_KEY_ACCESS, "portal");
|
||||
pw_impl_client_update_properties(client, &SPA_DICT_INIT(items, 1));
|
||||
|
||||
pw_log_info(NAME" %p: portal managed client %p added", impl, client);
|
||||
|
||||
/* portal makes this connection and will change the permissions before
|
||||
* handing this connection to the client */
|
||||
permissions[0] = PW_PERMISSION_INIT(PW_ID_ANY, PW_PERM_RWX);
|
||||
pw_impl_client_update_permissions(client, 1, permissions);
|
||||
return;
|
||||
}
|
||||
|
||||
static const struct pw_context_events context_events = {
|
||||
PW_VERSION_CONTEXT_EVENTS,
|
||||
.check_access = context_check_access,
|
||||
};
|
||||
|
||||
static void module_destroy(void *data)
|
||||
{
|
||||
struct impl *impl = data;
|
||||
|
||||
spa_hook_remove(&impl->context_listener);
|
||||
spa_hook_remove(&impl->module_listener);
|
||||
|
||||
spa_dbus_connection_destroy(impl->conn);
|
||||
|
||||
if (impl->properties)
|
||||
pw_properties_free(impl->properties);
|
||||
|
||||
free(impl);
|
||||
}
|
||||
|
||||
static const struct pw_impl_module_events module_events = {
|
||||
PW_VERSION_IMPL_MODULE_EVENTS,
|
||||
.destroy = module_destroy,
|
||||
};
|
||||
|
||||
static void on_portal_pid_received(DBusPendingCall *pending,
|
||||
void *user_data)
|
||||
{
|
||||
struct impl *impl = user_data;
|
||||
DBusMessage *m;
|
||||
DBusError error;
|
||||
uint32_t portal_pid = 0;
|
||||
|
||||
m = dbus_pending_call_steal_reply(pending);
|
||||
dbus_pending_call_unref(pending);
|
||||
impl->portal_pid_pending = NULL;
|
||||
|
||||
if (!m) {
|
||||
pw_log_error("Failed to receive portal pid");
|
||||
return;
|
||||
}
|
||||
|
||||
dbus_error_init(&error);
|
||||
dbus_message_get_args(m, &error, DBUS_TYPE_UINT32, &portal_pid,
|
||||
DBUS_TYPE_INVALID);
|
||||
dbus_message_unref(m);
|
||||
|
||||
if (dbus_error_is_set(&error)) {
|
||||
impl->portal_pid = 0;
|
||||
}
|
||||
else {
|
||||
pw_log_info("Got portal pid %d", portal_pid);
|
||||
impl->portal_pid = portal_pid;
|
||||
impl->first = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void update_portal_pid(struct impl *impl)
|
||||
{
|
||||
DBusMessage *m;
|
||||
const char *name;
|
||||
DBusPendingCall *pending;
|
||||
|
||||
impl->portal_pid = 0;
|
||||
|
||||
m = dbus_message_new_method_call("org.freedesktop.DBus",
|
||||
"/",
|
||||
"org.freedesktop.DBus",
|
||||
"GetConnectionUnixProcessID");
|
||||
|
||||
name = "org.freedesktop.portal.Desktop";
|
||||
dbus_message_append_args(m,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
dbus_connection_send_with_reply(impl->bus, m, &pending, -1);
|
||||
dbus_pending_call_set_notify(pending, on_portal_pid_received, impl, NULL);
|
||||
if (impl->portal_pid_pending != NULL) {
|
||||
dbus_pending_call_cancel(impl->portal_pid_pending);
|
||||
dbus_pending_call_unref(impl->portal_pid_pending);
|
||||
}
|
||||
impl->portal_pid_pending = pending;
|
||||
}
|
||||
|
||||
static DBusHandlerResult name_owner_changed_handler(DBusConnection *connection,
|
||||
DBusMessage *message,
|
||||
void *user_data)
|
||||
{
|
||||
struct impl *impl = user_data;
|
||||
const char *name;
|
||||
const char *old_owner;
|
||||
const char *new_owner;
|
||||
|
||||
if (!dbus_message_is_signal(message, "org.freedesktop.DBus",
|
||||
"NameOwnerChanged"))
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
if (!dbus_message_get_args(message, NULL,
|
||||
DBUS_TYPE_STRING, &name,
|
||||
DBUS_TYPE_STRING, &old_owner,
|
||||
DBUS_TYPE_STRING, &new_owner,
|
||||
DBUS_TYPE_INVALID)) {
|
||||
pw_log_error("Failed to get OwnerChanged args");
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
}
|
||||
|
||||
if (strcmp(name, "org.freedesktop.portal.Desktop") != 0)
|
||||
return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
|
||||
|
||||
if (strcmp(new_owner, "") == 0) {
|
||||
impl->portal_pid = 0;
|
||||
if (impl->portal_pid_pending != NULL) {
|
||||
dbus_pending_call_cancel(impl->portal_pid_pending);
|
||||
dbus_pending_call_unref(impl->portal_pid_pending);
|
||||
}
|
||||
}
|
||||
else {
|
||||
update_portal_pid(impl);
|
||||
}
|
||||
|
||||
return DBUS_HANDLER_RESULT_HANDLED;
|
||||
}
|
||||
|
||||
static int init_dbus_connection(struct impl *impl)
|
||||
{
|
||||
DBusError error;
|
||||
|
||||
impl->bus = spa_dbus_connection_get(impl->conn);
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
dbus_bus_add_match(impl->bus,
|
||||
"type='signal',\
|
||||
sender='org.freedesktop.DBus',\
|
||||
interface='org.freedesktop.DBus',\
|
||||
member='NameOwnerChanged'",
|
||||
&error);
|
||||
if (dbus_error_is_set(&error)) {
|
||||
pw_log_error("Failed to add name owner changed listener: %s",
|
||||
error.message);
|
||||
dbus_error_free(&error);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dbus_connection_add_filter(impl->bus, name_owner_changed_handler,
|
||||
impl, NULL);
|
||||
|
||||
update_portal_pid(impl);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
SPA_EXPORT
|
||||
int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||
{
|
||||
struct pw_context *context = pw_impl_module_get_context(module);
|
||||
struct impl *impl;
|
||||
struct spa_dbus *dbus;
|
||||
const struct spa_support *support;
|
||||
uint32_t n_support;
|
||||
|
||||
support = pw_context_get_support(context, &n_support);
|
||||
|
||||
dbus = spa_support_find(support, n_support, SPA_TYPE_INTERFACE_DBus);
|
||||
if (dbus == NULL)
|
||||
return -ENOTSUP;
|
||||
|
||||
impl = calloc(1, sizeof(struct impl));
|
||||
if (impl == NULL)
|
||||
return -ENOMEM;
|
||||
|
||||
pw_log_debug("module %p: new", impl);
|
||||
|
||||
impl->context = context;
|
||||
impl->properties = args ? pw_properties_new_string(args) : NULL;
|
||||
|
||||
impl->conn = spa_dbus_get_connection(dbus, SPA_DBUS_TYPE_SESSION);
|
||||
if (impl->conn == NULL)
|
||||
goto error;
|
||||
|
||||
if (init_dbus_connection(impl) != 0)
|
||||
goto error;
|
||||
|
||||
pw_context_add_listener(context, &impl->context_listener, &context_events, impl);
|
||||
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
|
||||
|
||||
return 0;
|
||||
|
||||
error:
|
||||
free(impl);
|
||||
pw_log_error("Failed to connect to system bus");
|
||||
return -ENOMEM;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue