1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2007 Novell, Inc.
4  * Copyright (C) 2008 Red Hat, Inc.
5  * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 #include "config.h"
23 
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <fcntl.h>
27 #include <unistd.h>
28 #include <string.h>
29 #include <signal.h>
30 #include <locale.h>
31 #include <sys/stat.h>
32 #include <sys/types.h>
33 
34 #include <glib.h>
35 #include <glib/gi18n.h>
36 #include <glib/gstdio.h>
37 #include <glib-object.h>
38 #include <gio/gio.h>
39 
40 #include "gsm-manager.h"
41 #include "org.gnome.SessionManager.h"
42 
43 #ifdef ENABLE_SYSTEMD_JOURNAL
44 #include <systemd/sd-journal.h>
45 #endif
46 
47 #ifdef HAVE_SYSTEMD
48 #include <systemd/sd-daemon.h>
49 #else
50 /* So we don't need to add ifdef's everywhere */
51 #define sd_notify(u, m)            do {} while (0)
52 #define sd_notifyf(u, m, ...)      do {} while (0)
53 #endif
54 
55 #include "gsm-store.h"
56 #include "gsm-inhibitor.h"
57 #include "gsm-presence.h"
58 #include "gsm-shell.h"
59 
60 #include "gsm-xsmp-server.h"
61 #include "gsm-xsmp-client.h"
62 #include "gsm-dbus-client.h"
63 
64 #include "gsm-autostart-app.h"
65 
66 #include "gsm-util.h"
67 #include "gsm-icon-names.h"
68 #include "gsm-system.h"
69 #include "gsm-session-save.h"
70 #include "gsm-shell-extensions.h"
71 #include "gsm-fail-whale.h"
72 
73 #define GSM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_MANAGER, GsmManagerPrivate))
74 
75 /* UUIDs for log messages */
76 #define GSM_MANAGER_STARTUP_SUCCEEDED_MSGID     "0ce153587afa4095832d233c17a88001"
77 #define GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID "10dd2dc188b54a5e98970f56499d1f73"
78 
79 #define GSM_MANAGER_DBUS_PATH "/org/gnome/SessionManager"
80 #define GSM_MANAGER_DBUS_NAME "org.gnome.SessionManager"
81 #define GSM_MANAGER_DBUS_IFACE "org.gnome.SessionManager"
82 
83 /* Probably about the longest amount of time someone could reasonably
84  * want to wait, at least for something happening more than once.
85  * We can get deployed on very slow media though like CDROM devices,
86  * often with complex stacking/compressing filesystems on top, which
87  * is not a recipie for speed.   Particularly now that we throw up
88  * a fail whale if required components don't show up quickly enough,
89  * let's make this fairly long.
90  */
91 #define GSM_MANAGER_PHASE_TIMEOUT 90 /* seconds */
92 
93 #define GDM_FLEXISERVER_COMMAND "gdmflexiserver"
94 #define GDM_FLEXISERVER_ARGS    "--startnew Standard"
95 
96 #define SESSION_SCHEMA            "org.gnome.desktop.session"
97 #define KEY_IDLE_DELAY            "idle-delay"
98 #define KEY_SESSION_NAME          "session-name"
99 
100 #define GSM_MANAGER_SCHEMA        "org.gnome.SessionManager"
101 #define KEY_AUTOSAVE              "auto-save-session"
102 #define KEY_AUTOSAVE_ONE_SHOT     "auto-save-session-one-shot"
103 #define KEY_LOGOUT_PROMPT         "logout-prompt"
104 #define KEY_SHOW_FALLBACK_WARNING "show-fallback-warning"
105 
106 #define SCREENSAVER_SCHEMA        "org.gnome.desktop.screensaver"
107 #define KEY_SLEEP_LOCK            "lock-enabled"
108 
109 #define LOCKDOWN_SCHEMA           "org.gnome.desktop.lockdown"
110 #define KEY_DISABLE_LOG_OUT       "disable-log-out"
111 #define KEY_DISABLE_USER_SWITCHING "disable-user-switching"
112 
113 static void app_registered (GsmApp     *app, GParamSpec *spec, GsmManager *manager);
114 
115 typedef enum
116 {
117         GSM_MANAGER_LOGOUT_NONE,
118         GSM_MANAGER_LOGOUT_LOGOUT,
119         GSM_MANAGER_LOGOUT_REBOOT,
120         GSM_MANAGER_LOGOUT_REBOOT_INTERACT,
121         GSM_MANAGER_LOGOUT_SHUTDOWN,
122         GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT,
123 } GsmManagerLogoutType;
124 
125 struct GsmManagerPrivate
126 {
127         gboolean                failsafe;
128         gboolean                systemd_managed;
129         gboolean                systemd_initialized;
130         gboolean                manager_initialized;
131         GsmStore               *clients;
132         GsmStore               *inhibitors;
133         GsmInhibitorFlag        inhibited_actions;
134         GsmStore               *apps;
135         GsmPresence            *presence;
136         GsmXsmpServer          *xsmp_server;
137 
138         char                   *session_name;
139         gboolean                is_fallback_session : 1;
140 
141         /* Current status */
142         GsmManagerPhase         phase;
143         guint                   phase_timeout_id;
144         GSList                 *required_apps;
145         GSList                 *pending_apps;
146         GsmManagerLogoutMode    logout_mode;
147         GSList                 *query_clients;
148         guint                   query_timeout_id;
149         /* This is used for GSM_MANAGER_PHASE_END_SESSION only at the moment,
150          * since it uses a sublist of all running client that replied in a
151          * specific way */
152         GSList                 *next_query_clients;
153         /* This is the action that will be done just before we exit */
154         GsmManagerLogoutType    logout_type;
155 
156         /* List of clients which were disconnected due to disabled condition
157          * and shouldn't be automatically restarted */
158         GSList                 *condition_clients;
159 
160         GSList                 *pending_end_session_tasks;
161         GCancellable           *end_session_cancellable;
162 
163         GSettings              *settings;
164         GSettings              *session_settings;
165         GSettings              *screensaver_settings;
166         GSettings              *lockdown_settings;
167 
168         GsmSystem              *system;
169         GDBusConnection        *connection;
170         GsmExportedManager     *skeleton;
171         gboolean                dbus_disconnected : 1;
172 
173         GsmShell               *shell;
174         guint                   shell_end_session_dialog_canceled_id;
175         guint                   shell_end_session_dialog_open_failed_id;
176         guint                   shell_end_session_dialog_confirmed_logout_id;
177         guint                   shell_end_session_dialog_confirmed_shutdown_id;
178         guint                   shell_end_session_dialog_confirmed_reboot_id;
179 };
180 
181 enum {
182         PROP_0,
183         PROP_CLIENT_STORE,
184         PROP_SESSION_NAME,
185         PROP_FALLBACK,
186         PROP_FAILSAFE,
187         PROP_SYSTEMD_MANAGED
188 };
189 
190 enum {
191         PHASE_CHANGED,
192         LAST_SIGNAL
193 };
194 
195 static guint signals [LAST_SIGNAL] = { 0 };
196 
197 static void     gsm_manager_class_init  (GsmManagerClass *klass);
198 static void     gsm_manager_init        (GsmManager      *manager);
199 
200 static gboolean auto_save_is_enabled (GsmManager *manager);
201 static void     maybe_save_session   (GsmManager *manager);
202 
203 static gboolean _log_out_is_locked_down     (GsmManager *manager);
204 
205 static void     _handle_client_end_session_response (GsmManager *manager,
206                                                      GsmClient  *client,
207                                                      gboolean    is_ok,
208                                                      gboolean    do_last,
209                                                      gboolean    cancel,
210                                                      const char *reason);
211 static void     show_shell_end_session_dialog (GsmManager                   *manager,
212                                                GsmShellEndSessionDialogType  type);
213 static gpointer manager_object = NULL;
214 
215 G_DEFINE_TYPE (GsmManager, gsm_manager, G_TYPE_OBJECT)
216 
217 static const GDBusErrorEntry gsm_manager_error_entries[] = {
218         { GSM_MANAGER_ERROR_GENERAL, GSM_MANAGER_DBUS_IFACE ".GeneralError" },
219         { GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION, GSM_MANAGER_DBUS_IFACE ".NotInInitialization" },
220         { GSM_MANAGER_ERROR_NOT_IN_RUNNING, GSM_MANAGER_DBUS_IFACE ".NotInRunning" },
221         { GSM_MANAGER_ERROR_ALREADY_REGISTERED, GSM_MANAGER_DBUS_IFACE ".AlreadyRegistered" },
222         { GSM_MANAGER_ERROR_NOT_REGISTERED, GSM_MANAGER_DBUS_IFACE ".NotRegistered" },
223         { GSM_MANAGER_ERROR_INVALID_OPTION, GSM_MANAGER_DBUS_IFACE ".InvalidOption" },
224         { GSM_MANAGER_ERROR_LOCKED_DOWN, GSM_MANAGER_DBUS_IFACE ".LockedDown" }
225 };
226 
227 GQuark
gsm_manager_error_quark(void)228 gsm_manager_error_quark (void)
229 {
230         static volatile gsize quark_volatile = 0;
231 
232         g_dbus_error_register_error_domain ("gsm_manager_error",
233                                             &quark_volatile,
234                                             gsm_manager_error_entries,
235                                             G_N_ELEMENTS (gsm_manager_error_entries));
236         return quark_volatile;
237 }
238 
239 static gboolean
start_app_or_warn(GsmManager * manager,GsmApp * app)240 start_app_or_warn (GsmManager *manager,
241                    GsmApp     *app)
242 {
243         gboolean res;
244         GError *error = NULL;
245 
246         g_debug ("GsmManager: starting app '%s'", gsm_app_peek_id (app));
247 
248         res = gsm_app_start (app, &error);
249         if (error != NULL) {
250                 g_warning ("Failed to start app: %s", error->message);
251                 g_clear_error (&error);
252         }
253         return res;
254 }
255 
256 static gboolean
is_app_required(GsmManager * manager,GsmApp * app)257 is_app_required (GsmManager *manager,
258                  GsmApp     *app)
259 {
260         return g_slist_find (manager->priv->required_apps, app) != NULL;
261 }
262 
263 static void
on_required_app_failure(GsmManager * manager,GsmApp * app)264 on_required_app_failure (GsmManager  *manager,
265                          GsmApp      *app)
266 {
267         const gchar *app_id;
268         gboolean allow_logout;
269         GsmShellExtensions *extensions;
270 
271         app_id = gsm_app_peek_app_id (app);
272 
273         if (g_str_equal (app_id, "org.gnome.Shell")) {
274                 extensions = g_object_new (GSM_TYPE_SHELL_EXTENSIONS, NULL);
275                 gsm_shell_extensions_disable_all (extensions);
276         } else {
277                 extensions = NULL;
278         }
279 
280         if (gsm_system_is_login_session (manager->priv->system)) {
281                 allow_logout = FALSE;
282         } else {
283                 allow_logout = !_log_out_is_locked_down (manager);
284         }
285 
286 #ifdef ENABLE_SYSTEMD_JOURNAL
287         sd_journal_send ("MESSAGE_ID=%s", GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID,
288                          "PRIORITY=%d", 3,
289                          "MESSAGE=Unrecoverable failure in required component %s", app_id,
290                          NULL);
291 #endif
292 
293         gsm_fail_whale_dialog_we_failed (FALSE,
294                                          allow_logout,
295                                          extensions);
296 }
297 
298 static void
on_display_server_failure(GsmManager * manager,GsmApp * app)299 on_display_server_failure (GsmManager *manager,
300                            GsmApp     *app)
301 {
302         const gchar *app_id;
303         GsmShellExtensions *extensions;
304 
305         app_id = gsm_app_peek_app_id (app);
306 
307         if (g_str_equal (app_id, "org.gnome.Shell")) {
308                 extensions = g_object_new (GSM_TYPE_SHELL_EXTENSIONS, NULL);
309                 gsm_shell_extensions_disable_all (extensions);
310 
311                 g_object_unref (extensions);
312         } else {
313                 extensions = NULL;
314         }
315 
316 #ifdef ENABLE_SYSTEMD_JOURNAL
317         sd_journal_send ("MESSAGE_ID=%s", GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID,
318                          "PRIORITY=%d", 3,
319                          "MESSAGE=Unrecoverable failure in required component %s", app_id,
320                          NULL);
321 #endif
322 
323         gsm_quit ();
324 }
325 
326 static gboolean
_debug_client(const char * id,GsmClient * client,GsmManager * manager)327 _debug_client (const char *id,
328                GsmClient  *client,
329                GsmManager *manager)
330 {
331         g_debug ("GsmManager: Client %s", gsm_client_peek_id (client));
332         return FALSE;
333 }
334 
335 static void
debug_clients(GsmManager * manager)336 debug_clients (GsmManager *manager)
337 {
338         gsm_store_foreach (manager->priv->clients,
339                            (GsmStoreFunc)_debug_client,
340                            manager);
341 }
342 
343 static gboolean
_find_by_cookie(const char * id,GsmInhibitor * inhibitor,guint * cookie_ap)344 _find_by_cookie (const char   *id,
345                  GsmInhibitor *inhibitor,
346                  guint        *cookie_ap)
347 {
348         guint cookie_b;
349 
350         cookie_b = gsm_inhibitor_peek_cookie (inhibitor);
351 
352         return (*cookie_ap == cookie_b);
353 }
354 
355 static gboolean
_client_has_startup_id(const char * id,GsmClient * client,const char * startup_id_a)356 _client_has_startup_id (const char *id,
357                         GsmClient  *client,
358                         const char *startup_id_a)
359 {
360         const char *startup_id_b;
361 
362         startup_id_b = gsm_client_peek_startup_id (client);
363         if (IS_STRING_EMPTY (startup_id_b)) {
364                 return FALSE;
365         }
366 
367         return (strcmp (startup_id_a, startup_id_b) == 0);
368 }
369 
370 static void
app_condition_changed(GsmApp * app,gboolean condition,GsmManager * manager)371 app_condition_changed (GsmApp     *app,
372                        gboolean    condition,
373                        GsmManager *manager)
374 {
375         GsmClient *client;
376 
377         g_debug ("GsmManager: app:%s condition changed condition:%d",
378                  gsm_app_peek_id (app),
379                  condition);
380 
381         client = (GsmClient *)gsm_store_find (manager->priv->clients,
382                                               (GsmStoreFunc)_client_has_startup_id,
383                                               (char *)gsm_app_peek_startup_id (app));
384 
385         if (condition) {
386                 if (!gsm_app_is_running (app) && client == NULL) {
387                         start_app_or_warn (manager, app);
388                 } else {
389                         g_debug ("GsmManager: not starting - app still running '%s'", gsm_app_peek_id (app));
390                 }
391         } else {
392                 GError  *error;
393                 gboolean res;
394 
395                 if (client != NULL) {
396                         /* Kill client in case condition if false and make sure it won't
397                          * be automatically restarted by adding the client to
398                          * condition_clients */
399                         manager->priv->condition_clients =
400                                 g_slist_prepend (manager->priv->condition_clients, client);
401 
402                         g_debug ("GsmManager: stopping client %s for app", gsm_client_peek_id (client));
403 
404                         error = NULL;
405                         res = gsm_client_stop (client, &error);
406                         if (! res) {
407                                 g_warning ("Not able to stop app client from its condition: %s",
408                                            error->message);
409                                 g_error_free (error);
410                         }
411                 } else {
412                         g_debug ("GsmManager: stopping app %s", gsm_app_peek_id (app));
413 
414                         /* If we don't have a client then we should try to kill the app */
415                         error = NULL;
416                         res = gsm_app_stop (app, &error);
417                         if (! res) {
418                                 g_warning ("Not able to stop app from its condition: %s",
419                                            error->message);
420                                 g_error_free (error);
421                         }
422                 }
423         }
424 }
425 
426 static const char *
phase_num_to_name(guint phase)427 phase_num_to_name (guint phase)
428 {
429         const char *name;
430 
431         switch (phase) {
432         case GSM_MANAGER_PHASE_STARTUP:
433                 name = "STARTUP";
434                 break;
435         case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
436                 name = "EARLY_INITIALIZATION";
437                 break;
438         case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
439                 name = "PRE_DISPLAY_SERVER";
440                 break;
441         case GSM_MANAGER_PHASE_DISPLAY_SERVER:
442                 name = "DISPLAY_SERVER";
443                 break;
444         case GSM_MANAGER_PHASE_INITIALIZATION:
445                 name = "INITIALIZATION";
446                 break;
447         case GSM_MANAGER_PHASE_WINDOW_MANAGER:
448                 name = "WINDOW_MANAGER";
449                 break;
450         case GSM_MANAGER_PHASE_PANEL:
451                 name = "PANEL";
452                 break;
453         case GSM_MANAGER_PHASE_DESKTOP:
454                 name = "DESKTOP";
455                 break;
456         case GSM_MANAGER_PHASE_APPLICATION:
457                 name = "APPLICATION";
458                 break;
459         case GSM_MANAGER_PHASE_RUNNING:
460                 name = "RUNNING";
461                 break;
462         case GSM_MANAGER_PHASE_QUERY_END_SESSION:
463                 name = "QUERY_END_SESSION";
464                 break;
465         case GSM_MANAGER_PHASE_END_SESSION:
466                 name = "END_SESSION";
467                 break;
468         case GSM_MANAGER_PHASE_EXIT:
469                 name = "EXIT";
470                 break;
471         default:
472                 g_assert_not_reached ();
473                 break;
474         }
475 
476         return name;
477 }
478 
479 static void start_phase (GsmManager *manager);
480 
481 static void
gsm_manager_quit(GsmManager * manager)482 gsm_manager_quit (GsmManager *manager)
483 {
484         /* See the comment in request_reboot() for some more details about how
485          * this works. */
486 
487         switch (manager->priv->logout_type) {
488         case GSM_MANAGER_LOGOUT_LOGOUT:
489         case GSM_MANAGER_LOGOUT_NONE:
490                 gsm_quit ();
491                 break;
492         case GSM_MANAGER_LOGOUT_REBOOT:
493         case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
494                 gsm_system_complete_shutdown (manager->priv->system);
495                 gsm_quit ();
496                 break;
497         case GSM_MANAGER_LOGOUT_SHUTDOWN:
498         case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
499                 gsm_system_complete_shutdown (manager->priv->system);
500                 gsm_quit ();
501                 break;
502         default:
503                 g_assert_not_reached ();
504                 break;
505         }
506 }
507 
508 static gboolean do_query_end_session_exit (GsmManager *manager);
509 
510 static void
end_phase(GsmManager * manager)511 end_phase (GsmManager *manager)
512 {
513         gboolean start_next_phase = TRUE;
514 
515         g_debug ("GsmManager: ending phase %s",
516                  phase_num_to_name (manager->priv->phase));
517 
518         g_slist_free (manager->priv->pending_apps);
519         manager->priv->pending_apps = NULL;
520 
521         g_slist_free (manager->priv->query_clients);
522         manager->priv->query_clients = NULL;
523 
524         g_slist_free (manager->priv->next_query_clients);
525         manager->priv->next_query_clients = NULL;
526 
527         if (manager->priv->query_timeout_id > 0) {
528                 g_source_remove (manager->priv->query_timeout_id);
529                 manager->priv->query_timeout_id = 0;
530         }
531         if (manager->priv->phase_timeout_id > 0) {
532                 g_source_remove (manager->priv->phase_timeout_id);
533                 manager->priv->phase_timeout_id = 0;
534         }
535 
536         switch (manager->priv->phase) {
537         case GSM_MANAGER_PHASE_STARTUP:
538         case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
539         case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
540         case GSM_MANAGER_PHASE_DISPLAY_SERVER:
541                 break;
542         case GSM_MANAGER_PHASE_INITIALIZATION:
543                 manager->priv->manager_initialized = TRUE;
544                 /* Wait for systemd if it isn't initialized yet*/
545                 if (manager->priv->systemd_managed && !manager->priv->systemd_initialized) {
546                         sd_notify (0, "STATUS=GNOME Session Manager waiting for gnome-session-initialized.target (via signal)");
547                         start_next_phase = FALSE;
548                 }
549                 break;
550         case GSM_MANAGER_PHASE_WINDOW_MANAGER:
551         case GSM_MANAGER_PHASE_PANEL:
552         case GSM_MANAGER_PHASE_DESKTOP:
553         case GSM_MANAGER_PHASE_APPLICATION:
554                 break;
555         case GSM_MANAGER_PHASE_RUNNING:
556                 if (_log_out_is_locked_down (manager)) {
557                         g_warning ("Unable to logout: Logout has been locked down");
558                         start_next_phase = FALSE;
559                 }
560                 break;
561         case GSM_MANAGER_PHASE_QUERY_END_SESSION:
562                 if (!do_query_end_session_exit (manager))
563                         start_next_phase = FALSE;
564                 break;
565         case GSM_MANAGER_PHASE_END_SESSION:
566                 maybe_save_session (manager);
567                 break;
568         case GSM_MANAGER_PHASE_EXIT:
569                 start_next_phase = FALSE;
570                 gsm_manager_quit (manager);
571                 break;
572         default:
573                 g_assert_not_reached ();
574                 break;
575         }
576 
577         if (start_next_phase) {
578                 manager->priv->phase++;
579                 start_phase (manager);
580         }
581 }
582 
583 static void
app_event_during_startup(GsmManager * manager,GsmApp * app)584 app_event_during_startup (GsmManager *manager,
585                           GsmApp     *app)
586 {
587         if (!(manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION))
588                 return;
589 
590         manager->priv->pending_apps = g_slist_remove (manager->priv->pending_apps, app);
591 
592         if (manager->priv->pending_apps == NULL) {
593                 if (manager->priv->phase_timeout_id > 0) {
594                         g_source_remove (manager->priv->phase_timeout_id);
595                         manager->priv->phase_timeout_id = 0;
596                 }
597 
598                 end_phase (manager);
599         }
600 }
601 
602 static gboolean
is_app_display_server(GsmManager * manager,GsmApp * app)603 is_app_display_server (GsmManager *manager,
604                        GsmApp     *app)
605 {
606         GsmManagerPhase phase;
607 
608         /* Apps can only really act as a display server if
609          * we're a wayland session.
610          */
611         if (g_strcmp0 (g_getenv ("XDG_SESSION_TYPE"), "wayland") != 0)
612                 return FALSE;
613 
614         phase = gsm_app_peek_phase (app);
615 
616         return (phase == GSM_MANAGER_PHASE_DISPLAY_SERVER &&
617                 is_app_required (manager, app));
618 }
619 
620 static void
_restart_app(GsmManager * manager,GsmApp * app)621 _restart_app (GsmManager *manager,
622               GsmApp     *app)
623 {
624         GError *error = NULL;
625 
626         if (is_app_display_server (manager, app)) {
627                 on_display_server_failure (manager, app);
628                 return;
629         }
630 
631         if (!gsm_app_restart (app, &error)) {
632                 if (is_app_required (manager, app)) {
633                         on_required_app_failure (manager, app);
634                 } else {
635                         g_warning ("Error on restarting session managed app: %s", error->message);
636                 }
637                 g_clear_error (&error);
638 
639                 app_event_during_startup (manager, app);
640         }
641 }
642 
643 static void
app_died(GsmApp * app,int signal,GsmManager * manager)644 app_died (GsmApp     *app,
645           int         signal,
646           GsmManager *manager)
647 {
648         g_warning ("Application '%s' killed by signal %d", gsm_app_peek_app_id (app), signal);
649 
650         if (gsm_app_get_registered (app) && gsm_app_peek_autorestart (app)) {
651                 g_debug ("Component '%s' is autorestart, ignoring died signal",
652                          gsm_app_peek_app_id (app));
653                 return;
654         }
655 
656         _restart_app (manager, app);
657 
658         /* For now, we don't do anything with crashes from
659          * non-required apps after they hit the restart limit.
660          *
661          * Note that both required and not-required apps will be
662          * caught by ABRT/apport type infrastructure, and it'd be
663          * better to pick up the crash from there and do something
664          * un-intrusive about it generically.
665          */
666 }
667 
668 static void
app_exited(GsmApp * app,guchar exit_code,GsmManager * manager)669 app_exited (GsmApp     *app,
670             guchar      exit_code,
671             GsmManager *manager)
672 {
673         if (exit_code != 0)
674                 g_warning ("App '%s' exited with code %d", gsm_app_peek_app_id (app), exit_code);
675         else
676                 g_debug ("App %s exited successfully", gsm_app_peek_app_id (app));
677 
678         /* Consider that non-success exit status means "crash" for required components */
679         if (exit_code != 0 && is_app_required (manager, app)) {
680                 if (gsm_app_get_registered (app) && gsm_app_peek_autorestart (app)) {
681                         g_debug ("Component '%s' is autorestart, ignoring non-successful exit",
682                                  gsm_app_peek_app_id (app));
683                         return;
684                 }
685 
686                 _restart_app (manager, app);
687         } else {
688                 app_event_during_startup (manager, app);
689         }
690 }
691 
692 static void
app_registered(GsmApp * app,GParamSpec * spec,GsmManager * manager)693 app_registered (GsmApp     *app,
694                 GParamSpec *spec,
695                 GsmManager *manager)
696 {
697         if (!gsm_app_get_registered (app)) {
698                 return;
699         }
700 
701         g_debug ("App %s registered", gsm_app_peek_app_id (app));
702 
703         app_event_during_startup (manager, app);
704 }
705 
706 static gboolean
on_phase_timeout(GsmManager * manager)707 on_phase_timeout (GsmManager *manager)
708 {
709         GSList *a;
710 
711         manager->priv->phase_timeout_id = 0;
712 
713         switch (manager->priv->phase) {
714         case GSM_MANAGER_PHASE_STARTUP:
715         case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
716         case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
717         case GSM_MANAGER_PHASE_DISPLAY_SERVER:
718         case GSM_MANAGER_PHASE_INITIALIZATION:
719         case GSM_MANAGER_PHASE_WINDOW_MANAGER:
720         case GSM_MANAGER_PHASE_PANEL:
721         case GSM_MANAGER_PHASE_DESKTOP:
722         case GSM_MANAGER_PHASE_APPLICATION:
723                 for (a = manager->priv->pending_apps; a; a = a->next) {
724                         GsmApp *app = a->data;
725                         g_warning ("Application '%s' failed to register before timeout",
726                                    gsm_app_peek_app_id (app));
727                         if (is_app_required (manager, app))
728                                 on_required_app_failure (manager, app);
729                 }
730                 break;
731         case GSM_MANAGER_PHASE_RUNNING:
732                 break;
733         case GSM_MANAGER_PHASE_QUERY_END_SESSION:
734         case GSM_MANAGER_PHASE_END_SESSION:
735                 break;
736         case GSM_MANAGER_PHASE_EXIT:
737                 break;
738         default:
739                 g_assert_not_reached ();
740                 break;
741         }
742 
743         end_phase (manager);
744 
745         return FALSE;
746 }
747 
748 static gboolean
_start_app(const char * id,GsmApp * app,GsmManager * manager)749 _start_app (const char *id,
750             GsmApp     *app,
751             GsmManager *manager)
752 {
753         if (gsm_app_peek_phase (app) != manager->priv->phase) {
754                 goto out;
755         }
756 
757         /* Keep track of app autostart condition in order to react
758          * accordingly in the future. */
759         g_signal_connect (app,
760                           "condition-changed",
761                           G_CALLBACK (app_condition_changed),
762                           manager);
763 
764         if (gsm_app_peek_is_disabled (app)
765             || gsm_app_peek_is_conditionally_disabled (app)) {
766                 g_debug ("GsmManager: Skipping disabled app: %s", id);
767                 goto out;
768         }
769 
770         if (!start_app_or_warn (manager, app))
771                 goto out;
772 
773         if (manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION) {
774                 /* Historical note - apparently,
775                  * e.g. gnome-settings-daemon used to "daemonize", and
776                  * so gnome-session assumes process exit means "ok
777                  * we're done".  Of course this is broken, we don't
778                  * even distinguish between exit code 0 versus not-0,
779                  * nor do we have any metadata which tells us a
780                  * process is going to "daemonize" or not (and
781                  * basically nothing should be anyways).
782                  */
783                 g_signal_connect (app,
784                                   "exited",
785                                   G_CALLBACK (app_exited),
786                                   manager);
787                 g_signal_connect (app,
788                                   "notify::registered",
789                                   G_CALLBACK (app_registered),
790                                   manager);
791                 g_signal_connect (app,
792                                   "died",
793                                   G_CALLBACK (app_died),
794                                   manager);
795                 manager->priv->pending_apps = g_slist_prepend (manager->priv->pending_apps, app);
796         }
797  out:
798         return FALSE;
799 }
800 
801 static void
do_phase_startup(GsmManager * manager)802 do_phase_startup (GsmManager *manager)
803 {
804         gsm_store_foreach (manager->priv->apps,
805                            (GsmStoreFunc)_start_app,
806                            manager);
807 
808         if (manager->priv->pending_apps != NULL) {
809                 if (manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION) {
810                         manager->priv->phase_timeout_id = g_timeout_add_seconds (GSM_MANAGER_PHASE_TIMEOUT,
811                                                                                  (GSourceFunc)on_phase_timeout,
812                                                                                  manager);
813                 }
814         } else {
815                 end_phase (manager);
816         }
817 }
818 
819 typedef struct {
820         GsmManager *manager;
821         guint       flags;
822 } ClientEndSessionData;
823 
824 
825 static gboolean
_client_end_session(GsmClient * client,ClientEndSessionData * data)826 _client_end_session (GsmClient            *client,
827                      ClientEndSessionData *data)
828 {
829         gboolean ret;
830         GError  *error;
831 
832         error = NULL;
833         ret = gsm_client_end_session (client, data->flags, &error);
834         if (! ret) {
835                 g_warning ("Unable to query client: %s", error->message);
836                 g_error_free (error);
837                 /* FIXME: what should we do if we can't communicate with client? */
838         } else {
839                 g_debug ("GsmManager: adding client to end-session clients: %s", gsm_client_peek_id (client));
840                 data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
841                                                                       client);
842         }
843 
844         return FALSE;
845 }
846 
847 static gboolean
_client_end_session_helper(const char * id,GsmClient * client,ClientEndSessionData * data)848 _client_end_session_helper (const char           *id,
849                             GsmClient            *client,
850                             ClientEndSessionData *data)
851 {
852         return _client_end_session (client, data);
853 }
854 
855 static void
complete_end_session_tasks(GsmManager * manager)856 complete_end_session_tasks (GsmManager *manager)
857 {
858         GSList *l;
859 
860         for (l = manager->priv->pending_end_session_tasks;
861              l != NULL;
862              l = l->next) {
863                 GTask *task = G_TASK (l->data);
864                 if (!g_task_return_error_if_cancelled (task))
865                     g_task_return_boolean (task, TRUE);
866         }
867 
868         g_slist_free_full (manager->priv->pending_end_session_tasks,
869                            (GDestroyNotify) g_object_unref);
870         manager->priv->pending_end_session_tasks = NULL;
871 }
872 
873 static void
do_phase_end_session(GsmManager * manager)874 do_phase_end_session (GsmManager *manager)
875 {
876         ClientEndSessionData data;
877 
878         complete_end_session_tasks (manager);
879 
880         data.manager = manager;
881         data.flags = 0;
882 
883         if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
884                 data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
885         }
886         if (auto_save_is_enabled (manager)) {
887                 data.flags |= GSM_CLIENT_END_SESSION_FLAG_SAVE;
888         }
889 
890         if (manager->priv->phase_timeout_id > 0) {
891                 g_source_remove (manager->priv->phase_timeout_id);
892                 manager->priv->phase_timeout_id = 0;
893         }
894 
895         if (gsm_store_size (manager->priv->clients) > 0) {
896                 manager->priv->phase_timeout_id = g_timeout_add_seconds (GSM_MANAGER_PHASE_TIMEOUT,
897                                                                          (GSourceFunc)on_phase_timeout,
898                                                                          manager);
899 
900                 gsm_store_foreach (manager->priv->clients,
901                                    (GsmStoreFunc)_client_end_session_helper,
902                                    &data);
903         } else {
904                 end_phase (manager);
905         }
906 }
907 
908 static void
do_phase_end_session_part_2(GsmManager * manager)909 do_phase_end_session_part_2 (GsmManager *manager)
910 {
911         ClientEndSessionData data;
912 
913         data.manager = manager;
914         data.flags = 0;
915 
916         if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
917                 data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
918         }
919         if (auto_save_is_enabled (manager)) {
920                 data.flags |= GSM_CLIENT_END_SESSION_FLAG_SAVE;
921         }
922         data.flags |= GSM_CLIENT_END_SESSION_FLAG_LAST;
923 
924         /* keep the timeout that was started at the beginning of the
925          * GSM_MANAGER_PHASE_END_SESSION phase */
926 
927         if (g_slist_length (manager->priv->next_query_clients) > 0) {
928                 g_slist_foreach (manager->priv->next_query_clients,
929                                  (GFunc)_client_end_session,
930                                  &data);
931 
932                 g_slist_free (manager->priv->next_query_clients);
933                 manager->priv->next_query_clients = NULL;
934         } else {
935                 end_phase (manager);
936         }
937 }
938 
939 static gboolean
_client_stop(const char * id,GsmClient * client,gpointer user_data)940 _client_stop (const char *id,
941               GsmClient  *client,
942               gpointer    user_data)
943 {
944         gboolean ret;
945         GError  *error;
946 
947         error = NULL;
948         ret = gsm_client_stop (client, &error);
949         if (! ret) {
950                 g_warning ("Unable to stop client: %s", error->message);
951                 g_error_free (error);
952                 /* FIXME: what should we do if we can't communicate with client? */
953         } else {
954                 g_debug ("GsmManager: stopped client: %s", gsm_client_peek_id (client));
955         }
956 
957         return FALSE;
958 }
959 
960 #ifdef HAVE_SYSTEMD
961 static void
maybe_restart_user_bus(GsmManager * manager)962 maybe_restart_user_bus (GsmManager *manager)
963 {
964         GsmSystem *system;
965         g_autoptr(GVariant) reply = NULL;
966         g_autoptr(GError) error = NULL;
967 
968         if (manager->priv->dbus_disconnected)
969                 return;
970 
971         system = gsm_get_system ();
972 
973         if (!gsm_system_is_last_session_for_user (system))
974                 return;
975 
976         reply = g_dbus_connection_call_sync (manager->priv->connection,
977                                              "org.freedesktop.systemd1",
978                                              "/org/freedesktop/systemd1",
979                                              "org.freedesktop.systemd1.Manager",
980                                              "StopUnit",
981                                              g_variant_new ("(ss)", "dbus.service", "fail"),
982                                              NULL,
983                                              G_DBUS_CALL_FLAGS_NONE,
984                                              -1,
985                                              NULL,
986                                              &error);
987 
988         if (error != NULL) {
989                 g_debug ("GsmManager: reloading user bus failed: %s", error->message);
990         }
991 }
992 #endif
993 
994 static void
do_phase_exit(GsmManager * manager)995 do_phase_exit (GsmManager *manager)
996 {
997         if (gsm_store_size (manager->priv->clients) > 0) {
998                 gsm_store_foreach (manager->priv->clients,
999                                    (GsmStoreFunc)_client_stop,
1000                                    NULL);
1001         }
1002 
1003 #ifdef HAVE_SYSTEMD
1004         if (!manager->priv->systemd_managed)
1005                 maybe_restart_user_bus (manager);
1006 #endif
1007 
1008         end_phase (manager);
1009 }
1010 
1011 static gboolean
_client_query_end_session(const char * id,GsmClient * client,ClientEndSessionData * data)1012 _client_query_end_session (const char           *id,
1013                            GsmClient            *client,
1014                            ClientEndSessionData *data)
1015 {
1016         gboolean ret;
1017         GError  *error;
1018 
1019         error = NULL;
1020         ret = gsm_client_query_end_session (client, data->flags, &error);
1021         if (! ret) {
1022                 g_warning ("Unable to query client: %s", error->message);
1023                 g_error_free (error);
1024                 /* FIXME: what should we do if we can't communicate with client? */
1025         } else {
1026                 g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client));
1027                 data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
1028                                                                       client);
1029         }
1030 
1031         return FALSE;
1032 }
1033 
1034 static gboolean
inhibitor_has_flag(gpointer key,GsmInhibitor * inhibitor,gpointer data)1035 inhibitor_has_flag (gpointer      key,
1036                     GsmInhibitor *inhibitor,
1037                     gpointer      data)
1038 {
1039         guint flag;
1040         guint flags;
1041 
1042         flag = GPOINTER_TO_UINT (data);
1043 
1044         flags = gsm_inhibitor_peek_flags (inhibitor);
1045 
1046         return (flags & flag);
1047 }
1048 
1049 static gboolean
gsm_manager_is_logout_inhibited(GsmManager * manager)1050 gsm_manager_is_logout_inhibited (GsmManager *manager)
1051 {
1052         GsmInhibitor *inhibitor;
1053 
1054         if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
1055                 return FALSE;
1056         }
1057 
1058         if (manager->priv->inhibitors == NULL) {
1059                 return FALSE;
1060         }
1061 
1062         inhibitor = (GsmInhibitor *)gsm_store_find (manager->priv->inhibitors,
1063                                                     (GsmStoreFunc)inhibitor_has_flag,
1064                                                     GUINT_TO_POINTER (GSM_INHIBITOR_FLAG_LOGOUT));
1065         if (inhibitor == NULL) {
1066                 return FALSE;
1067         }
1068         return TRUE;
1069 }
1070 
1071 static gboolean
gsm_manager_is_idle_inhibited(GsmManager * manager)1072 gsm_manager_is_idle_inhibited (GsmManager *manager)
1073 {
1074         GsmInhibitor *inhibitor;
1075 
1076         if (manager->priv->inhibitors == NULL) {
1077                 return FALSE;
1078         }
1079 
1080         inhibitor = (GsmInhibitor *)gsm_store_find (manager->priv->inhibitors,
1081                                                     (GsmStoreFunc)inhibitor_has_flag,
1082                                                     GUINT_TO_POINTER (GSM_INHIBITOR_FLAG_IDLE));
1083         if (inhibitor == NULL) {
1084                 return FALSE;
1085         }
1086         return TRUE;
1087 }
1088 
1089 static gboolean
_client_cancel_end_session(const char * id,GsmClient * client,GsmManager * manager)1090 _client_cancel_end_session (const char *id,
1091                             GsmClient  *client,
1092                             GsmManager *manager)
1093 {
1094         gboolean res;
1095         GError  *error;
1096 
1097         error = NULL;
1098         res = gsm_client_cancel_end_session (client, &error);
1099         if (! res) {
1100                 g_warning ("Unable to cancel end session: %s", error->message);
1101                 g_error_free (error);
1102         }
1103 
1104         return FALSE;
1105 }
1106 
1107 static gboolean
inhibitor_is_jit(gpointer key,GsmInhibitor * inhibitor,GsmManager * manager)1108 inhibitor_is_jit (gpointer      key,
1109                   GsmInhibitor *inhibitor,
1110                   GsmManager   *manager)
1111 {
1112         gboolean    matches;
1113         const char *id;
1114 
1115         id = gsm_inhibitor_peek_client_id (inhibitor);
1116 
1117         matches = (id != NULL && id[0] != '\0');
1118 
1119         return matches;
1120 }
1121 
1122 static void
cancel_end_session(GsmManager * manager)1123 cancel_end_session (GsmManager *manager)
1124 {
1125         /* just ignore if received outside of shutdown */
1126         if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) {
1127                 return;
1128         }
1129 
1130         /* switch back to running phase */
1131         g_debug ("GsmManager: Cancelling the end of session");
1132 
1133         g_cancellable_cancel (manager->priv->end_session_cancellable);
1134 
1135         gsm_manager_set_phase (manager, GSM_MANAGER_PHASE_RUNNING);
1136         manager->priv->logout_mode = GSM_MANAGER_LOGOUT_MODE_NORMAL;
1137 
1138         manager->priv->logout_type = GSM_MANAGER_LOGOUT_NONE;
1139 
1140         /* clear all JIT inhibitors */
1141         gsm_store_foreach_remove (manager->priv->inhibitors,
1142                                   (GsmStoreFunc)inhibitor_is_jit,
1143                                   (gpointer)manager);
1144 
1145         gsm_store_foreach (manager->priv->clients,
1146                            (GsmStoreFunc)_client_cancel_end_session,
1147                            NULL);
1148 
1149         start_phase (manager);
1150 }
1151 
1152 static void
end_session_or_show_shell_dialog(GsmManager * manager)1153 end_session_or_show_shell_dialog (GsmManager *manager)
1154 {
1155         gboolean logout_prompt;
1156         GsmShellEndSessionDialogType type;
1157         gboolean logout_inhibited;
1158 
1159         switch (manager->priv->logout_type) {
1160         case GSM_MANAGER_LOGOUT_LOGOUT:
1161                 type = GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT;
1162                 break;
1163         case GSM_MANAGER_LOGOUT_REBOOT:
1164         case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
1165                 type = GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART;
1166                 break;
1167         case GSM_MANAGER_LOGOUT_SHUTDOWN:
1168         case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
1169                 type = GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN;
1170                 break;
1171         default:
1172                 g_warning ("Unexpected logout type %d when creating end session dialog",
1173                            manager->priv->logout_type);
1174                 type = GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT;
1175                 break;
1176         }
1177 
1178         logout_inhibited = gsm_manager_is_logout_inhibited (manager);
1179         logout_prompt = g_settings_get_boolean (manager->priv->settings,
1180                                                 KEY_LOGOUT_PROMPT);
1181 
1182         switch (manager->priv->logout_mode) {
1183         case GSM_MANAGER_LOGOUT_MODE_NORMAL:
1184                 if (logout_inhibited || logout_prompt) {
1185                         show_shell_end_session_dialog (manager, type);
1186                 } else {
1187                         end_phase (manager);
1188                 }
1189                 break;
1190 
1191         case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION:
1192                 if (logout_inhibited) {
1193                         show_shell_end_session_dialog (manager, type);
1194                 } else {
1195                         end_phase (manager);
1196                 }
1197                 break;
1198 
1199         case GSM_MANAGER_LOGOUT_MODE_FORCE:
1200                 end_phase (manager);
1201                 break;
1202         default:
1203                 g_assert_not_reached ();
1204                 break;
1205         }
1206 
1207 }
1208 
1209 static void
query_end_session_complete(GsmManager * manager)1210 query_end_session_complete (GsmManager *manager)
1211 {
1212 
1213         g_debug ("GsmManager: query end session complete");
1214 
1215         /* Remove the timeout since this can be called from outside the timer
1216          * and we don't want to have it called twice */
1217         if (manager->priv->query_timeout_id > 0) {
1218                 g_source_remove (manager->priv->query_timeout_id);
1219                 manager->priv->query_timeout_id = 0;
1220         }
1221 
1222         end_session_or_show_shell_dialog (manager);
1223 }
1224 
1225 static guint32
generate_cookie(void)1226 generate_cookie (void)
1227 {
1228         guint32 cookie;
1229 
1230         cookie = (guint32)g_random_int_range (1, G_MAXINT32);
1231 
1232         return cookie;
1233 }
1234 
1235 static guint32
_generate_unique_cookie(GsmManager * manager)1236 _generate_unique_cookie (GsmManager *manager)
1237 {
1238         guint32 cookie;
1239 
1240         do {
1241                 cookie = generate_cookie ();
1242         } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL);
1243 
1244         return cookie;
1245 }
1246 
1247 static gboolean
_on_query_end_session_timeout(GsmManager * manager)1248 _on_query_end_session_timeout (GsmManager *manager)
1249 {
1250         GSList *l;
1251 
1252         manager->priv->query_timeout_id = 0;
1253 
1254         g_debug ("GsmManager: query end session timed out");
1255 
1256         for (l = manager->priv->query_clients; l != NULL; l = l->next) {
1257                 guint         cookie;
1258                 GsmInhibitor *inhibitor;
1259                 const char   *bus_name;
1260                 char         *app_id;
1261 
1262                 g_warning ("Client '%s' failed to reply before timeout",
1263                            gsm_client_peek_id (l->data));
1264 
1265                 /* Don't add "not responding" inhibitors if logout is forced
1266                  */
1267                 if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
1268                         continue;
1269                 }
1270 
1271                 /* Add JIT inhibit for unresponsive client */
1272                 if (GSM_IS_DBUS_CLIENT (l->data)) {
1273                         bus_name = gsm_dbus_client_get_bus_name (l->data);
1274                 } else {
1275                         bus_name = NULL;
1276                 }
1277 
1278                 app_id = g_strdup (gsm_client_peek_app_id (l->data));
1279                 if (IS_STRING_EMPTY (app_id)) {
1280                         /* XSMP clients don't give us an app id unless we start them */
1281                         g_free (app_id);
1282                         app_id = gsm_client_get_app_name (l->data);
1283                 }
1284 
1285                 cookie = _generate_unique_cookie (manager);
1286                 inhibitor = gsm_inhibitor_new_for_client (gsm_client_peek_id (l->data),
1287                                                           app_id,
1288                                                           GSM_INHIBITOR_FLAG_LOGOUT,
1289                                                           _("Not responding"),
1290                                                           bus_name,
1291                                                           cookie);
1292                 g_free (app_id);
1293                 gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor));
1294                 g_object_unref (inhibitor);
1295         }
1296 
1297         g_slist_free (manager->priv->query_clients);
1298         manager->priv->query_clients = NULL;
1299 
1300         query_end_session_complete (manager);
1301 
1302         return FALSE;
1303 }
1304 
1305 static void
do_phase_query_end_session(GsmManager * manager)1306 do_phase_query_end_session (GsmManager *manager)
1307 {
1308         ClientEndSessionData data;
1309 
1310         data.manager = manager;
1311         data.flags = 0;
1312 
1313         if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
1314                 data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
1315         }
1316         /* We only query if an app is ready to log out, so we don't use
1317          * GSM_CLIENT_END_SESSION_FLAG_SAVE here.
1318          */
1319 
1320         debug_clients (manager);
1321         g_debug ("GsmManager: sending query-end-session to clients (logout mode: %s)",
1322                  manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_NORMAL? "normal" :
1323                  manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE? "forceful":
1324                  "no confirmation");
1325         gsm_store_foreach (manager->priv->clients,
1326                            (GsmStoreFunc)_client_query_end_session,
1327                            &data);
1328 
1329         /* This phase doesn't time out unless logout is forced. Typically, this
1330          * separate timer is only used to show UI. */
1331         manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)_on_query_end_session_timeout, manager);
1332 }
1333 
1334 static void
update_idle(GsmManager * manager)1335 update_idle (GsmManager *manager)
1336 {
1337         if (gsm_manager_is_idle_inhibited (manager)) {
1338                 gsm_presence_set_idle_enabled (manager->priv->presence, FALSE);
1339         } else {
1340                 gsm_presence_set_idle_enabled (manager->priv->presence, TRUE);
1341         }
1342 }
1343 
1344 static void
start_phase(GsmManager * manager)1345 start_phase (GsmManager *manager)
1346 {
1347 
1348         g_debug ("GsmManager: starting phase %s\n",
1349                  phase_num_to_name (manager->priv->phase));
1350 
1351         /* reset state */
1352         g_slist_free (manager->priv->pending_apps);
1353         manager->priv->pending_apps = NULL;
1354         g_slist_free (manager->priv->query_clients);
1355         manager->priv->query_clients = NULL;
1356         g_slist_free (manager->priv->next_query_clients);
1357         manager->priv->next_query_clients = NULL;
1358 
1359         if (manager->priv->query_timeout_id > 0) {
1360                 g_source_remove (manager->priv->query_timeout_id);
1361                 manager->priv->query_timeout_id = 0;
1362         }
1363         if (manager->priv->phase_timeout_id > 0) {
1364                 g_source_remove (manager->priv->phase_timeout_id);
1365                 manager->priv->phase_timeout_id = 0;
1366         }
1367 
1368         sd_notifyf (0, "STATUS=GNOME Session Manager phase is %s", phase_num_to_name (manager->priv->phase));
1369 
1370         switch (manager->priv->phase) {
1371         case GSM_MANAGER_PHASE_STARTUP:
1372         case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
1373         case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
1374                 do_phase_startup (manager);
1375                 break;
1376         case GSM_MANAGER_PHASE_DISPLAY_SERVER:
1377                 sd_notify (0, "READY=1");
1378                 do_phase_startup (manager);
1379                 break;
1380         case GSM_MANAGER_PHASE_INITIALIZATION:
1381         case GSM_MANAGER_PHASE_WINDOW_MANAGER:
1382         case GSM_MANAGER_PHASE_PANEL:
1383         case GSM_MANAGER_PHASE_DESKTOP:
1384         case GSM_MANAGER_PHASE_APPLICATION:
1385                 do_phase_startup (manager);
1386                 break;
1387         case GSM_MANAGER_PHASE_RUNNING:
1388 #ifdef ENABLE_SYSTEMD_JOURNAL
1389                 sd_journal_send ("MESSAGE_ID=%s", GSM_MANAGER_STARTUP_SUCCEEDED_MSGID,
1390                                  "PRIORITY=%d", 5,
1391                                  "MESSAGE=Entering running state",
1392                                  NULL);
1393 #endif
1394                 gsm_xsmp_server_start_accepting_new_clients (manager->priv->xsmp_server);
1395                 if (manager->priv->pending_end_session_tasks != NULL)
1396                         complete_end_session_tasks (manager);
1397                 g_object_unref (manager->priv->end_session_cancellable);
1398                 manager->priv->end_session_cancellable = g_cancellable_new ();
1399                 gsm_exported_manager_emit_session_running (manager->priv->skeleton);
1400                 update_idle (manager);
1401                 break;
1402         case GSM_MANAGER_PHASE_QUERY_END_SESSION:
1403                 gsm_xsmp_server_stop_accepting_new_clients (manager->priv->xsmp_server);
1404                 do_phase_query_end_session (manager);
1405                 break;
1406         case GSM_MANAGER_PHASE_END_SESSION:
1407                 sd_notify (0, "STOPPING=1");
1408 
1409                 do_phase_end_session (manager);
1410                 break;
1411         case GSM_MANAGER_PHASE_EXIT:
1412                 sd_notify (0, "STOPPING=1");
1413 
1414                 do_phase_exit (manager);
1415                 break;
1416         default:
1417                 g_assert_not_reached ();
1418                 break;
1419         }
1420 }
1421 
1422 static gboolean
_debug_app_for_phase(const char * id,GsmApp * app,gpointer data)1423 _debug_app_for_phase (const char *id,
1424                       GsmApp     *app,
1425                       gpointer    data)
1426 {
1427         guint phase;
1428 
1429         phase = GPOINTER_TO_UINT (data);
1430 
1431         if (gsm_app_peek_phase (app) != phase) {
1432                 return FALSE;
1433         }
1434 
1435         g_debug ("GsmManager:\tID: %s\tapp-id:%s\tis-disabled:%d\tis-conditionally-disabled:%d",
1436                  gsm_app_peek_id (app),
1437                  gsm_app_peek_app_id (app),
1438                  gsm_app_peek_is_disabled (app),
1439                  gsm_app_peek_is_conditionally_disabled (app));
1440 
1441         return FALSE;
1442 }
1443 
1444 static void
debug_app_summary(GsmManager * manager)1445 debug_app_summary (GsmManager *manager)
1446 {
1447         guint phase;
1448 
1449         g_debug ("GsmManager: App startup summary");
1450         for (phase = GSM_MANAGER_PHASE_EARLY_INITIALIZATION; phase < GSM_MANAGER_PHASE_RUNNING; phase++) {
1451                 g_debug ("GsmManager: Phase %s", phase_num_to_name (phase));
1452                 gsm_store_foreach (manager->priv->apps,
1453                                    (GsmStoreFunc)_debug_app_for_phase,
1454                                    GUINT_TO_POINTER (phase));
1455         }
1456 }
1457 
1458 void
gsm_manager_start(GsmManager * manager)1459 gsm_manager_start (GsmManager *manager)
1460 {
1461         g_debug ("GsmManager: GSM starting to manage");
1462 
1463         g_return_if_fail (GSM_IS_MANAGER (manager));
1464 
1465         gsm_xsmp_server_start (manager->priv->xsmp_server);
1466         gsm_manager_set_phase (manager, GSM_MANAGER_PHASE_EARLY_INITIALIZATION);
1467         debug_app_summary (manager);
1468         start_phase (manager);
1469 }
1470 
1471 char *
_gsm_manager_get_default_session(GsmManager * manager)1472 _gsm_manager_get_default_session (GsmManager     *manager)
1473 {
1474         g_autoptr(GSettings) session_settings = NULL;
1475 
1476         if (manager)
1477                 session_settings = g_object_ref (manager->priv->session_settings);
1478         else
1479                 session_settings  = g_settings_new (SESSION_SCHEMA);
1480         return g_settings_get_string (session_settings,
1481                                       KEY_SESSION_NAME);
1482 }
1483 
1484 void
_gsm_manager_set_active_session(GsmManager * manager,const char * session_name,gboolean is_fallback)1485 _gsm_manager_set_active_session (GsmManager     *manager,
1486                                  const char     *session_name,
1487                                  gboolean        is_fallback)
1488 {
1489         g_free (manager->priv->session_name);
1490         manager->priv->session_name = g_strdup (session_name);
1491         manager->priv->is_fallback_session = is_fallback;
1492 
1493         gsm_exported_manager_set_session_name (manager->priv->skeleton, session_name);
1494 }
1495 
1496 void
_gsm_manager_set_renderer(GsmManager * manager,const char * renderer)1497 _gsm_manager_set_renderer (GsmManager *manager,
1498                            const char *renderer)
1499 {
1500         gsm_exported_manager_set_renderer (manager->priv->skeleton, renderer);
1501 }
1502 
1503 static gboolean
_app_has_app_id(const char * id,GsmApp * app,const char * app_id_a)1504 _app_has_app_id (const char   *id,
1505                  GsmApp       *app,
1506                  const char   *app_id_a)
1507 {
1508         const char *app_id_b;
1509 
1510         app_id_b = gsm_app_peek_app_id (app);
1511         return (app_id_b != NULL && strcmp (app_id_a, app_id_b) == 0);
1512 }
1513 
1514 static GsmApp *
find_app_for_app_id(GsmManager * manager,const char * app_id)1515 find_app_for_app_id (GsmManager *manager,
1516                      const char *app_id)
1517 {
1518         GsmApp *app;
1519         app = (GsmApp *)gsm_store_find (manager->priv->apps,
1520                                         (GsmStoreFunc)_app_has_app_id,
1521                                         (char *)app_id);
1522         return app;
1523 }
1524 
1525 static gboolean
inhibitor_has_client_id(gpointer key,GsmInhibitor * inhibitor,const char * client_id_a)1526 inhibitor_has_client_id (gpointer      key,
1527                          GsmInhibitor *inhibitor,
1528                          const char   *client_id_a)
1529 {
1530         gboolean    matches;
1531         const char *client_id_b;
1532 
1533         client_id_b = gsm_inhibitor_peek_client_id (inhibitor);
1534 
1535         matches = FALSE;
1536         if (! IS_STRING_EMPTY (client_id_a) && ! IS_STRING_EMPTY (client_id_b)) {
1537                 matches = (strcmp (client_id_a, client_id_b) == 0);
1538                 if (matches) {
1539                         g_debug ("GsmManager: removing JIT inhibitor for %s for reason '%s'",
1540                                  gsm_inhibitor_peek_client_id (inhibitor),
1541                                  gsm_inhibitor_peek_reason (inhibitor));
1542                 }
1543         }
1544 
1545         return matches;
1546 }
1547 
1548 static gboolean
_app_has_startup_id(const char * id,GsmApp * app,const char * startup_id_a)1549 _app_has_startup_id (const char *id,
1550                      GsmApp     *app,
1551                      const char *startup_id_a)
1552 {
1553         const char *startup_id_b;
1554 
1555         startup_id_b = gsm_app_peek_startup_id (app);
1556 
1557         if (IS_STRING_EMPTY (startup_id_b)) {
1558                 return FALSE;
1559         }
1560 
1561         return (strcmp (startup_id_a, startup_id_b) == 0);
1562 }
1563 
1564 static GsmApp *
find_app_for_startup_id(GsmManager * manager,const char * startup_id)1565 find_app_for_startup_id (GsmManager *manager,
1566                         const char *startup_id)
1567 {
1568         GsmApp *found_app;
1569         GSList *a;
1570 
1571         found_app = NULL;
1572 
1573         /* If we're starting up the session, try to match the new client
1574          * with one pending apps for the current phase. If not, try to match
1575          * with any of the autostarted apps. */
1576         if (manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION) {
1577                 for (a = manager->priv->pending_apps; a != NULL; a = a->next) {
1578                         GsmApp *app = GSM_APP (a->data);
1579 
1580                         if (strcmp (startup_id, gsm_app_peek_startup_id (app)) == 0) {
1581                                 found_app = app;
1582                                 goto out;
1583                         }
1584                 }
1585         } else {
1586                 GsmApp *app;
1587 
1588                 app = (GsmApp *)gsm_store_find (manager->priv->apps,
1589                                                 (GsmStoreFunc)_app_has_startup_id,
1590                                                 (char *)startup_id);
1591                 if (app != NULL) {
1592                         found_app = app;
1593                         goto out;
1594                 }
1595         }
1596  out:
1597         return found_app;
1598 }
1599 
1600 static void
_disconnect_client(GsmManager * manager,GsmClient * client)1601 _disconnect_client (GsmManager *manager,
1602                     GsmClient  *client)
1603 {
1604         gboolean              is_condition_client;
1605         GsmApp               *app;
1606         const char           *app_id;
1607         const char           *startup_id;
1608         gboolean              app_restart;
1609         GsmClientRestartStyle client_restart_hint;
1610 
1611         g_debug ("GsmManager: disconnect client: %s", gsm_client_peek_id (client));
1612 
1613         /* take a ref so it doesn't get finalized */
1614         g_object_ref (client);
1615 
1616         gsm_client_set_status (client, GSM_CLIENT_FINISHED);
1617 
1618         is_condition_client = FALSE;
1619         if (g_slist_find (manager->priv->condition_clients, client)) {
1620                 manager->priv->condition_clients = g_slist_remove (manager->priv->condition_clients, client);
1621 
1622                 is_condition_client = TRUE;
1623         }
1624 
1625         /* remove any inhibitors for this client */
1626         gsm_store_foreach_remove (manager->priv->inhibitors,
1627                                   (GsmStoreFunc)inhibitor_has_client_id,
1628                                   (gpointer)gsm_client_peek_id (client));
1629 
1630         app = NULL;
1631 
1632         /* first try to match on startup ID */
1633         startup_id = gsm_client_peek_startup_id (client);
1634         if (! IS_STRING_EMPTY (startup_id)) {
1635                 app = find_app_for_startup_id (manager, startup_id);
1636 
1637         }
1638 
1639         /* then try to find matching app-id */
1640         if (app == NULL) {
1641                 app_id = gsm_client_peek_app_id (client);
1642                 if (! IS_STRING_EMPTY (app_id)) {
1643                         g_debug ("GsmManager: disconnect for app '%s'", app_id);
1644                         app = find_app_for_app_id (manager, app_id);
1645                 }
1646         }
1647 
1648         switch (manager->priv->phase) {
1649         case GSM_MANAGER_PHASE_QUERY_END_SESSION:
1650                 /* Instead of answering our end session query, the client just exited.
1651                  * Treat that as an "okay, end the session" answer.
1652                  *
1653                  * This call implicitly removes any inhibitors for the client, along
1654                  * with removing the client from the pending query list.
1655                  */
1656                 _handle_client_end_session_response (manager,
1657                                                      client,
1658                                                      TRUE,
1659                                                      FALSE,
1660                                                      FALSE,
1661                                                      "Client exited in "
1662                                                      "query end session phase "
1663                                                      "instead of end session "
1664                                                      "phase");
1665                 break;
1666         case GSM_MANAGER_PHASE_END_SESSION:
1667                 if (! g_slist_find (manager->priv->query_clients, client)) {
1668                         /* the client sent its EndSessionResponse and we already
1669                          * processed it.
1670                          */
1671                         break;
1672                 }
1673 
1674                 /* Client exited without sending EndSessionResponse.
1675                  * The likely reason is that its exit code is written in a way
1676                  * that never returns, and sending EndSessionResponse is handled
1677                  * in library code after the callback. Or maybe the application
1678                  * crashed while handling EndSession. Or it was lazy.
1679                  */
1680                 _handle_client_end_session_response (manager,
1681                                                      client,
1682                                                      TRUE,
1683                                                      FALSE,
1684                                                      FALSE,
1685                                                      "Client exited in "
1686                                                      "end session phase without "
1687                                                      "sending EndSessionResponse");
1688         default:
1689                 /* do nothing */
1690                 break;
1691         }
1692 
1693         if (manager->priv->dbus_disconnected && GSM_IS_DBUS_CLIENT (client)) {
1694                 g_debug ("GsmManager: dbus disconnected, not restarting application");
1695                 goto out;
1696         }
1697 
1698         if (app == NULL) {
1699                 g_debug ("GsmManager: unable to find application for client - not restarting");
1700                 goto out;
1701         }
1702 
1703         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
1704                 g_debug ("GsmManager: in shutdown, not restarting application");
1705                 goto out;
1706         }
1707 
1708         app_restart = gsm_app_peek_autorestart (app);
1709         client_restart_hint = gsm_client_peek_restart_style_hint (client);
1710 
1711         /* allow legacy clients to override the app info */
1712         if (! app_restart
1713             && client_restart_hint != GSM_CLIENT_RESTART_IMMEDIATELY) {
1714                 g_debug ("GsmManager: autorestart not set, not restarting application");
1715                 goto out;
1716         }
1717 
1718         if (is_condition_client) {
1719                 g_debug ("GsmManager: app conditionally disabled, not restarting application");
1720                 goto out;
1721         }
1722 
1723         g_debug ("GsmManager: restarting app");
1724 
1725         _restart_app (manager, app);
1726 
1727  out:
1728         g_object_unref (client);
1729 }
1730 
1731 typedef struct {
1732         const char *service_name;
1733         GsmManager *manager;
1734 } RemoveClientData;
1735 
1736 static gboolean
_disconnect_dbus_client(const char * id,GsmClient * client,RemoveClientData * data)1737 _disconnect_dbus_client (const char       *id,
1738                          GsmClient        *client,
1739                          RemoveClientData *data)
1740 {
1741         const char *name;
1742 
1743         if (! GSM_IS_DBUS_CLIENT (client)) {
1744                 return FALSE;
1745         }
1746 
1747         /* If no service name, then we simply disconnect all clients */
1748         if (!data->service_name) {
1749                 _disconnect_client (data->manager, client);
1750                 return TRUE;
1751         }
1752 
1753         name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client));
1754         if (IS_STRING_EMPTY (name)) {
1755                 return FALSE;
1756         }
1757 
1758         if (strcmp (data->service_name, name) == 0) {
1759                 _disconnect_client (data->manager, client);
1760                 return TRUE;
1761         }
1762 
1763         return FALSE;
1764 }
1765 
1766 /**
1767  * remove_clients_for_connection:
1768  * @manager: a #GsmManager
1769  * @service_name: a service name
1770  *
1771  * Disconnects clients that own @service_name.
1772  *
1773  * If @service_name is NULL, then disconnects all clients for the connection.
1774  */
1775 static void
remove_clients_for_connection(GsmManager * manager,const char * service_name)1776 remove_clients_for_connection (GsmManager *manager,
1777                                const char *service_name)
1778 {
1779         RemoveClientData data;
1780 
1781         data.service_name = service_name;
1782         data.manager = manager;
1783 
1784         /* disconnect dbus clients for name */
1785         gsm_store_foreach_remove (manager->priv->clients,
1786                                   (GsmStoreFunc)_disconnect_dbus_client,
1787                                   &data);
1788 
1789         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION
1790             && gsm_store_size (manager->priv->clients) == 0) {
1791                 g_debug ("GsmManager: last client disconnected - exiting");
1792                 end_phase (manager);
1793         }
1794 }
1795 
1796 static void
gsm_manager_set_failsafe(GsmManager * manager,gboolean enabled)1797 gsm_manager_set_failsafe (GsmManager *manager,
1798                           gboolean    enabled)
1799 {
1800         g_return_if_fail (GSM_IS_MANAGER (manager));
1801 
1802         manager->priv->failsafe = enabled;
1803 }
1804 
1805 gboolean
gsm_manager_get_failsafe(GsmManager * manager)1806 gsm_manager_get_failsafe (GsmManager *manager)
1807 {
1808         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
1809 
1810         return manager->priv->failsafe;
1811 }
1812 
1813 gboolean
gsm_manager_get_systemd_managed(GsmManager * manager)1814 gsm_manager_get_systemd_managed (GsmManager *manager)
1815 {
1816         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
1817 
1818         return manager->priv->systemd_managed;
1819 }
1820 
1821 static void
on_client_disconnected(GsmClient * client,GsmManager * manager)1822 on_client_disconnected (GsmClient  *client,
1823                         GsmManager *manager)
1824 {
1825         g_debug ("GsmManager: disconnect client");
1826         _disconnect_client (manager, client);
1827         gsm_store_remove (manager->priv->clients, gsm_client_peek_id (client));
1828         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION
1829             && gsm_store_size (manager->priv->clients) == 0) {
1830                 g_debug ("GsmManager: last client disconnected - exiting");
1831                 end_phase (manager);
1832         }
1833 }
1834 
1835 static gboolean
on_xsmp_client_register_request(GsmXSMPClient * client,char ** id,GsmManager * manager)1836 on_xsmp_client_register_request (GsmXSMPClient *client,
1837                                  char         **id,
1838                                  GsmManager    *manager)
1839 {
1840         gboolean handled;
1841         char    *new_id;
1842         GsmApp  *app;
1843 
1844         handled = TRUE;
1845         new_id = NULL;
1846 
1847         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
1848                 goto out;
1849         }
1850 
1851         if (IS_STRING_EMPTY (*id)) {
1852                 new_id = gsm_util_generate_startup_id ();
1853         } else {
1854                 GsmClient *client;
1855 
1856                 client = (GsmClient *)gsm_store_find (manager->priv->clients,
1857                                                       (GsmStoreFunc)_client_has_startup_id,
1858                                                       *id);
1859                 /* We can't have two clients with the same id. */
1860                 if (client != NULL) {
1861                         goto out;
1862                 }
1863 
1864                 new_id = g_strdup (*id);
1865         }
1866 
1867         g_debug ("GsmManager: Adding new client %s to session", new_id);
1868 
1869         g_signal_connect (client,
1870                           "disconnected",
1871                           G_CALLBACK (on_client_disconnected),
1872                           manager);
1873 
1874         /* If it's a brand new client id, we just accept the client*/
1875         if (IS_STRING_EMPTY (*id)) {
1876                 goto out;
1877         }
1878 
1879         app = find_app_for_startup_id (manager, new_id);
1880         if (app != NULL) {
1881                 gsm_client_set_app_id (GSM_CLIENT (client), gsm_app_peek_app_id (app));
1882                 goto out;
1883         }
1884 
1885         /* app not found */
1886         g_free (new_id);
1887         new_id = NULL;
1888 
1889  out:
1890         g_free (*id);
1891         *id = new_id;
1892 
1893         return handled;
1894 }
1895 
1896 static void
on_xsmp_client_register_confirmed(GsmXSMPClient * client,const gchar * id,GsmManager * manager)1897 on_xsmp_client_register_confirmed (GsmXSMPClient *client,
1898                                    const gchar   *id,
1899                                    GsmManager    *manager)
1900 {
1901         GsmApp *app;
1902 
1903         app = find_app_for_startup_id (manager, id);
1904 
1905         if (app != NULL) {
1906                 gsm_app_set_registered (app, TRUE);
1907         }
1908 }
1909 
1910 static gboolean
auto_save_is_enabled(GsmManager * manager)1911 auto_save_is_enabled (GsmManager *manager)
1912 {
1913         /* Note that saving/restoring sessions is not really possible on systemd, as
1914          * XSMP clients cannot be reliably mapped to .desktop files. */
1915         if (manager->priv->systemd_managed)
1916                 return FALSE;
1917 
1918         return g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE_ONE_SHOT)
1919             || g_settings_get_boolean (manager->priv->settings, KEY_AUTOSAVE);
1920 }
1921 
1922 static void
maybe_save_session(GsmManager * manager)1923 maybe_save_session (GsmManager *manager)
1924 {
1925         GError *error;
1926 
1927         if (gsm_system_is_login_session (manager->priv->system))
1928                 return;
1929 
1930         /* We only allow session saving when session is running or when
1931          * logging out */
1932         if (manager->priv->phase != GSM_MANAGER_PHASE_RUNNING &&
1933             manager->priv->phase != GSM_MANAGER_PHASE_END_SESSION) {
1934                 return;
1935         }
1936 
1937         if (!auto_save_is_enabled (manager)) {
1938                 gsm_session_save_clear ();
1939                 return;
1940         }
1941 
1942         error = NULL;
1943         gsm_session_save (manager->priv->clients, manager->priv->apps, &error);
1944 
1945         if (error) {
1946                 g_warning ("Error saving session: %s", error->message);
1947                 g_error_free (error);
1948         }
1949 }
1950 
1951 static void
_handle_client_end_session_response(GsmManager * manager,GsmClient * client,gboolean is_ok,gboolean do_last,gboolean cancel,const char * reason)1952 _handle_client_end_session_response (GsmManager *manager,
1953                                      GsmClient  *client,
1954                                      gboolean    is_ok,
1955                                      gboolean    do_last,
1956                                      gboolean    cancel,
1957                                      const char *reason)
1958 {
1959         /* just ignore if received outside of shutdown */
1960         if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) {
1961                 return;
1962         }
1963 
1964         g_debug ("GsmManager: Response from end session request: is-ok=%d do-last=%d cancel=%d reason=%s", is_ok, do_last, cancel, reason ? reason :"");
1965 
1966         if (cancel) {
1967                 cancel_end_session (manager);
1968                 return;
1969         }
1970 
1971         manager->priv->query_clients = g_slist_remove (manager->priv->query_clients, client);
1972 
1973         if (! is_ok && manager->priv->logout_mode != GSM_MANAGER_LOGOUT_MODE_FORCE) {
1974                 guint         cookie;
1975                 GsmInhibitor *inhibitor;
1976                 char         *app_id;
1977                 const char   *bus_name;
1978 
1979                 /* FIXME: do we support updating the reason? */
1980 
1981                 /* Create JIT inhibit */
1982                 if (GSM_IS_DBUS_CLIENT (client)) {
1983                         bus_name = gsm_dbus_client_get_bus_name (GSM_DBUS_CLIENT (client));
1984                 } else {
1985                         bus_name = NULL;
1986                 }
1987 
1988                 app_id = g_strdup (gsm_client_peek_app_id (client));
1989                 if (IS_STRING_EMPTY (app_id)) {
1990                         /* XSMP clients don't give us an app id unless we start them */
1991                         g_free (app_id);
1992                         app_id = gsm_client_get_app_name (client);
1993                 }
1994 
1995                 cookie = _generate_unique_cookie (manager);
1996                 inhibitor = gsm_inhibitor_new_for_client (gsm_client_peek_id (client),
1997                                                           app_id,
1998                                                           GSM_INHIBITOR_FLAG_LOGOUT,
1999                                                           reason != NULL ? reason : _("Not responding"),
2000                                                           bus_name,
2001                                                           cookie);
2002                 g_free (app_id);
2003                 gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor));
2004                 g_object_unref (inhibitor);
2005         } else {
2006                 gsm_store_foreach_remove (manager->priv->inhibitors,
2007                                           (GsmStoreFunc)inhibitor_has_client_id,
2008                                           (gpointer)gsm_client_peek_id (client));
2009         }
2010 
2011         if (manager->priv->phase == GSM_MANAGER_PHASE_QUERY_END_SESSION) {
2012                 if (manager->priv->query_clients == NULL) {
2013                         query_end_session_complete (manager);
2014                 }
2015         } else if (manager->priv->phase == GSM_MANAGER_PHASE_END_SESSION) {
2016                 if (do_last) {
2017                         /* This only makes sense if we're in part 1 of
2018                          * GSM_MANAGER_PHASE_END_SESSION. Doing this in part 2
2019                          * can only happen because of a buggy client that loops
2020                          * wanting to be last again and again. The phase
2021                          * timeout will take care of this issue. */
2022                         manager->priv->next_query_clients = g_slist_prepend (manager->priv->next_query_clients,
2023                                                                              client);
2024                 }
2025 
2026                 /* we can continue to the next step if all clients have replied
2027                  * and if there's no inhibitor */
2028                 if (manager->priv->query_clients != NULL
2029                     || gsm_manager_is_logout_inhibited (manager)) {
2030                         return;
2031                 }
2032 
2033                 if (manager->priv->next_query_clients != NULL) {
2034                         do_phase_end_session_part_2 (manager);
2035                 } else {
2036                         end_phase (manager);
2037                 }
2038         }
2039 }
2040 
2041 static void
on_client_end_session_response(GsmClient * client,gboolean is_ok,gboolean do_last,gboolean cancel,const char * reason,GsmManager * manager)2042 on_client_end_session_response (GsmClient  *client,
2043                                 gboolean    is_ok,
2044                                 gboolean    do_last,
2045                                 gboolean    cancel,
2046                                 const char *reason,
2047                                 GsmManager *manager)
2048 {
2049         _handle_client_end_session_response (manager,
2050                                              client,
2051                                              is_ok,
2052                                              do_last,
2053                                              cancel,
2054                                              reason);
2055 }
2056 
2057 static void
on_xsmp_client_logout_request(GsmXSMPClient * client,gboolean show_dialog,GsmManager * manager)2058 on_xsmp_client_logout_request (GsmXSMPClient *client,
2059                                gboolean       show_dialog,
2060                                GsmManager    *manager)
2061 {
2062         GError *error;
2063         int     logout_mode;
2064 
2065         if (show_dialog) {
2066                 logout_mode = GSM_MANAGER_LOGOUT_MODE_NORMAL;
2067         } else {
2068                 logout_mode = GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION;
2069         }
2070 
2071         error = NULL;
2072         gsm_manager_logout (manager, logout_mode, &error);
2073         if (error != NULL) {
2074                 g_warning ("Unable to logout: %s", error->message);
2075                 g_error_free (error);
2076         }
2077 }
2078 
2079 static void
on_store_client_added(GsmStore * store,const char * id,GsmManager * manager)2080 on_store_client_added (GsmStore   *store,
2081                        const char *id,
2082                        GsmManager *manager)
2083 {
2084         GsmClient *client;
2085 
2086         g_debug ("GsmManager: Client added: %s", id);
2087 
2088         client = (GsmClient *)gsm_store_lookup (store, id);
2089 
2090         /* a bit hacky */
2091         if (GSM_IS_XSMP_CLIENT (client)) {
2092                 g_signal_connect (client,
2093                                   "register-request",
2094                                   G_CALLBACK (on_xsmp_client_register_request),
2095                                   manager);
2096                 g_signal_connect (client,
2097                                   "register-confirmed",
2098                                   G_CALLBACK (on_xsmp_client_register_confirmed),
2099                                   manager);
2100                 g_signal_connect (client,
2101                                   "logout-request",
2102                                   G_CALLBACK (on_xsmp_client_logout_request),
2103                                   manager);
2104         }
2105 
2106         g_signal_connect (client,
2107                           "end-session-response",
2108                           G_CALLBACK (on_client_end_session_response),
2109                           manager);
2110 
2111         gsm_exported_manager_emit_client_added (manager->priv->skeleton, id);
2112         /* FIXME: disconnect signal handler */
2113 }
2114 
2115 static void
on_store_client_removed(GsmStore * store,const char * id,GsmManager * manager)2116 on_store_client_removed (GsmStore   *store,
2117                          const char *id,
2118                          GsmManager *manager)
2119 {
2120         g_debug ("GsmManager: Client removed: %s", id);
2121 
2122         gsm_exported_manager_emit_client_removed (manager->priv->skeleton, id);
2123 }
2124 
2125 static void
gsm_manager_set_client_store(GsmManager * manager,GsmStore * store)2126 gsm_manager_set_client_store (GsmManager *manager,
2127                               GsmStore   *store)
2128 {
2129         g_return_if_fail (GSM_IS_MANAGER (manager));
2130 
2131         if (store != NULL) {
2132                 g_object_ref (store);
2133         }
2134 
2135         if (manager->priv->clients != NULL) {
2136                 g_signal_handlers_disconnect_by_func (manager->priv->clients,
2137                                                       on_store_client_added,
2138                                                       manager);
2139                 g_signal_handlers_disconnect_by_func (manager->priv->clients,
2140                                                       on_store_client_removed,
2141                                                       manager);
2142 
2143                 g_object_unref (manager->priv->clients);
2144         }
2145 
2146 
2147         g_debug ("GsmManager: setting client store %p", store);
2148 
2149         manager->priv->clients = store;
2150 
2151         if (manager->priv->clients != NULL) {
2152                 if (manager->priv->xsmp_server)
2153                         g_object_unref (manager->priv->xsmp_server);
2154 
2155                 manager->priv->xsmp_server = gsm_xsmp_server_new (store);
2156 
2157                 g_signal_connect (manager->priv->clients,
2158                                   "added",
2159                                   G_CALLBACK (on_store_client_added),
2160                                   manager);
2161                 g_signal_connect (manager->priv->clients,
2162                                   "removed",
2163                                   G_CALLBACK (on_store_client_removed),
2164                                   manager);
2165         }
2166 }
2167 
2168 static void
gsm_manager_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)2169 gsm_manager_set_property (GObject       *object,
2170                           guint          prop_id,
2171                           const GValue  *value,
2172                           GParamSpec    *pspec)
2173 {
2174         GsmManager *self;
2175 
2176         self = GSM_MANAGER (object);
2177 
2178         switch (prop_id) {
2179         case PROP_FAILSAFE:
2180                 gsm_manager_set_failsafe (self, g_value_get_boolean (value));
2181                 break;
2182          case PROP_FALLBACK:
2183                 self->priv->is_fallback_session = g_value_get_boolean (value);
2184                 break;
2185          case PROP_CLIENT_STORE:
2186                 gsm_manager_set_client_store (self, g_value_get_object (value));
2187                 break;
2188         case PROP_SYSTEMD_MANAGED:
2189                 self->priv->systemd_managed = g_value_get_boolean (value);
2190                 break;
2191         default:
2192                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2193                 break;
2194         }
2195 }
2196 
2197 static void
gsm_manager_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)2198 gsm_manager_get_property (GObject    *object,
2199                           guint       prop_id,
2200                           GValue     *value,
2201                           GParamSpec *pspec)
2202 {
2203         GsmManager *self;
2204 
2205         self = GSM_MANAGER (object);
2206 
2207         switch (prop_id) {
2208         case PROP_FAILSAFE:
2209                 g_value_set_boolean (value, self->priv->failsafe);
2210                 break;
2211         case PROP_SESSION_NAME:
2212                 g_value_set_string (value, self->priv->session_name);
2213                 break;
2214         case PROP_FALLBACK:
2215                 g_value_set_boolean (value, self->priv->is_fallback_session);
2216                 break;
2217         case PROP_CLIENT_STORE:
2218                 g_value_set_object (value, self->priv->clients);
2219                 break;
2220         default:
2221                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
2222                 break;
2223         }
2224 }
2225 
2226 static gboolean
_find_app_provides(const char * id,GsmApp * app,const char * service)2227 _find_app_provides (const char *id,
2228                     GsmApp     *app,
2229                     const char *service)
2230 {
2231         return gsm_app_provides (app, service);
2232 }
2233 
2234 static GObject *
gsm_manager_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)2235 gsm_manager_constructor (GType                  type,
2236                          guint                  n_construct_properties,
2237                          GObjectConstructParam *construct_properties)
2238 {
2239         GsmManager *manager;
2240 
2241         manager = GSM_MANAGER (G_OBJECT_CLASS (gsm_manager_parent_class)->constructor (type,
2242                                                                                        n_construct_properties,
2243                                                                                        construct_properties));
2244         return G_OBJECT (manager);
2245 }
2246 
2247 static void
update_inhibited_actions(GsmManager * manager,GsmInhibitorFlag new_inhibited_actions)2248 update_inhibited_actions (GsmManager *manager,
2249                           GsmInhibitorFlag new_inhibited_actions)
2250 {
2251         if (manager->priv->inhibited_actions == new_inhibited_actions)
2252                 return;
2253 
2254         gsm_system_set_inhibitors (manager->priv->system, new_inhibited_actions);
2255 
2256         manager->priv->inhibited_actions = new_inhibited_actions;
2257         gsm_exported_manager_set_inhibited_actions (manager->priv->skeleton,
2258                                                     manager->priv->inhibited_actions);
2259 }
2260 
2261 static void
on_inhibitor_vanished(GsmInhibitor * inhibitor,GsmManager * manager)2262 on_inhibitor_vanished (GsmInhibitor *inhibitor,
2263                        GsmManager   *manager)
2264 {
2265         gsm_store_remove (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor));
2266 }
2267 
2268 static void
on_store_inhibitor_added(GsmStore * store,const char * id,GsmManager * manager)2269 on_store_inhibitor_added (GsmStore   *store,
2270                           const char *id,
2271                           GsmManager *manager)
2272 {
2273         GsmInhibitor *i;
2274         GsmInhibitorFlag new_inhibited_actions;
2275 
2276         g_debug ("GsmManager: Inhibitor added: %s", id);
2277 
2278         i = GSM_INHIBITOR (gsm_store_lookup (store, id));
2279 
2280         new_inhibited_actions = manager->priv->inhibited_actions | gsm_inhibitor_peek_flags (i);
2281         update_inhibited_actions (manager, new_inhibited_actions);
2282 
2283         g_signal_connect_object (i, "vanished", G_CALLBACK (on_inhibitor_vanished), manager, 0);
2284 
2285         gsm_exported_manager_emit_inhibitor_added (manager->priv->skeleton, id);
2286 
2287         update_idle (manager);
2288 }
2289 
2290 static gboolean
collect_inhibition_flags(const char * id,GObject * object,gpointer user_data)2291 collect_inhibition_flags (const char *id,
2292                           GObject    *object,
2293                           gpointer    user_data)
2294 {
2295         GsmInhibitorFlag *new_inhibited_actions = user_data;
2296 
2297         *new_inhibited_actions |= gsm_inhibitor_peek_flags (GSM_INHIBITOR (object));
2298 
2299         return FALSE;
2300 }
2301 
2302 static void
on_store_inhibitor_removed(GsmStore * store,const char * id,GsmManager * manager)2303 on_store_inhibitor_removed (GsmStore   *store,
2304                             const char *id,
2305                             GsmManager *manager)
2306 {
2307         GsmInhibitorFlag new_inhibited_actions;
2308 
2309         g_debug ("GsmManager: Inhibitor removed: %s", id);
2310 
2311         new_inhibited_actions = 0;
2312         gsm_store_foreach (manager->priv->inhibitors,
2313                            collect_inhibition_flags,
2314                            &new_inhibited_actions);
2315         update_inhibited_actions (manager, new_inhibited_actions);
2316 
2317         gsm_exported_manager_emit_inhibitor_removed (manager->priv->skeleton, id);
2318 
2319         update_idle (manager);
2320 
2321         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
2322                 end_session_or_show_shell_dialog (manager);
2323         }
2324 }
2325 
2326 static void
gsm_manager_dispose(GObject * object)2327 gsm_manager_dispose (GObject *object)
2328 {
2329         GsmManager *manager = GSM_MANAGER (object);
2330 
2331         g_debug ("GsmManager: disposing manager");
2332 
2333         g_clear_object (&manager->priv->end_session_cancellable);
2334         g_clear_object (&manager->priv->xsmp_server);
2335 
2336         if (manager->priv->clients != NULL) {
2337                 g_signal_handlers_disconnect_by_func (manager->priv->clients,
2338                                                       on_store_client_added,
2339                                                       manager);
2340                 g_signal_handlers_disconnect_by_func (manager->priv->clients,
2341                                                       on_store_client_removed,
2342                                                       manager);
2343                 g_object_unref (manager->priv->clients);
2344                 manager->priv->clients = NULL;
2345         }
2346 
2347         g_clear_object (&manager->priv->apps);
2348         g_slist_free (manager->priv->required_apps);
2349         manager->priv->required_apps = NULL;
2350 
2351         if (manager->priv->inhibitors != NULL) {
2352                 g_signal_handlers_disconnect_by_func (manager->priv->inhibitors,
2353                                                       on_store_inhibitor_added,
2354                                                       manager);
2355                 g_signal_handlers_disconnect_by_func (manager->priv->inhibitors,
2356                                                       on_store_inhibitor_removed,
2357                                                       manager);
2358 
2359                 g_object_unref (manager->priv->inhibitors);
2360                 manager->priv->inhibitors = NULL;
2361         }
2362 
2363         g_clear_object (&manager->priv->presence);
2364         g_clear_object (&manager->priv->settings);
2365         g_clear_object (&manager->priv->session_settings);
2366         g_clear_object (&manager->priv->screensaver_settings);
2367         g_clear_object (&manager->priv->lockdown_settings);
2368         g_clear_object (&manager->priv->system);
2369         g_clear_object (&manager->priv->shell);
2370 
2371         if (manager->priv->skeleton != NULL) {
2372                 g_dbus_interface_skeleton_unexport_from_connection (G_DBUS_INTERFACE_SKELETON (manager->priv->skeleton),
2373                                                                     manager->priv->connection);
2374                 g_clear_object (&manager->priv->skeleton);
2375         }
2376 
2377         g_clear_object (&manager->priv->connection);
2378 
2379         G_OBJECT_CLASS (gsm_manager_parent_class)->dispose (object);
2380 }
2381 
2382 static void
gsm_manager_class_init(GsmManagerClass * klass)2383 gsm_manager_class_init (GsmManagerClass *klass)
2384 {
2385         GObjectClass   *object_class = G_OBJECT_CLASS (klass);
2386 
2387         object_class->get_property = gsm_manager_get_property;
2388         object_class->set_property = gsm_manager_set_property;
2389         object_class->constructor = gsm_manager_constructor;
2390         object_class->dispose = gsm_manager_dispose;
2391 
2392         signals [PHASE_CHANGED] =
2393                 g_signal_new ("phase-changed",
2394                               G_TYPE_FROM_CLASS (object_class),
2395                               G_SIGNAL_RUN_LAST,
2396                               G_STRUCT_OFFSET (GsmManagerClass, phase_changed),
2397                               NULL, NULL, NULL,
2398                               G_TYPE_NONE,
2399                               1, G_TYPE_STRING);
2400 
2401         g_object_class_install_property (object_class,
2402                                          PROP_FAILSAFE,
2403                                          g_param_spec_boolean ("failsafe",
2404                                                                NULL,
2405                                                                NULL,
2406                                                                FALSE,
2407                                                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2408         /**
2409          * GsmManager::session-name
2410          *
2411          * Then name of the currently active session, typically "gnome" or "gnome-fallback".
2412          * This may be the name of the configured default session, or the name of a fallback
2413          * session in case we fell back.
2414          */
2415         g_object_class_install_property (object_class,
2416                                          PROP_SESSION_NAME,
2417                                          g_param_spec_string ("session-name",
2418                                                               NULL,
2419                                                               NULL,
2420                                                               NULL,
2421                                                               G_PARAM_READABLE));
2422 
2423         /**
2424          * GsmManager::fallback
2425          *
2426          * If %TRUE, the current session is running in the "fallback" mode;
2427          * this is distinct from whether or not it was configured as default.
2428          */
2429         g_object_class_install_property (object_class,
2430                                          PROP_FALLBACK,
2431                                          g_param_spec_boolean ("fallback",
2432                                                                NULL,
2433                                                                NULL,
2434                                                                FALSE,
2435                                                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2436 
2437         g_object_class_install_property (object_class,
2438                                          PROP_CLIENT_STORE,
2439                                          g_param_spec_object ("client-store",
2440                                                               NULL,
2441                                                               NULL,
2442                                                               GSM_TYPE_STORE,
2443                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
2444 
2445         g_object_class_install_property (object_class,
2446                                          PROP_SYSTEMD_MANAGED,
2447                                          g_param_spec_boolean ("systemd-managed",
2448                                                                NULL,
2449                                                                NULL,
2450                                                                FALSE,
2451                                                                G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
2452 
2453         g_type_class_add_private (klass, sizeof (GsmManagerPrivate));
2454 }
2455 
2456 static void
on_presence_status_changed(GsmPresence * presence,guint status,GsmManager * manager)2457 on_presence_status_changed (GsmPresence  *presence,
2458                             guint         status,
2459                             GsmManager   *manager)
2460 {
2461         GsmSystem *system;
2462 
2463         system = gsm_get_system ();
2464         gsm_system_set_session_idle (system,
2465                                      (status == GSM_PRESENCE_STATUS_IDLE));
2466         g_object_unref (system);
2467 }
2468 
2469 static void
on_gsm_system_active_changed(GsmSystem * system,GParamSpec * pspec,GsmManager * self)2470 on_gsm_system_active_changed (GsmSystem  *system,
2471                               GParamSpec *pspec,
2472                               GsmManager *self)
2473 {
2474         gboolean is_active;
2475 
2476         is_active = gsm_system_is_active (self->priv->system);
2477 
2478         g_debug ("emitting SessionIsActive");
2479         gsm_exported_manager_set_session_is_active (self->priv->skeleton, is_active);
2480 }
2481 
2482 static gboolean
_log_out_is_locked_down(GsmManager * manager)2483 _log_out_is_locked_down (GsmManager *manager)
2484 {
2485         return g_settings_get_boolean (manager->priv->lockdown_settings,
2486                                        KEY_DISABLE_LOG_OUT);
2487 }
2488 
2489 static void
complete_end_session_task(GsmManager * manager,GAsyncResult * result,GDBusMethodInvocation * invocation)2490 complete_end_session_task (GsmManager            *manager,
2491                            GAsyncResult          *result,
2492                            GDBusMethodInvocation *invocation)
2493 {
2494         GError *error = NULL;
2495 
2496         if (!g_task_propagate_boolean (G_TASK (result), &error))
2497                 g_dbus_method_invocation_take_error (invocation, error);
2498         else
2499                 g_dbus_method_invocation_return_value (invocation, NULL);
2500 }
2501 
2502 static void
request_reboot(GsmManager * manager)2503 request_reboot (GsmManager *manager)
2504 {
2505         g_debug ("GsmManager: requesting reboot");
2506 
2507         /* FIXME: We need to support a more structured shutdown here,
2508          * but that's blocking on an improved ConsoleKit api.
2509          *
2510          * See https://bugzilla.gnome.org/show_bug.cgi?id=585614
2511          */
2512         manager->priv->logout_type = GSM_MANAGER_LOGOUT_REBOOT_INTERACT;
2513         end_phase (manager);
2514 }
2515 
2516 static void
request_shutdown(GsmManager * manager)2517 request_shutdown (GsmManager *manager)
2518 {
2519         g_debug ("GsmManager: requesting shutdown");
2520 
2521         /* See the comment in request_reboot() for some more details about
2522          * what work needs to be done here. */
2523         manager->priv->logout_type = GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT;
2524         end_phase (manager);
2525 }
2526 
2527 static void
request_logout(GsmManager * manager,GsmManagerLogoutMode mode)2528 request_logout (GsmManager           *manager,
2529                 GsmManagerLogoutMode  mode)
2530 {
2531         g_debug ("GsmManager: requesting logout");
2532 
2533         manager->priv->logout_mode = mode;
2534         manager->priv->logout_type = GSM_MANAGER_LOGOUT_LOGOUT;
2535 
2536         end_phase (manager);
2537 }
2538 
2539 static gboolean
gsm_manager_shutdown(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)2540 gsm_manager_shutdown (GsmExportedManager    *skeleton,
2541                       GDBusMethodInvocation *invocation,
2542                       GsmManager            *manager)
2543 {
2544         GTask *task;
2545 
2546         g_debug ("GsmManager: Shutdown called");
2547 
2548         if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
2549                 g_dbus_method_invocation_return_error (invocation,
2550                                                        GSM_MANAGER_ERROR,
2551                                                        GSM_MANAGER_ERROR_NOT_IN_RUNNING,
2552                                                        "Shutdown interface is only available after the Running phase starts");
2553                 return TRUE;
2554         }
2555 
2556         if (_log_out_is_locked_down (manager)) {
2557                 g_dbus_method_invocation_return_error (invocation,
2558                                                        GSM_MANAGER_ERROR,
2559                                                        GSM_MANAGER_ERROR_LOCKED_DOWN,
2560                                                        "Logout has been locked down");
2561                 return TRUE;
2562         }
2563 
2564         task = g_task_new (manager, manager->priv->end_session_cancellable, (GAsyncReadyCallback) complete_end_session_task, invocation);
2565 
2566         manager->priv->pending_end_session_tasks = g_slist_prepend (manager->priv->pending_end_session_tasks,
2567                                                                     task);
2568 
2569         request_shutdown (manager);
2570 
2571         return TRUE;
2572 }
2573 
2574 static gboolean
gsm_manager_reboot(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)2575 gsm_manager_reboot (GsmExportedManager    *skeleton,
2576                     GDBusMethodInvocation *invocation,
2577                     GsmManager            *manager)
2578 {
2579         GTask *task;
2580 
2581         g_debug ("GsmManager: Reboot called");
2582 
2583         if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
2584                 g_dbus_method_invocation_return_error (invocation,
2585                                                        GSM_MANAGER_ERROR,
2586                                                        GSM_MANAGER_ERROR_NOT_IN_RUNNING,
2587                                                        "Reboot interface is only available after the Running phase starts");
2588                 return TRUE;
2589         }
2590 
2591         if (_log_out_is_locked_down (manager)) {
2592                 g_dbus_method_invocation_return_error (invocation,
2593                                                        GSM_MANAGER_ERROR,
2594                                                        GSM_MANAGER_ERROR_LOCKED_DOWN,
2595                                                        "Logout has been locked down");
2596                 return TRUE;
2597         }
2598 
2599         task = g_task_new (manager, manager->priv->end_session_cancellable, (GAsyncReadyCallback) complete_end_session_task, invocation);
2600 
2601         manager->priv->pending_end_session_tasks = g_slist_prepend (manager->priv->pending_end_session_tasks,
2602                                                                     task);
2603 
2604         request_reboot (manager);
2605 
2606         return TRUE;
2607 }
2608 
2609 static gboolean
gsm_manager_can_shutdown(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)2610 gsm_manager_can_shutdown (GsmExportedManager    *skeleton,
2611                           GDBusMethodInvocation *invocation,
2612                           GsmManager            *manager)
2613 {
2614         gboolean shutdown_available;
2615 
2616         g_debug ("GsmManager: CanShutdown called");
2617 
2618         shutdown_available = !_log_out_is_locked_down (manager) &&
2619                 (gsm_system_can_stop (manager->priv->system)
2620                  || gsm_system_can_restart (manager->priv->system)
2621                  || gsm_system_can_suspend (manager->priv->system)
2622                  || gsm_system_can_hibernate (manager->priv->system));
2623 
2624         gsm_exported_manager_complete_can_shutdown (skeleton, invocation, shutdown_available);
2625 
2626         return TRUE;
2627 }
2628 
2629 static gboolean
gsm_manager_can_reboot_to_firmware_setup(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)2630 gsm_manager_can_reboot_to_firmware_setup (GsmExportedManager    *skeleton,
2631                                           GDBusMethodInvocation *invocation,
2632                                           GsmManager            *manager)
2633 {
2634         gboolean reboot_to_firmware_available;
2635 
2636         g_debug ("GsmManager: CanRebootToFirmwareSetup called");
2637 
2638         reboot_to_firmware_available = !_log_out_is_locked_down (manager) &&
2639                 gsm_system_can_restart_to_firmware_setup (manager->priv->system);
2640 
2641         gsm_exported_manager_complete_can_reboot_to_firmware_setup (skeleton, invocation, reboot_to_firmware_available);
2642 
2643         return TRUE;
2644 }
2645 
2646 static gboolean
gsm_manager_set_reboot_to_firmware_setup(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,gboolean enable,GsmManager * manager)2647 gsm_manager_set_reboot_to_firmware_setup (GsmExportedManager    *skeleton,
2648                                           GDBusMethodInvocation *invocation,
2649                                           gboolean               enable,
2650                                           GsmManager            *manager)
2651 {
2652         g_debug ("GsmManager: SetRebootToFirmwareSetup called");
2653 
2654         gsm_system_set_restart_to_firmware_setup (manager->priv->system, enable);
2655 
2656         gsm_exported_manager_complete_set_reboot_to_firmware_setup (skeleton, invocation);
2657 
2658         return TRUE;
2659 }
2660 
2661 static gboolean
gsm_manager_setenv(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,const char * variable,const char * value,GsmManager * manager)2662 gsm_manager_setenv (GsmExportedManager    *skeleton,
2663                     GDBusMethodInvocation *invocation,
2664                     const char            *variable,
2665                     const char            *value,
2666                     GsmManager            *manager)
2667 {
2668         if (manager->priv->phase > GSM_MANAGER_PHASE_INITIALIZATION) {
2669                 g_dbus_method_invocation_return_error (invocation,
2670                                                        GSM_MANAGER_ERROR,
2671                                                        GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
2672                                                        "Setenv interface is only available during the DisplayServer and Initialization phase");
2673         } else {
2674                 gsm_util_setenv (variable, value);
2675                 gsm_exported_manager_complete_setenv (skeleton, invocation);
2676         }
2677 
2678         return TRUE;
2679 }
2680 
2681 static gboolean
gsm_manager_initialized(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)2682 gsm_manager_initialized (GsmExportedManager    *skeleton,
2683                          GDBusMethodInvocation *invocation,
2684                          GsmManager            *manager)
2685 {
2686         /* Signaled by helper when gnome-session-initialized.target is reached. */
2687         if (!manager->priv->systemd_managed) {
2688                 g_dbus_method_invocation_return_error (invocation,
2689                                                        GSM_MANAGER_ERROR,
2690                                                        GSM_MANAGER_ERROR_GENERAL,
2691                                                        "Initialized interface is only available when gnome-session is managed by systemd");
2692         } else if (manager->priv->systemd_initialized) {
2693                 g_dbus_method_invocation_return_error (invocation,
2694                                                        GSM_MANAGER_ERROR,
2695                                                        GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
2696                                                        "Systemd initialization was already signaled");
2697         } else if (manager->priv->phase > GSM_MANAGER_PHASE_INITIALIZATION) {
2698                 g_dbus_method_invocation_return_error (invocation,
2699                                                        GSM_MANAGER_ERROR,
2700                                                        GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
2701                                                        "Initialized interface is only available during startup");
2702         } else {
2703                 manager->priv->systemd_initialized = TRUE;
2704 
2705                 if (manager->priv->manager_initialized) {
2706                         g_assert (manager->priv->phase == GSM_MANAGER_PHASE_INITIALIZATION);
2707                         manager->priv->phase++;
2708                         start_phase (manager);
2709                 }
2710 
2711                 gsm_exported_manager_complete_initialized (skeleton, invocation);
2712         }
2713 
2714         return TRUE;
2715 }
2716 
2717 static gboolean
is_valid_category(int category)2718 is_valid_category (int category)
2719 {
2720         int categories[] = {
2721                 LC_CTYPE,
2722                 LC_NUMERIC,
2723                 LC_TIME,
2724                 LC_COLLATE,
2725                 LC_MONETARY,
2726                 LC_MESSAGES,
2727 #if defined (LC_PAPER)
2728                 LC_PAPER,
2729 #endif
2730 #if defined (LC_NAME)
2731                 LC_NAME,
2732 #endif
2733 #if defined (LC_ADDRESS)
2734                 LC_ADDRESS,
2735 #endif
2736 #if defined (LC_TELEPHONE)
2737                 LC_TELEPHONE,
2738 #endif
2739 #if defined (LC_MEASUREMENT)
2740                 LC_MEASUREMENT,
2741 #endif
2742 #if defined (LC_IDENTIFICATION)
2743                 LC_IDENTIFICATION,
2744 #endif
2745                 LC_ALL
2746         };
2747         guint i;
2748 
2749         for (i = 0; i < G_N_ELEMENTS(categories); i++)
2750                 if (categories[i] == category)
2751                         return TRUE;
2752 
2753         return FALSE;
2754 }
2755 
2756 static gboolean
gsm_manager_get_locale(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,int category,GsmManager * manager)2757 gsm_manager_get_locale (GsmExportedManager    *skeleton,
2758                         GDBusMethodInvocation *invocation,
2759                         int                    category,
2760                         GsmManager            *manager)
2761 {
2762         if (!is_valid_category (category)) {
2763                 g_dbus_method_invocation_return_error (invocation,
2764                                                        GSM_MANAGER_ERROR,
2765                                                        GSM_MANAGER_ERROR_INVALID_OPTION,
2766                                                        "GetLocale doesn't support locale category '%d'", category);
2767         } else {
2768                 const char *value;
2769                 value = setlocale (category, NULL);
2770                 if (value == NULL)
2771                         value = "";
2772 
2773                 gsm_exported_manager_complete_get_locale (skeleton, invocation, value);
2774         }
2775 
2776         return TRUE;
2777 }
2778 
2779 static gboolean
gsm_manager_initialization_error(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,const char * message,gboolean fatal,GsmManager * manager)2780 gsm_manager_initialization_error (GsmExportedManager    *skeleton,
2781                                   GDBusMethodInvocation *invocation,
2782                                   const char            *message,
2783                                   gboolean               fatal,
2784                                   GsmManager            *manager)
2785 {
2786         if (manager->priv->phase != GSM_MANAGER_PHASE_INITIALIZATION) {
2787                 g_dbus_method_invocation_return_error (invocation,
2788                                                        GSM_MANAGER_ERROR,
2789                                                        GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION,
2790                                                        "InitializationError interface is only available during the Initialization phase");
2791                 return TRUE;
2792         }
2793 
2794         gsm_util_init_error (fatal, "%s", message);
2795         gsm_exported_manager_complete_initialization_error (skeleton, invocation);
2796 
2797         return TRUE;
2798 }
2799 
2800 static void
user_logout(GsmManager * manager,GsmManagerLogoutMode mode)2801 user_logout (GsmManager           *manager,
2802              GsmManagerLogoutMode  mode)
2803 {
2804         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
2805                 manager->priv->logout_mode = mode;
2806                 end_session_or_show_shell_dialog (manager);
2807                 return;
2808         }
2809 
2810         request_logout (manager, mode);
2811 }
2812 
2813 gboolean
gsm_manager_logout(GsmManager * manager,guint logout_mode,GError ** error)2814 gsm_manager_logout (GsmManager *manager,
2815                     guint logout_mode,
2816                     GError **error)
2817 {
2818         if (manager->priv->phase < GSM_MANAGER_PHASE_RUNNING) {
2819                 g_set_error (error,
2820                              GSM_MANAGER_ERROR,
2821                              GSM_MANAGER_ERROR_NOT_IN_RUNNING,
2822                              "Logout interface is only available after the Running phase starts");
2823                 return FALSE;
2824         }
2825 
2826         if (_log_out_is_locked_down (manager)) {
2827                 g_set_error (error,
2828                              GSM_MANAGER_ERROR,
2829                              GSM_MANAGER_ERROR_LOCKED_DOWN,
2830                              "Logout has been locked down");
2831                 return FALSE;
2832         }
2833 
2834         switch (logout_mode) {
2835         case GSM_MANAGER_LOGOUT_MODE_NORMAL:
2836         case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION:
2837         case GSM_MANAGER_LOGOUT_MODE_FORCE:
2838                 user_logout (manager, logout_mode);
2839                 break;
2840 
2841         default:
2842                 g_debug ("Unknown logout mode option");
2843 
2844                 g_set_error (error,
2845                              GSM_MANAGER_ERROR,
2846                              GSM_MANAGER_ERROR_INVALID_OPTION,
2847                              "Unknown logout mode flag");
2848                 return FALSE;
2849         }
2850 
2851         return TRUE;
2852 }
2853 
2854 static gboolean
gsm_manager_logout_dbus(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,guint logout_mode,GsmManager * manager)2855 gsm_manager_logout_dbus (GsmExportedManager    *skeleton,
2856                          GDBusMethodInvocation *invocation,
2857                          guint                  logout_mode,
2858                          GsmManager            *manager)
2859 {
2860         GError *error = NULL;
2861 
2862         g_debug ("GsmManager: Logout called");
2863 
2864         if (!gsm_manager_logout (manager, logout_mode, &error)) {
2865                 g_dbus_method_invocation_take_error (invocation, error);
2866         } else {
2867                 gsm_exported_manager_complete_logout (skeleton, invocation);
2868         }
2869 
2870         return TRUE;
2871 }
2872 
2873 static gboolean
gsm_manager_register_client(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,const char * app_id,const char * startup_id,GsmManager * manager)2874 gsm_manager_register_client (GsmExportedManager    *skeleton,
2875                              GDBusMethodInvocation *invocation,
2876                              const char            *app_id,
2877                              const char            *startup_id,
2878                              GsmManager            *manager)
2879 {
2880         char       *new_startup_id;
2881         const char *sender;
2882         GsmClient  *client;
2883         GsmApp     *app;
2884 
2885         app = NULL;
2886         client = NULL;
2887 
2888         g_debug ("GsmManager: RegisterClient %s", startup_id);
2889 
2890         if (manager->priv->phase >= GSM_MANAGER_PHASE_QUERY_END_SESSION) {
2891                 g_debug ("Unable to register client: shutting down");
2892 
2893                 g_dbus_method_invocation_return_error (invocation,
2894                                                        GSM_MANAGER_ERROR,
2895                                                        GSM_MANAGER_ERROR_NOT_IN_RUNNING,
2896                                                        "Unable to register client");
2897                 return TRUE;
2898         }
2899 
2900         if (IS_STRING_EMPTY (startup_id)) {
2901                 new_startup_id = gsm_util_generate_startup_id ();
2902         } else {
2903 
2904                 client = (GsmClient *)gsm_store_find (manager->priv->clients,
2905                                                       (GsmStoreFunc)_client_has_startup_id,
2906                                                       (char *)startup_id);
2907                 /* We can't have two clients with the same startup id. */
2908                 if (client != NULL) {
2909                         g_debug ("Unable to register client: already registered");
2910 
2911                         g_dbus_method_invocation_return_error (invocation,
2912                                                                GSM_MANAGER_ERROR,
2913                                                                GSM_MANAGER_ERROR_ALREADY_REGISTERED,
2914                                                                "Unable to register client");
2915                         return TRUE;
2916                 }
2917 
2918                 new_startup_id = g_strdup (startup_id);
2919         }
2920 
2921         g_debug ("GsmManager: Adding new client %s to session", new_startup_id);
2922 
2923         if (app == NULL && !IS_STRING_EMPTY (startup_id)) {
2924                 app = find_app_for_startup_id (manager, startup_id);
2925         }
2926         if (app == NULL && !IS_STRING_EMPTY (app_id)) {
2927                 /* try to associate this app id with a known app */
2928                 app = find_app_for_app_id (manager, app_id);
2929         }
2930 
2931         sender = g_dbus_method_invocation_get_sender (invocation);
2932         client = gsm_dbus_client_new (new_startup_id, sender);
2933         if (client == NULL) {
2934                 g_debug ("Unable to create client");
2935 
2936                 g_dbus_method_invocation_return_error (invocation,
2937                                                        GSM_MANAGER_ERROR,
2938                                                        GSM_MANAGER_ERROR_GENERAL,
2939                                                        "Unable to register client");
2940                 return TRUE;
2941         }
2942 
2943         gsm_store_add (manager->priv->clients, gsm_client_peek_id (client), G_OBJECT (client));
2944         /* the store will own the ref */
2945         g_object_unref (client);
2946 
2947         g_signal_connect (client,
2948                           "disconnected",
2949                           G_CALLBACK (on_client_disconnected),
2950                           manager);
2951 
2952         if (app != NULL) {
2953                 gsm_client_set_app_id (client, gsm_app_peek_app_id (app));
2954                 gsm_app_set_registered (app, TRUE);
2955         } else {
2956                 /* if an app id is specified store it in the client
2957                    so we can save it later */
2958                 gsm_client_set_app_id (client, app_id);
2959         }
2960 
2961         gsm_client_set_status (client, GSM_CLIENT_REGISTERED);
2962 
2963         g_assert (new_startup_id != NULL);
2964         g_free (new_startup_id);
2965 
2966         gsm_exported_manager_complete_register_client (skeleton, invocation, gsm_client_peek_id (client));
2967 
2968         return TRUE;
2969 }
2970 
2971 static gboolean
gsm_manager_unregister_client(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,const char * client_id,GsmManager * manager)2972 gsm_manager_unregister_client (GsmExportedManager    *skeleton,
2973                                GDBusMethodInvocation *invocation,
2974                                const char            *client_id,
2975                                GsmManager            *manager)
2976 {
2977         GsmClient *client;
2978 
2979         g_debug ("GsmManager: UnregisterClient %s", client_id);
2980 
2981         client = (GsmClient *)gsm_store_lookup (manager->priv->clients, client_id);
2982         if (client == NULL) {
2983                 g_debug ("Unable to unregister client: not registered");
2984 
2985                 g_dbus_method_invocation_return_error (invocation,
2986                                                        GSM_MANAGER_ERROR,
2987                                                        GSM_MANAGER_ERROR_NOT_REGISTERED,
2988                                                        "Unable to unregister client");
2989                 return TRUE;
2990         }
2991 
2992         /* don't disconnect client here, only change the status.
2993            Wait until it leaves the bus before disconnecting it */
2994         gsm_client_set_status (client, GSM_CLIENT_UNREGISTERED);
2995 
2996         gsm_exported_manager_complete_unregister_client (skeleton, invocation);
2997 
2998         return TRUE;
2999 }
3000 
3001 static gboolean
gsm_manager_inhibit(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,const char * app_id,guint toplevel_xid,const char * reason,guint flags,GsmManager * manager)3002 gsm_manager_inhibit (GsmExportedManager    *skeleton,
3003                      GDBusMethodInvocation *invocation,
3004                      const char            *app_id,
3005                      guint                  toplevel_xid,
3006                      const char            *reason,
3007                      guint                  flags,
3008                      GsmManager            *manager)
3009 {
3010         GsmInhibitor *inhibitor;
3011         guint         cookie;
3012 
3013         g_debug ("GsmManager: Inhibit xid=%u app_id=%s reason=%s flags=%u",
3014                  toplevel_xid,
3015                  app_id,
3016                  reason,
3017                  flags);
3018 
3019         if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
3020                 GError *new_error;
3021 
3022                 new_error = g_error_new (GSM_MANAGER_ERROR,
3023                                          GSM_MANAGER_ERROR_GENERAL,
3024                                          "Forced logout cannot be inhibited");
3025                 g_debug ("GsmManager: Unable to inhibit: %s", new_error->message);
3026                 g_dbus_method_invocation_take_error (invocation, new_error);
3027                 return TRUE;
3028         }
3029 
3030         if (IS_STRING_EMPTY (app_id)) {
3031                 GError *new_error;
3032 
3033                 new_error = g_error_new (GSM_MANAGER_ERROR,
3034                                          GSM_MANAGER_ERROR_GENERAL,
3035                                          "Application ID not specified");
3036                 g_debug ("GsmManager: Unable to inhibit: %s", new_error->message);
3037                 g_dbus_method_invocation_take_error (invocation, new_error);
3038                 return TRUE;
3039         }
3040 
3041         if (IS_STRING_EMPTY (reason)) {
3042                 GError *new_error;
3043 
3044                 new_error = g_error_new (GSM_MANAGER_ERROR,
3045                                          GSM_MANAGER_ERROR_GENERAL,
3046                                          "Reason not specified");
3047                 g_debug ("GsmManager: Unable to inhibit: %s", new_error->message);
3048                 g_dbus_method_invocation_take_error (invocation, new_error);
3049                 return FALSE;
3050         }
3051 
3052         if (flags == 0) {
3053                 GError *new_error;
3054 
3055                 new_error = g_error_new (GSM_MANAGER_ERROR,
3056                                          GSM_MANAGER_ERROR_GENERAL,
3057                                          "Invalid inhibit flags");
3058                 g_debug ("GsmManager: Unable to inhibit: %s", new_error->message);
3059                 g_dbus_method_invocation_take_error (invocation, new_error);
3060                 return FALSE;
3061         }
3062 
3063         cookie = _generate_unique_cookie (manager);
3064         inhibitor = gsm_inhibitor_new (app_id,
3065                                        toplevel_xid,
3066                                        flags,
3067                                        reason,
3068                                        g_dbus_method_invocation_get_sender (invocation),
3069                                        cookie);
3070         gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor));
3071         g_object_unref (inhibitor);
3072 
3073         gsm_exported_manager_complete_inhibit (skeleton, invocation, cookie);
3074 
3075         return TRUE;
3076 }
3077 
3078 static gboolean
gsm_manager_uninhibit(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,guint cookie,GsmManager * manager)3079 gsm_manager_uninhibit (GsmExportedManager    *skeleton,
3080                        GDBusMethodInvocation *invocation,
3081                        guint                  cookie,
3082                        GsmManager            *manager)
3083 {
3084         GsmInhibitor *inhibitor;
3085 
3086         g_debug ("GsmManager: Uninhibit %u", cookie);
3087 
3088         inhibitor = (GsmInhibitor *)gsm_store_find (manager->priv->inhibitors,
3089                                                     (GsmStoreFunc)_find_by_cookie,
3090                                                     &cookie);
3091         if (inhibitor == NULL) {
3092                 GError *new_error;
3093 
3094                 new_error = g_error_new (GSM_MANAGER_ERROR,
3095                                          GSM_MANAGER_ERROR_GENERAL,
3096                                          "Unable to uninhibit: Invalid cookie");
3097                 g_debug ("Unable to uninhibit: %s", new_error->message);
3098                 g_dbus_method_invocation_take_error (invocation, new_error);
3099                 return TRUE;
3100         }
3101 
3102         g_debug ("GsmManager: removing inhibitor %s %u reason '%s' %u connection %s",
3103                  gsm_inhibitor_peek_app_id (inhibitor),
3104                  gsm_inhibitor_peek_toplevel_xid (inhibitor),
3105                  gsm_inhibitor_peek_reason (inhibitor),
3106                  gsm_inhibitor_peek_flags (inhibitor),
3107                  gsm_inhibitor_peek_bus_name (inhibitor));
3108 
3109         gsm_store_remove (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor));
3110 
3111         gsm_exported_manager_complete_uninhibit (skeleton, invocation);
3112 
3113         return TRUE;
3114 }
3115 
3116 static gboolean
gsm_manager_is_inhibited(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,guint flags,GsmManager * manager)3117 gsm_manager_is_inhibited (GsmExportedManager    *skeleton,
3118                           GDBusMethodInvocation *invocation,
3119                           guint                  flags,
3120                           GsmManager            *manager)
3121 {
3122         GsmInhibitor *inhibitor;
3123         gboolean is_inhibited;
3124 
3125         if (manager->priv->inhibitors == NULL
3126             || gsm_store_size (manager->priv->inhibitors) == 0) {
3127                 is_inhibited = FALSE;
3128         } else {
3129                 inhibitor = (GsmInhibitor *) gsm_store_find (manager->priv->inhibitors,
3130                                                              (GsmStoreFunc)inhibitor_has_flag,
3131                                                              GUINT_TO_POINTER (flags));
3132                 if (inhibitor == NULL) {
3133                         is_inhibited = FALSE;
3134                 } else {
3135                         is_inhibited = TRUE;
3136                 }
3137         }
3138 
3139         gsm_exported_manager_complete_is_inhibited (skeleton, invocation, is_inhibited);
3140 
3141         return TRUE;
3142 }
3143 
3144 static gboolean
listify_store_ids(char * id,GObject * object,GPtrArray ** array)3145 listify_store_ids (char       *id,
3146                    GObject    *object,
3147                    GPtrArray **array)
3148 {
3149         g_ptr_array_add (*array, g_strdup (id));
3150         return FALSE;
3151 }
3152 
3153 static gboolean
gsm_manager_get_clients(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)3154 gsm_manager_get_clients (GsmExportedManager    *skeleton,
3155                          GDBusMethodInvocation *invocation,
3156                          GsmManager            *manager)
3157 {
3158         GPtrArray *clients;
3159 
3160         clients = g_ptr_array_new_with_free_func (g_free);
3161         gsm_store_foreach (manager->priv->clients,
3162                            (GsmStoreFunc) listify_store_ids,
3163                            &clients);
3164         g_ptr_array_add (clients, NULL);
3165 
3166         gsm_exported_manager_complete_get_clients (skeleton, invocation,
3167                                                    (const gchar * const *) clients->pdata);
3168         g_ptr_array_unref (clients);
3169 
3170         return TRUE;
3171 }
3172 
3173 static gboolean
gsm_manager_get_inhibitors(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)3174 gsm_manager_get_inhibitors (GsmExportedManager    *skeleton,
3175                             GDBusMethodInvocation *invocation,
3176                             GsmManager            *manager)
3177 {
3178         GPtrArray *inhibitors;
3179 
3180         inhibitors = g_ptr_array_new_with_free_func (g_free);
3181         gsm_store_foreach (manager->priv->inhibitors,
3182                            (GsmStoreFunc) listify_store_ids,
3183                            &inhibitors);
3184         g_ptr_array_add (inhibitors, NULL);
3185 
3186         gsm_exported_manager_complete_get_inhibitors (skeleton, invocation,
3187                                                       (const gchar * const *) inhibitors->pdata);
3188         g_ptr_array_unref (inhibitors);
3189 
3190         return TRUE;
3191 }
3192 
3193 static gboolean
_app_has_autostart_condition(const char * id,GsmApp * app,const char * condition)3194 _app_has_autostart_condition (const char *id,
3195                               GsmApp     *app,
3196                               const char *condition)
3197 {
3198         gboolean has;
3199         gboolean disabled;
3200 
3201         has = gsm_app_has_autostart_condition (app, condition);
3202         disabled = gsm_app_peek_is_disabled (app);
3203 
3204         return has && !disabled;
3205 }
3206 
3207 static gboolean
gsm_manager_is_autostart_condition_handled(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,const char * condition,GsmManager * manager)3208 gsm_manager_is_autostart_condition_handled (GsmExportedManager    *skeleton,
3209                                             GDBusMethodInvocation *invocation,
3210                                             const char            *condition,
3211                                             GsmManager            *manager)
3212 {
3213         GsmApp *app;
3214         gboolean handled;
3215 
3216         app = (GsmApp *) gsm_store_find (manager->priv->apps,(
3217                                          GsmStoreFunc) _app_has_autostart_condition,
3218                                          (char *)condition);
3219 
3220         if (app != NULL) {
3221                 handled = TRUE;
3222         } else {
3223                 handled = FALSE;
3224         }
3225 
3226         gsm_exported_manager_complete_is_autostart_condition_handled (skeleton, invocation, handled);
3227 
3228         return TRUE;
3229 }
3230 
3231 static gboolean
gsm_manager_is_session_running(GsmExportedManager * skeleton,GDBusMethodInvocation * invocation,GsmManager * manager)3232 gsm_manager_is_session_running (GsmExportedManager    *skeleton,
3233                                 GDBusMethodInvocation *invocation,
3234                                 GsmManager            *manager)
3235 {
3236         gsm_exported_manager_complete_is_session_running (skeleton, invocation,
3237                                                           manager->priv->phase == GSM_MANAGER_PHASE_RUNNING);
3238         return TRUE;
3239 }
3240 
3241 static void
on_session_connection_closed(GDBusConnection * connection,gboolean remote_peer_vanished,GError * error,gpointer user_data)3242 on_session_connection_closed (GDBusConnection *connection,
3243                               gboolean remote_peer_vanished,
3244                               GError *error,
3245                               gpointer user_data)
3246 {
3247         GsmManager *manager;
3248 
3249         manager = GSM_MANAGER (user_data);
3250 
3251         g_debug ("GsmManager: dbus disconnected; disconnecting dbus clients...");
3252         manager->priv->dbus_disconnected = TRUE;
3253         remove_clients_for_connection (manager, NULL);
3254 }
3255 
3256 static gboolean
register_manager(GsmManager * manager)3257 register_manager (GsmManager *manager)
3258 {
3259         GDBusConnection *connection;
3260         GsmExportedManager *skeleton;
3261         GError *error = NULL;
3262 
3263         connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
3264 
3265         if (error != NULL) {
3266                 g_critical ("error getting session bus: %s", error->message);
3267                 g_error_free (error);
3268 
3269                 exit (1);
3270         }
3271 
3272         skeleton = gsm_exported_manager_skeleton_new ();
3273         g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
3274                                           connection,
3275                                           GSM_MANAGER_DBUS_PATH, &error);
3276 
3277         if (error != NULL) {
3278                 g_critical ("error exporting manager on session bus: %s", error->message);
3279                 g_error_free (error);
3280 
3281                 exit (1);
3282         }
3283 
3284         g_signal_connect (skeleton, "handle-can-reboot-to-firmware-setup",
3285                           G_CALLBACK (gsm_manager_can_reboot_to_firmware_setup), manager);
3286         g_signal_connect (skeleton, "handle-can-shutdown",
3287                           G_CALLBACK (gsm_manager_can_shutdown), manager);
3288         g_signal_connect (skeleton, "handle-get-clients",
3289                           G_CALLBACK (gsm_manager_get_clients), manager);
3290         g_signal_connect (skeleton, "handle-get-inhibitors",
3291                           G_CALLBACK (gsm_manager_get_inhibitors), manager);
3292         g_signal_connect (skeleton, "handle-get-locale",
3293                           G_CALLBACK (gsm_manager_get_locale), manager);
3294         g_signal_connect (skeleton, "handle-inhibit",
3295                           G_CALLBACK (gsm_manager_inhibit), manager);
3296         g_signal_connect (skeleton, "handle-initialization-error",
3297                           G_CALLBACK (gsm_manager_initialization_error), manager);
3298         g_signal_connect (skeleton, "handle-is-autostart-condition-handled",
3299                           G_CALLBACK (gsm_manager_is_autostart_condition_handled), manager);
3300         g_signal_connect (skeleton, "handle-is-inhibited",
3301                           G_CALLBACK (gsm_manager_is_inhibited), manager);
3302         g_signal_connect (skeleton, "handle-is-session-running",
3303                           G_CALLBACK (gsm_manager_is_session_running), manager);
3304         g_signal_connect (skeleton, "handle-logout",
3305                           G_CALLBACK (gsm_manager_logout_dbus), manager);
3306         g_signal_connect (skeleton, "handle-reboot",
3307                           G_CALLBACK (gsm_manager_reboot), manager);
3308         g_signal_connect (skeleton, "handle-register-client",
3309                           G_CALLBACK (gsm_manager_register_client), manager);
3310         g_signal_connect (skeleton, "handle-set-reboot-to-firmware-setup",
3311                           G_CALLBACK (gsm_manager_set_reboot_to_firmware_setup), manager);
3312         g_signal_connect (skeleton, "handle-setenv",
3313                           G_CALLBACK (gsm_manager_setenv), manager);
3314         g_signal_connect (skeleton, "handle-initialized",
3315                           G_CALLBACK (gsm_manager_initialized), manager);
3316         g_signal_connect (skeleton, "handle-shutdown",
3317                           G_CALLBACK (gsm_manager_shutdown), manager);
3318         g_signal_connect (skeleton, "handle-uninhibit",
3319                           G_CALLBACK (gsm_manager_uninhibit), manager);
3320         g_signal_connect (skeleton, "handle-unregister-client",
3321                           G_CALLBACK (gsm_manager_unregister_client), manager);
3322 
3323         manager->priv->dbus_disconnected = FALSE;
3324         g_signal_connect (connection, "closed",
3325                           G_CALLBACK (on_session_connection_closed), manager);
3326 
3327         manager->priv->connection = connection;
3328         manager->priv->skeleton = skeleton;
3329 
3330         g_signal_connect (manager->priv->system, "notify::active",
3331                           G_CALLBACK (on_gsm_system_active_changed), manager);
3332 
3333         /* cold-plug SessionIsActive */
3334         on_gsm_system_active_changed (manager->priv->system, NULL, manager);
3335 
3336         return TRUE;
3337 }
3338 
3339 static gboolean
idle_timeout_get_mapping(GValue * value,GVariant * variant,gpointer user_data)3340 idle_timeout_get_mapping (GValue *value,
3341                           GVariant *variant,
3342                           gpointer user_data)
3343 {
3344         guint32 idle_timeout;
3345 
3346         idle_timeout = g_variant_get_uint32 (variant);
3347         g_value_set_uint (value, idle_timeout * 1000);
3348 
3349         return TRUE;
3350 }
3351 
3352 static void
gsm_manager_init(GsmManager * manager)3353 gsm_manager_init (GsmManager *manager)
3354 {
3355 
3356         manager->priv = GSM_MANAGER_GET_PRIVATE (manager);
3357 
3358         manager->priv->settings = g_settings_new (GSM_MANAGER_SCHEMA);
3359         manager->priv->session_settings = g_settings_new (SESSION_SCHEMA);
3360         manager->priv->screensaver_settings = g_settings_new (SCREENSAVER_SCHEMA);
3361         manager->priv->lockdown_settings = g_settings_new (LOCKDOWN_SCHEMA);
3362 
3363         manager->priv->inhibitors = gsm_store_new ();
3364         g_signal_connect (manager->priv->inhibitors,
3365                           "added",
3366                           G_CALLBACK (on_store_inhibitor_added),
3367                           manager);
3368         g_signal_connect (manager->priv->inhibitors,
3369                           "removed",
3370                           G_CALLBACK (on_store_inhibitor_removed),
3371                           manager);
3372 
3373         manager->priv->apps = gsm_store_new ();
3374 
3375         manager->priv->presence = gsm_presence_new ();
3376         g_signal_connect (manager->priv->presence,
3377                           "status-changed",
3378                           G_CALLBACK (on_presence_status_changed),
3379                           manager);
3380 
3381         g_settings_bind_with_mapping (manager->priv->session_settings,
3382                                       KEY_IDLE_DELAY,
3383                                       manager->priv->presence,
3384                                       "idle-timeout",
3385                                       G_SETTINGS_BIND_GET,
3386                                       idle_timeout_get_mapping,
3387                                       NULL,
3388                                       NULL, NULL);
3389 
3390         manager->priv->system = gsm_get_system ();
3391         manager->priv->shell = gsm_get_shell ();
3392         manager->priv->end_session_cancellable = g_cancellable_new ();
3393 }
3394 
3395 GsmManager *
gsm_manager_get(void)3396 gsm_manager_get (void)
3397 {
3398         return manager_object;
3399 }
3400 
3401 GsmManager *
gsm_manager_new(GsmStore * client_store,gboolean failsafe,gboolean systemd_managed)3402 gsm_manager_new (GsmStore *client_store,
3403                  gboolean  failsafe,
3404                  gboolean  systemd_managed)
3405 {
3406         if (manager_object != NULL) {
3407                 g_object_ref (manager_object);
3408         } else {
3409                 gboolean res;
3410 
3411                 manager_object = g_object_new (GSM_TYPE_MANAGER,
3412                                                "client-store", client_store,
3413                                                "failsafe", failsafe,
3414                                                "systemd-managed", systemd_managed,
3415                                                NULL);
3416 
3417                 g_object_add_weak_pointer (manager_object,
3418                                            (gpointer *) &manager_object);
3419                 res = register_manager (manager_object);
3420                 if (! res) {
3421                         g_object_unref (manager_object);
3422                         return NULL;
3423                 }
3424         }
3425 
3426         return GSM_MANAGER (manager_object);
3427 }
3428 
3429 static void
disconnect_shell_dialog_signals(GsmManager * manager)3430 disconnect_shell_dialog_signals (GsmManager *manager)
3431 {
3432         if (manager->priv->shell_end_session_dialog_canceled_id != 0) {
3433                 g_signal_handler_disconnect (manager->priv->shell,
3434                                              manager->priv->shell_end_session_dialog_canceled_id);
3435                 manager->priv->shell_end_session_dialog_canceled_id = 0;
3436         }
3437 
3438         if (manager->priv->shell_end_session_dialog_confirmed_logout_id != 0) {
3439                 g_signal_handler_disconnect (manager->priv->shell,
3440                                              manager->priv->shell_end_session_dialog_confirmed_logout_id);
3441                 manager->priv->shell_end_session_dialog_confirmed_logout_id = 0;
3442         }
3443 
3444         if (manager->priv->shell_end_session_dialog_confirmed_shutdown_id != 0) {
3445                 g_signal_handler_disconnect (manager->priv->shell,
3446                                              manager->priv->shell_end_session_dialog_confirmed_shutdown_id);
3447                 manager->priv->shell_end_session_dialog_confirmed_shutdown_id = 0;
3448         }
3449 
3450         if (manager->priv->shell_end_session_dialog_confirmed_reboot_id != 0) {
3451                 g_signal_handler_disconnect (manager->priv->shell,
3452                                              manager->priv->shell_end_session_dialog_confirmed_reboot_id);
3453                 manager->priv->shell_end_session_dialog_confirmed_reboot_id = 0;
3454         }
3455 
3456         if (manager->priv->shell_end_session_dialog_open_failed_id != 0) {
3457                 g_signal_handler_disconnect (manager->priv->shell,
3458                                              manager->priv->shell_end_session_dialog_open_failed_id);
3459                 manager->priv->shell_end_session_dialog_open_failed_id = 0;
3460         }
3461 }
3462 
3463 static void
on_shell_end_session_dialog_canceled(GsmShell * shell,GsmManager * manager)3464 on_shell_end_session_dialog_canceled (GsmShell   *shell,
3465                                       GsmManager *manager)
3466 {
3467         cancel_end_session (manager);
3468         disconnect_shell_dialog_signals (manager);
3469 }
3470 
3471 static void
_handle_end_session_dialog_response(GsmManager * manager,GsmManagerLogoutType logout_type)3472 _handle_end_session_dialog_response (GsmManager           *manager,
3473                                      GsmManagerLogoutType  logout_type)
3474 {
3475         /* Note we're checking for END_SESSION here and
3476          * QUERY_END_SESSION in the fallback cases elsewhere.
3477          *
3478          * That's because they run at different times in the logout
3479          * process. The shell combines the inhibit and
3480          * confirmation dialogs, so it gets displayed after we've collected
3481          * inhibitors. The fallback code has two distinct dialogs, once of
3482          * which we can (and do show) before collecting the inhibitors.
3483          */
3484         if (manager->priv->phase >= GSM_MANAGER_PHASE_END_SESSION) {
3485                 /* Already shutting down, nothing more to do */
3486                 return;
3487         }
3488 
3489         manager->priv->logout_mode = GSM_MANAGER_LOGOUT_MODE_FORCE;
3490         manager->priv->logout_type = logout_type;
3491         end_phase (manager);
3492 }
3493 
3494 static void
on_shell_end_session_dialog_confirmed_logout(GsmShell * shell,GsmManager * manager)3495 on_shell_end_session_dialog_confirmed_logout (GsmShell   *shell,
3496                                               GsmManager *manager)
3497 {
3498         _handle_end_session_dialog_response (manager, GSM_MANAGER_LOGOUT_LOGOUT);
3499         disconnect_shell_dialog_signals (manager);
3500 }
3501 
3502 static void
on_shell_end_session_dialog_confirmed_shutdown(GsmShell * shell,GsmManager * manager)3503 on_shell_end_session_dialog_confirmed_shutdown (GsmShell   *shell,
3504                                                 GsmManager *manager)
3505 {
3506         _handle_end_session_dialog_response (manager, GSM_MANAGER_LOGOUT_SHUTDOWN);
3507         disconnect_shell_dialog_signals (manager);
3508 }
3509 
3510 static void
on_shell_end_session_dialog_confirmed_reboot(GsmShell * shell,GsmManager * manager)3511 on_shell_end_session_dialog_confirmed_reboot (GsmShell   *shell,
3512                                               GsmManager *manager)
3513 {
3514         _handle_end_session_dialog_response (manager, GSM_MANAGER_LOGOUT_REBOOT);
3515         disconnect_shell_dialog_signals (manager);
3516 }
3517 
3518 static void
connect_shell_dialog_signals(GsmManager * manager)3519 connect_shell_dialog_signals (GsmManager *manager)
3520 {
3521         if (manager->priv->shell_end_session_dialog_canceled_id != 0)
3522                 return;
3523 
3524         manager->priv->shell_end_session_dialog_canceled_id =
3525                 g_signal_connect (manager->priv->shell,
3526                                   "end-session-dialog-canceled",
3527                                   G_CALLBACK (on_shell_end_session_dialog_canceled),
3528                                   manager);
3529 
3530         manager->priv->shell_end_session_dialog_open_failed_id =
3531                 g_signal_connect (manager->priv->shell,
3532                                   "end-session-dialog-open-failed",
3533                                   G_CALLBACK (on_shell_end_session_dialog_canceled),
3534                                   manager);
3535 
3536         manager->priv->shell_end_session_dialog_confirmed_logout_id =
3537                 g_signal_connect (manager->priv->shell,
3538                                   "end-session-dialog-confirmed-logout",
3539                                   G_CALLBACK (on_shell_end_session_dialog_confirmed_logout),
3540                                   manager);
3541 
3542         manager->priv->shell_end_session_dialog_confirmed_shutdown_id =
3543                 g_signal_connect (manager->priv->shell,
3544                                   "end-session-dialog-confirmed-shutdown",
3545                                   G_CALLBACK (on_shell_end_session_dialog_confirmed_shutdown),
3546                                   manager);
3547 
3548         manager->priv->shell_end_session_dialog_confirmed_reboot_id =
3549                 g_signal_connect (manager->priv->shell,
3550                                   "end-session-dialog-confirmed-reboot",
3551                                   G_CALLBACK (on_shell_end_session_dialog_confirmed_reboot),
3552                                   manager);
3553 }
3554 
3555 static void
show_shell_end_session_dialog(GsmManager * manager,GsmShellEndSessionDialogType type)3556 show_shell_end_session_dialog (GsmManager                   *manager,
3557                                GsmShellEndSessionDialogType  type)
3558 {
3559         if (!gsm_shell_is_running (manager->priv->shell))
3560                 return;
3561 
3562         gsm_shell_open_end_session_dialog (manager->priv->shell,
3563                                            type,
3564                                            manager->priv->inhibitors);
3565         connect_shell_dialog_signals (manager);
3566 }
3567 
3568 /*
3569   dbus-send --session --type=method_call --print-reply
3570       --dest=org.gnome.SessionManager
3571       /org/gnome/SessionManager
3572       org.freedesktop.DBus.Introspectable.Introspect
3573 */
3574 
3575 gboolean
gsm_manager_set_phase(GsmManager * manager,GsmManagerPhase phase)3576 gsm_manager_set_phase (GsmManager      *manager,
3577                        GsmManagerPhase  phase)
3578 {
3579         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
3580         manager->priv->phase = phase;
3581         return (TRUE);
3582 }
3583 
3584 static void
append_app(GsmManager * manager,GsmApp * app,const char * provides,gboolean is_required)3585 append_app (GsmManager *manager,
3586             GsmApp     *app,
3587             const char *provides,
3588             gboolean    is_required)
3589 {
3590         const char *id;
3591         const char *app_id;
3592         GsmApp     *dup;
3593 
3594         id = gsm_app_peek_id (app);
3595         if (IS_STRING_EMPTY (id)) {
3596                 g_debug ("GsmManager: not adding app: no id");
3597                 return;
3598         }
3599 
3600         dup = (GsmApp *)gsm_store_lookup (manager->priv->apps, id);
3601         if (dup != NULL) {
3602                 g_debug ("GsmManager: not adding app: already added");
3603                 return;
3604         }
3605 
3606         app_id = gsm_app_peek_app_id (app);
3607         if (IS_STRING_EMPTY (app_id)) {
3608                 g_debug ("GsmManager: not adding app: no app-id");
3609                 return;
3610         }
3611 
3612         dup = find_app_for_app_id (manager, app_id);
3613         if (dup != NULL) {
3614                 g_debug ("GsmManager: not adding app: app-id '%s' already exists", app_id);
3615 
3616                 if (provides && GSM_IS_AUTOSTART_APP (dup))
3617                         gsm_autostart_app_add_provides (GSM_AUTOSTART_APP (dup), provides);
3618 
3619                 if (is_required &&
3620                     !g_slist_find (manager->priv->required_apps, dup)) {
3621                         g_debug ("GsmManager: making app '%s' required", gsm_app_peek_app_id (dup));
3622                         manager->priv->required_apps = g_slist_prepend (manager->priv->required_apps, dup);
3623                 }
3624 
3625                 return;
3626         }
3627 
3628         gsm_store_add (manager->priv->apps, id, G_OBJECT (app));
3629         if (is_required) {
3630                 g_debug ("GsmManager: adding required app %s", gsm_app_peek_app_id (app));
3631                 manager->priv->required_apps = g_slist_prepend (manager->priv->required_apps, app);
3632         }
3633 }
3634 
3635 static gboolean
add_autostart_app_internal(GsmManager * manager,const char * path,const char * provides,gboolean is_required)3636 add_autostart_app_internal (GsmManager *manager,
3637                             const char *path,
3638                             const char *provides,
3639                             gboolean    is_required)
3640 {
3641         GsmApp  *app;
3642         char   **internal_provides;
3643         GError *error = NULL;
3644 
3645         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
3646         g_return_val_if_fail (path != NULL, FALSE);
3647 
3648         /* Note: if we cannot add the app because its service is already
3649          * provided, because its app-id is taken, or because of any other
3650          * reason meaning there is already an app playing its role, then we
3651          * should make sure that relevant properties (like
3652          * provides/is_required) are set in the pre-existing app if needed. */
3653 
3654         /* first check to see if service is already provided */
3655         if (provides != NULL) {
3656                 GsmApp *dup;
3657 
3658                 dup = (GsmApp *)gsm_store_find (manager->priv->apps,
3659                                                 (GsmStoreFunc)_find_app_provides,
3660                                                 (char *)provides);
3661                 if (dup != NULL) {
3662                         g_debug ("GsmManager: service '%s' is already provided", provides);
3663 
3664                         if (is_required &&
3665                             !g_slist_find (manager->priv->required_apps, dup)) {
3666                                 g_debug ("GsmManager: making app '%s' required", gsm_app_peek_app_id (dup));
3667                                 manager->priv->required_apps = g_slist_prepend (manager->priv->required_apps, dup);
3668                         }
3669 
3670                         return FALSE;
3671                 }
3672         }
3673 
3674         app = gsm_autostart_app_new (path, manager->priv->systemd_managed, &error);
3675         if (app == NULL) {
3676                 g_warning ("%s", error->message);
3677                 g_clear_error (&error);
3678                 return FALSE;
3679         }
3680 
3681         internal_provides = gsm_app_get_provides (app);
3682         if (internal_provides) {
3683                 int i;
3684                 gboolean provided = FALSE;
3685 
3686                 for (i = 0; internal_provides[i] != NULL; i++) {
3687                         GsmApp *dup;
3688 
3689                         dup = (GsmApp *)gsm_store_find (manager->priv->apps,
3690                                                         (GsmStoreFunc)_find_app_provides,
3691                                                         (char *)internal_provides[i]);
3692                         if (dup != NULL) {
3693                                 g_debug ("GsmManager: service '%s' is already provided", internal_provides[i]);
3694 
3695                                 if (is_required &&
3696                                     !g_slist_find (manager->priv->required_apps, dup)) {
3697                                         g_debug ("GsmManager: making app '%s' required", gsm_app_peek_app_id (dup));
3698                                         manager->priv->required_apps = g_slist_prepend (manager->priv->required_apps, dup);
3699                                 }
3700 
3701                                 provided = TRUE;
3702                                 break;
3703                         }
3704                 }
3705 
3706                 g_strfreev (internal_provides);
3707 
3708                 if (provided) {
3709                         g_object_unref (app);
3710                         return FALSE;
3711                 }
3712         }
3713 
3714         if (provides)
3715                 gsm_autostart_app_add_provides (GSM_AUTOSTART_APP (app), provides);
3716 
3717         g_debug ("GsmManager: read %s", path);
3718         append_app (manager, app, provides, is_required);
3719         g_object_unref (app);
3720 
3721         return TRUE;
3722 }
3723 
3724 gboolean
gsm_manager_add_autostart_app(GsmManager * manager,const char * path,const char * provides)3725 gsm_manager_add_autostart_app (GsmManager *manager,
3726                                const char *path,
3727                                const char *provides)
3728 {
3729         return add_autostart_app_internal (manager,
3730                                            path,
3731                                            provides,
3732                                            FALSE);
3733 }
3734 
3735 /**
3736  * gsm_manager_add_required_app:
3737  * @manager: a #GsmManager
3738  * @path: Path to desktop file
3739  * @provides: What the component provides, as a space separated list
3740  *
3741  * Similar to gsm_manager_add_autostart_app(), except marks the
3742  * component as being required; we then try harder to ensure
3743  * it's running and inform the user if we can't.
3744  *
3745  */
3746 gboolean
gsm_manager_add_required_app(GsmManager * manager,const char * path,const char * provides)3747 gsm_manager_add_required_app (GsmManager *manager,
3748                               const char *path,
3749                               const char *provides)
3750 {
3751         return add_autostart_app_internal (manager,
3752                                            path,
3753                                            provides,
3754                                            TRUE);
3755 }
3756 
3757 
3758 gboolean
gsm_manager_add_autostart_apps_from_dir(GsmManager * manager,const char * path)3759 gsm_manager_add_autostart_apps_from_dir (GsmManager *manager,
3760                                          const char *path)
3761 {
3762         GDir       *dir;
3763         const char *name;
3764 
3765         g_return_val_if_fail (GSM_IS_MANAGER (manager), FALSE);
3766         g_return_val_if_fail (path != NULL, FALSE);
3767 
3768         g_debug ("GsmManager: *** Adding autostart apps for %s", path);
3769 
3770         dir = g_dir_open (path, 0, NULL);
3771         if (dir == NULL) {
3772                 return FALSE;
3773         }
3774 
3775         while ((name = g_dir_read_name (dir))) {
3776                 char *desktop_file;
3777 
3778                 if (!g_str_has_suffix (name, ".desktop")) {
3779                         continue;
3780                 }
3781 
3782                 desktop_file = g_build_filename (path, name, NULL);
3783                 gsm_manager_add_autostart_app (manager, desktop_file, NULL);
3784                 g_free (desktop_file);
3785         }
3786 
3787         g_dir_close (dir);
3788 
3789         return TRUE;
3790 }
3791 
3792 static void
on_shutdown_prepared(GsmSystem * system,gboolean success,GsmManager * manager)3793 on_shutdown_prepared (GsmSystem  *system,
3794                       gboolean    success,
3795                       GsmManager *manager)
3796 {
3797         g_debug ("GsmManager: on_shutdown_prepared, success: %d", success);
3798         g_signal_handlers_disconnect_by_func (system, on_shutdown_prepared, manager);
3799 
3800         if (success) {
3801                 /* move to end-session phase */
3802                 g_assert (manager->priv->phase == GSM_MANAGER_PHASE_QUERY_END_SESSION);
3803                 manager->priv->phase++;
3804                 start_phase (manager);
3805         } else {
3806                 disconnect_shell_dialog_signals (manager);
3807                 gsm_shell_close_end_session_dialog (manager->priv->shell);
3808                 /* back to running phase */
3809                 cancel_end_session (manager);
3810         }
3811 }
3812 
3813 static gboolean
do_query_end_session_exit(GsmManager * manager)3814 do_query_end_session_exit (GsmManager *manager)
3815 {
3816         gboolean reboot = FALSE;
3817         gboolean shutdown = FALSE;
3818 
3819         switch (manager->priv->logout_type) {
3820         case GSM_MANAGER_LOGOUT_LOGOUT:
3821                 break;
3822         case GSM_MANAGER_LOGOUT_REBOOT:
3823         case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
3824                 reboot = TRUE;
3825                 break;
3826         case GSM_MANAGER_LOGOUT_SHUTDOWN:
3827         case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
3828                 shutdown = TRUE;
3829                 break;
3830         default:
3831                 g_warning ("Unexpected logout type %d in do_query_end_session_exit()",
3832                            manager->priv->logout_type);
3833                 break;
3834         }
3835 
3836         if (reboot || shutdown) {
3837                 g_signal_connect (manager->priv->system, "shutdown-prepared",
3838                                   G_CALLBACK (on_shutdown_prepared), manager);
3839                 gsm_system_prepare_shutdown (manager->priv->system, reboot);
3840                 return FALSE; /* don't leave query end session yet */
3841         }
3842 
3843         return TRUE; /* go to end session phase */
3844 }
3845