diff options
-rw-r--r-- | README.md | 6 | ||||
-rw-r--r-- | src/app_info.c | 32 | ||||
-rw-r--r-- | src/app_info.h | 7 | ||||
-rw-r--r-- | src/app_launcher.c | 149 | ||||
-rw-r--r-- | src/meson.build | 1 | ||||
-rw-r--r-- | src/process_manager.c | 220 | ||||
-rw-r--r-- | src/process_manager.h | 38 | ||||
-rw-r--r-- | src/systemd_manager.c | 120 | ||||
-rw-r--r-- | src/systemd_manager.h | 10 |
9 files changed, 186 insertions, 397 deletions
@@ -13,9 +13,9 @@ This interface can be used to: For more details about the D-Bus interface, please refer to the file `data/org.automotivelinux.AppLaunch.xml`. -Applications can be started either through D-Bus activation (using their D-Bus -name) or by specifying a command line to be executed, and are monitored until -they exit. Please note `applaunchd` allows only one instance of a given +Applications are enumerated from systemd's list of available units based on +the pattern agl-app*@*.service, and are started and controled using their +systemd unit. Please note `applaunchd` allows only one instance of a given application. AGL repo for source code: diff --git a/src/app_info.c b/src/app_info.c index 0d25d37..97ecf7e 100644 --- a/src/app_info.c +++ b/src/app_info.c @@ -24,9 +24,7 @@ struct _AppInfo { gchar *app_id; gchar *name; gchar *icon_path; - gchar *command; - gboolean systemd_activated; - gboolean graphical; + gchar *service; AppStatus status; @@ -50,7 +48,7 @@ static void app_info_dispose(GObject *object) g_clear_pointer(&self->app_id, g_free); g_clear_pointer(&self->name, g_free); g_clear_pointer(&self->icon_path, g_free); - g_clear_pointer(&self->app_id, g_free); + g_clear_pointer(&self->service, g_free); g_clear_pointer(&self->runtime_data, g_free); G_OBJECT_CLASS(app_info_parent_class)->dispose(object); @@ -78,18 +76,14 @@ static void app_info_init(AppInfo *self) */ AppInfo *app_info_new(const gchar *app_id, const gchar *name, - const gchar *icon_path, const gchar *command, - gboolean systemd_activated, - gboolean graphical) + const gchar *icon_path, const gchar *service) { AppInfo *self = g_object_new(APPLAUNCHD_TYPE_APP_INFO, NULL); self->app_id = g_strdup(app_id); self->name = g_strdup(name); self->icon_path = g_strdup(icon_path); - self->command = g_strdup(command); - self->systemd_activated = systemd_activated; - self->graphical = graphical; + self->service = g_strdup(service); return self; } @@ -115,25 +109,11 @@ const gchar *app_info_get_icon_path(AppInfo *self) return self->icon_path; } -const gchar *app_info_get_command(AppInfo *self) +const gchar *app_info_get_service(AppInfo *self) { g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(self), NULL); - return self->command; -} - -gboolean app_info_get_systemd_activated(AppInfo *self) -{ - g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(self), FALSE); - - return self->systemd_activated; -} - -gboolean app_info_get_graphical(AppInfo *self) -{ - g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(self), FALSE); - - return self->graphical; + return self->service; } AppStatus app_info_get_status(AppInfo *self) diff --git a/src/app_info.h b/src/app_info.h index 5e69dc3..f420965 100644 --- a/src/app_info.h +++ b/src/app_info.h @@ -33,16 +33,13 @@ G_DECLARE_FINAL_TYPE(AppInfo, app_info, APPLAUNCHD, APP_INFO, GObject); AppInfo *app_info_new(const gchar *app_id, const gchar *name, - const gchar *icon_path, const gchar *command, - gboolean systemd_activated, gboolean graphical); + const gchar *icon_path, const gchar *service); /* Accessors for read-only members */ const gchar *app_info_get_app_id(AppInfo *self); const gchar *app_info_get_name(AppInfo *self); const gchar *app_info_get_icon_path(AppInfo *self); -const gchar *app_info_get_command(AppInfo *self); -gboolean app_info_get_systemd_activated(AppInfo *self); -gboolean app_info_get_graphical(AppInfo *self); +const gchar *app_info_get_service(AppInfo *self); /* Accessors for read-write members */ AppStatus app_info_get_status(AppInfo *self); diff --git a/src/app_launcher.c b/src/app_launcher.c index 423bf19..417f59a 100644 --- a/src/app_launcher.c +++ b/src/app_launcher.c @@ -14,11 +14,8 @@ * limitations under the License. */ -#include <gio/gdesktopappinfo.h> - #include "app_info.h" #include "app_launcher.h" -#include "process_manager.h" #include "systemd_manager.h" #include "utils.h" @@ -29,7 +26,6 @@ typedef struct _AppLauncher { sd_event *event; sd_bus *bus; - ProcessManager *process_manager; SystemdManager *systemd_manager; GList *apps_list; @@ -57,114 +53,87 @@ static void app_launcher_started_cb(AppLauncher *self, /* * This function is executed during the object initialization. It goes through * all available applications on the system and creates a static list - * containing all the relevant info (ID, name, command, icon...) for further + * containing all the relevant info (ID, name, unit, icon...) for further * processing. */ static void app_launcher_update_applications_list(AppLauncher *self) { - g_autoptr(GList) app_list = g_app_info_get_all(); g_auto(GStrv) dirlist = NULL; - guint len = g_list_length(app_list); char *xdg_data_dirs = getenv("XDG_DATA_DIRS"); if (xdg_data_dirs) dirlist = g_strsplit(getenv("XDG_DATA_DIRS"), ":", -1); - for (guint i = 0; i < len; i++) { - GAppInfo *appinfo = g_list_nth_data(app_list, i); - const gchar *desktop_id = g_app_info_get_id(appinfo); - GIcon *icon = g_app_info_get_icon(appinfo); - g_autoptr(GDesktopAppInfo) desktop_info = g_desktop_app_info_new(desktop_id); + GList *units = NULL; + if (!systemd_manager_enumerate_app_units(self->systemd_manager, self, &units)) { + return; + } + + GList *iterator; + for (iterator = units; iterator != NULL; iterator = iterator->next) { g_autofree const gchar *app_id = NULL; g_autofree const gchar *icon_path = NULL; AppInfo *app_info = NULL; - gboolean systemd_activated, graphical; - if (!desktop_info) { - g_warning("Unable to find .desktop file for application '%s'", desktop_id); + if (!iterator->data) continue; - } - /* Check the application should be part of the apps list */ - if (!g_app_info_should_show(appinfo)) { - g_debug("Application '%s' shouldn't be shown, skipping...", desktop_id); - continue; - } + // Parse service and app id out of unit filename + gchar *service = g_strrstr(iterator->data, "/"); + if (!service) + service = iterator->data; + else + service += 1; - if (g_desktop_app_info_get_is_hidden(desktop_info)) { - g_debug("Application '%s' is hidden, skipping...", desktop_id); - continue; + g_autofree char *tmp = g_strdup(service); + char *end = tmp + strlen(tmp); + while (end > tmp && *end != '.') { + --end; } - if (g_desktop_app_info_get_nodisplay(desktop_info)) { - g_debug("Application '%s' has NoDisplay set, skipping...", desktop_id); + if (end > tmp) { + *end = '\0'; + } else { + g_free(tmp); continue; } - - /* - * The application ID is usually the .desktop file name. However, a common practice - * is that .desktop files are named after the executable name, in which case the - * "StartupWMClass" property indicates the wayland app-id. - */ - app_id = g_strdup(g_desktop_app_info_get_startup_wm_class(desktop_info)); - if (!app_id) { - app_id = g_strdup(desktop_id); - gchar *extension = g_strrstr(app_id, ".desktop"); - if (extension) - *extension = 0; + while (end > tmp && *end != '@') { + --end; } - - /* - * An application can be D-Bus activated if one of those conditions are met: - * - its .desktop file contains a "DBusActivatable=true" line - * - it provides a corresponding D-Bus service file - * HACK: Use "DBusActivatable=true" in .desktop to mark systemd-based service - */ - - /* Default to non-DBus-activatable */ - systemd_activated = FALSE; - if (g_desktop_app_info_get_boolean(desktop_info, - G_KEY_FILE_DESKTOP_KEY_DBUS_ACTIVATABLE)) { - systemd_activated = TRUE; - } else if (dirlist) { - const gchar *desktop_filename = g_desktop_app_info_get_filename(desktop_info); - g_autofree gchar *service_file = g_strconcat(app_id, ".service", NULL); - - for (GStrv xdg_data_dir = dirlist; *xdg_data_dir != NULL ; xdg_data_dir++) { - g_autofree gchar *service_path = NULL; - - /* Search only in the XDG_DATA_DIR where the .desktop file is located */ - if (!g_str_has_prefix(desktop_filename, *xdg_data_dir)) - continue; - - service_path = g_build_filename(*xdg_data_dir, "dbus-1", "services", - service_file, NULL); - if (g_file_test(service_path, G_FILE_TEST_EXISTS)) { - systemd_activated = TRUE; - break; - } - } + if (end > tmp) { + app_id = g_strdup(end + 1); + } + // Potentially handle non-template agl-app-foo.service units here + + // Try getting display name from unit Description property + char *name = NULL; + if (!systemd_manager_get_app_description(self->systemd_manager, + self, + service, + &name) || + name == NULL) { + + // Fall back to the application ID + g_warning("Could not retrieve Description of '%s'", service); + name = app_id; } - - /* Applications with "Terminal=True" are not graphical apps */ - graphical = !g_desktop_app_info_get_boolean(desktop_info, - G_KEY_FILE_DESKTOP_KEY_TERMINAL); /* * GAppInfo retrieves the icon data but doesn't provide a way to retrieve * the corresponding file name, so we have to look it up by ourselves. */ - if (icon && dirlist) - icon_path = applaunchd_utils_get_icon(dirlist, g_icon_to_string(icon)); + if (app_id && dirlist) + icon_path = applaunchd_utils_get_icon(dirlist, app_id); - app_info = app_info_new(app_id, g_app_info_get_name(appinfo), + app_info = app_info_new(app_id, + name, icon_path ? icon_path : "", - g_app_info_get_commandline(appinfo), - systemd_activated, graphical); + service); - g_debug("Adding application '%s'", app_id); + g_debug("Adding application '%s' with display name '%s'", app_id, name); self->apps_list = g_list_append(self->apps_list, app_info); } + g_list_free_full(units, g_free); } /* @@ -186,9 +155,6 @@ static GVariant *app_launcher_get_list_variant(AppLauncher *self, gboolean graph GVariantBuilder app_builder; AppInfo *app_info = g_list_nth_data(self->apps_list, i); - if (graphical && !app_info_get_graphical(app_info)) - continue; - g_variant_builder_init (&app_builder, G_VARIANT_TYPE("(sss)")); /* Create application entry */ @@ -229,10 +195,7 @@ static gboolean app_launcher_start_app(AppLauncher *self, AppInfo *app_info) app_launcher_started_cb(self, app_id, NULL); return TRUE; case APP_STATUS_INACTIVE: - if (app_info_get_systemd_activated(app_info)) - systemd_manager_start_app(self->systemd_manager, app_info); - else - process_manager_start_app(self->process_manager, app_info); + systemd_manager_start_app(self->systemd_manager, app_info); return TRUE; default: g_critical("Unknown status %d for application '%s'", app_status, app_id); @@ -257,7 +220,7 @@ static gboolean app_launcher_handle_start(applaunchdAppLaunch *object, AppLauncher *self = APPLAUNCHD_APP_LAUNCHER(object); g_return_val_if_fail(APPLAUNCHD_IS_APP_LAUNCHER(self), FALSE); - /* Seach the apps list for the given app-id */ + /* Search the apps list for the given app-id */ app = app_launcher_get_app_info(self, app_id); if (!app) { g_dbus_method_invocation_return_error(invocation, G_DBUS_ERROR, @@ -343,7 +306,6 @@ static void app_launcher_dispose(GObject *object) if (self->apps_list) g_list_free_full(g_steal_pointer(&self->apps_list), g_object_unref); - g_clear_object(&self->process_manager); g_clear_object(&self->systemd_manager); G_OBJECT_CLASS(app_launcher_parent_class)->dispose(object); @@ -375,17 +337,6 @@ static void app_launcher_init (AppLauncher *self) g_source_attach(g_sd_event_create_source(self->event, self->bus), g_main_loop_get_context(main_loop)); /* - * Create the process manager and connect to its signals - * so we get notified on app startup/termination - */ - self->process_manager = g_object_new(APPLAUNCHD_TYPE_PROCESS_MANAGER, - NULL); - g_signal_connect_swapped(self->process_manager, "started", - G_CALLBACK(app_launcher_started_cb), self); - g_signal_connect_swapped(self->process_manager, "terminated", - G_CALLBACK(app_launcher_terminated_cb), self); - - /* * Create the systemd manager and connect to its signals * so we get notified on app startup/termination */ diff --git a/src/meson.build b/src/meson.build index 761ad9b..f44aef3 100644 --- a/src/meson.build +++ b/src/meson.build @@ -28,7 +28,6 @@ executable ( 'main.c', 'app_info.c', 'app_info.h', 'app_launcher.c', 'app_launcher.h', - 'process_manager.c', 'process_manager.h', 'systemd_manager.c', 'systemd_manager.h', 'utils.c', 'utils.h', ], diff --git a/src/process_manager.c b/src/process_manager.c deleted file mode 100644 index ad3ea33..0000000 --- a/src/process_manager.c +++ /dev/null @@ -1,220 +0,0 @@ -/* - * Copyright (C) 2021 Collabora Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include "app_launcher.h" -#include "process_manager.h" - -struct _ProcessManager { - GObject parent_instance; - - GList *process_data; -}; - -G_DEFINE_TYPE(ProcessManager, process_manager, G_TYPE_OBJECT); - -enum { - STARTED, - TERMINATED, - N_SIGNALS -}; -static guint signals[N_SIGNALS]; - -/* - * Application info structure, used for storing relevant data - * in the `running_apps` list - */ -struct process_runtime_data { - guint watcher; - GPid pid; - const gchar *app_id; -}; - -/* - * Initialization & cleanup functions - */ - -static void process_manager_dispose(GObject *object) -{ - ProcessManager *self = APPLAUNCHD_PROCESS_MANAGER(object); - - g_return_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self)); - - if (self->process_data) - g_list_free_full(g_steal_pointer(&self->process_data), g_free); - - G_OBJECT_CLASS(process_manager_parent_class)->dispose(object); -} - -static void process_manager_finalize(GObject *object) -{ - G_OBJECT_CLASS(process_manager_parent_class)->finalize(object); -} - -static void process_manager_class_init(ProcessManagerClass *klass) -{ - GObjectClass *object_class = (GObjectClass *)klass; - - object_class->dispose = process_manager_dispose; - object_class->finalize = process_manager_finalize; - - signals[STARTED] = g_signal_new("started", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0 , - NULL, NULL, NULL, G_TYPE_NONE, - 1, G_TYPE_STRING); - - signals[TERMINATED] = g_signal_new("terminated", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, 0 , - NULL, NULL, NULL, G_TYPE_NONE, - 1, G_TYPE_STRING); -} - -static void process_manager_init(ProcessManager *self) -{ -} - -/* - * Internal functions - */ - -static const gchar *get_app_id_for_pid(ProcessManager *self, GPid pid) -{ - g_return_val_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self), NULL); - - AppLauncher *app_launcher = app_launcher_get_default(); - guint len = g_list_length(self->process_data); - - for (guint i = 0; i < len; i++) { - struct process_runtime_data *runtime_data = - g_list_nth_data(self->process_data, i); - - if (runtime_data->pid == pid) - return runtime_data->app_id; - } - - return NULL; -} - -/* - * Internal callbacks - */ - -/* - * This function is called when a watched process terminated, so we can: - * - cleanup this application's data (and reap the process so it - * doesn't become a zombie) - * - notify listeners that the process terminated - */ -static void process_manager_app_terminated_cb(GPid pid, - gint wait_status, - gpointer data) -{ - ProcessManager *self = data; - AppLauncher *app_launcher = app_launcher_get_default(); - struct process_runtime_data *runtime_data; - const gchar *app_id; - AppInfo *app_info; - - g_return_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self)); - - app_id = get_app_id_for_pid(self, pid); - if (!app_id) { - g_warning("Unable to retrieve app id for pid %d", pid); - return; - } - - app_info = app_launcher_get_app_info(app_launcher, app_id); - if (!app_info) { - g_warning("Unable to find running app with pid %d", pid); - return; - } - - if (g_spawn_check_exit_status(wait_status, NULL)) - g_debug("Application '%s' terminated with exit code %i", - app_id, WEXITSTATUS(wait_status)); - else - g_warning("Application '%s' crashed", app_id); - - g_spawn_close_pid(pid); - - runtime_data = app_info_get_runtime_data(app_info); - g_source_remove(runtime_data->watcher); - - app_info_set_status(app_info, APP_STATUS_INACTIVE); - app_info_set_runtime_data(app_info, NULL); - - self->process_data = g_list_remove(self->process_data, runtime_data); - g_free(runtime_data); - - g_signal_emit(self, signals[TERMINATED], 0, app_id); -} - -/* - * Public functions - */ - -ProcessManager *process_manager_new(void) -{ - return g_object_new(APPLAUNCHD_TYPE_PROCESS_MANAGER, NULL); -} - -/* - * Start an application by executing the provided command line. - */ -gboolean process_manager_start_app(ProcessManager *self, - AppInfo *app_info) -{ - g_return_val_if_fail(APPLAUNCHD_IS_PROCESS_MANAGER(self), FALSE); - g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(app_info), FALSE); - - gboolean success; - g_autofree GStrv args = NULL; - const gchar *app_id = app_info_get_app_id(app_info); - const gchar *command = app_info_get_command(app_info); - struct process_runtime_data *runtime_data; - - runtime_data = g_new0(struct process_runtime_data, 1); - if (!runtime_data) { - g_critical("Unable to allocate runtime data structure for '%s'", - app_id); - return FALSE; - } - - runtime_data->app_id = app_id; - - args = g_strsplit(command, " ", -1); - success = g_spawn_async(NULL, args, NULL, - G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH, - NULL, NULL, &runtime_data->pid, NULL); - if (!success) { - g_critical("Unable to start application '%s'", app_id); - g_free(runtime_data); - return FALSE; - } - - /* - * Add a watcher for the child PID in order to get notified when it dies - */ - runtime_data->watcher = g_child_watch_add(runtime_data->pid, - process_manager_app_terminated_cb, - self); - self->process_data = g_list_append(self->process_data, runtime_data); - app_info_set_runtime_data(app_info, runtime_data); - app_info_set_status(app_info, APP_STATUS_RUNNING); - - g_signal_emit(self, signals[STARTED], 0, app_id); - - return TRUE; -} diff --git a/src/process_manager.h b/src/process_manager.h deleted file mode 100644 index 1979cba..0000000 --- a/src/process_manager.h +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright (C) 2021 Collabora Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#ifndef PROCESSMANAGER_H -#define PROCESSMANAGER_H - -#include <glib-object.h> - -#include "app_info.h" - -G_BEGIN_DECLS - -#define APPLAUNCHD_TYPE_PROCESS_MANAGER process_manager_get_type() - -G_DECLARE_FINAL_TYPE(ProcessManager, process_manager, - APPLAUNCHD, PROCESS_MANAGER, GObject); - -ProcessManager *process_manager_new(void); - -gboolean process_manager_start_app(ProcessManager *self, - AppInfo *app_info); - -G_END_DECLS - -#endif diff --git a/src/systemd_manager.c b/src/systemd_manager.c index 3fae7fc..63e7094 100644 --- a/src/systemd_manager.c +++ b/src/systemd_manager.c @@ -147,7 +147,119 @@ SystemdManager *systemd_manager_new(void) } /* - * Start an application by executing the provided command line. + * Get app unit list + */ +gboolean systemd_manager_enumerate_app_units(SystemdManager *self, + AppLauncher *launcher, + GList **units) +{ + g_return_val_if_fail(APPLAUNCHD_IS_SYSTEMD_MANAGER(self), FALSE); + g_return_val_if_fail(APPLAUNCHD_IS_APP_LAUNCHER(launcher), FALSE); + g_return_val_if_fail(units != NULL, FALSE); + + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; + const char *path; + int r; + + r = sd_bus_call_method( + app_launcher_get_bus(launcher), /* bus */ + "org.freedesktop.systemd1", /* service to contact */ + "/org/freedesktop/systemd1", /* object path */ + "org.freedesktop.systemd1.Manager", /* interface name */ + "ListUnitFilesByPatterns", /* method name */ + &error, /* object to return error in */ + &m, /* return message on success */ + "asas", /* input signature */ + 0, /* first argument (empty array) */ + 1, /* second argument (array) */ + "agl-app*@*.service" + ); + if (r < 0) { + g_critical("Failed to issue method call: %s", error.message); + goto finish; + } + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "(ss)"); + if (r < 0) { + g_critical("Failed to parse response message: %s", strerror(-r)); + goto finish; + } + + const char *unit; + const char *state; + while ((r = sd_bus_message_read(m, "(ss)", &unit, &state)) > 0) { + if (!g_str_has_suffix(unit, "@.service")) + *units = g_list_prepend(*units, g_strdup(unit)); + } + if (r < 0) { + g_critical("Failed to parse unit entry: %s", strerror(-r)); + goto finish; + } + + // Exit array + r = sd_bus_message_exit_container(m); + if (r < 0) { + g_critical("Failed to parse response message 5: %s", strerror(-r)); + goto finish; + } + + return TRUE; + +finish: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + g_list_free_full(*units, g_free); + *units = NULL; + return FALSE; +} + +/* + * Get app unit description property + */ +gboolean systemd_manager_get_app_description(SystemdManager *self, + AppLauncher *launcher, + gchar *service, + gchar **description) +{ + g_return_val_if_fail(APPLAUNCHD_IS_SYSTEMD_MANAGER(self), FALSE); + g_return_val_if_fail(APPLAUNCHD_IS_APP_LAUNCHER(launcher), FALSE); + g_return_val_if_fail(service != NULL, FALSE); + g_return_val_if_fail(description != NULL, FALSE); + + sd_bus_error error = SD_BUS_ERROR_NULL; + sd_bus_message *m = NULL; + gchar *esc_service = NULL; + const char *path; + int r; + + /* Get the escaped unit name in the systemd hierarchy */ + sd_bus_path_encode("/org/freedesktop/systemd1/unit", service, &esc_service); + + r = sd_bus_get_property_string( + app_launcher_get_bus(launcher), /* bus */ + "org.freedesktop.systemd1", /* service to contact */ + esc_service, /* object path */ + "org.freedesktop.systemd1.Unit", + "Description", + &error, + description); + if (r < 0) { + g_critical("Failed to issue method call: %s", error.message); + goto finish; + } + return TRUE; + +finish: + sd_bus_error_free(&error); + sd_bus_message_unref(m); + g_free(*description); + *description = NULL; + return FALSE; +} + +/* + * Start an application by executing its service. */ gboolean systemd_manager_start_app(SystemdManager *self, AppInfo *app_info) @@ -156,10 +268,9 @@ gboolean systemd_manager_start_app(SystemdManager *self, g_return_val_if_fail(APPLAUNCHD_IS_APP_INFO(app_info), FALSE); AppLauncher *launcher = app_launcher_get_default(); - g_autofree gchar *service = NULL; gchar *esc_service = NULL; const gchar *app_id = app_info_get_app_id(app_info); - const gchar *command = app_info_get_command(app_info); + const gchar *service = app_info_get_service(app_info); struct systemd_runtime_data *runtime_data; sd_bus_error error = SD_BUS_ERROR_NULL; @@ -173,10 +284,9 @@ gboolean systemd_manager_start_app(SystemdManager *self, return FALSE; } - /* Compose the corresponding service name */ - service = g_strdup_printf("agl-app@%s.service", command); /* Get the escaped unit name in the systemd hierarchy */ sd_bus_path_encode("/org/freedesktop/systemd1/unit", service, &esc_service); + g_debug("Trying to start service '%s', unit path '%s'", service, esc_service); runtime_data->mgr = self; runtime_data->esc_service = esc_service; diff --git a/src/systemd_manager.h b/src/systemd_manager.h index a8a4ac7..b866948 100644 --- a/src/systemd_manager.h +++ b/src/systemd_manager.h @@ -20,6 +20,7 @@ #include <glib-object.h> #include "app_info.h" +#include "app_launcher.h" G_BEGIN_DECLS @@ -30,6 +31,15 @@ G_DECLARE_FINAL_TYPE(SystemdManager, systemd_manager, SystemdManager *systemd_manager_new(void); +gboolean systemd_manager_enumerate_app_units(SystemdManager *self, + AppLauncher *launcher, + GList **units); + +gboolean systemd_manager_get_app_description(SystemdManager *self, + AppLauncher *launcher, + gchar *service, + gchar **description); + gboolean systemd_manager_start_app(SystemdManager *self, AppInfo *app_info); |