[gnome-packagekit] Add optional systemd support



commit b139de03145f577d32bdc1c549a7b08e71ef4061
Author: Matthias Clasen <mclasen redhat com>
Date:   Sat Dec 24 01:09:33 2011 -0500

    Add optional systemd support
    
    This patch adds a --enable-systemd configure flag that makes
    gnome-packagekit use systemd instead of ConsoleKit for rebooting.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=666788

 configure.ac             |   36 +++++++++++++++
 src/Makefile.am          |   14 +++++-
 src/gpk-distro-upgrade.c |   25 +++++++++++
 src/gpk-update-viewer.c  |   25 +++++++++++
 src/systemd-proxy.c      |  107 ++++++++++++++++++++++++++++++++++++++++++++++
 src/systemd-proxy.h      |   41 +++++++++++++++++
 6 files changed, 246 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 7d75864..b468bde 100644
--- a/configure.ac
+++ b/configure.ac
@@ -138,6 +138,42 @@ fi
 AM_CONDITIONAL(HAVE_GUDEV, test x$HAVE_GUDEV = xyes)
 
 dnl ---------------------------------------------------------------------------
+dnl systemd integration
+dnl ---------------------------------------------------------------------------
+AC_ARG_ENABLE([systemd],
+              AS_HELP_STRING([--enable-systemd], [Use systemd]),
+              [with_systemd=$enableval],
+              [with_systemd=auto])
+
+PKG_CHECK_MODULES(SYSTEMD,
+                  [libsystemd-login polkit-gobject-1],
+                  [have_systemd=yes], [have_systemd=no])
+
+AC_MSG_CHECKING([whether to use systemd])
+
+if test x$with_systemd = xauto ; then
+        if test x$have_systemd = xno ; then
+                with_systemd=no
+        else
+                with_systemd=yes
+        fi
+fi
+
+AC_MSG_RESULT($with_systemd)
+
+if test x$with_systemd = xyes; then
+        if test x$have_systemd = xno; then
+                AC_MSG_ERROR([Systemd support explicitly required, but systemd not found])
+        fi
+        AC_DEFINE(HAVE_SYSTEMD, 1, [Define if systemd is used for session tracking])
+fi
+
+AC_SUBST(SYSTEMD_CFLAGS)
+AC_SUBST(SYSTEMD_LIBS)
+
+AM_CONDITIONAL(WITH_SYSTEMD, [test "$with_systemd" = "yes"], [Using systemd])
+
+dnl ---------------------------------------------------------------------------
 dnl - Enable small form factor code
 dnl ---------------------------------------------------------------------------
 AC_ARG_ENABLE(small_form_factor, AS_HELP_STRING([--enable-small-form-factor],[enable small form factor code]),
diff --git a/src/Makefile.am b/src/Makefile.am
index 7c3e974..c15f6b8 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -11,6 +11,7 @@ INCLUDES =						\
 	$(NOTIFY_CFLAGS)				\
 	$(PACKAGEKIT_CFLAGS)				\
 	$(GUDEV_CFLAGS)					\
+	$(SYSTEMD_CFLAGS)				\
 	$(GNOME_MENUS_CFLAGS)				\
 	-DI_KNOW_THE_UPOWER_API_IS_SUBJECT_TO_CHANGE	\
 	-DI_KNOW_THE_PACKAGEKIT_GLIB2_API_IS_SUBJECT_TO_CHANGE	\
@@ -50,8 +51,6 @@ libgpkshared_a_SOURCES =				\
 	egg-string.h					\
 	egg-markdown.c					\
 	egg-markdown.h					\
-	egg-console-kit.c				\
-	egg-console-kit.h				\
 	egg-dbus-monitor.c				\
 	egg-dbus-monitor.h				\
 	gpk-debug.c					\
@@ -90,6 +89,16 @@ libgpkshared_a_SOURCES =				\
 	gpk-error.h					\
 	$(NULL)
 
+if WITH_SYSTEMD
+libgpkshared_a_SOURCES +=				\
+	systemd-proxy.c					\
+	systemd-proxy.h
+else
+libgpkshared_a_SOURCES +=				\
+	egg-console-kit.c				\
+	egg-console-kit.h
+endif
+
 shared_LIBS =						\
 	$(GLIB_LIBS)					\
 	$(GIO_LIBS)					\
@@ -97,6 +106,7 @@ shared_LIBS =						\
 	$(GTK_LIBS)					\
 	$(GUDEV_LIBS)					\
 	$(NOTIFY_LIBS)					\
+	$(SYSTEMD_LIBS)					\
 	$(PACKAGEKIT_LIBS)				\
 	$(GNOME_MENUS_LIBS)				\
 	$(UPOWER_LIBS)					\
diff --git a/src/gpk-distro-upgrade.c b/src/gpk-distro-upgrade.c
index f74d14c..566a26f 100644
--- a/src/gpk-distro-upgrade.c
+++ b/src/gpk-distro-upgrade.c
@@ -26,7 +26,12 @@
 #include <locale.h>
 #include <packagekit-glib2/packagekit.h>
 
+#ifdef HAVE_SYSTEMD
+#include "systemd-proxy.h"
+#else
 #include "egg-console-kit.h"
+#endif
+
 #include "gpk-animated-icon.h"
 #include "gpk-common.h"
 #include "gpk-debug.h"
@@ -40,7 +45,11 @@ enum {
 };
 
 typedef struct {
+#ifdef HAVE_SYSTEMD
+        SystemdProxy    *systemd_proxy;
+#else
 	EggConsoleKit	*console_kit;
+#endif
 	GCancellable	*cancellable;
 	GtkListStore	*distro_upgrade_store;
 	GtkWidget	*assistant;
@@ -108,7 +117,11 @@ gpk_distro_upgrade_restart_response_cb (GtkDialog *dialog, gint response_id, Gpk
 
 	/* restart */
 	if (response_id == GTK_RESPONSE_OK) {
+#ifdef HAVE_SYSTEMD
+                ret = systemd_proxy_restart (priv->systemd_proxy, &error);
+#else
 		ret = egg_console_kit_restart (priv->console_kit, &error);
+#endif
 		if (!ret) {
 			g_warning ("Cannot restart: %s", error->message);
 			g_error_free (error);
@@ -164,8 +177,12 @@ gpk_distro_upgrade_upgrade_system_cb (PkClient *client, GAsyncResult *res, GpkDi
 						  _("When you are ready, you can restart your system and continue the upgrade process."),
 						  _("Make sure you have saved any unsaved work before restarting."));
 
+#ifdef HAVE_SYSTEMD
+        ret = systemd_proxy_can_restart (priv->systemd_proxy, &can_restart, &error);
+#else
 	/* check with ConsoleKit we can restart */
 	ret = egg_console_kit_can_restart (priv->console_kit, &can_restart, &error);
+#endif
 	if (!ret) {
 		g_warning ("cannot get consolekit CanRestart data: %s", error->message);
 		g_error_free (error);
@@ -764,7 +781,11 @@ main (int argc, char *argv[])
 	g_type_init ();
 	gtk_init (&argc, &argv);
 	priv = g_new0 (GpkDistroUpgradePrivate, 1);
+#ifdef HAVE_SYSTEMD
+        priv->systemd_proxy = systemd_proxy_new ();
+#else
 	priv->console_kit = egg_console_kit_new ();
+#endif
 	priv->cancellable = g_cancellable_new ();
 	priv->client = pk_client_new ();
 	g_object_set (priv->client,
@@ -799,7 +820,11 @@ main (int argc, char *argv[])
 out:
 	g_object_unref (priv->cancellable);
 	g_object_unref (priv->client);
+#ifdef HAVE_SYSTEMD
+        systemd_proxy_free (priv->systemd_proxy);
+#else
 	g_object_unref (priv->console_kit);
+#endif
 	g_free (priv);
         if (application)
                 g_object_unref (application);
diff --git a/src/gpk-update-viewer.c b/src/gpk-update-viewer.c
index 67caffd..100cd2e 100644
--- a/src/gpk-update-viewer.c
+++ b/src/gpk-update-viewer.c
@@ -32,7 +32,11 @@
 
 #include "egg-string.h"
 #include "egg-markdown.h"
+#ifdef HAVE_SYSTEMD
+#include "systemd-proxy.h"
+#else
 #include "egg-console-kit.h"
+#endif
 
 #include "gpk-cell-renderer-info.h"
 #include "gpk-cell-renderer-restart.h"
@@ -57,7 +61,11 @@ static	guint			 auto_shutdown_id = 0;
 static	guint			 size_total = 0;
 static	guint			 number_total = 0;
 static	PkRestartEnum		 restart_worst = 0;
+#ifdef HAVE_SYSTEMD
+static  SystemdProxy            *proxy = NULL;
+#else
 static	EggConsoleKit		*console = NULL;
+#endif
 static	EggMarkdown		*markdown = NULL;
 static	GCancellable		*cancellable = NULL;
 static	GSettings		*settings = NULL;
@@ -240,7 +248,11 @@ gpk_update_viewer_check_restart (void)
 	/* check to see if restart is possible */
 	if (restart_update == PK_RESTART_ENUM_SYSTEM ||
 	    restart_update == PK_RESTART_ENUM_SECURITY_SYSTEM) {
+#ifdef HAVE_SYSTEMD
+                systemd_proxy_can_restart (proxy, &show_button, NULL);
+#else
 		egg_console_kit_can_restart (console, &show_button, NULL);
+#endif
 	}
 
 	/* only show the button if we can do the action */
@@ -260,8 +272,12 @@ gpk_update_viewer_check_restart (void)
 
 	/* do the action */
 	if (restart_update == PK_RESTART_ENUM_SYSTEM)
+#ifdef HAVE_SYSTEMD
+                ret = systemd_proxy_restart (proxy, &error);
+#else
 		/* use consolekit to restart */
 		ret = egg_console_kit_restart (console, &error);
+#endif
 		if (!ret) {
 			/* TRANSLATORS: the PackageKit request did not complete, and it did not send an error */
 			gpk_update_viewer_error_dialog (_("Could not restart"), NULL, error->message);
@@ -3149,7 +3165,11 @@ gpk_update_viewer_application_startup_cb (GtkApplication *_application, gpointer
 	restart_update = PK_RESTART_ENUM_NONE;
 
 	settings = g_settings_new (GPK_SETTINGS_SCHEMA);
+#ifdef HAVE_SYSTEMD
+        proxy = systemd_proxy_new ();
+#else
 	console = egg_console_kit_new ();
+#endif
 	cancellable = g_cancellable_new ();
 	markdown = egg_markdown_new ();
 	egg_markdown_set_output (markdown, EGG_MARKDOWN_OUTPUT_PANGO);
@@ -3391,8 +3411,13 @@ main (int argc, char *argv[])
 		g_object_unref (builder);
 	if (cancellable != NULL)
 		g_object_unref (cancellable);
+#ifdef HAVE_SYSTEMD
+        if (proxy != NULL)
+                systemd_proxy_free (proxy);
+#else
 	if (console != NULL)
 		g_object_unref (console);
+#endif
 	if (control != NULL)
 		g_object_unref (control);
 	if (settings != NULL)
diff --git a/src/systemd-proxy.c b/src/systemd-proxy.c
new file mode 100644
index 0000000..50fec25
--- /dev/null
+++ b/src/systemd-proxy.c
@@ -0,0 +1,107 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Matthias Clasen
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include <config.h>
+
+#include <gio/gio.h>
+#include <polkit/polkit.h>
+
+#include "systemd-proxy.h"
+
+#define SYSTEMD_DBUS_NAME      "org.freedesktop.login1"
+#define SYSTEMD_DBUS_PATH      "/org/freedesktop/login1"
+#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager"
+#define SYSTEMD_REBOOT_ACTION  "org.freedesktop.login1.reboot"
+
+struct _SystemdProxy {
+        PolkitAuthority *authority;
+        PolkitSubject *subject;
+};
+
+SystemdProxy *
+systemd_proxy_new (void)
+{
+        SystemdProxy *proxy;
+
+        proxy = g_new0 (SystemdProxy, 1);
+
+        proxy->authority = polkit_authority_get_sync (NULL, NULL);
+        proxy->subject = polkit_unix_session_new_for_process_sync (getpid(), NULL, NULL);
+
+        return proxy;
+}
+
+void
+systemd_proxy_free (SystemdProxy *proxy)
+{
+        g_object_unref (proxy->authority);
+        g_object_unref (proxy->subject);
+
+        g_free (proxy);
+}
+
+gboolean
+systemd_proxy_can_restart (SystemdProxy  *proxy,
+                           gboolean      *can_restart,
+                           GError       **error)
+{
+        PolkitAuthorizationResult *res;
+        GError *local_error = NULL;
+
+        *can_restart = FALSE;
+        res = polkit_authority_check_authorization_sync (proxy->authority,
+                                                         proxy->subject,
+                                                         SYSTEMD_REBOOT_ACTION,
+                                                         NULL,
+                                                         POLKIT_CHECK_AUTHORIZATION_FLAGS_NONE,
+                                                         NULL,
+                                                         &local_error);
+        if (res == NULL) {
+                g_propagate_error (error, local_error);
+                return FALSE;
+        }
+
+        *can_restart = polkit_authorization_result_get_is_authorized (res) ||
+                       polkit_authorization_result_get_is_challenge (res);
+
+        g_object_unref (res);
+
+        return TRUE;
+}
+
+gboolean
+systemd_proxy_restart (SystemdProxy  *proxy,
+                       GError       **error)
+{
+        GDBusConnection *bus;
+
+        bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, NULL);
+        g_dbus_connection_call (bus,
+                                SYSTEMD_DBUS_NAME,
+                                SYSTEMD_DBUS_PATH,
+                                SYSTEMD_DBUS_INTERFACE,
+                                "Reboot",
+                                g_variant_new ("(b)", TRUE),
+                                NULL, 0, G_MAXINT, NULL, NULL, NULL);
+        g_object_unref (bus);
+
+        return TRUE;
+}
diff --git a/src/systemd-proxy.h b/src/systemd-proxy.h
new file mode 100644
index 0000000..133be52
--- /dev/null
+++ b/src/systemd-proxy.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2011 Matthias Clasen
+ *
+ * Licensed under the GNU General Public License Version 2
+ *
+ * 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
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef __SYSTEMD_PROXY_H__
+#define __SYSTEMD_PROXY_H__
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _SystemdProxy SystemdProxy;
+
+SystemdProxy *systemd_proxy_new (void);
+void          systemd_proxy_free (SystemdProxy *proxy);
+gboolean      systemd_proxy_can_restart (SystemdProxy  *proxy,
+                                         gboolean      *can_restart,
+                                         GError       **error);
+gboolean      systemd_proxy_restart     (SystemdProxy  *proxy,
+                                         GError       **error);
+
+G_END_DECLS
+
+#endif  /* __SYSTEMD_PROXY_H__ */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]