gsm-manager.c 128 KB
Newer Older
1 2 3
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 *
 * Copyright (C) 2007 Novell, Inc.
4
 * Copyright (C) 2008 Red Hat, Inc.
5 6 7 8 9 10 11 12 13 14 15 16 17
 * Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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 23 24 25 26 27 28 29
 *
 */

#include "config.h"

#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
30
#include <locale.h>
31 32 33 34 35 36 37
#include <sys/stat.h>
#include <sys/types.h>

#include <glib.h>
#include <glib/gi18n.h>
#include <glib/gstdio.h>
#include <glib-object.h>
38
#include <gio/gio.h>
39 40

#include "gsm-manager.h"
41
#include "org.gnome.SessionManager.h"
42

43 44 45 46
#ifdef HAVE_SYSTEMD
#include <systemd/sd-journal.h>
#endif

47
#include "gsm-store.h"
48
#include "gsm-inhibitor.h"
William Jon McCann's avatar
William Jon McCann committed
49
#include "gsm-presence.h"
50
#include "gsm-shell.h"
51

52
#include "gsm-xsmp-server.h"
53
#include "gsm-xsmp-client.h"
54
#include "gsm-dbus-client.h"
55

56
#include "gsm-autostart-app.h"
57

58
#include "gsm-util.h"
59
#include "gsm-icon-names.h"
60
#include "gsm-system.h"
61
#include "gsm-session-save.h"
62
#include "gsm-shell-extensions.h"
63
#include "gsm-fail-whale.h"
64 65 66

#define GSM_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSM_TYPE_MANAGER, GsmManagerPrivate))

67 68 69 70
/* UUIDs for log messages */
#define GSM_MANAGER_STARTUP_SUCCEEDED_MSGID     "0ce153587afa4095832d233c17a88001"
#define GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID "10dd2dc188b54a5e98970f56499d1f73"

71 72
#define GSM_MANAGER_DBUS_PATH "/org/gnome/SessionManager"
#define GSM_MANAGER_DBUS_NAME "org.gnome.SessionManager"
73
#define GSM_MANAGER_DBUS_IFACE "org.gnome.SessionManager"
74

75 76 77 78 79 80 81
/* Probably about the longest amount of time someone could reasonably
 * want to wait, at least for something happening more than once.
 * We can get deployed on very slow media though like CDROM devices,
 * often with complex stacking/compressing filesystems on top, which
 * is not a recipie for speed.   Particularly now that we throw up
 * a fail whale if required components don't show up quickly enough,
 * let's make this fairly long.
82
 */
83
#define GSM_MANAGER_PHASE_TIMEOUT 90 /* seconds */
84

85 86 87
#define GDM_FLEXISERVER_COMMAND "gdmflexiserver"
#define GDM_FLEXISERVER_ARGS    "--startnew Standard"

88 89
#define SESSION_SCHEMA            "org.gnome.desktop.session"
#define KEY_IDLE_DELAY            "idle-delay"
90
#define KEY_SESSION_NAME          "session-name"
91

92 93
#define GSM_MANAGER_SCHEMA        "org.gnome.SessionManager"
#define KEY_AUTOSAVE              "auto-save-session"
94
#define KEY_AUTOSAVE_ONE_SHOT     "auto-save-session-one-shot"
95
#define KEY_LOGOUT_PROMPT         "logout-prompt"
Vincent Untz's avatar
Vincent Untz committed
96
#define KEY_SHOW_FALLBACK_WARNING "show-fallback-warning"
97

98
#define SCREENSAVER_SCHEMA        "org.gnome.desktop.screensaver"
99
#define KEY_SLEEP_LOCK            "lock-enabled"
100

101 102
#define LOCKDOWN_SCHEMA           "org.gnome.desktop.lockdown"
#define KEY_DISABLE_LOG_OUT       "disable-log-out"
103
#define KEY_DISABLE_USER_SWITCHING "disable-user-switching"
104

105
static void app_registered (GsmApp     *app, GParamSpec *spec, GsmManager *manager);
106

107 108 109 110 111 112 113 114 115 116
typedef enum
{
        GSM_MANAGER_LOGOUT_NONE,
        GSM_MANAGER_LOGOUT_LOGOUT,
        GSM_MANAGER_LOGOUT_REBOOT,
        GSM_MANAGER_LOGOUT_REBOOT_INTERACT,
        GSM_MANAGER_LOGOUT_SHUTDOWN,
        GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT,
} GsmManagerLogoutType;

117 118 119
struct GsmManagerPrivate
{
        gboolean                failsafe;
120 121
        GsmStore               *clients;
        GsmStore               *inhibitors;
122
        GsmInhibitorFlag        inhibited_actions;
123
        GsmStore               *apps;
William Jon McCann's avatar
William Jon McCann committed
124
        GsmPresence            *presence;
125
        GsmXsmpServer          *xsmp_server;
126

127
        char                   *session_name;
128 129
        gboolean                is_fallback_session : 1;

130 131
        /* Current status */
        GsmManagerPhase         phase;
132
        guint                   phase_timeout_id;
133
        GSList                 *required_apps;
134
        GSList                 *pending_apps;
135
        GsmManagerLogoutMode    logout_mode;
136 137
        GSList                 *query_clients;
        guint                   query_timeout_id;
138 139 140
        /* This is used for GSM_MANAGER_PHASE_END_SESSION only at the moment,
         * since it uses a sublist of all running client that replied in a
         * specific way */
141
        GSList                 *next_query_clients;
142 143
        /* This is the action that will be done just before we exit */
        GsmManagerLogoutType    logout_type;
144 145 146 147 148

        /* List of clients which were disconnected due to disabled condition
         * and shouldn't be automatically restarted */
        GSList                 *condition_clients;

149 150 151
        GSList                 *pending_end_session_tasks;
        GCancellable           *end_session_cancellable;

152 153 154
        GSettings              *settings;
        GSettings              *session_settings;
        GSettings              *screensaver_settings;
155
        GSettings              *lockdown_settings;
156

157
        GsmSystem              *system;
158 159
        GDBusConnection        *connection;
        GsmExportedManager     *skeleton;
160
        gboolean                dbus_disconnected : 1;
161

162 163 164
        GsmShell               *shell;
        guint                   shell_end_session_dialog_canceled_id;
        guint                   shell_end_session_dialog_open_failed_id;
165 166 167
        guint                   shell_end_session_dialog_confirmed_logout_id;
        guint                   shell_end_session_dialog_confirmed_shutdown_id;
        guint                   shell_end_session_dialog_confirmed_reboot_id;
168 169 170 171 172
};

enum {
        PROP_0,
        PROP_CLIENT_STORE,
173
        PROP_SESSION_NAME,
174
        PROP_FALLBACK,
175
        PROP_FAILSAFE
176 177 178 179 180 181 182
};

enum {
        PHASE_CHANGED,
        LAST_SIGNAL
};

183
static guint signals [LAST_SIGNAL] = { 0 };
184 185 186 187

static void     gsm_manager_class_init  (GsmManagerClass *klass);
static void     gsm_manager_init        (GsmManager      *manager);

188
static gboolean auto_save_is_enabled (GsmManager *manager);
189
static void     maybe_save_session   (GsmManager *manager);
190

191
static gboolean _log_out_is_locked_down     (GsmManager *manager);
192

193 194 195 196 197 198
static void     _handle_client_end_session_response (GsmManager *manager,
                                                     GsmClient  *client,
                                                     gboolean    is_ok,
                                                     gboolean    do_last,
                                                     gboolean    cancel,
                                                     const char *reason);
199 200
static void     show_shell_end_session_dialog (GsmManager                   *manager,
                                               GsmShellEndSessionDialogType  type);
201 202 203 204
static gpointer manager_object = NULL;

G_DEFINE_TYPE (GsmManager, gsm_manager, G_TYPE_OBJECT)

205 206 207 208 209 210 211 212 213 214
static const GDBusErrorEntry gsm_manager_error_entries[] = {
        { GSM_MANAGER_ERROR_GENERAL, GSM_MANAGER_DBUS_IFACE ".GeneralError" },
        { GSM_MANAGER_ERROR_NOT_IN_INITIALIZATION, GSM_MANAGER_DBUS_IFACE ".NotInInitialization" },
        { GSM_MANAGER_ERROR_NOT_IN_RUNNING, GSM_MANAGER_DBUS_IFACE ".NotInRunning" },
        { GSM_MANAGER_ERROR_ALREADY_REGISTERED, GSM_MANAGER_DBUS_IFACE ".AlreadyRegistered" },
        { GSM_MANAGER_ERROR_NOT_REGISTERED, GSM_MANAGER_DBUS_IFACE ".NotRegistered" },
        { GSM_MANAGER_ERROR_INVALID_OPTION, GSM_MANAGER_DBUS_IFACE ".InvalidOption" },
        { GSM_MANAGER_ERROR_LOCKED_DOWN, GSM_MANAGER_DBUS_IFACE ".LockedDown" }
};

215 216 217
GQuark
gsm_manager_error_quark (void)
{
218
        static volatile gsize quark_volatile = 0;
219

220 221 222 223 224
        g_dbus_error_register_error_domain ("gsm_manager_error",
                                            &quark_volatile,
                                            gsm_manager_error_entries,
                                            G_N_ELEMENTS (gsm_manager_error_entries));
        return quark_volatile;
225 226
}

227 228 229 230 231 232 233 234 235 236 237
static gboolean
start_app_or_warn (GsmManager *manager,
                   GsmApp     *app)
{
        gboolean res;
        GError *error = NULL;

        g_debug ("GsmManager: starting app '%s'", gsm_app_peek_id (app));

        res = gsm_app_start (app, &error);
        if (error != NULL) {
238
                g_warning ("Failed to start app: %s", error->message);
239 240 241 242 243
                g_clear_error (&error);
        }
        return res;
}

244 245 246 247 248 249 250 251 252
static gboolean
is_app_required (GsmManager *manager,
                 GsmApp     *app)
{
        return g_slist_find (manager->priv->required_apps, app) != NULL;
}

static void
on_required_app_failure (GsmManager  *manager,
253
                         GsmApp      *app)
254
{
255
        const gchar *app_id;
256
        gboolean allow_logout;
257
        GsmShellExtensions *extensions;
258 259

        app_id = gsm_app_peek_app_id (app);
260

261
        if (g_str_equal (app_id, "org.gnome.Shell")) {
262 263 264 265 266
                extensions = g_object_new (GSM_TYPE_SHELL_EXTENSIONS, NULL);
                gsm_shell_extensions_disable_all (extensions);
        } else {
                extensions = NULL;
        }
267

268
        if (gsm_system_is_login_session (manager->priv->system)) {
269 270 271 272 273
                allow_logout = FALSE;
        } else {
                allow_logout = !_log_out_is_locked_down (manager);
        }

274 275 276 277 278 279 280
#ifdef HAVE_SYSTEMD
        sd_journal_send ("MESSAGE_ID=%s", GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID,
                         "PRIORITY=%d", 3,
                         "MESSAGE=Unrecoverable failure in required component %s", app_id,
                         NULL);
#endif

281
        gsm_fail_whale_dialog_we_failed (FALSE,
282
                                         allow_logout,
283
                                         extensions);
284 285
}

286 287 288 289 290 291 292 293 294
static void
on_display_server_failure (GsmManager *manager,
                           GsmApp     *app)
{
        const gchar *app_id;
        GsmShellExtensions *extensions;

        app_id = gsm_app_peek_app_id (app);

295
        if (g_str_equal (app_id, "org.gnome.Shell")) {
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313
                extensions = g_object_new (GSM_TYPE_SHELL_EXTENSIONS, NULL);
                gsm_shell_extensions_disable_all (extensions);

                g_object_unref (extensions);
        } else {
                extensions = NULL;
        }

#ifdef HAVE_SYSTEMD
        sd_journal_send ("MESSAGE_ID=%s", GSM_MANAGER_UNRECOVERABLE_FAILURE_MSGID,
                         "PRIORITY=%d", 3,
                         "MESSAGE=Unrecoverable failure in required component %s", app_id,
                         NULL);
#endif

        gsm_quit ();
}

314 315 316 317 318
static gboolean
_debug_client (const char *id,
               GsmClient  *client,
               GsmManager *manager)
{
319
        g_debug ("GsmManager: Client %s", gsm_client_peek_id (client));
320 321 322 323 324 325
        return FALSE;
}

static void
debug_clients (GsmManager *manager)
{
326 327 328
        gsm_store_foreach (manager->priv->clients,
                           (GsmStoreFunc)_debug_client,
                           manager);
329 330
}

331 332 333 334 335 336 337
static gboolean
_find_by_cookie (const char   *id,
                 GsmInhibitor *inhibitor,
                 guint        *cookie_ap)
{
        guint cookie_b;

338
        cookie_b = gsm_inhibitor_peek_cookie (inhibitor);
339 340

        return (*cookie_ap == cookie_b);
341 342
}

343
static gboolean
344 345 346
_client_has_startup_id (const char *id,
                        GsmClient  *client,
                        const char *startup_id_a)
347
{
348
        const char *startup_id_b;
349

350
        startup_id_b = gsm_client_peek_startup_id (client);
351
        if (IS_STRING_EMPTY (startup_id_b)) {
352 353 354
                return FALSE;
        }

355
        return (strcmp (startup_id_a, startup_id_b) == 0);
356 357
}

358 359 360 361 362
static void
app_condition_changed (GsmApp     *app,
                       gboolean    condition,
                       GsmManager *manager)
{
363
        GsmClient *client;
364

365 366 367 368
        g_debug ("GsmManager: app:%s condition changed condition:%d",
                 gsm_app_peek_id (app),
                 condition);

369
        client = (GsmClient *)gsm_store_find (manager->priv->clients,
370
                                              (GsmStoreFunc)_client_has_startup_id,
371
                                              (char *)gsm_app_peek_startup_id (app));
372 373

        if (condition) {
374
                if (!gsm_app_is_running (app) && client == NULL) {
375
                        start_app_or_warn (manager, app);
376 377
                } else {
                        g_debug ("GsmManager: not starting - app still running '%s'", gsm_app_peek_id (app));
378 379
                }
        } else {
380 381 382
                GError  *error;
                gboolean res;

383 384 385 386
                if (client != NULL) {
                        /* Kill client in case condition if false and make sure it won't
                         * be automatically restarted by adding the client to
                         * condition_clients */
387 388 389
                        manager->priv->condition_clients =
                                g_slist_prepend (manager->priv->condition_clients, client);

390
                        g_debug ("GsmManager: stopping client %s for app", gsm_client_peek_id (client));
391

392 393
                        error = NULL;
                        res = gsm_client_stop (client, &error);
394
                        if (! res) {
395 396 397 398 399 400 401 402 403 404
                                g_warning ("Not able to stop app client from its condition: %s",
                                           error->message);
                                g_error_free (error);
                        }
                } else {
                        g_debug ("GsmManager: stopping app %s", gsm_app_peek_id (app));

                        /* If we don't have a client then we should try to kill the app */
                        error = NULL;
                        res = gsm_app_stop (app, &error);
405
                        if (! res) {
406 407 408 409
                                g_warning ("Not able to stop app from its condition: %s",
                                           error->message);
                                g_error_free (error);
                        }
410
                }
411 412 413
        }
}

414 415 416 417 418 419 420 421
static const char *
phase_num_to_name (guint phase)
{
        const char *name;

        switch (phase) {
        case GSM_MANAGER_PHASE_STARTUP:
                name = "STARTUP";
William Jon McCann's avatar
William Jon McCann committed
422
                break;
423 424 425
        case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
                name = "EARLY_INITIALIZATION";
                break;
426 427 428
        case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
                name = "PRE_DISPLAY_SERVER";
                break;
429 430 431
        case GSM_MANAGER_PHASE_DISPLAY_SERVER:
                name = "DISPLAY_SERVER";
                break;
432 433
        case GSM_MANAGER_PHASE_INITIALIZATION:
                name = "INITIALIZATION";
William Jon McCann's avatar
William Jon McCann committed
434
                break;
435 436
        case GSM_MANAGER_PHASE_WINDOW_MANAGER:
                name = "WINDOW_MANAGER";
William Jon McCann's avatar
William Jon McCann committed
437
                break;
438 439
        case GSM_MANAGER_PHASE_PANEL:
                name = "PANEL";
William Jon McCann's avatar
William Jon McCann committed
440
                break;
441 442
        case GSM_MANAGER_PHASE_DESKTOP:
                name = "DESKTOP";
William Jon McCann's avatar
William Jon McCann committed
443
                break;
444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466
        case GSM_MANAGER_PHASE_APPLICATION:
                name = "APPLICATION";
                break;
        case GSM_MANAGER_PHASE_RUNNING:
                name = "RUNNING";
                break;
        case GSM_MANAGER_PHASE_QUERY_END_SESSION:
                name = "QUERY_END_SESSION";
                break;
        case GSM_MANAGER_PHASE_END_SESSION:
                name = "END_SESSION";
                break;
        case GSM_MANAGER_PHASE_EXIT:
                name = "EXIT";
                break;
        default:
                g_assert_not_reached ();
                break;
        }

        return name;
}

467 468
static void start_phase (GsmManager *manager);

469 470 471 472 473 474 475 476
static void
gsm_manager_quit (GsmManager *manager)
{
        /* See the comment in request_reboot() for some more details about how
         * this works. */

        switch (manager->priv->logout_type) {
        case GSM_MANAGER_LOGOUT_LOGOUT:
477
        case GSM_MANAGER_LOGOUT_NONE:
478
                gsm_quit ();
479 480 481
                break;
        case GSM_MANAGER_LOGOUT_REBOOT:
        case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
482
                gsm_system_complete_shutdown (manager->priv->system);
483 484 485
                break;
        case GSM_MANAGER_LOGOUT_SHUTDOWN:
        case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
486
                gsm_system_complete_shutdown (manager->priv->system);
487 488 489 490 491 492 493
                break;
        default:
                g_assert_not_reached ();
                break;
        }
}

494 495
static gboolean do_query_end_session_exit (GsmManager *manager);

496 497 498
static void
end_phase (GsmManager *manager)
{
499 500
        gboolean start_next_phase = TRUE;

501
        g_debug ("GsmManager: ending phase %s",
502 503
                 phase_num_to_name (manager->priv->phase));

504 505 506
        g_slist_free (manager->priv->pending_apps);
        manager->priv->pending_apps = NULL;

507 508 509
        g_slist_free (manager->priv->query_clients);
        manager->priv->query_clients = NULL;

510 511
        g_slist_free (manager->priv->next_query_clients);
        manager->priv->next_query_clients = NULL;
512

513 514 515 516
        if (manager->priv->query_timeout_id > 0) {
                g_source_remove (manager->priv->query_timeout_id);
                manager->priv->query_timeout_id = 0;
        }
517 518 519 520
        if (manager->priv->phase_timeout_id > 0) {
                g_source_remove (manager->priv->phase_timeout_id);
                manager->priv->phase_timeout_id = 0;
        }
521

522 523
        switch (manager->priv->phase) {
        case GSM_MANAGER_PHASE_STARTUP:
524
        case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
525
        case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
526
        case GSM_MANAGER_PHASE_DISPLAY_SERVER:
527 528 529 530 531
        case GSM_MANAGER_PHASE_INITIALIZATION:
        case GSM_MANAGER_PHASE_WINDOW_MANAGER:
        case GSM_MANAGER_PHASE_PANEL:
        case GSM_MANAGER_PHASE_DESKTOP:
        case GSM_MANAGER_PHASE_APPLICATION:
532
                break;
533
        case GSM_MANAGER_PHASE_RUNNING:
534 535 536 537 538
                if (_log_out_is_locked_down (manager)) {
                        g_warning ("Unable to logout: Logout has been locked down");
                        start_next_phase = FALSE;
                }
                break;
539
        case GSM_MANAGER_PHASE_QUERY_END_SESSION:
540 541
                if (!do_query_end_session_exit (manager))
                        start_next_phase = FALSE;
542
                break;
543
        case GSM_MANAGER_PHASE_END_SESSION:
544
                maybe_save_session (manager);
545 546
                break;
        case GSM_MANAGER_PHASE_EXIT:
547
                start_next_phase = FALSE;
548
                gsm_manager_quit (manager);
549 550 551 552
                break;
        default:
                g_assert_not_reached ();
                break;
553
        }
554 555 556 557 558

        if (start_next_phase) {
                manager->priv->phase++;
                start_phase (manager);
        }
559 560
}

561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
static void
app_event_during_startup (GsmManager *manager,
                          GsmApp     *app)
{
        if (!(manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION))
                return;

        manager->priv->pending_apps = g_slist_remove (manager->priv->pending_apps, app);

        if (manager->priv->pending_apps == NULL) {
                if (manager->priv->phase_timeout_id > 0) {
                        g_source_remove (manager->priv->phase_timeout_id);
                        manager->priv->phase_timeout_id = 0;
                }

                end_phase (manager);
        }
}

580 581 582 583 584 585
static gboolean
is_app_display_server (GsmManager *manager,
                       GsmApp     *app)
{
        GsmManagerPhase phase;

586 587 588 589 590 591
        /* Apps can only really act as a display server if
         * we're a wayland session.
         */
        if (g_strcmp0 (g_getenv ("XDG_SESSION_TYPE"), "wayland") != 0)
                return FALSE;

592 593 594 595 596 597
        phase = gsm_app_peek_phase (app);

        return (phase == GSM_MANAGER_PHASE_DISPLAY_SERVER &&
                is_app_required (manager, app));
}

598
static void
599 600
_restart_app (GsmManager *manager,
              GsmApp     *app)
601
{
602 603
        GError *error = NULL;

604 605 606 607 608
        if (is_app_display_server (manager, app)) {
                on_display_server_failure (manager, app);
                return;
        }

609 610
        if (!gsm_app_restart (app, &error)) {
                if (is_app_required (manager, app)) {
611
                        on_required_app_failure (manager, app);
612 613
                } else {
                        g_warning ("Error on restarting session managed app: %s", error->message);
614
                }
615
                g_clear_error (&error);
616 617

                app_event_during_startup (manager, app);
618
        }
619 620 621 622
}

static void
app_died (GsmApp     *app,
623
          int         signal,
624 625
          GsmManager *manager)
{
626
        g_warning ("Application '%s' killed by signal %d", gsm_app_peek_app_id (app), signal);
627

628
        if (gsm_app_get_registered (app) && gsm_app_peek_autorestart (app)) {
629 630 631 632 633 634
                g_debug ("Component '%s' is autorestart, ignoring died signal",
                         gsm_app_peek_app_id (app));
                return;
        }

        _restart_app (manager, app);
635

636 637 638 639 640 641 642
        /* For now, we don't do anything with crashes from
         * non-required apps after they hit the restart limit.
         *
         * Note that both required and not-required apps will be
         * caught by ABRT/apport type infrastructure, and it'd be
         * better to pick up the crash from there and do something
         * un-intrusive about it generically.
643 644 645
         */
}

646 647 648 649 650
static void
app_exited (GsmApp     *app,
            guchar      exit_code,
            GsmManager *manager)
{
651 652 653 654
        if (exit_code != 0)
                g_warning ("App '%s' exited with code %d", gsm_app_peek_app_id (app), exit_code);
        else
                g_debug ("App %s exited successfully", gsm_app_peek_app_id (app));
655

656 657
        /* Consider that non-success exit status means "crash" for required components */
        if (exit_code != 0 && is_app_required (manager, app)) {
658
                if (gsm_app_get_registered (app) && gsm_app_peek_autorestart (app)) {
659
                        g_debug ("Component '%s' is autorestart, ignoring non-successful exit",
660 661 662 663 664 665 666 667
                                 gsm_app_peek_app_id (app));
                        return;
                }

                _restart_app (manager, app);
        } else {
                app_event_during_startup (manager, app);
        }
668 669
}

670 671
static void
app_registered (GsmApp     *app,
672
                GParamSpec *spec,
673 674
                GsmManager *manager)
{
675 676 677 678
        if (!gsm_app_get_registered (app)) {
                return;
        }

679 680
        g_debug ("App %s registered", gsm_app_peek_app_id (app));

681
        app_event_during_startup (manager, app);
682 683 684
}

static gboolean
685
on_phase_timeout (GsmManager *manager)
686 687 688
{
        GSList *a;

689
        manager->priv->phase_timeout_id = 0;
690

691 692
        switch (manager->priv->phase) {
        case GSM_MANAGER_PHASE_STARTUP:
693
        case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
694
        case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
695
        case GSM_MANAGER_PHASE_DISPLAY_SERVER:
696 697 698 699 700 701
        case GSM_MANAGER_PHASE_INITIALIZATION:
        case GSM_MANAGER_PHASE_WINDOW_MANAGER:
        case GSM_MANAGER_PHASE_PANEL:
        case GSM_MANAGER_PHASE_DESKTOP:
        case GSM_MANAGER_PHASE_APPLICATION:
                for (a = manager->priv->pending_apps; a; a = a->next) {
702
                        GsmApp *app = a->data;
703
                        g_warning ("Application '%s' failed to register before timeout",
704 705
                                   gsm_app_peek_app_id (app));
                        if (is_app_required (manager, app))
706
                                on_required_app_failure (manager, app);
707 708 709 710 711 712 713 714 715 716 717 718
                }
                break;
        case GSM_MANAGER_PHASE_RUNNING:
                break;
        case GSM_MANAGER_PHASE_QUERY_END_SESSION:
        case GSM_MANAGER_PHASE_END_SESSION:
                break;
        case GSM_MANAGER_PHASE_EXIT:
                break;
        default:
                g_assert_not_reached ();
                break;
719 720 721
        }

        end_phase (manager);
722

723 724 725
        return FALSE;
}

726
static gboolean
727 728 729
_start_app (const char *id,
            GsmApp     *app,
            GsmManager *manager)
730
{
731
        if (gsm_app_peek_phase (app) != manager->priv->phase) {
732
                goto out;
733
        }
734

735 736 737 738 739 740
        /* Keep track of app autostart condition in order to react
         * accordingly in the future. */
        g_signal_connect (app,
                          "condition-changed",
                          G_CALLBACK (app_condition_changed),
                          manager);
741

742 743
        if (gsm_app_peek_is_disabled (app)
            || gsm_app_peek_is_conditionally_disabled (app)) {
744
                g_debug ("GsmManager: Skipping disabled app: %s", id);
745
                goto out;
746
        }
747

748
        if (!start_app_or_warn (manager, app))
749
                goto out;
750

751
        if (manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION) {
752 753 754 755 756 757 758 759 760
                /* Historical note - apparently,
                 * e.g. gnome-settings-daemon used to "daemonize", and
                 * so gnome-session assumes process exit means "ok
                 * we're done".  Of course this is broken, we don't
                 * even distinguish between exit code 0 versus not-0,
                 * nor do we have any metadata which tells us a
                 * process is going to "daemonize" or not (and
                 * basically nothing should be anyways).
                 */
761 762
                g_signal_connect (app,
                                  "exited",
763
                                  G_CALLBACK (app_exited),
764
                                  manager);
765
                g_signal_connect (app,
766
                                  "notify::registered",
767 768
                                  G_CALLBACK (app_registered),
                                  manager);
769 770 771 772
                g_signal_connect (app,
                                  "died",
                                  G_CALLBACK (app_died),
                                  manager);
773 774
                manager->priv->pending_apps = g_slist_prepend (manager->priv->pending_apps, app);
        }
775 776
 out:
        return FALSE;
777
}
778

779
static void
780
do_phase_startup (GsmManager *manager)
781
{
782 783 784
        gsm_store_foreach (manager->priv->apps,
                           (GsmStoreFunc)_start_app,
                           manager);
785 786 787

        if (manager->priv->pending_apps != NULL) {
                if (manager->priv->phase < GSM_MANAGER_PHASE_APPLICATION) {
788
                        manager->priv->phase_timeout_id = g_timeout_add_seconds (GSM_MANAGER_PHASE_TIMEOUT,
789
                                                                                 (GSourceFunc)on_phase_timeout,
790
                                                                                 manager);
791 792 793 794 795 796
                }
        } else {
                end_phase (manager);
        }
}

797 798 799 800
typedef struct {
        GsmManager *manager;
        guint       flags;
} ClientEndSessionData;
801 802


803
static gboolean
804
_client_end_session (GsmClient            *client,
805
                     ClientEndSessionData *data)
806
{
807 808
        gboolean ret;
        GError  *error;
809

810 811 812 813 814 815 816 817 818 819 820
        error = NULL;
        ret = gsm_client_end_session (client, data->flags, &error);
        if (! ret) {
                g_warning ("Unable to query client: %s", error->message);
                g_error_free (error);
                /* FIXME: what should we do if we can't communicate with client? */
        } else {
                g_debug ("GsmManager: adding client to end-session clients: %s", gsm_client_peek_id (client));
                data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
                                                                      client);
        }
821 822

        return FALSE;
823 824
}

825 826 827 828 829 830 831 832
static gboolean
_client_end_session_helper (const char           *id,
                            GsmClient            *client,
                            ClientEndSessionData *data)
{
        return _client_end_session (client, data);
}

833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850
static void
complete_end_session_tasks (GsmManager *manager)
{
        GSList *l;

        for (l = manager->priv->pending_end_session_tasks;
             l != NULL;
             l = l->next) {
                GTask *task = G_TASK (l->data);
                if (!g_task_return_error_if_cancelled (task))
                    g_task_return_boolean (task, TRUE);
        }

        g_slist_free_full (manager->priv->pending_end_session_tasks,
                           (GDestroyNotify) g_object_unref);
        manager->priv->pending_end_session_tasks = NULL;
}

851
static void
852
do_phase_end_session (GsmManager *manager)
853
{
854
        ClientEndSessionData data;
855

856 857
        complete_end_session_tasks (manager);

858 859
        data.manager = manager;
        data.flags = 0;
860

861
        if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
862
                data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
863
        }
864 865 866 867
        if (auto_save_is_enabled (manager)) {
                data.flags |= GSM_CLIENT_END_SESSION_FLAG_SAVE;
        }

868 869 870
        if (manager->priv->phase_timeout_id > 0) {
                g_source_remove (manager->priv->phase_timeout_id);
                manager->priv->phase_timeout_id = 0;
871 872
        }

873
        if (gsm_store_size (manager->priv->clients) > 0) {
874
                manager->priv->phase_timeout_id = g_timeout_add_seconds (GSM_MANAGER_PHASE_TIMEOUT,
875 876
                                                                         (GSourceFunc)on_phase_timeout,
                                                                         manager);
877

878
                gsm_store_foreach (manager->priv->clients,
879
                                   (GsmStoreFunc)_client_end_session_helper,
880
                                   &data);
881
        } else {
882
                end_phase (manager);
883 884 885 886
        }
}

static void
887
do_phase_end_session_part_2 (GsmManager *manager)
888 889 890 891 892 893
{
        ClientEndSessionData data;

        data.manager = manager;
        data.flags = 0;

894
        if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
895 896 897 898 899 900 901
                data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
        }
        if (auto_save_is_enabled (manager)) {
                data.flags |= GSM_CLIENT_END_SESSION_FLAG_SAVE;
        }
        data.flags |= GSM_CLIENT_END_SESSION_FLAG_LAST;

902 903
        /* keep the timeout that was started at the beginning of the
         * GSM_MANAGER_PHASE_END_SESSION phase */
904 905 906

        if (g_slist_length (manager->priv->next_query_clients) > 0) {
                g_slist_foreach (manager->priv->next_query_clients,
907
                                 (GFunc)_client_end_session,
908
                                 &data);
909 910 911

                g_slist_free (manager->priv->next_query_clients);
                manager->priv->next_query_clients = NULL;
912 913 914 915 916
        } else {
                end_phase (manager);
        }
}

917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945
static gboolean
_client_stop (const char *id,
              GsmClient  *client,
              gpointer    user_data)
{
        gboolean ret;
        GError  *error;

        error = NULL;
        ret = gsm_client_stop (client, &error);
        if (! ret) {
                g_warning ("Unable to stop client: %s", error->message);
                g_error_free (error);
                /* FIXME: what should we do if we can't communicate with client? */
        } else {
                g_debug ("GsmManager: stopped client: %s", gsm_client_peek_id (client));
        }

        return FALSE;
}

static void
do_phase_exit (GsmManager *manager)
{
        if (gsm_store_size (manager->priv->clients) > 0) {
                gsm_store_foreach (manager->priv->clients,
                                   (GsmStoreFunc)_client_stop,
                                   NULL);
        }
946 947

        end_phase (manager);
948 949
}

950 951 952 953 954
static gboolean
_client_query_end_session (const char           *id,
                           GsmClient            *client,
                           ClientEndSessionData *data)
{
955 956 957 958 959 960 961 962 963 964 965 966 967 968
        gboolean ret;
        GError  *error;

        error = NULL;
        ret = gsm_client_query_end_session (client, data->flags, &error);
        if (! ret) {
                g_warning ("Unable to query client: %s", error->message);
                g_error_free (error);
                /* FIXME: what should we do if we can't communicate with client? */
        } else {
                g_debug ("GsmManager: adding client to query clients: %s", gsm_client_peek_id (client));
                data->manager->priv->query_clients = g_slist_prepend (data->manager->priv->query_clients,
                                                                      client);
        }
969

970 971
        return FALSE;
}
972

973 974 975 976 977
static gboolean
inhibitor_has_flag (gpointer      key,
                    GsmInhibitor *inhibitor,
                    gpointer      data)
{
978 979 980 981
        guint flag;
        guint flags;

        flag = GPOINTER_TO_UINT (data);
982

983
        flags = gsm_inhibitor_peek_flags (inhibitor);
984

985
        return (flags & flag);
986 987
}

988
static gboolean
989
gsm_manager_is_logout_inhibited (GsmManager *manager)
990
{
991
        GsmInhibitor *inhibitor;
992

993 994 995 996
        if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
                return FALSE;
        }

997
        if (manager->priv->inhibitors == NULL) {
998 999 1000
                return FALSE;
        }

1001 1002
        inhibitor = (GsmInhibitor *)gsm_store_find (manager->priv->inhibitors,
                                                    (GsmStoreFunc)inhibitor_has_flag,
1003
                                                    GUINT_TO_POINTER (GSM_INHIBITOR_FLAG_LOGOUT));
1004
        if (inhibitor == NULL) {
1005 1006
                return FALSE;
        }
1007
        return TRUE;
1008 1009
}

William Jon McCann's avatar
William Jon McCann committed
1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027
static gboolean
gsm_manager_is_idle_inhibited (GsmManager *manager)
{
        GsmInhibitor *inhibitor;

        if (manager->priv->inhibitors == NULL) {
                return FALSE;
        }

        inhibitor = (GsmInhibitor *)gsm_store_find (manager->priv->inhibitors,
                                                    (GsmStoreFunc)inhibitor_has_flag,
                                                    GUINT_TO_POINTER (GSM_INHIBITOR_FLAG_IDLE));
        if (inhibitor == NULL) {
                return FALSE;
        }
        return TRUE;
}

1028 1029 1030 1031
static gboolean
_client_cancel_end_session (const char *id,
                            GsmClient  *client,
                            GsmManager *manager)
1032
{
1033 1034 1035 1036 1037 1038 1039 1040 1041
        gboolean res;
        GError  *error;

        error = NULL;
        res = gsm_client_cancel_end_session (client, &error);
        if (! res) {
                g_warning ("Unable to cancel end session: %s", error->message);
                g_error_free (error);
        }
1042

1043
        return FALSE;
1044 1045
}

1046
static gboolean
1047 1048 1049
inhibitor_is_jit (gpointer      key,
                  GsmInhibitor *inhibitor,
                  GsmManager   *manager)
1050
{
1051
        gboolean    matches;
1052
        const char *id;
1053

1054
        id = gsm_inhibitor_peek_client_id (inhibitor);
1055

1056
        matches = (id != NULL && id[0] != '\0');
1057 1058 1059 1060 1061

        return matches;
}

static void
1062
cancel_end_session (GsmManager *manager)
1063
{
1064 1065 1066 1067 1068
        /* just ignore if received outside of shutdown */
        if (manager->priv->phase < GSM_MANAGER_PHASE_QUERY_END_SESSION) {
                return;
        }

1069
        /* switch back to running phase */
1070
        g_debug ("GsmManager: Cancelling the end of session");
1071

1072 1073
        g_cancellable_cancel (manager->priv->end_session_cancellable);

1074
        /* clear all JIT inhibitors */
1075 1076 1077
        gsm_store_foreach_remove (manager->priv->inhibitors,
                                  (GsmStoreFunc)inhibitor_is_jit,
                                  (gpointer)manager);
1078

1079 1080 1081
        gsm_store_foreach (manager->priv->clients,
                           (GsmStoreFunc)_client_cancel_end_session,
                           NULL);
1082

1083
        gsm_manager_set_phase (manager, GSM_MANAGER_PHASE_RUNNING);
1084
        manager->priv->logout_mode = GSM_MANAGER_LOGOUT_MODE_NORMAL;
1085

1086 1087
        manager->priv->logout_type = GSM_MANAGER_LOGOUT_NONE;

1088
        start_phase (manager);
1089 1090
}

1091 1092 1093
static void
end_session_or_show_shell_dialog (GsmManager *manager)
{
1094
        gboolean logout_prompt;
1095
        GsmShellEndSessionDialogType type;
1096
        gboolean logout_inhibited;
1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116

        switch (manager->priv->logout_type) {
        case GSM_MANAGER_LOGOUT_LOGOUT:
                type = GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT;
                break;
        case GSM_MANAGER_LOGOUT_REBOOT:
        case GSM_MANAGER_LOGOUT_REBOOT_INTERACT:
                type = GSM_SHELL_END_SESSION_DIALOG_TYPE_RESTART;
                break;
        case GSM_MANAGER_LOGOUT_SHUTDOWN:
        case GSM_MANAGER_LOGOUT_SHUTDOWN_INTERACT:
                type = GSM_SHELL_END_SESSION_DIALOG_TYPE_SHUTDOWN;
                break;
        default:
                g_warning ("Unexpected logout type %d when creating end session dialog",
                           manager->priv->logout_type);
                type = GSM_SHELL_END_SESSION_DIALOG_TYPE_LOGOUT;
                break;
        }

1117 1118 1119
        logout_inhibited = gsm_manager_is_logout_inhibited (manager);
        logout_prompt = g_settings_get_boolean (manager->priv->settings,
                                                KEY_LOGOUT_PROMPT);
1120

1121 1122 1123
        switch (manager->priv->logout_mode) {
        case GSM_MANAGER_LOGOUT_MODE_NORMAL:
                if (logout_inhibited || logout_prompt) {
1124 1125 1126 1127
                        show_shell_end_session_dialog (manager, type);
                } else {
                        end_phase (manager);
                }
1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143
                break;

        case GSM_MANAGER_LOGOUT_MODE_NO_CONFIRMATION:
                if (logout_inhibited) {
                        show_shell_end_session_dialog (manager, type);
                } else {
                        end_phase (manager);
                }
                break;

        case GSM_MANAGER_LOGOUT_MODE_FORCE:
                end_phase (manager);
                break;
        default:
                g_assert_not_reached ();
                break;
1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159 1160
        }

}

static void
query_end_session_complete (GsmManager *manager)
{

        g_debug ("GsmManager: query end session complete");

        /* Remove the timeout since this can be called from outside the timer
         * and we don't want to have it called twice */
        if (manager->priv->query_timeout_id > 0) {
                g_source_remove (manager->priv->query_timeout_id);
                manager->priv->query_timeout_id = 0;
        }

1161
        end_session_or_show_shell_dialog (manager);
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180
}

static guint32
generate_cookie (void)
{
        guint32 cookie;

        cookie = (guint32)g_random_int_range (1, G_MAXINT32);

        return cookie;
}

static guint32
_generate_unique_cookie (GsmManager *manager)
{
        guint32 cookie;

        do {
                cookie = generate_cookie ();
1181
        } while (gsm_store_find (manager->priv->inhibitors, (GsmStoreFunc)_find_by_cookie, &cookie) != NULL);
1182 1183 1184 1185 1186

        return cookie;
}

static gboolean
1187
_on_query_end_session_timeout (GsmManager *manager)
1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198
{
        GSList *l;

        manager->priv->query_timeout_id = 0;

        g_debug ("GsmManager: query end session timed out");

        for (l = manager->priv->query_clients; l != NULL; l = l->next) {
                guint         cookie;
                GsmInhibitor *inhibitor;
                const char   *bus_name;
1199
                char         *app_id;
1200 1201

                g_warning ("Client '%s' failed to reply before timeout",
1202
                           gsm_client_peek_id (l->data));
1203

1204 1205
                /* Don't add "not responding" inhibitors if logout is forced
                 */
1206
                if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
1207 1208 1209
                        continue;
                }

1210 1211 1212 1213 1214 1215 1216
                /* Add JIT inhibit for unresponsive client */
                if (GSM_IS_DBUS_CLIENT (l->data)) {
                        bus_name = gsm_dbus_client_get_bus_name (l->data);
                } else {
                        bus_name = NULL;
                }

1217
                app_id = g_strdup (gsm_client_peek_app_id (l->data));
1218
                if (IS_STRING_EMPTY (app_id)) {
1219
                        /* XSMP clients don't give us an app id unless we start them */
1220
                        g_free (app_id);
1221 1222 1223
                        app_id = gsm_client_get_app_name (l->data);
                }

1224
                cookie = _generate_unique_cookie (manager);
1225
                inhibitor = gsm_inhibitor_new_for_client (gsm_client_peek_id (l->data),
1226
                                                          app_id,
1227 1228 1229 1230
                                                          GSM_INHIBITOR_FLAG_LOGOUT,
                                                          _("Not responding"),
                                                          bus_name,
                                                          cookie);
1231
                g_free (app_id);
1232
                gsm_store_add (manager->priv->inhibitors, gsm_inhibitor_peek_id (inhibitor), G_OBJECT (inhibitor));
1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251
                g_object_unref (inhibitor);
        }

        g_slist_free (manager->priv->query_clients);
        manager->priv->query_clients = NULL;

        query_end_session_complete (manager);

        return FALSE;
}

static void
do_phase_query_end_session (GsmManager *manager)
{
        ClientEndSessionData data;

        data.manager = manager;
        data.flags = 0;

1252
        if (manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE) {
1253 1254
                data.flags |= GSM_CLIENT_END_SESSION_FLAG_FORCEFUL;
        }
1255 1256 1257
        /* We only query if an app is ready to log out, so we don't use
         * GSM_CLIENT_END_SESSION_FLAG_SAVE here.
         */
1258 1259

        debug_clients (manager);
1260 1261 1262 1263
        g_debug ("GsmManager: sending query-end-session to clients (logout mode: %s)",
                 manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_NORMAL? "normal" :
                 manager->priv->logout_mode == GSM_MANAGER_LOGOUT_MODE_FORCE? "forceful":
                 "no confirmation");
1264 1265 1266
        gsm_store_foreach (manager->priv->clients,
                           (GsmStoreFunc)_client_query_end_session,
                           &data);
1267

1268 1269
        /* This phase doesn't time out unless logout is forced. Typically, this
         * separate timer is only used to show UI. */
1270
        manager->priv->query_timeout_id = g_timeout_add_seconds (1, (GSourceFunc)_on_query_end_session_timeout, manager);
1271 1272
}

William Jon McCann's avatar
William Jon McCann committed
1273 1274 1275 1276 1277 1278 1279 1280 1281 1282
static void
update_idle (GsmManager *manager)
{
        if (gsm_manager_is_idle_inhibited (manager)) {
                gsm_presence_set_idle_enabled (manager->priv->presence, FALSE);
        } else {
                gsm_presence_set_idle_enabled (manager->priv->presence, TRUE);
        }
}

1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294
static void
start_phase (GsmManager *manager)
{

        g_debug ("GsmManager: starting phase %s\n",
                 phase_num_to_name (manager->priv->phase));

        /* reset state */
        g_slist_free (manager->priv->pending_apps);
        manager->priv->pending_apps = NULL;
        g_slist_free (manager->priv->query_clients);
        manager->priv->query_clients = NULL;
1295 1296
        g_slist_free (manager->priv->next_query_clients);
        manager->priv->next_query_clients = NULL;
1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308

        if (manager->priv->query_timeout_id > 0) {
                g_source_remove (manager->priv->query_timeout_id);
                manager->priv->query_timeout_id = 0;
        }
        if (manager->priv->phase_timeout_id > 0) {
                g_source_remove (manager->priv->phase_timeout_id);
                manager->priv->phase_timeout_id = 0;
        }

        switch (manager->priv->phase) {
        case GSM_MANAGER_PHASE_STARTUP:
1309
        case GSM_MANAGER_PHASE_EARLY_INITIALIZATION:
1310
        case GSM_MANAGER_PHASE_PRE_DISPLAY_SERVER:
1311
        case GSM_MANAGER_PHASE_DISPLAY_SERVER:
1312 1313 1314 1315 1316 1317 1318 1319
        case GSM_MANAGER_PHASE_INITIALIZATION:
        case GSM_MANAGER_PHASE_WINDOW_MANAGER:
        case GSM_MANAGER_PHASE_PANEL:
        case GSM_MANAGER_PHASE_DESKTOP:
        case GSM_MANAGER_PHASE_APPLICATION:
                do_phase_startup (manager);
                break;
        case GSM_MANAGER_PHASE_RUNNING:
1320 1321 1322 1323 1324 1325
#ifdef HAVE_SYSTEMD                
                sd_journal_send ("MESSAGE_ID=%s", GSM_MANAGER_STARTUP_SUCCEEDED_MSGID,
                                 "PRIORITY=%d", 5,
                                 "MESSAGE=Entering running state",
                                 NULL);
#endif
1326
                gsm_xsmp_server_start_accepting_new_clients (manager->priv->xsmp_server);
1327 1328 1329 1330
                if (manager->priv->pending_end_session_tasks != NULL)
                        complete_end_session_tasks (manager);
                g_object_unref (manager->priv->end_session_cancellable);
                manager->priv->end_session_cancellable = g_cancellable_new ();
1331
                gsm_exported_manager_emit_session_running (manager->priv->skeleton);
William Jon McCann's avatar
William Jon McCann committed
1332
                update_idle (manager);
1333 1334
                break;
        case GSM_MANAGER_PHASE_QUERY_END_SESSION:
1335
                gsm_xsmp_server_stop_accepting_new_clients (manager->priv->xsmp_server);
1336 1337 1338 1339 1340 1341
                do_phase_query_end_session (manager);
                break;
        case GSM_MANAGER_PHASE_END_SESSION:
                do_phase_end_session (manager);
                break;
        case GSM_MANAGER_PHASE_EXIT:
1342
                do_phase_exit (manager);
1343 1344 1345 1346 1347 1348 1349
                break;
        default:
                g_assert_not_reached ();
                break;
        }
}

1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365 1366 1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377
static gboolean
_debug_app_for_phase (const char *id,
                      GsmApp     *app,
                      gpointer    data)
{
        guint phase;

        phase = GPOINTER_TO_UINT (data);

        if (gsm_app_peek_phase (app) != phase) {
                return FALSE;
        }

        g_debug ("GsmManager:\tID: %s\tapp-id:%s\tis-disabled:%d\tis-conditionally-disabled:%d",
                 gsm_app_peek_id (app),
                 gsm_app_peek_app_id (app),
                 gsm_app_peek_is_disabled (app),
                 gsm_app_peek_is_conditionally_disabled (app));

        return FALSE;
}

static void
debug_app_summary (GsmManager *manager)
{
        guint phase;

        g_debug ("GsmManager: App startup summary");
1378
        for (phase = GSM_MANAGER_PHASE_EARLY_INITIALIZATION; phase < GSM_MANAGER_PHASE_RUNNING; phase++) {
1379 1380 1381 1382 1383 1384 1385
                g_debug ("GsmManager: Phase %s", phase_num_to_name (phase));
                gsm_store_foreach (manager->priv->apps,
                                   (GsmStoreFunc)_debug_app_for_phase,
                                   GUINT_TO_POINTER (phase));
        }
}

1386 1387 1388 1389 1390
void
gsm_manager_start (GsmManager *manager)
{
        g_debug ("GsmManager: GSM starting to manage");

1391