[glib] application: Add dbus register/unregister hooks



commit 4979c1d075e08bcdc7a6569afae2052dac5eea81
Author: Christian Persch <chpe gnome org>
Date:   Sat May 5 16:52:28 2012 +0200

    application: Add dbus register/unregister hooks
    
    When the application is using its D-Bus backend, it is useful to be able
    to export extra D-Bus objects at the right time, i.e. *before* the application
    tries to own the bus name. This is accomplished here by adding a hook
    in GApplicationClass for this; and a corresponding hook that will be called
    on unregistration to undo whatever the register hook did.
    
    Bug #675509.

 gio/gapplication.c                         |   36 ++++++++++
 gio/gapplication.h                         |   10 +++-
 gio/gapplicationimpl-dbus.c                |   15 ++++-
 gio/tests/Makefile.am                      |    4 +
 gio/tests/gapplication-example-dbushooks.c |   99 ++++++++++++++++++++++++++++
 5 files changed, 162 insertions(+), 2 deletions(-)
---
diff --git a/gio/gapplication.c b/gio/gapplication.c
index 32341cf..1172a59 100644
--- a/gio/gapplication.c
+++ b/gio/gapplication.c
@@ -159,6 +159,14 @@
  * </xi:include>
  * </programlisting>
  * </example>
+ *
+ * <example id="gapplication-example-dbushooks"><title>Using extra D-Bus hooks with a GApplication</title>
+ * <programlisting>
+ * <xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; parse="text" href="../../../../gio/tests/gapplication-example-dbushooks.c">
+ *   <xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback>
+ * </xi:include>
+ * </programlisting>
+ * </example>
  */
 
 /**
@@ -190,6 +198,16 @@
  *     g_application_run() if the use-count is non-zero. Since 2.32,
  *     GApplication is iterating the main context directly and is not
  *     using @run_mainloop anymore
+ * @dbus_register: invoked locally during registration, if the application is
+ *     using its D-Bus backend. You can use this to export extra objects on the
+ *     bus, that need to exist before the application tries to own the bus name.
+ *     The function is passed the #GDBusConnection to to session bus, and the
+ *     object path that #GApplication will use to export is D-Bus API.
+ *     If this function returns %TRUE, registration will proceed; otherwise
+ *     registration will abort. Since: 2.34
+ * @dbus_unregister: invoked locally during unregistration, if the application
+ *     is using its D-Bus backend. Use this to undo anything done by the
+ *     @dbus_register vfunc. Since: 2.34
  *
  * Virtual function table for #GApplication.
  *
@@ -506,6 +524,22 @@ g_application_real_add_platform_data (GApplication    *application,
 {
 }
 
+static gboolean
+g_application_real_dbus_register (GApplication    *application,
+                                  GDBusConnection *connection,
+                                  const gchar     *object_path,
+                                  GError         **error)
+{
+  return TRUE;
+}
+
+static void
+g_application_real_dbus_unregister (GApplication    *application,
+                                    GDBusConnection *connection,
+                                    const gchar     *object_path)
+{
+}
+
 /* GObject implementation stuff {{{1 */
 static void
 g_application_set_property (GObject      *object,
@@ -682,6 +716,8 @@ g_application_class_init (GApplicationClass *class)
   class->command_line = g_application_real_command_line;
   class->local_command_line = g_application_real_local_command_line;
   class->add_platform_data = g_application_real_add_platform_data;
+  class->dbus_register = g_application_real_dbus_register;
+  class->dbus_unregister = g_application_real_dbus_unregister;
 
   g_object_class_install_property (object_class, PROP_APPLICATION_ID,
     g_param_spec_string ("application-id",
diff --git a/gio/gapplication.h b/gio/gapplication.h
index f5d912f..087682e 100644
--- a/gio/gapplication.h
+++ b/gio/gapplication.h
@@ -90,8 +90,16 @@ struct _GApplicationClass
   void                      (* run_mainloop)        (GApplication              *application);
   void                      (* shutdown)            (GApplication              *application);
 
+  gboolean                  (* dbus_register)       (GApplication              *application,
+                                                     GDBusConnection           *connection,
+                                                     const gchar               *object_path,
+                                                     GError                   **error);
+  void                      (* dbus_unregister)     (GApplication              *application,
+                                                     GDBusConnection           *connection,
+                                                     const gchar               *object_path);
+
   /*< private >*/
-  gpointer padding[11];
+  gpointer padding[9];
 };
 
 GType                   g_application_get_type                          (void) G_GNUC_CONST;
diff --git a/gio/gapplicationimpl-dbus.c b/gio/gapplicationimpl-dbus.c
index df3f103..1248d0f 100644
--- a/gio/gapplicationimpl-dbus.c
+++ b/gio/gapplicationimpl-dbus.c
@@ -97,7 +97,7 @@ struct _GApplicationImpl
 
   gboolean         properties_live;
   gboolean         primary;
-  gpointer         app;
+  GApplication    *app;
 };
 
 
@@ -228,6 +228,7 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
   const static GDBusInterfaceVTable vtable = {
     g_application_impl_method_call,
   };
+  GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
   GVariant *reply;
   guint32 rval;
 
@@ -271,6 +272,12 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
   if (impl->actions_id == 0)
     return FALSE;
 
+  if (!app_class->dbus_register (impl->app,
+                                 impl->session_bus,
+                                 impl->object_path,
+                                 error))
+    return FALSE;
+
   if (impl->bus_name == NULL)
     {
       /* If this is a non-unique application then it is sufficient to
@@ -315,6 +322,12 @@ g_application_impl_attempt_primary (GApplicationImpl  *impl,
 static void
 g_application_impl_stop_primary (GApplicationImpl *impl)
 {
+  GApplicationClass *app_class = G_APPLICATION_GET_CLASS (impl->app);
+
+  app_class->dbus_unregister (impl->app,
+                              impl->session_bus,
+                              impl->object_path);
+
   if (impl->object_id)
     {
       g_dbus_connection_unregister_object (impl->session_bus, impl->object_id);
diff --git a/gio/tests/Makefile.am b/gio/tests/Makefile.am
index c5cf59d..14411e2 100644
--- a/gio/tests/Makefile.am
+++ b/gio/tests/Makefile.am
@@ -120,6 +120,7 @@ SAMPLE_PROGS = 				\
 	gapplication-example-cmdline2	\
 	gapplication-example-cmdline3	\
 	gapplication-example-actions	\
+	gapplication-example-dbushooks	\
 	gdbus-daemon			\
 	$(NULL)
 
@@ -451,6 +452,9 @@ gapplication_example_cmdline3_LDADD   = $(progs_ldadd)
 gapplication_example_actions_SOURCES = gapplication-example-actions.c
 gapplication_example_actions_LDADD   = $(progs_ldadd)
 
+gapplication_example_dbushooks_SOURCES = gapplication-example-dbushooks.c
+gapplication_example_dbushooks_LDADD   = $(progs_ldadd)
+
 gmenumodel_SOURCES = gmenumodel.c gdbus-sessionbus.h gdbus-sessionbus.c
 gmenumodel_LDADD = $(progs_ldadd)
 
diff --git a/gio/tests/gapplication-example-dbushooks.c b/gio/tests/gapplication-example-dbushooks.c
new file mode 100644
index 0000000..ab33f46
--- /dev/null
+++ b/gio/tests/gapplication-example-dbushooks.c
@@ -0,0 +1,99 @@
+#include <gio/gio.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void
+activate (GApplication *application)
+{
+  g_print ("activated\n");
+
+  /* Note: when doing a longer-lasting action here that returns
+   * to the mainloop, you should use g_application_hold() and
+   * g_application_release() to keep the application alive until
+   * the action is completed.
+   */
+}
+
+typedef GApplication TestApplication;
+typedef GApplicationClass TestApplicationClass;
+
+static GType test_application_get_type (void);
+G_DEFINE_TYPE (TestApplication, test_application, G_TYPE_APPLICATION)
+
+static gboolean
+test_application_dbus_register (GApplication    *application,
+                                GDBusConnection *connection,
+                                const gchar     *object_path,
+                                GError         **error)
+{
+  /* We must chain up to the parent class */
+  if (!G_APPLICATION_CLASS (test_application_parent_class)->dbus_register (application,
+                                                                           connection,
+                                                                           object_path,
+                                                                           error))
+    return FALSE;
+
+  /* Now we can do our own stuff here. For example, we could export some D-Bus objects */
+  return TRUE;
+}
+
+static void
+test_application_dbus_unregister (GApplication    *application,
+                                  GDBusConnection *connection,
+                                  const gchar     *object_path)
+{
+  /* Do our own stuff here, e.g. unexport any D-Bus objects we exported in the dbus_register
+   * hook above. Be sure to check that we actually did export them, since the hook
+   * above might have returned early due to the parent class' hook returning FALSE!
+   */
+
+  /* Lastly, we must chain up to the parent class */
+  G_APPLICATION_CLASS (test_application_parent_class)->dbus_unregister (application,
+                                                                        connection,
+                                                                        object_path);
+}
+
+static void
+test_application_init (TestApplication *app)
+{
+}
+
+static void
+test_application_class_init (TestApplicationClass *class)
+{
+  GApplicationClass *g_application_class = G_APPLICATION_CLASS (class);
+
+  g_application_class->dbus_register = test_application_dbus_register;
+  g_application_class->dbus_unregister = test_application_dbus_unregister;
+}
+
+static GApplication *
+test_application_new (const gchar       *application_id,
+                      GApplicationFlags  flags)
+{
+  g_return_val_if_fail (g_application_id_is_valid (application_id), NULL);
+
+  g_type_init ();
+
+  return g_object_new (test_application_get_type (),
+                       "application-id", application_id,
+                       "flags", flags,
+                       NULL);
+}
+
+int
+main (int argc, char **argv)
+{
+  GApplication *app;
+  int status;
+
+  app = test_application_new ("org.gtk.TestApplication", 0);
+  g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
+  g_application_set_inactivity_timeout (app, 10000);
+
+  status = g_application_run (app, argc, argv);
+
+  g_object_unref (app);
+
+  return status;
+}



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