Blob Blame History Raw
## Description: Add gnome session restart support to ensure we always have
##              a authentication agent running
## Author: Michael Vogt <mvo@ubuntu.com>
## Origin: inspired by the at-spi dbus support code
## Bug: http://launchpad.net/bugs/623819
Index: policykit-1-gnome-0.105/src/main.c
===================================================================
--- policykit-1-gnome-0.105.orig/src/main.c	2011-10-25 11:30:59.000000000 -0400
+++ policykit-1-gnome-0.105/src/main.c	2011-12-19 09:23:47.635697248 -0500
@@ -38,11 +38,150 @@
 
 static GDBusConnection *session_bus_connection = NULL;
 
+// session management support for auto-restart
+#define SM_DBUS_NAME      "org.gnome.SessionManager"
+#define SM_DBUS_PATH      "/org/gnome/SessionManager"
+#define SM_DBUS_INTERFACE "org.gnome.SessionManager"
+#define SM_CLIENT_DBUS_INTERFACE "org.gnome.SessionManager.ClientPrivate"
+
+static GDBusProxy      *sm_proxy;
+static GDBusProxy      *client_proxy = NULL;
+
+static  GMainLoop *loop;
+
+
+static void
+stop_cb (void)
+{
+        g_main_loop_quit (loop);
+}
+
+static gboolean
+end_session_response (gboolean is_okay, const gchar *reason)
+{
+        GVariant *res;
+        GError *error = NULL;
+
+        res = g_dbus_proxy_call_sync (client_proxy,
+                                      "EndSessionResponse",
+                                      g_variant_new ("(bs)",
+                                                     is_okay,
+                                                     reason),
+                                      G_DBUS_CALL_FLAGS_NONE,
+                                      -1, /* timeout */
+                                      NULL, /* GCancellable */
+                                      &error);
+        if (! res) {
+                g_warning ("Failed to call EndSessionResponse: %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        g_variant_unref (res);
+        return TRUE;
+}
+
+static void
+query_end_session_cb (void)
+{
+        end_session_response (TRUE, "");
+}
+
+static void
+end_session_cb (void)
+{
+        end_session_response (TRUE, "");
+        g_main_loop_quit (loop);
+}
+
+static void
+signal_cb (GDBusProxy *proxy, gchar *sender_name, gchar *signal_name,
+           GVariant *parameters, gpointer user_data)
+{
+        if (strcmp (signal_name, "Stop") == 0) {
+                stop_cb ();
+        } else if (strcmp (signal_name, "QueryEndSession") == 0) {
+                query_end_session_cb ();
+        } else if (strcmp (signal_name, "EndSession") == 0) {
+                end_session_cb ();
+        }
+}
+
+static gboolean
+register_client_to_gnome_session (void)
+{
+        GError     *error = NULL;
+        GVariant   *res;
+        const char *startup_id;
+        const char *app_id;
+        char       *client_id;
+
+        startup_id = g_getenv ("DESKTOP_AUTOSTART_ID");
+        app_id = "polkit-gnome-authentication-agent-1.desktop";
+
+        sm_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                  G_DBUS_PROXY_FLAGS_NONE,
+                                                  NULL, /* GDBusInterfaceInfo */
+                                                  SM_DBUS_NAME,
+                                                  SM_DBUS_PATH,
+                                                  SM_DBUS_INTERFACE,
+                                                  NULL, /* GCancellable */
+                                                  &error);
+        if (sm_proxy == NULL) {
+                g_message("Failed to get session manager: %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        res = g_dbus_proxy_call_sync (sm_proxy,
+                                      "RegisterClient",
+                                      g_variant_new ("(ss)",
+                                                     app_id,
+                                                     startup_id),
+                                      G_DBUS_CALL_FLAGS_NONE,
+                                      -1, /* timeout */
+                                      NULL, /* GCancellable */
+                                      &error);
+        if (! res) {
+                g_warning ("Failed to register client: %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        if (! g_variant_is_of_type (res, G_VARIANT_TYPE ("(o)"))) {
+                g_warning ("RegisterClient returned unexpected type %s",
+                           g_variant_get_type_string (res));
+                return FALSE;
+        }
+
+        g_variant_get (res, "(&o)", &client_id);
+
+        // implement the signals to fix "policykit agent not responding"
+        // error (LP: #623819)
+        client_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                      G_DBUS_PROXY_FLAGS_NONE,
+                                                      NULL, /* GDBusInterfaceInfo */
+                                                      SM_DBUS_NAME,
+                                                      client_id,
+                                                      SM_CLIENT_DBUS_INTERFACE,
+                                                      NULL, /* GCancellable */
+                                                      &error);
+        g_variant_unref (res);
+        if (client_proxy == NULL) {
+                g_message("Failed to get client proxy: %s", error->message);
+                g_error_free (error);
+                return FALSE;
+        }
+
+        g_signal_connect (client_proxy, "g-signal", G_CALLBACK (signal_cb), NULL);
+
+        return TRUE;
+}
+
 int
 main (int argc, char **argv)
 {
   gint ret;
-  GMainLoop *loop;
   PolkitAgentListener *listener;
   GError *error;
 
@@ -101,6 +240,8 @@
    */
   session_bus_connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
 
+  register_client_to_gnome_session();
+
   g_main_loop_run (loop);
 
   ret = 0;