pub(crate) const DESTINATION: &str = "org.freedesktop.portal.Flatpak";
pub(crate) const PATH: &str = "/org/freedesktop/portal/Flatpak";
use crate::{
helpers::{call_method, receive_signal},
Error,
};
use enumflags2::BitFlags;
use serde::Serialize;
use serde_repr::{Deserialize_repr, Serialize_repr};
use std::{collections::HashMap, os::unix::prelude::AsRawFd};
use zvariant::Fd;
use zvariant_derive::{DeserializeDict, SerializeDict, Type, TypeDict};
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Copy, Clone, BitFlags, Debug, Type)]
#[repr(u32)]
pub enum SandboxFlags {
DisplayAccess = 1,
SoundAccess = 2,
GpuAccess = 4,
SessionBusAccess = 8,
AccessibilityBusAccess = 16,
}
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Copy, Clone, BitFlags, Debug, Type)]
#[repr(u32)]
pub enum SpawnFlags {
ClearEnv = 1,
Latest = 2,
Sandbox = 4,
NoNetwork = 8,
Kill = 16,
Expose = 32,
Emit = 64,
}
#[derive(Serialize_repr, Deserialize_repr, PartialEq, Copy, Clone, BitFlags, Debug, Type)]
#[repr(u32)]
pub enum SupportsFlags {
ExposePids = 1,
}
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
pub struct SpawnOptions {
sandbox_expose: Option<Vec<String>>,
sandbox_expose_ro: Option<Vec<String>>,
sandbox_expose_fd: Option<Vec<Fd>>,
sandbox_expose_fd_ro: Option<Vec<Fd>>,
sandbox_flags: Option<BitFlags<SandboxFlags>>,
}
impl SpawnOptions {
pub fn sandbox_expose<S: AsRef<str> + zvariant::Type + Serialize>(
mut self,
sandbox_expose: &[S],
) -> Self {
self.sandbox_expose = Some(
sandbox_expose
.iter()
.map(|s| s.as_ref().to_string())
.collect(),
);
self
}
pub fn sandbox_expose_ro<S: AsRef<str> + zvariant::Type + Serialize>(
mut self,
sandbox_expose_ro: &[S],
) -> Self {
self.sandbox_expose_ro = Some(
sandbox_expose_ro
.iter()
.map(|s| s.as_ref().to_string())
.collect(),
);
self
}
pub fn sandbox_expose_fd<F: AsRawFd>(mut self, sandbox_expose_fd: &[&F]) -> Self {
self.sandbox_expose_fd = Some(
sandbox_expose_fd
.iter()
.map(|f| Fd::from(f.as_raw_fd()))
.collect(),
);
self
}
pub fn sandbox_expose_fd_ro<F: AsRawFd>(mut self, sandbox_expose_fd_ro: &[&F]) -> Self {
self.sandbox_expose_fd_ro = Some(
sandbox_expose_fd_ro
.iter()
.map(|f| Fd::from(f.as_raw_fd()))
.collect(),
);
self
}
pub fn sandbox_flags(mut self, sandbox_flags: BitFlags<SandboxFlags>) -> Self {
self.sandbox_flags = Some(sandbox_flags);
self
}
}
#[derive(SerializeDict, DeserializeDict, TypeDict, Debug, Default)]
struct CreateMonitorOptions {}
#[derive(Debug)]
#[doc(alias = "org.freedesktop.portal.Flatpak")]
pub struct FlatpakProxy<'a>(zbus::azync::Proxy<'a>);
impl<'a> FlatpakProxy<'a> {
pub async fn new(connection: &zbus::azync::Connection) -> Result<FlatpakProxy<'a>, Error> {
let proxy = zbus::ProxyBuilder::new_bare(connection)
.interface("org.freedesktop.portal.Flatpak")
.path(PATH)?
.destination(DESTINATION)
.build_async()
.await?;
Ok(Self(proxy))
}
pub fn inner(&self) -> &zbus::azync::Proxy<'_> {
&self.0
}
#[doc(alias = "CreateUpdateMonitor")]
pub async fn create_update_monitor(&self) -> Result<UpdateMonitorProxy<'a>, Error> {
let options = CreateMonitorOptions::default();
let path: zvariant::OwnedObjectPath = self
.0
.call_method("CreateUpdateMonitor", &(options))
.await?
.body()?;
UpdateMonitorProxy::new(self.0.connection(), path.into_inner()).await
}
pub async fn receive_spawn_started(&self) -> Result<(u32, u32), Error> {
receive_signal(&self.0, "SpawnStarted").await
}
#[doc(alias = "SpawnExited")]
pub async fn receive_spawn_existed(&self) -> Result<(u32, u32), Error> {
receive_signal(&self.0, "SpawnExited").await
}
#[doc(alias = "Spawn")]
pub async fn spawn<S: AsRef<str> + zvariant::Type + Serialize>(
&self,
cwd_path: &str,
argv: &[S],
fds: HashMap<u32, Fd>,
envs: HashMap<&str, &str>,
flags: BitFlags<SpawnFlags>,
options: SpawnOptions,
) -> Result<u32, Error> {
call_method(
&self.0,
"Spawn",
&(cwd_path, argv, fds, envs, flags, options),
)
.await
}
#[doc(alias = "SpawnSignal")]
pub async fn spawn_signal(
&self,
pid: u32,
signal: u32,
to_process_group: bool,
) -> Result<(), Error> {
call_method(&self.0, "SpawnSignal", &(pid, signal, to_process_group)).await
}
pub async fn supports(&self) -> Result<BitFlags<SupportsFlags>, Error> {
self.inner()
.get_property::<BitFlags<SupportsFlags>>("supports")
.await
.map_err(From::from)
}
}
mod update_monitor;
pub use update_monitor::{UpdateInfo, UpdateMonitorProxy, UpdateProgress, UpdateStatus};