mirror of
https://gitlab.freedesktop.org/pipewire/pipewire
synced 2024-09-06 16:56:00 +00:00
![Peter Hutterer](/assets/img/avatar_default.png)
This is a multi-step process involving 4 processes and two modules. Let's add some graphs to make this slightly easier to comprehend for those not familiar with how portals work.
216 lines
6.3 KiB
Plaintext
216 lines
6.3 KiB
Plaintext
/** \page page_portal Portal Access Control
|
|
|
|
This document explains how clients from the portal are handled.
|
|
|
|
The portal is a DBus service that exposes interfaces to
|
|
request access to the PipeWire daemon to perform a certain set of
|
|
functions. The PipeWire daemon runs outside the sandbox, the portal is a way
|
|
for clients inside the sandbox to connect to and use PipeWire.
|
|
|
|
The PipeWire socket is not exposed in the sandbox. Instead, The portal
|
|
connects to PipeWire on behalf of the client, informing PipeWire that this
|
|
client is a portal-managed client. PipeWire can detect and enforce
|
|
extra permission checks on the portal managed clients.
|
|
|
|
Once such portal is the [Camera
|
|
portal](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.portal.Camera)
|
|
that provides a PipeWire session to stream video from a camera.
|
|
|
|
# Use cases
|
|
|
|
### new portal managed clients need device permissions configured
|
|
|
|
When a new client is detected, the available objects need to be
|
|
scanned and permissions configured for each of them.
|
|
|
|
Only the devices belonging to the media_roles given by the
|
|
portal are considered.
|
|
|
|
### new devices need to be made visible to portal managed clients
|
|
|
|
Newly created objects are made visible to a client when the client
|
|
is allowed to interact with it.
|
|
|
|
Only the devices belonging to the media_roles given by the
|
|
portal are considered.
|
|
|
|
### permissions for a device need to be revoked
|
|
|
|
The session manager listens to changes in the permissions of devices
|
|
and will remove the client permissions accordingly.
|
|
|
|
Usually this is implemented by listening to the permission store
|
|
DBus object. The desktop environment might provide a configuration panel
|
|
where these permissions can be managed.
|
|
|
|
|
|
# Design
|
|
|
|
## The portal
|
|
|
|
A sandboxed client cannot connect to PipeWire directly. Instead, it connects
|
|
to the sandbox side of the portal which then connects the PipeWire daemon to
|
|
configure the session. The portal then hands the file descriptor of the
|
|
PipeWire connection to the client and the client can use this file descriptor
|
|
to interface with the PipeWire session directly.
|
|
|
|
When the portal connects, it will set the following properties on the
|
|
client object:
|
|
|
|
- `"pipewire.access.portal.is_portal" = true` for the connection of the
|
|
portal itself (as opposed to a client managed by the portal).
|
|
- `"pipewire.access.portal.app_id"` the [application id](https://docs.flatpak.org/en/latest/conventions.html#application-ids) of the client.
|
|
- `"pipewire.access.portal.media_roles"` media roles of the client.
|
|
Currently only `"Camera"` is defined.
|
|
|
|
Before returning the connection to a client, the portal configures
|
|
minimal permissions on the client. No objects are initially visible. It is
|
|
the task of the \ref page_session_manager to make the objects in the graph
|
|
visible, depending on the client's `media_roles` (see also \ref
|
|
PW_KEY_MEDIA_ROLE).
|
|
|
|
## The PipeWire portal module
|
|
|
|
The pipewire daemon uses the \ref page_module_portal to find the PID of the
|
|
processes that owns the DBus name `org.freedesktop.portal.Desktop`
|
|
(see the [XDG Desktop Portal](https://github.com/flatpak/xdg-desktop-portal)).
|
|
|
|
Client connections from this PID are tagged as \ref PW_KEY_ACCESS
|
|
`"portal"` (see \ref page_module_access). It will also set ALL permissions for
|
|
this client so that it can resume.
|
|
|
|
\dot
|
|
digraph pw {
|
|
compound=true;
|
|
node [shape="box"];
|
|
rankdir="TB";
|
|
|
|
dbus [label="org.freedesktop.portal.Desktop"];
|
|
|
|
portal_access [label="PipeWire (mod: Portal Access)"];
|
|
portal [label="xdg-desktop-portal"];
|
|
|
|
dbus -> portal_access [arrowhead="dot"];
|
|
dbus -> portal [arrowhead="dot"];
|
|
|
|
portal_access -> portal [label="pipewire.access = portal"];
|
|
|
|
{ rank="same"; portal_access; portal}
|
|
}
|
|
\enddot
|
|
|
|
## The client
|
|
|
|
A client can ask the portal for a connection to the PipeWire daemon.
|
|
|
|
\dot
|
|
digraph pw {
|
|
compound=true;
|
|
node [shape="box"];
|
|
rankdir="LR";
|
|
|
|
pw [label="PipeWire"];
|
|
portal [label="xdg-desktop-portal"];
|
|
client [label="client"];
|
|
|
|
client -> portal;
|
|
portal -> pw [label="portal.is_portal=true", arrowhead="none"]
|
|
|
|
{rank="min"; pw};
|
|
{rank="max"; client};
|
|
}
|
|
\enddot
|
|
|
|
The portal maintains an (unrestricted) connection to the PipeWire daemon with
|
|
`"pipewire.access.portal.is_portal" = true` to identify the nodes the client
|
|
needs access to. It then creates a new restricted connection for the client,
|
|
tagged with additional information.
|
|
|
|
\dot
|
|
digraph pw {
|
|
compound=true;
|
|
node [shape="box"];
|
|
rankdir="LR";
|
|
|
|
pw [label="PipeWire"];
|
|
portal [label="xdg-desktop-portal"];
|
|
client [label="client"];
|
|
|
|
client -> portal [arrowhead="none"];
|
|
portal -> pw [label="portal.is_portal=true", arrowhead="none"]
|
|
portal -> pw [label="portal.app_id = $appid"]
|
|
|
|
{rank="min"; pw};
|
|
{rank="max"; client};
|
|
}
|
|
\enddot
|
|
|
|
|
|
The file descriptor for this restricted connection is passed back to the
|
|
client which can now make use of the resources it has been permitted to
|
|
access.
|
|
|
|
\dot
|
|
digraph pw {
|
|
compound=true;
|
|
node [shape="box"];
|
|
rankdir="LR";
|
|
|
|
pw [label="PipeWire"];
|
|
portal [label="xdg-desktop-portal"];
|
|
client [label="client"];
|
|
|
|
portal -> pw [label="portal.is_portal=true", arrowhead="none"]
|
|
|
|
pw->client [label="restricted connection"];
|
|
|
|
{rank="min"; pw};
|
|
{rank="max"; client};
|
|
}
|
|
\enddot
|
|
|
|
## The session manager
|
|
|
|
The session manager listens for new clients to appear. It will use the
|
|
\ref PW_KEY_ACCESS property to find portal connections. For client connections
|
|
from the portal the session manager checks the requested `media_roles` and
|
|
enables or disables access to the respective PipeWire objects.
|
|
It might have to consult a database to decide what is allowed, for example the
|
|
[org.freedesktop.impl.portal.PermissionStore](https://flatpak.github.io/xdg-desktop-portal/portal-docs.html#gdbus-org.freedesktop.impl.portal.PermissionStore).
|
|
|
|
\dot
|
|
strict digraph pw {
|
|
compound=true;
|
|
node [shape="box"];
|
|
rankdir="LR";
|
|
|
|
portal [label="xdg-desktop-portal"];
|
|
client [label="client"];
|
|
|
|
|
|
subgraph {
|
|
rankdir="TB";
|
|
permissions [label="PermissionStore"];
|
|
|
|
sm->permissions;
|
|
|
|
sm [label="Session Manager"];
|
|
pw [label="PipeWire"];
|
|
sm -> pw [headlabel="allow $media.roles"];
|
|
pw -> sm;
|
|
portal -> pw [label="portal.app_id = $appid"];
|
|
}
|
|
|
|
client -> portal [arrowhead="none"];
|
|
|
|
{rank="min"; sm, pw};
|
|
{rank="max"; client};
|
|
}
|
|
\enddot
|
|
|
|
In the case of the [XDG Desktop
|
|
Portal](https://github.com/flatpak/xdg-desktop-portal), the portal itself
|
|
queries the PermissionStore directly.
|
|
|
|
*/
|