mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2026-05-03 06:47:04 -04:00
impl-core: gate portal clients on stolen-fd reconnect
When the XDG camera portal steals a PW fd and hands it to an app, the app can connect before the session manager has set up permissions, seeing no camera nodes. Gate portal clients in core_hello by removing PW_PERM_R from PW_ID_CORE, triggering the busy state so daemon stops reading from the client socket until the session manager restores permissions. A marker property (pipewire.access.portal.gated) notifies the session manager to ungate after attaching the PermissionManager. The property is cleared before each gate cycle to handle repeated fd steals on the same client. Only gate when the session manager has set the capability property pipewire.access.portal.gate-supported on the client, so older session managers that cannot ungate are unaffected. Check ALL clients in the context rather than this client specifically because the portal may create a brand new client for each camera session and the session manager won't have processed it yet. Fixes: https://gitlab.freedesktop.org/pipewire/wireplumber/-/work_items/941
This commit is contained in:
parent
593132e434
commit
c5083e7f32
1 changed files with 39 additions and 1 deletions
|
|
@ -171,7 +171,11 @@ static int core_hello(void *object, uint32_t version)
|
||||||
struct pw_impl_core *this = client->core;
|
struct pw_impl_core *this = client->core;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
pw_log_debug("%p: hello %d from resource %p", context, version, resource);
|
const char *access = spa_dict_lookup(client->info.props, PW_KEY_ACCESS);
|
||||||
|
|
||||||
|
pw_log_debug("%p: hello %d from resource %p access=%s",
|
||||||
|
context, version, resource, access ? access : "(null)");
|
||||||
|
|
||||||
pw_map_for_each(&client->objects, destroy_resource, client);
|
pw_map_for_each(&client->objects, destroy_resource, client);
|
||||||
|
|
||||||
resource->version = version;
|
resource->version = version;
|
||||||
|
|
@ -186,6 +190,40 @@ static int core_hello(void *object, uint32_t version)
|
||||||
PW_PERM_ALL, PW_VERSION_CLIENT, PW_ID_CLIENT)) < 0)
|
PW_PERM_ALL, PW_VERSION_CLIENT, PW_ID_CLIENT)) < 0)
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The portal has stolen the fd and handed it to app. Gate the
|
||||||
|
* client until the session manager sets up permissions
|
||||||
|
* by removing PW_PERM_R from PW_ID_CORE which triggers
|
||||||
|
* the busy state. */
|
||||||
|
if (access && spa_streq(access, "portal")) {
|
||||||
|
bool gate_supported = false;
|
||||||
|
struct pw_impl_client *c;
|
||||||
|
spa_list_for_each(c, &context->client_list, link) {
|
||||||
|
const char *gs = spa_dict_lookup(&c->properties->dict,
|
||||||
|
"pipewire.access.portal.gate-supported");
|
||||||
|
if (gs && spa_streq(gs, "true")) {
|
||||||
|
gate_supported = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (gate_supported) {
|
||||||
|
struct pw_permission perms[1];
|
||||||
|
perms[0] = PW_PERMISSION_INIT(PW_ID_CORE, PW_PERM_W|PW_PERM_X);
|
||||||
|
pw_impl_client_update_permissions(client, 1, perms);
|
||||||
|
|
||||||
|
struct spa_dict_item items[2];
|
||||||
|
items[0] = SPA_DICT_ITEM_INIT(
|
||||||
|
"pipewire.access.portal.gated", NULL);
|
||||||
|
items[1] = SPA_DICT_ITEM_INIT(
|
||||||
|
"pipewire.access.portal.gated", "true");
|
||||||
|
pw_impl_client_update_properties(client,
|
||||||
|
&SPA_DICT_INIT(items, 2));
|
||||||
|
pw_log_info("%p: portal client %p gated until session "
|
||||||
|
"manager restores PW_ID_CORE permissions",
|
||||||
|
context, client);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue