Skip to content

Commit aeffc3f

Browse files
committed
feat: sandbox assets finding and optimizations (#6)
- DesktopAppInfo refuses to get desktop files from flatpak - even though it has access to them and is pointed to them - get_sandboxed_icon_for_id get the keyfile and icon name manually and caches it - Application tests if some sandboxed folders exist / are accessible and sets them to be later used by keyfile - IconTheme gets some more folders for access from flatpak Reviewed-on: https://codeberg.org/GeopJr/Turntable/pulls/6
1 parent 314ca1b commit aeffc3f

File tree

5 files changed

+102
-15
lines changed

5 files changed

+102
-15
lines changed

build-aux/dev.geopjr.Turntable.json

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@
2828
"--filesystem=~/.var/app/ca.edestcroix.Recordbox/data/Recordbox/:ro",
2929
"--filesystem=~/.var/app/org.gnome.Rhythmbox3/cache/rhythmbox/album-art/:ro",
3030
"--filesystem=~/.var/app/org.gnome.Lollypop/cache/lollypop/:ro",
31-
"--filesystem=~/.cache/:ro"
31+
"--filesystem=~/.cache/:ro",
32+
"--filesystem=xdg-data/applications",
33+
"--filesystem=~/.local/share/xdg-desktop-portal:ro",
34+
"--filesystem=/var/lib/snapd/:ro",
35+
"--filesystem=xdg-data/flatpak:ro"
3236
],
3337
"build-options" : {
3438
"append-path" : "/usr/lib/sdk/vala/bin",
@@ -52,7 +56,8 @@
5256
"builddir" : true,
5357
"buildsystem" : "meson",
5458
"config-opts": [
55-
"-Ddevel=true"
59+
"-Ddevel=true",
60+
"-Dsandboxed=true"
5661
],
5762
"build-options": {
5863
"arch": {

meson.build

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,16 @@ asresources = gnome.compile_resources(
7070
c_name: 'as',
7171
)
7272

73+
if get_option('sandboxed')
74+
add_project_arguments(['--define=SANDBOXED'], language: 'vala')
75+
endif
76+
7377
scrobbling = false
7478
libsoup_dep = dependency('libsoup-3.0', required: false)
7579
json_glib_dep = dependency('json-glib-1.0', version: '>=1.4.4', required: false)
7680
libsecret_dep = dependency('libsecret-1', required: false)
7781

78-
if get_option('scrobbling') and libsoup_dep.found () and json_glib_dep.found () and libsecret_dep.found ()
82+
if get_option('scrobbling') and libsoup_dep.found () and json_glib_dep.found () and libsecret_dep.found ()
7983
scrobbling = true
8084
add_project_arguments(['--define=SCROBBLING'], language: 'vala')
8185
endif

meson_options.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
option('devel', type: 'boolean', value: false)
22
option('scrobbling', type: 'boolean', value: true)
3+
option('sandboxed', type: 'boolean', value: false)
34

45
# Distros need to fill these for last.fm to work.
56
# You can get a key on https://www.last.fm/api/account/create

src/Application.vala

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
namespace Turntable {
2-
public static bool is_flatpak = false;
32
public static Mpris.Manager mpris_manager;
43
public const int PROGRESS_UPDATE_TIME = 1000; // it was 250ms, turns out it updates every second?
54
public static Application application;
65
public static bool debug_enabled = false;
76
public static bool is_rtl = false;
7+
#if SANDBOXED
8+
public static string[]? desktop_file_dirs = null;
9+
#endif
810

911
// public static Utils.Cache custom_color_cache;
1012
public static Utils.Settings settings;
@@ -13,6 +15,7 @@ namespace Turntable {
1315
public static Scrobbling.AccountManager account_manager;
1416
public static bool cli_list_clients = false;
1517
public static string cli_client_id_scrobble;
18+
public static bool cli_mode = false;
1619
#endif
1720
public class Application : Adw.Application {
1821
#if SCROBBLING
@@ -32,10 +35,14 @@ namespace Turntable {
3235
{ "quit", quit }
3336
};
3437

35-
string troubleshooting = "os: %s %s\nprefix: %s\nflatpak: %s\nversion: %s (%s)\ngtk: %u.%u.%u (%d.%d.%d)\nlibadwaita: %u.%u.%u (%d.%d.%d)\ndebug-logs: %s\nscrobbling: %s".printf (
38+
string troubleshooting = "os: %s %s\nprefix: %s\nsandboxed: %s\nversion: %s (%s)\ngtk: %u.%u.%u (%d.%d.%d)\nlibadwaita: %u.%u.%u (%d.%d.%d)\ndebug-logs: %s\nscrobbling: %s".printf (
3639
GLib.Environment.get_os_info ("NAME"), GLib.Environment.get_os_info ("VERSION"),
3740
Build.PREFIX,
38-
Turntable.is_flatpak.to_string (),
41+
#if SANDBOXED
42+
"true",
43+
#else
44+
"false",
45+
#endif
3946
Build.VERSION, Build.PROFILE,
4047
Gtk.get_major_version (), Gtk.get_minor_version (), Gtk.get_micro_version (),
4148
Gtk.MAJOR_VERSION, Gtk.MINOR_VERSION, Gtk.MICRO_VERSION,
@@ -48,7 +55,7 @@ namespace Turntable {
4855
Soup.MAJOR_VERSION, Soup.MINOR_VERSION, Soup.MICRO_VERSION,
4956
Json.MAJOR_VERSION, Json.MINOR_VERSION, Json.MICRO_VERSION,
5057
Secret.MAJOR_VERSION, Secret.MINOR_VERSION, Secret.MICRO_VERSION,
51-
@"$(cli_list_clients || cli_client_id_scrobble != null)"
58+
cli_mode.to_string ()
5259
)
5360
#else
5461
"false"
@@ -81,6 +88,18 @@ namespace Turntable {
8188
this.add_action_entries (APP_ENTRIES, this);
8289
this.set_accels_for_action ("app.quit", {"<primary>q"});
8390
this.set_accels_for_action ("app.new-window", {"<primary>n"});
91+
92+
#if SANDBOXED
93+
var display = Gdk.Display.get_default ();
94+
if (display != null) {
95+
string home = GLib.Environment.get_home_dir ();
96+
var theme = Gtk.IconTheme.get_for_display (display);
97+
theme.add_search_path (@"$home/.local/share/icons");
98+
theme.add_search_path (@"$home/.local/share/flatpak/exports/share/icons");
99+
theme.add_search_path ("/var/lib/snapd/desktop/icons");
100+
theme.add_search_path ("/var/lib/flatpak/exports/share/icons");
101+
}
102+
#endif
84103
}
85104

86105
public static int main (string[] args) {
@@ -102,15 +121,44 @@ namespace Turntable {
102121
Intl.textdomain (Build.GETTEXT_PACKAGE);
103122

104123
debug_enabled = !GLib.Log.writer_default_would_drop (GLib.LogLevelFlags.LEVEL_DEBUG, "Turntable");
105-
is_flatpak = GLib.Environment.get_variable ("FLATPAK_ID") != null || GLib.File.new_for_path ("/.flatpak-info").query_exists ();
106124
GLib.Environment.unset_variable ("GTK_THEME");
125+
126+
#if SCROBBLING
127+
cli_mode = cli_list_clients || cli_client_id_scrobble != null;
128+
#endif
129+
130+
#if SANDBOXED
131+
#if SCROBBLING
132+
if (!cli_mode)
133+
#endif
134+
{
135+
string[] temp_dirs = {};
136+
string home = GLib.Environment.get_home_dir ();
137+
string[] def_dirs = {
138+
"/usr/share/applications",
139+
@"$home/.local/share/applications",
140+
"/var/lib/flatpak/exports/share/applications",
141+
@"$home/.local/share/flatpak/exports/share/applications",
142+
"/var/lib/snapd/desktop/applications"
143+
};
144+
145+
foreach (string path in def_dirs) {
146+
if (GLib.FileUtils.test (path, GLib.FileTest.IS_DIR)) {
147+
temp_dirs += path;
148+
}
149+
}
150+
151+
desktop_file_dirs = temp_dirs;
152+
}
153+
#endif
154+
107155
mpris_manager = new Mpris.Manager ();
108-
application = new Application ();
109156

110157
#if SCROBBLING
111-
if (cli_list_clients || cli_client_id_scrobble != null) return (new Utils.CLI ()). run ();
158+
if (cli_mode) return (new Utils.CLI ()).run ();
112159
#endif
113160

161+
application = new Application ();
114162
return application.run (args);
115163
}
116164

src/Mpris/Entry.vala

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,25 @@ public class Turntable.Mpris.Entry : GLib.Object {
5454
}
5555
}
5656

57+
#if SANDBOXED
58+
GLib.HashTable<string, string> cached_desktop_icons = new GLib.HashTable<string, string> (str_hash, str_equal);
59+
private string get_sandboxed_icon_for_id (string id) {
60+
if (cached_desktop_icons.contains (id)) return cached_desktop_icons.get (id);
61+
62+
string icon = "application-x-executable-symbolic";
63+
try {
64+
var key_file = new GLib.KeyFile ();
65+
if (key_file.load_from_dirs (@"$id.desktop", desktop_file_dirs, null, GLib.KeyFileFlags.NONE)) {
66+
var icon_key = key_file.get_string ("Desktop Entry", "Icon");
67+
if (icon_key != null) icon = icon_key;
68+
}
69+
} catch {}
70+
71+
cached_desktop_icons.set (id, icon);
72+
return icon;
73+
}
74+
#endif
75+
5776
public Entry (string name, DesktopBus.Mpris.MediaPlayer2 media_player) {
5877
this.bus_namespace = name;
5978
parent_bus_namespace = name;
@@ -62,12 +81,22 @@ public class Turntable.Mpris.Entry : GLib.Object {
6281
parent_bus_namespace = @"org.mpris.MediaPlayer2.$(namespace_parts[0]).$(namespace_parts[1]).$(namespace_parts[2])";
6382
}
6483

65-
var app_info = media_player.desktop_entry == null ? null : new GLib.DesktopAppInfo (@"$(media_player.desktop_entry).desktop");
6684
string icon = "application-x-executable-symbolic";
67-
if (app_info != null) {
68-
var app_icon = app_info.get_icon ();
69-
if (app_icon != null) icon = app_icon.to_string ();
70-
}
85+
#if SCROBBLING
86+
if (!cli_mode) {
87+
#endif
88+
#if SANDBOXED
89+
icon = get_sandboxed_icon_for_id (media_player.desktop_entry);
90+
#else
91+
var app_info = media_player.desktop_entry == null ? null : new GLib.DesktopAppInfo (@"$(media_player.desktop_entry).desktop");
92+
if (app_info != null) {
93+
var app_icon = app_info.get_icon ();
94+
if (app_icon != null) icon = app_icon.to_string ();
95+
}
96+
#endif
97+
#if SCROBBLING
98+
}
99+
#endif
71100

72101
this.client_info = {
73102
media_player.identity,

0 commit comments

Comments
 (0)