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