From cbc579825c98d56361ce234ec4c3cf72f8aad0af Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 16 Jul 2020 12:50:33 +0200 Subject: [PATCH] media-session: add flatpak module Add a module that gives full access to flatpak apps. Later we should do something more restrictive. --- src/examples/media-session/access-flatpak.c | 182 ++++++++++++++++++++ src/examples/media-session/media-session.c | 4 +- src/examples/meson.build | 1 + 3 files changed, 186 insertions(+), 1 deletion(-) create mode 100644 src/examples/media-session/access-flatpak.c diff --git a/src/examples/media-session/access-flatpak.c b/src/examples/media-session/access-flatpak.c new file mode 100644 index 000000000..8542c786d --- /dev/null +++ b/src/examples/media-session/access-flatpak.c @@ -0,0 +1,182 @@ +/* PipeWire + * + * Copyright © 2020 Wim Taymans + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include +#include + +#include "config.h" + +#include "pipewire/pipewire.h" + +#include "media-session.h" + +#define NAME "access-flatpak" +#define SESSION_KEY "access-flatpak" + +struct impl { + struct sm_media_session *session; + struct spa_hook listener; + + struct pw_context *context; + + struct spa_list client_list; + int seq; +}; + +struct client { + struct sm_client *obj; + + uint32_t id; + struct impl *impl; + + struct spa_list link; /**< link in impl client_list */ + + struct spa_hook listener; + unsigned int active:1; +}; + +static void object_update(void *data) +{ + struct client *client = data; + struct impl *impl = client->impl; + const char *str; + + pw_log_debug(NAME" %p: client %p %08x", impl, client, client->obj->obj.changed); + + if (client->obj->obj.avail & SM_CLIENT_CHANGE_MASK_INFO && + !client->active) { + struct pw_permission permissions[1]; + + if (client->obj->info == NULL || client->obj->info->props == NULL || + (str = spa_dict_lookup(client->obj->info->props, "pipewire.access")) == NULL || + strcmp(str, "flatpak") != 0) + return; + + /* full access for now */ + permissions[0] = PW_PERMISSION_INIT(PW_ID_ANY, PW_PERM_RWX); + pw_client_update_permissions(client->obj->obj.proxy, + 1, permissions); + client->active = true; + } +} + +static const struct sm_object_events object_events = { + SM_VERSION_OBJECT_EVENTS, + .update = object_update +}; + +static int +handle_client(struct impl *impl, struct sm_object *object) +{ + struct client *client; + + pw_log_debug(NAME" %p: client", impl); + + client = sm_object_add_data(object, SESSION_KEY, sizeof(struct client)); + client->obj = (struct sm_client*)object; + client->id = object->id; + client->impl = impl; + spa_list_append(&impl->client_list, &client->link); + + client->obj->obj.mask |= SM_CLIENT_CHANGE_MASK_INFO; + sm_object_add_listener(&client->obj->obj, &client->listener, &object_events, client); + + return 1; +} + +static void destroy_client(struct impl *impl, struct client *client) +{ + spa_list_remove(&client->link); + sm_object_remove_data((struct sm_object*)client->obj, SESSION_KEY); +} + +static void session_create(void *data, struct sm_object *object) +{ + struct impl *impl = data; + int res; + + pw_log_debug(NAME " %p: create global '%d'", impl, object->id); + + if (strcmp(object->type, PW_TYPE_INTERFACE_Client) == 0) + res = handle_client(impl, object); + else + res = 0; + + if (res < 0) + pw_log_warn(NAME" %p: can't handle global %d", impl, object->id); +} + +static void session_remove(void *data, struct sm_object *object) +{ + struct impl *impl = data; + pw_log_debug(NAME " %p: remove global '%d'", impl, object->id); + + if (strcmp(object->type, PW_TYPE_INTERFACE_Client) == 0) { + struct client *client; + + if ((client = sm_object_get_data(object, SESSION_KEY)) != NULL) + destroy_client(impl, client); + } +} + +static void session_destroy(void *data) +{ + struct impl *impl = data; + struct client *client; + + spa_list_consume(client, &impl->client_list, link) + destroy_client(impl, client); + + spa_hook_remove(&impl->listener); + free(impl); +} + +static const struct sm_media_session_events session_events = { + SM_VERSION_MEDIA_SESSION_EVENTS, + .create = session_create, + .remove = session_remove, + .destroy = session_destroy, +}; + +int sm_access_flatpak_start(struct sm_media_session *session) +{ + struct impl *impl; + + impl = calloc(1, sizeof(struct impl)); + if (impl == NULL) + return -errno; + + impl->session = session; + impl->context = session->context; + + spa_list_init(&impl->client_list); + + sm_media_session_add_listener(impl->session, + &impl->listener, + &session_events, impl); + return 0; +} diff --git a/src/examples/media-session/media-session.c b/src/examples/media-session/media-session.c index 05511e7a4..d3f4ece38 100644 --- a/src/examples/media-session/media-session.c +++ b/src/examples/media-session/media-session.c @@ -66,6 +66,7 @@ #define sm_media_session_emit_rescan(s,seq) sm_media_session_emit(s, rescan, 0, seq) #define sm_media_session_emit_destroy(s) sm_media_session_emit(s, destroy, 0) +int sm_access_flatpak_start(struct sm_media_session *sess); int sm_metadata_start(struct sm_media_session *sess); int sm_alsa_midi_start(struct sm_media_session *sess); int sm_v4l2_monitor_start(struct sm_media_session *sess); @@ -1767,7 +1768,7 @@ static void do_quit(void *data, int signal_number) pw_main_loop_quit(impl->loop); } -#define DEFAULT_ENABLED "alsa-pcm,alsa-seq,v4l2,bluez5,metadata,suspend-node,policy-node" +#define DEFAULT_ENABLED "flatpak,alsa-pcm,alsa-seq,v4l2,bluez5,metadata,suspend-node,policy-node" #define DEFAULT_DISABLED "" static const struct { @@ -1777,6 +1778,7 @@ static const struct { const char *props; } modules[] = { + { "flatpak", "manage flatpak access", sm_access_flatpak_start, NULL }, { "metadata", "export metadata API", sm_metadata_start, NULL }, { "alsa-seq", "alsa seq midi support", sm_alsa_midi_start, NULL }, { "alsa-pcm", "alsa pcm udev detection", sm_alsa_monitor_start, NULL }, diff --git a/src/examples/meson.build b/src/examples/meson.build index 56f9eeecd..5f11022d9 100644 --- a/src/examples/meson.build +++ b/src/examples/meson.build @@ -67,6 +67,7 @@ executable('export-spa-device', if alsa_dep.found() executable('pipewire-media-session', + 'media-session/access-flatpak.c', 'media-session/alsa-midi.c', 'media-session/alsa-monitor.c', 'media-session/alsa-endpoint.c',