Skip to content

Commit

Permalink
feat(background): Autostart method
Browse files Browse the repository at this point in the history
  • Loading branch information
joshuamegnauth54 committed Sep 16, 2024
1 parent 1885362 commit c82b8ad
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 7 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ time = { version = "0.3.31", features = [
"macros",
] }
url = "2.5"
shlex = "1"
# i18n
i18n-embed = { version = "0.14.1", features = [
"fluent-system",
Expand Down
133 changes: 126 additions & 7 deletions src/background.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,20 @@
// SPDX-License-Identifier: GPL-3.0-only

use std::sync::{Arc, Condvar, Mutex};
use std::{
borrow::Cow,
io,
sync::{Arc, Condvar, Mutex},
};

// use ashpd::enumflags2::{bitflags, BitFlag, BitFlags};
use cosmic::{iced::window, widget};
use cosmic_protocols::toplevel_info::v1::client::zcosmic_toplevel_handle_v1;
use futures::{FutureExt, TryFutureExt};
use tokio::sync::{mpsc, watch};
use tokio::{
fs,
io::AsyncWriteExt,
sync::{mpsc, watch},
};
use zbus::{fdo, object_server::SignalContext, zvariant};

use crate::{
Expand Down Expand Up @@ -134,7 +142,7 @@ impl Background {
}
// Dialog
PermissionDialog::Ask => {
log::debug!("Requesting user permission for {app_id} ({name})",);
log::debug!("Requesting background permission for running app {app_id} ({name})",);

let handle = handle.to_owned();
let id = window::Id::unique();
Expand All @@ -160,16 +168,127 @@ impl Background {

/// Enable or disable autostart for an application
///
/// Deprecated but seemingly still in use
/// Deprecated in terms of the portal but seemingly still in use
/// Spec: https://specifications.freedesktop.org/autostart-spec/latest/
pub async fn enable_autostart(
&self,
app_id: String,
enable: bool,
commandline: Vec<String>,
exec: Vec<String>,
flags: u32,
) -> fdo::Result<bool> {
log::warn!("Autostart not implemented");
Ok(enable)
log::info!(
"{} autostart for {app_id}",
if enable { "Enabling" } else { "Disabling" }
);

let Some((autostart_dir, launch_entry)) = dirs::config_dir().map(|config| {
let autostart = config.join("autostart");
(
autostart.clone(),
autostart.join(format!("{app_id}.desktop")),
)
}) else {
return Err(fdo::Error::FileNotFound("XDG_CONFIG_HOME".into()));
};

if !enable {
log::debug!("Removing autostart entry {}", launch_entry.display());
match fs::remove_file(&launch_entry).await {
Ok(()) => Ok(false),
Err(e) if e.kind() == io::ErrorKind::NotFound => {
log::error!("Autostart entry for {app_id} doesn't exist");
Ok(false)
}
Err(e) => {
log::error!(
"Error removing autostart entry for {app_id}\n\tPath: {}\n\tError: {e}",
launch_entry.display()
);
Err(fdo::Error::FileNotFound(format!(
"{e}: ({})",
launch_entry.display()
)))
}
}
} else {
match fs::create_dir(&autostart_dir).await {
Ok(()) => log::debug!("Created autostart directory at {}", autostart_dir.display()),
Err(e) if e.kind() == io::ErrorKind::AlreadyExists => (),
Err(e) => {
log::error!(
"Error creating autostart directory: {e} (app: {app_id}) (dir: {})",
autostart_dir.display()
);
return Err(fdo::Error::IOError(format!(
"{e}: ({})",
autostart_dir.display()
)));
}
}

let mut autostart_fde = freedesktop_desktop_entry::DesktopEntry {
appid: Cow::Borrowed(&app_id),
path: Default::default(),
groups: Default::default(),
ubuntu_gettext_domain: None,
};
autostart_fde.add_desktop_entry("Type", "Application");
autostart_fde.add_desktop_entry("Name", &app_id);

log::debug!("{app_id} autostart command line: {exec:?}");
let exec = match shlex::try_join(exec.iter().map(|term| term.as_str())) {
Ok(exec) => exec,
Err(e) => {
log::error!("Failed to sanitize command line for {app_id}\n\tCommand: {exec:?}\n\tError: {e}");
return Err(fdo::Error::InvalidArgs(format!("{e}: {exec:?}")));
}
};
log::debug!("{app_id} sanitized autostart command line: {exec}");
autostart_fde.add_desktop_entry("Exec", &exec);

let dbus_activation = flags & 0x1 == 1;
if dbus_activation {
autostart_fde.add_desktop_entry("DBusActivatable", "true");
}

// GNOME and KDE both set this key
autostart_fde.add_desktop_entry("X-Flatpak", &app_id);

match fs::OpenOptions::new()
.create_new(true)
.write(true)
.mode(0o644)
.open(&launch_entry)
.map_ok(tokio::io::BufWriter::new)
.await
{
Ok(mut file) => {
if let Err(e) = file.write_all(autostart_fde.to_string().as_bytes()).await {
log::error!(
"Failed writing autostart entry {app_id} to {}: {e}",
launch_entry.display()
);
Err(fdo::Error::IOError(format!(
"{e}: {}",
launch_entry.display()
)))
} else {
Ok(true)
}
}
Err(e) => {
log::error!(
"Failed to open `{}` to write autostart entry for {app_id}: {e}",
launch_entry.display()
);
Err(fdo::Error::IOError(format!(
"{e}: {}",
launch_entry.display()
)))
}
}
}
}

/// Emitted when running applications change their state
Expand Down

0 comments on commit c82b8ad

Please sign in to comment.