Skip to content

Commit 286b1be

Browse files
authored
fix: panic on Ubuntu (GNOME) when opening apps (#821)
On Ubuntu (the GNOME version), Coco would panic when users open an app due to the reason that Coco thinks it is running in an unsupported desktop environment (DE). We rely on the environment variable XDG_CURRENT_DESKTOP to detect the DE, Ubuntu sets this variable to "ubuntu:GNOME" instead of just "GNOME", which was not handled by the previous implementation. This commit supports this case. Also, when Coco runs in an unsupported DE, opening apps should not panic the app. After this commit, we would return an error.
1 parent 3722178 commit 286b1be

2 files changed

Lines changed: 78 additions & 9 deletions

File tree

docs/content.en/docs/release-notes/_index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ Information about release notes of Coco Server is provided here.
4040
- fix: fix ctrl+k not working #815
4141
- fix: fix update window config sync #818
4242
- fix: fix enter key on subpages #819
43+
- fix: panic on Ubuntu (GNOME) when opening apps #821
4344

4445
### ✈️ Improvements
4546

src-tauri/src/util/mod.rs

Lines changed: 77 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,14 @@ use std::{path::Path, process::Command};
77
use tauri::{AppHandle, Runtime};
88
use tauri_plugin_shell::ShellExt;
99

10+
/// We use this env variable to determine the DE on Linux.
11+
const XDG_CURRENT_DESKTOP: &str = "XDG_CURRENT_DESKTOP";
12+
13+
#[derive(Debug, PartialEq)]
1014
enum LinuxDesktopEnvironment {
1115
Gnome,
1216
Kde,
17+
Unsupported { xdg_current_desktop: String },
1318
}
1419

1520
impl LinuxDesktopEnvironment {
@@ -35,6 +40,14 @@ impl LinuxDesktopEnvironment {
3540
.arg(path)
3641
.output()
3742
.map_err(|e| e.to_string())?,
43+
Self::Unsupported {
44+
xdg_current_desktop,
45+
} => {
46+
return Err(format!(
47+
"Cannot open apps as this Linux desktop environment [{}] is not supported",
48+
xdg_current_desktop
49+
));
50+
}
3851
};
3952

4053
if !cmd_output.status.success() {
@@ -49,20 +62,23 @@ impl LinuxDesktopEnvironment {
4962
}
5063
}
5164

65+
/// None means that it is likely that we do not have a desktop environment.
5266
fn get_linux_desktop_environment() -> Option<LinuxDesktopEnvironment> {
53-
let de_os_str = std::env::var_os("XDG_CURRENT_DESKTOP")?;
54-
let de_str = de_os_str
55-
.into_string()
56-
.expect("$XDG_CURRENT_DESKTOP should be UTF-8 encoded");
67+
let de_os_str = std::env::var_os(XDG_CURRENT_DESKTOP)?;
68+
let de_str = de_os_str.into_string().unwrap_or_else(|_os_string| {
69+
panic!("${} should be UTF-8 encoded", XDG_CURRENT_DESKTOP);
70+
});
5771

5872
let de = match de_str.as_str() {
5973
"GNOME" => LinuxDesktopEnvironment::Gnome,
74+
// Ubuntu uses "ubuntu:GNOME" instead of just "GNOME", they really love
75+
// their distro name.
76+
"ubuntu:GNOME" => LinuxDesktopEnvironment::Gnome,
6077
"KDE" => LinuxDesktopEnvironment::Kde,
6178

62-
unsupported_de => unimplemented!(
63-
"This desktop environment [{}] has not been supported yet",
64-
unsupported_de
65-
),
79+
_ => LinuxDesktopEnvironment::Unsupported {
80+
xdg_current_desktop: de_str,
81+
},
6682
};
6783

6884
Some(de)
@@ -77,7 +93,7 @@ pub async fn open<R: Runtime>(app_handle: AppHandle<R>, path: String) -> Result<
7793
let borrowed_path = Path::new(&path);
7894
if let Some(file_extension) = borrowed_path.extension() {
7995
if file_extension == "desktop" {
80-
let desktop_environment = get_linux_desktop_environment().expect("The Linux OS is running without a desktop, Coco could never run in such a environment");
96+
let desktop_environment = get_linux_desktop_environment().expect("The Linux OS is running without a desktop, Coco could never run in such an environment");
8197
return desktop_environment.launch_app_via_desktop_file(path);
8298
}
8399
}
@@ -88,3 +104,55 @@ pub async fn open<R: Runtime>(app_handle: AppHandle<R>, path: String) -> Result<
88104
.open(path, None)
89105
.map_err(|e| e.to_string())
90106
}
107+
108+
#[cfg(test)]
109+
mod tests {
110+
use super::*;
111+
112+
// This test modifies env var XDG_CURRENT_DESKTOP, which is kinda unsafe
113+
// but considering this is just test, it is ok to do so.
114+
#[test]
115+
fn test_get_linux_desktop_environment() {
116+
// SAFETY: Rust code won't modify/read XDG_CURRENT_DESKTOP concurrently, we
117+
// have no guarantee from the underlying C code.
118+
unsafe {
119+
// Save the original value if it exists
120+
let original_value = std::env::var_os(XDG_CURRENT_DESKTOP);
121+
122+
// Test when XDG_CURRENT_DESKTOP is not set
123+
std::env::remove_var(XDG_CURRENT_DESKTOP);
124+
assert!(get_linux_desktop_environment().is_none());
125+
126+
// Test GNOME
127+
std::env::set_var(XDG_CURRENT_DESKTOP, "GNOME");
128+
let result = get_linux_desktop_environment();
129+
assert_eq!(result.unwrap(), LinuxDesktopEnvironment::Gnome);
130+
131+
// Test ubuntu:GNOME
132+
std::env::set_var(XDG_CURRENT_DESKTOP, "ubuntu:GNOME");
133+
let result = get_linux_desktop_environment();
134+
assert_eq!(result.unwrap(), LinuxDesktopEnvironment::Gnome);
135+
136+
// Test KDE
137+
std::env::set_var(XDG_CURRENT_DESKTOP, "KDE");
138+
let result = get_linux_desktop_environment();
139+
assert_eq!(result.unwrap(), LinuxDesktopEnvironment::Kde);
140+
141+
// Test unsupported desktop environment
142+
std::env::set_var(XDG_CURRENT_DESKTOP, "XFCE");
143+
let result = get_linux_desktop_environment();
144+
assert_eq!(
145+
result.unwrap(),
146+
LinuxDesktopEnvironment::Unsupported {
147+
xdg_current_desktop: "XFCE".into()
148+
}
149+
);
150+
151+
// Restore the original value
152+
match original_value {
153+
Some(value) => std::env::set_var(XDG_CURRENT_DESKTOP, value),
154+
None => std::env::remove_var(XDG_CURRENT_DESKTOP),
155+
}
156+
}
157+
}
158+
}

0 commit comments

Comments
 (0)