Skip to content

Commit d3fbddc

Browse files
authored
Fix app discovery: [Merge pull request #149 from unsecretised/fix-app-discovery]
Fix app discovery
2 parents f06e007 + a4a5300 commit d3fbddc

File tree

1 file changed

+28
-1
lines changed

1 file changed

+28
-1
lines changed

src/platform/macos/discovery.rs

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ fn is_in_user_app_directory(path: &Path) -> bool {
192192
fn query_app(url: impl AsRef<NSURL>, store_icons: bool) -> Option<App> {
193193
let url = url.as_ref();
194194
let path = url.to_file_path()?;
195+
if is_nested_inside_another_app(&path) || is_helper_location(&path) {
196+
return None;
197+
}
195198

196199
let bundle = NSBundle::bundleWithURL(url)?;
197200
let info = bundle.infoDictionary()?;
@@ -216,7 +219,7 @@ fn query_app(url: impl AsRef<NSURL>, store_icons: bool) -> Option<App> {
216219
};
217220

218221
// Filter out background-only apps (daemons, agents, internal system apps)
219-
if is_truthy(ns_string!("LSUIElement")) || is_truthy(ns_string!("LSBackgroundOnly")) {
222+
if is_truthy(ns_string!("LSBackgroundOnly")) {
220223
return None;
221224
}
222225

@@ -280,3 +283,27 @@ pub(crate) fn get_installed_apps(store_icons: bool) -> Vec<App> {
280283
.filter_map(|url| query_app(url, store_icons))
281284
.collect()
282285
}
286+
287+
fn is_nested_inside_another_app(app_path: &Path) -> bool {
288+
// Walk up ancestors; if we find an *.app component that is NOT the last component,
289+
// then this app is nested inside another app bundle.
290+
let comps: Vec<_> = app_path.components().collect();
291+
// Normalize: if path ends with ".../Foo.app", we look for any earlier "*.app".
292+
for component in comps.iter().take(comps.len().saturating_sub(1)) {
293+
if let std::path::Component::Normal(name) = component
294+
&& name.to_string_lossy().ends_with(".app")
295+
{
296+
return true;
297+
}
298+
}
299+
false
300+
}
301+
302+
fn is_helper_location(path: &Path) -> bool {
303+
let s = path.to_string_lossy();
304+
s.contains("/Contents/Library/LoginItems/")
305+
|| s.contains("/Contents/XPCServices/")
306+
|| s.contains("/Contents/Helpers/")
307+
|| s.contains("/Contents/Frameworks/")
308+
|| s.contains("/Library/PrivilegedHelperTools/")
309+
}

0 commit comments

Comments
 (0)