[glib/gdbus: 1/6] Initial commit of GDBus work



commit 005257dc4e433408b2b734b630cbb5ab78f0325b
Author: David Zeuthen <davidz redhat com>
Date:   Mon Apr 20 01:01:11 2009 -0400

    Initial commit of GDBus work
---
 Makefile.am                             |    2 +-
 configure.in                            |   16 +-
 docs/reference/Makefile.am              |    2 +-
 docs/reference/gdbus/Makefile.am        |   72 ++
 docs/reference/gdbus/gdbus-docs.xml     |   42 +
 docs/reference/gdbus/gdbus-sections.txt |   70 ++
 docs/reference/gdbus/gdbus.types        |    5 +
 docs/reference/gdbus/version.xml.in     |    1 +
 gdbus-2.0-uninstalled.pc.in             |    6 +
 gdbus-2.0.pc.in                         |   11 +
 gdbus/Makefile.am                       |  195 +++++
 gdbus/abicheck.sh                       |   13 +
 gdbus/example-gbusnameowner.c           |   90 +++
 gdbus/gbusnameowner.c                   | 1244 +++++++++++++++++++++++++++++++
 gdbus/gbusnameowner.h                   |  114 +++
 gdbus/gdbus-marshal.list                |    1 +
 gdbus/gdbus.h                           |   37 +
 gdbus/gdbus.symbols                     |   73 ++
 gdbus/gdbusconnection.c                 |  964 ++++++++++++++++++++++++
 gdbus/gdbusconnection.h                 |  116 +++
 gdbus/gdbusenums.h                      |  225 ++++++
 gdbus/gdbusenumtypes.c.template         |   42 +
 gdbus/gdbusenumtypes.h.template         |   24 +
 gdbus/gdbuserror.c                      |  507 +++++++++++++
 gdbus/gdbuserror.h                      |   80 ++
 gdbus/gdbusmainloop.c                   |  782 +++++++++++++++++++
 gdbus/gdbusmainloop.h                   |   45 ++
 gdbus/gdbusprivate.c                    |   37 +
 gdbus/gdbusprivate.h                    |   38 +
 gdbus/gdbustypes.h                      |   39 +
 gdbus/makegdbusalias.pl                 |  137 ++++
 gdbus/pltcheck.sh                       |   19 +
 gdbus/tests/Makefile.am                 |   30 +
 gdbus/tests/connection.c                |  904 ++++++++++++++++++++++
 34 files changed, 5980 insertions(+), 3 deletions(-)

diff --git a/Makefile.am b/Makefile.am
index 8973778..966d5c1 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,7 +3,7 @@ include $(top_srcdir)/Makefile.decl
 
 AUTOMAKE_OPTIONS = 1.7
 
-SUBDIRS = . m4macros glib gmodule gthread gobject gio tests po docs
+SUBDIRS = . m4macros glib gmodule gthread gobject gio gdbus tests po docs
 DIST_SUBDIRS = $(SUBDIRS) build
 
 bin_SCRIPTS = glib-gettextize
diff --git a/configure.in b/configure.in
index 514fd75..77ee58d 100644
--- a/configure.in
+++ b/configure.in
@@ -10,7 +10,7 @@ m4_define(glib_configure_in)
 
 #
 # The following version number definitions apply to GLib, GModule, GObject,
-# GThread and GIO as a whole, so if changes occurred in any of them, they are
+# GThread, GIO and GDBus as a whole, so if changes occurred in any of them, they are
 # all treated with the same interface and binary age.
 #
 # Making releases:
@@ -2631,6 +2631,14 @@ fi
 
 AM_CONDITIONAL(ENABLE_MAN, test x$enable_man != xno)
 
+dnl *************************
+dnl *** Checks for dbus-1 ***
+dnl *************************
+
+PKG_CHECK_MODULES(DBUS, dbus-1)
+AC_SUBST(DBUS_CFLAGS)
+AC_SUBST(DBUS_LIBS)
+
 dnl ******************************
 dnl *** output the whole stuff ***
 dnl ******************************
@@ -3333,6 +3341,8 @@ gio-2.0.pc
 gio-unix-2.0.pc
 gio-2.0-uninstalled.pc
 gio-unix-2.0-uninstalled.pc
+gdbus-2.0.pc
+gdbus-2.0-uninstalled.pc
 glib-zip
 glib-gettextize
 Makefile
@@ -3360,6 +3370,8 @@ gio/fen/Makefile
 gio/fam/Makefile
 gio/win32/Makefile
 gio/tests/Makefile
+gdbus/Makefile
+gdbus/tests/Makefile
 po/Makefile.in
 docs/Makefile
 docs/reference/Makefile
@@ -3369,6 +3381,8 @@ docs/reference/gobject/Makefile
 docs/reference/gobject/version.xml
 docs/reference/gio/Makefile
 docs/reference/gio/version.xml
+docs/reference/gdbus/Makefile
+docs/reference/gdbus/version.xml
 tests/Makefile
 tests/gobject/Makefile
 tests/refcount/Makefile
diff --git a/docs/reference/Makefile.am b/docs/reference/Makefile.am
index 63cf90d..b815cb5 100644
--- a/docs/reference/Makefile.am
+++ b/docs/reference/Makefile.am
@@ -1,3 +1,3 @@
 include $(top_srcdir)/Makefile.decl
 
-SUBDIRS = glib gobject gio
+SUBDIRS = glib gobject gio gdbus
diff --git a/docs/reference/gdbus/Makefile.am b/docs/reference/gdbus/Makefile.am
new file mode 100644
index 0000000..f9e3086
--- /dev/null
+++ b/docs/reference/gdbus/Makefile.am
@@ -0,0 +1,72 @@
+include $(top_srcdir)/Makefile.decl
+NULL =
+
+# The name of the module.
+DOC_MODULE=gdbus
+
+# The top-level SGML file.
+DOC_MAIN_SGML_FILE=gdbus-docs.xml
+
+# Extra options to supply to gtkdoc-scan
+SCAN_OPTIONS=--deprecated-guards="G_DISABLE_DEPRECATED"
+
+#SCAN_OPTIONS+=--rebuild-sections
+
+# The directory containing the source code. Relative to $(srcdir)
+DOC_SOURCE_DIR=$(top_srcdir)/gdbus
+
+HFILE_GLOB=$(top_srcdir)/gdbus/*.h
+CFILE_GLOB=$(top_srcdir)/gdbus/*.c
+
+# Headers to ignore
+IGNORE_HFILES=				\
+        gdbus-marshal.h			\
+        gdbus.h				\
+        gdbusalias.h			\
+        gdbusalias.h			\
+        gdbusenumtypes.h		\
+        giomodule-priv.h		\
+        $(NULL)
+
+# CFLAGS and LDFLAGS for compiling scan program. Only needed
+# if $(DOC_MODULE).types is non-empty.
+INCLUDES = \
+        -I$(srcdir)                     \
+        -I$(top_srcdir)                 \
+        -I$(top_srcdir)/glib            \
+        -I$(top_srcdir)/gobject		\
+        -I$(top_builddir)               \
+        -I$(top_builddir)/glib          \
+        -I$(top_builddir)/gobject	\
+        $(GLIB_DEBUG_FLAGS)
+
+GTKDOC_LIBS = \
+        $(top_builddir)/glib/libglib-2.0.la		\
+        $(top_builddir)/gobject/libgobject-2.0.la	\
+        $(top_builddir)/gmodule/libgmodule-2.0.la	\
+        $(top_builddir)/gio/libgio-2.0.la		\
+        $(top_builddir)/gdbus/libgdbus-2.0.la		\
+        $(NULL)
+
+# Extra options to supply to gtkdoc-mkdb
+MKDB_OPTIONS = --output-format=xml --sgml-mode --name-space=g
+
+# Images to copy into HTML directory
+HTML_IMAGES =			\
+        $(NULL)
+
+content_files =                 \
+        version.xml		\
+        $(NULL)
+
+expand_content_files =		\
+        $(NULL)
+
+extra_files =                   \
+        version.xml.in		\
+        $(NULL)
+
+include $(top_srcdir)/gtk-doc.make
+
+EXTRA_DIST +=				\
+        version.xml.in
diff --git a/docs/reference/gdbus/gdbus-docs.xml b/docs/reference/gdbus/gdbus-docs.xml
new file mode 100644
index 0000000..3747302
--- /dev/null
+++ b/docs/reference/gdbus/gdbus-docs.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
+               "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd"; [
+<!ENTITY version SYSTEM "version.xml">
+]>
+<book lang="en" id="gdbus" xmlns:xi="http://www.w3.org/2003/XInclude";>
+<title>GDBus Reference Manual</title>
+  <bookinfo>
+    <title>GDBus Reference Manual</title>
+    <releaseinfo>
+      for GDBus &version;
+      The latest version of this documentation can be found on-line at
+      <ulink role="online-location" url="http://library.gnome.org/devel/gdbus/unstable/";>http://library.gnome.org/devel/gdbus/unstable/</ulink>.
+    </releaseinfo>
+  </bookinfo>
+
+  <part>
+  <title>API Reference</title>
+    <chapter id="lowlevel">
+        <title>Low-level GDBus</title>
+        <xi:include href="xml/gdbusmainloop.xml"/>
+        <xi:include href="xml/gdbuserror.xml"/>
+        <xi:include href="xml/gdbusconnection.xml"/>
+    </chapter>
+    <chapter id="convenience">
+        <title>GDBus Convenience</title>
+        <xi:include href="xml/gbusnameowner.xml"/>
+    </chapter>
+    <chapter id="cmapping">
+        <title>C Object Mapping</title>
+    </chapter>
+  </part>
+
+  <chapter id="gdbus-hierarchy">
+    <title>Object Hierarchy</title>
+      <xi:include href="xml/tree_index.sgml"/>
+  </chapter>
+
+  <index>
+    <title id="index-all">Index</title>
+  </index>
+</book>
diff --git a/docs/reference/gdbus/gdbus-sections.txt b/docs/reference/gdbus/gdbus-sections.txt
new file mode 100644
index 0000000..2640590
--- /dev/null
+++ b/docs/reference/gdbus/gdbus-sections.txt
@@ -0,0 +1,70 @@
+<SECTION>
+<FILE>gbusnameowner</FILE>
+<TITLE>GBusNameOwner</TITLE>
+GBusNameOwnerFlags
+GBusNameOwner
+GBusNameOwnerClass
+g_bus_name_owner_new
+g_bus_name_owner_new_finish
+g_bus_name_owner_new_for_connection
+g_bus_name_owner_new_for_connection_finish
+g_bus_name_owner_get_owns_name
+g_bus_name_owner_get_name
+g_bus_name_owner_get_flags
+g_bus_name_owner_get_connection
+<SUBSECTION Standard>
+G_BUS_NAME_OWNER
+G_IS_BUS_NAME_OWNER
+G_TYPE_BUS_NAME_OWNER
+g_bus_name_owner_get_type
+G_BUS_NAME_OWNER_CLASS
+G_IS_BUS_NAME_OWNER_CLASS
+G_BUS_NAME_OWNER_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdbusconnection</FILE>
+<TITLE>GDBusConnection</TITLE>
+GMessageBusType
+GDBusConnection
+GDBusConnectionClass
+g_dbus_connection_bus_get
+g_dbus_connection_bus_get_finish
+g_dbus_connection_bus_get_private
+g_dbus_connection_bus_get_private_finish
+g_dbus_connection_get_exit_on_close
+g_dbus_connection_set_exit_on_close
+g_dbus_connection_get_unique_name
+g_dbus_connection_get_is_open
+g_dbus_connection_get_bus_type
+g_dbus_connection_get_dbus_1_connection
+<SUBSECTION Standard>
+G_DBUS_CONNECTION
+G_IS_DBUS_CONNECTION
+G_TYPE_DBUS_CONNECTION
+g_dbus_connection_get_type
+G_DBUS_CONNECTION_CLASS
+G_IS_DBUS_CONNECTION_CLASS
+G_DBUS_CONNECTION_GET_CLASS
+</SECTION>
+
+<SECTION>
+<FILE>gdbusmainloop</FILE>
+g_dbus_integrate_dbus_1_connection
+g_dbus_unintegrate_dbus_1_connection
+g_dbus_integrate_dbus_1_server
+g_dbus_unintegrate_dbus_1_server
+</SECTION>
+
+<SECTION>
+<FILE>gdbuserror</FILE>
+G_DBUS_ERROR
+GDBusError
+g_dbus_error_get_remote_exception
+g_dbus_error_new_for_dbus_error
+g_dbus_error_new_for_dbus_error_valist
+g_dbus_error_set_dbus_error
+g_dbus_error_set_dbus_error_valist
+g_dbus_error_new_for_gerror
+</SECTION>
+
diff --git a/docs/reference/gdbus/gdbus.types b/docs/reference/gdbus/gdbus.types
new file mode 100644
index 0000000..778d932
--- /dev/null
+++ b/docs/reference/gdbus/gdbus.types
@@ -0,0 +1,5 @@
+g_dbus_connection_get_type
+g_bus_name_owner_get_type
+g_message_bus_type_get_type
+g_bus_name_owner_flags_get_type
+g_dbus_error_get_type
diff --git a/docs/reference/gdbus/version.xml.in b/docs/reference/gdbus/version.xml.in
new file mode 100644
index 0000000..d78bda9
--- /dev/null
+++ b/docs/reference/gdbus/version.xml.in
@@ -0,0 +1 @@
+ VERSION@
diff --git a/gdbus-2.0-uninstalled.pc.in b/gdbus-2.0-uninstalled.pc.in
new file mode 100644
index 0000000..636a4a7
--- /dev/null
+++ b/gdbus-2.0-uninstalled.pc.in
@@ -0,0 +1,6 @@
+Name: GDBus Uninstalled
+Description: gdbus library, Not Installed
+Version: @VERSION@
+Requires: glib-2.0-uninstalled,gobject-2.0-uninstalled,gio-2.0-uninstalled,gmodule-no-export-2.0-uninstalled
+Libs: ${pc_top_builddir}/${pcfiledir}/gdbus/libgdbus-2.0.la
+Cflags: -I${pc_top_builddir}/${pcfiledir}/@srcdir@
diff --git a/gdbus-2.0.pc.in b/gdbus-2.0.pc.in
new file mode 100644
index 0000000..afd3470
--- /dev/null
+++ b/gdbus-2.0.pc.in
@@ -0,0 +1,11 @@
+prefix= prefix@
+exec_prefix= exec_prefix@
+libdir= libdir@
+includedir= includedir@
+
+Name: GDBus
+Description: glib D-Bus library
+Version: @VERSION@
+Requires: glib-2.0,gobject-2.0,gio-2.0,gmodule-no-export-2.0
+Libs: -L${libdir} -lgdbus-2.0
+Cflags: 
diff --git a/gdbus/Makefile.am b/gdbus/Makefile.am
new file mode 100644
index 0000000..466e059
--- /dev/null
+++ b/gdbus/Makefile.am
@@ -0,0 +1,195 @@
+include $(top_srcdir)/Makefile.decl
+
+NULL =
+
+SUBDIRS=tests
+
+if OS_WIN32_AND_DLL_COMPILATION
+if MS_LIB_AVAILABLE
+noinst_DATA = gdbus-2.0.lib
+
+install_ms_lib_cmd = $(INSTALL) gdbus-2.0.lib $(DESTDIR)$(libdir)
+uninstall_ms_lib_cmd = -rm $(DESTDIR)$(libdir)/gdbus-2.0.lib
+endif
+endif
+
+install-ms-lib:
+	$(install_ms_lib_cmd)
+
+uninstall-ms-lib:
+	$(uninstall_ms_lib_cmd)
+
+gdbus.def: gdbus.symbols
+	(echo -e EXPORTS; $(CPP) -P -DINCLUDE_VARIABLES -DINCLUDE_INTERNAL_SYMBOLS -DG_OS_WIN32 -DALL_FILES - <$(srcdir)/gdbus.symbols | sed -e '/^$$/d' -e 's/^/	/' -e 's/G_GNUC_[^ ]*//g' | sort) > gdbus.def.tmp && \
+	  mv gdbus.def.tmp gdbus.def
+
+gdbusalias.h: gdbus.symbols
+	$(PERL) $(srcdir)/makegdbusalias.pl < $(srcdir)/gdbus.symbols > gdbusalias.h.tmp && \
+	  mv gdbusalias.h.tmp gdbusalias.h
+
+gdbusaliasdef.c: gdbus.symbols
+	$(PERL) $(srcdir)/makegdbusalias.pl -def < $(srcdir)/gdbus.symbols > gdbusaliasdef.c.tmp && \
+	  mv gdbusaliasdef.c.tmp gdbusaliasdef.c
+
+if OS_LINUX
+if HAVE_GNUC_VISIBILITY
+TESTS = abicheck.sh pltcheck.sh
+endif
+endif
+
+AM_CPPFLAGS = \
+	-DG_LOG_DOMAIN=\"GLib-DBus\"			\
+	-I$(top_builddir)				\
+	-I$(top_srcdir)					\
+	-I$(top_srcdir)/glib				\
+	-I$(top_srcdir)/gio				\
+	-I$(top_srcdir)/gobject				\
+	-I$(top_srcdir)/gmodule				\
+	$(GLIB_DEBUG_FLAGS)				\
+	-DG_DISABLE_DEPRECATED				\
+	-DG_DBUS_COMPILATION				\
+	$(NULL)
+
+lib_LTLIBRARIES = libgdbus-2.0.la
+
+marshal_sources = \
+        gdbus-marshal.h	\
+        gdbus-marshal.c	\
+	$(NULL)
+
+if CROSS_COMPILING
+  glib_genmarshal=$(GLIB_GENMARSHAL)
+else
+  glib_genmarshal=../gobject/glib-genmarshal
+endif
+
+gdbus-marshal.h: gdbus-marshal.list
+	$(glib_genmarshal) --prefix=_gdbus_marshal $(srcdir)/gdbus-marshal.list --header --internal > $  tmp && \
+	  mv $  tmp $@
+
+gdbus-marshal.c: gdbus-marshal.h gdbus-marshal.list
+	(echo "#include \"gdbus-marshal.h\""; \
+	$(glib_genmarshal) --prefix=_gdbus_marshal $(srcdir)/gdbus-marshal.list --body --internal) > $  tmp && \
+	  mv $  tmp $@
+
+gdbus_headers =				\
+	gdbus.h				\
+	gdbusenums.h			\
+	gdbustypes.h			\
+	gdbuserror.h			\
+	gdbusmainloop.h			\
+	gdbusconnection.h		\
+	gbusnameowner.h			\
+	$(NULL)
+
+libgdbus_2_0_la_SOURCES =						\
+	gdbus.h								\
+	gdbustypes.h							\
+	gdbusenumtypes.h						\
+	gdbus-marshal.h 		gdbus-marshal.c 		\
+	gdbusenumtypes.h		gdbusenumtypes.c		\
+	gdbuserror.h			gdbuserror.c			\
+	gdbusmainloop.h			gdbusmainloop.c			\
+	gdbusconnection.h		gdbusconnection.c		\
+	gbusnameowner.h			gbusnameowner.c			\
+	gdbusprivate.h			gdbusprivate.c			\
+	gdbusalias.h 							\
+	gdbusaliasdef.c							\
+	$(NULL)
+
+$(libgdbus_2_0_la_OBJECTS): $(marshal_sources)
+
+libgdbus_2_0_la_CFLAGS = 	\
+	$(DBUS_CFLAGS)		\
+	$(NULL)
+
+libgdbus_2_0_la_LIBADD = \
+	$(top_builddir)/glib/libglib-2.0.la 		\
+	$(top_builddir)/gobject/libgobject-2.0.la 	\
+	$(top_builddir)/gio/libgio-2.0.la 		\
+	$(top_builddir)/gmodule/libgmodule-2.0.la 	\
+	$(GLIB_LIBS) 					\
+	$(DBUS_LIBS)					\
+	$(NULL)
+
+if PLATFORM_WIN32
+no_undefined = -no-undefined
+endif
+
+if OS_WIN32_AND_DLL_COMPILATION
+export_symbols = -export-symbols gdbus.def
+gdbus_def = gdbus.def
+
+install-def-file:
+	$(INSTALL) gdbus.def $(DESTDIR)$(libdir)/gdbus-2.0.def
+
+uninstall-def-file:
+	-rm $(DESTDIR)$(libdir)/gdbus-2.0.def
+else
+install-def-file:
+uninstall-def-file:
+
+export_symbols = -export-symbols-regex '^g_.*'
+endif
+
+install-data-local: install-ms-lib install-def-file
+
+uninstall-local: uninstall-ms-lib uninstall-def-file
+
+libgdbus_2_0_la_LDFLAGS = \
+	-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) \
+	-export-dynamic $(no_undefined) $(export_symbols)
+
+libgdbus_2_0_la_DEPENDENCIES = $(gdbus_def)
+
+gdbusincludedir=$(includedir)/glib-2.0/gdbus/
+gdbusinclude_HEADERS = 			\
+	$(gdbus_headers)		\
+	gdbusenumtypes.h
+
+# these sources (also mentioned above) are generated.
+BUILT_SOURCES = 			\
+	gdbus-marshal.h 		\
+	gdbus-marshal.c 		\
+	gdbusalias.h 			\
+	gdbusaliasdef.c			\
+	gdbusenumtypes.h		\
+	gdbusenumtypes.c		\
+	$(NULL)
+
+EXTRA_DIST += 				\
+	gdbus-marshal.list		\
+	gdbus.symbols			\
+	gdbusenumtypes.h.template	\
+	gdbusenumtypes.c.template	\
+	makegdbusalias.pl		\
+	abicheck.sh			\
+	pltcheck.sh			\
+	$(NULL)
+
+CLEANFILES = 			\
+	$(marshal_sources)	\
+	$(NULL)
+
+gdbusenumtypes.h: $(gdbus_headers) gdbusenumtypes.h.template Makefile.am
+	( top_builddir=`cd $(top_builddir) && pwd`; \
+	  cd $(srcdir) && $$top_builddir/gobject/glib-mkenums --template gdbusenumtypes.h.template $(gdbus_headers) ) > \
+	    gdbusenumtypes.h.tmp && \
+	    mv gdbusenumtypes.h.tmp gdbusenumtypes.h
+
+gdbusenumtypes.c: $(gdbus_headers) gdbusenumtypes.c.template Makefile.am
+	( top_builddir=`cd $(top_builddir) && pwd`; \
+	  cd $(srcdir) && $$top_builddir/gobject/glib-mkenums --template gdbusenumtypes.c.template $(gdbus_headers) ) > \
+	    gdbusenumtypes.c.tmp && mv gdbusenumtypes.c.tmp gdbusenumtypes.c
+
+gdbus-2.0.lib: libgdbus-2.0.la gdbus.def
+	lib -machine:@LIB_EXE_MACHINE_FLAG@ -name:libgdbus-2.0-$(LT_CURRENT_MINUS_AGE).dll -def:gdbus.def -out:$@
+
+noinst_PROGRAMS = example-gbusnameowner
+
+example_gbusnameowner_SOURCES = example-gbusnameowner.c
+example_gbusnameowner_CFLAGS = $(DBUS_CFLAGS)
+example_gbusnameowner_LDADD = libgdbus-2.0.la
+
+clean-local :
+	rm -f *~
diff --git a/gdbus/abicheck.sh b/gdbus/abicheck.sh
new file mode 100755
index 0000000..61bd1b5
--- /dev/null
+++ b/gdbus/abicheck.sh
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+egrep '^#([^i]|if).*[^\]$' "${top_builddir:-..}/glibconfig.h" > glibconfig.cpp
+
+INCLUDES="-include ${top_builddir:-..}/config.h"
+INCLUDES="$INCLUDES -include glibconfig.cpp"
+
+cpp -DINCLUDE_VARIABLES -P $INCLUDES -DALL_FILES ${srcdir:-.}/gdbus.symbols | sed -e '/^$/d' -e 's/ G_GNUC.*$//' -e 's/ PRIVATE$//' | sort > expected-abi
+rm glibconfig.cpp
+
+nm -D -g --defined-only .libs/libgdbus-2.0.so | cut -d ' ' -f 3 | sort > actual-abi
+
+diff -u expected-abi actual-abi && rm expected-abi actual-abi
diff --git a/gdbus/example-gbusnameowner.c b/gdbus/example-gbusnameowner.c
new file mode 100644
index 0000000..05d4ee3
--- /dev/null
+++ b/gdbus/example-gbusnameowner.c
@@ -0,0 +1,90 @@
+
+#include <gdbus/gdbus.h>
+
+static void
+on_name_acquired (GBusNameOwner *owner,
+                  gpointer       user_data)
+{
+  g_debug ("Name acquired");
+}
+
+static void
+on_name_lost (GBusNameOwner *owner,
+              gpointer       user_data)
+{
+  g_debug ("Name lost");
+}
+
+static void
+name_owner_cb (GBusNameOwner *owner,
+               GAsyncResult  *res,
+               gpointer       user_data)
+{
+  GError *error;
+
+  error = NULL;
+  if (!g_bus_name_owner_new_finish (owner,
+                                    res,
+                                    NULL)) {
+    g_debug ("Failed to acquire name. Waiting in line.");
+  }
+}
+
+int
+main (int argc, char *argv[])
+{
+  GBusNameOwner *owner;
+  GBusNameOwnerFlags flags;
+  GMainLoop *loop;
+  GError *error;
+  GOptionContext *option_context;
+  gboolean opt_allow_replacement;
+  gboolean opt_replace;
+  GOptionEntry option_entries[] = {
+    { "allow-replacement", 'a', 0, G_OPTION_ARG_NONE, &opt_allow_replacement, "Allow replacement", NULL},
+    { "replace", 'r', 0, G_OPTION_ARG_NONE, &opt_replace, "Replace", NULL},
+    { NULL }
+  };
+
+  g_type_init ();
+
+  error = NULL;
+  option_context = g_option_context_new ("GBusNameOwner example");
+  g_option_context_add_main_entries (option_context,
+                                     option_entries,
+                                     NULL);
+  if (!g_option_context_parse (option_context,
+                               &argc,
+                               &argv,
+                               &error))
+    {
+      g_option_context_free (option_context);
+      g_printerr ("Failed to parse options: %s", error->message);
+      g_error_free (error);
+      return 1;
+    }
+  g_option_context_free (option_context);
+
+  loop = g_main_loop_new (NULL, FALSE);
+
+  flags = 0;
+  if (opt_allow_replacement)
+    flags |= G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
+  if (opt_replace)
+    flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
+
+  owner = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                                "org.gtk.GDBus.ExampleName",
+                                flags,
+                                NULL,
+                                (GAsyncReadyCallback) name_owner_cb,
+                                NULL);
+  g_signal_connect (owner, "name-acquired", G_CALLBACK (on_name_acquired), NULL);
+  g_signal_connect (owner, "name-lost", G_CALLBACK (on_name_lost), NULL);
+  g_main_loop_run (loop);
+
+  g_object_unref (owner);
+  g_main_loop_unref (loop);
+
+  return 0;
+}
diff --git a/gdbus/gbusnameowner.c b/gdbus/gbusnameowner.c
new file mode 100644
index 0000000..c90f2ca
--- /dev/null
+++ b/gdbus/gbusnameowner.c
@@ -0,0 +1,1244 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+
+#include "gbusnameowner.h"
+#include "gdbusenumtypes.h"
+#include "gdbusconnection.h"
+#include "gdbuserror.h"
+#include "gdbusprivate.h"
+
+#include "gdbusalias.h"
+
+/**
+ * SECTION:gbusnameowner
+ * @short_description: Own a well-known name on a bus
+ * @include: gdbus/gdbus.h
+ *
+ * #GBusNameOwner is a utility class that makes it easy to implement
+ * D-Bus services. See g_bus_name_owner_new() for an example.
+ */
+
+struct _GBusNameOwnerPrivate
+{
+  gchar *name;
+  GBusNameOwnerFlags flags;
+
+  GDBusConnection *connection;
+
+  gboolean owns_name;
+
+  gboolean in_construction_phase;
+};
+
+enum
+{
+  PROP_0,
+  PROP_NAME,
+  PROP_FLAGS,
+  PROP_OWNS_NAME,
+  PROP_CONNECTION,
+};
+
+enum
+{
+  NAME_LOST_SIGNAL,
+  NAME_ACQUIRED_SIGNAL,
+  LAST_SIGNAL,
+};
+
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+                 DBusMessage    *message,
+                 void           *user_data);
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void bus_request_name (GDBusConnection       *connection,
+                              const gchar           *name,
+                              guint                  flags,
+                              GAsyncReadyCallback    callback,
+                              gpointer               user_data);
+static guint bus_request_name_finish (GDBusConnection  *bus,
+                                      GAsyncResult     *res,
+                                      GError          **error);
+
+static guint bus_release_name_sync (GDBusConnection       *connection,
+                                    const gchar           *name,
+                                    GError               **error);
+
+#if 0
+static void bus_release_name (GDBusConnection       *connection,
+                              const gchar           *name,
+                              GAsyncReadyCallback    callback,
+                              gpointer               user_data);
+static guint bus_release_name_finish (GDBusConnection  *bus,
+                                      GAsyncResult     *res,
+                                      GError          **error);
+#endif
+
+static void on_connection_opened (GDBusConnection *connection,
+                                  gpointer         user_data);
+
+static void on_connection_closed (GDBusConnection *connection,
+                                  gpointer         user_data);
+
+static guint get_request_name_flags (GBusNameOwnerFlags flags);
+
+G_DEFINE_TYPE (GBusNameOwner, g_bus_name_owner, G_TYPE_OBJECT);
+
+static void
+g_bus_name_owner_finalize (GObject *object)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (object);
+
+  if (owner->priv->connection != NULL)
+    {
+      /* release the name if we own it */
+      if (owner->priv->owns_name)
+        {
+          /* Gah, even though there's a ReleaseName() method in flight,
+           * we can't use RequestName() until it is processed.. This must
+           * be a bug in the message bus daemon.
+           *
+           * So do ReleaseName() synchronously for now.
+           */
+          GError *error;
+          guint reply;
+          error = NULL;
+          reply = bus_release_name_sync (owner->priv->connection,
+                                         owner->priv->name,
+                                         &error);
+          if (error != NULL)
+            {
+              g_warning ("Error doing ReleaseName(): %s", error->message);
+              g_error_free (error);
+            }
+          else if (reply != DBUS_RELEASE_NAME_REPLY_RELEASED)
+            {
+              g_warning ("Expected DBUS_RELEASE_NAME_REPLY_RELEASED but got %d", reply);
+            }
+        }
+
+      g_signal_handlers_disconnect_by_func (owner->priv->connection, on_connection_opened, owner);
+      g_signal_handlers_disconnect_by_func (owner->priv->connection, on_connection_closed, owner);
+
+      if (g_dbus_connection_get_is_open (owner->priv->connection))
+        {
+          dbus_connection_remove_filter (g_dbus_connection_get_dbus_1_connection (owner->priv->connection),
+                                         filter_function,
+                                         owner);
+        }
+
+      g_object_unref (owner->priv->connection);
+    }
+  g_free (owner->priv->name);
+
+  if (G_OBJECT_CLASS (g_bus_name_owner_parent_class)->finalize != NULL)
+    G_OBJECT_CLASS (g_bus_name_owner_parent_class)->finalize (object);
+}
+
+static void
+g_bus_name_owner_get_property (GObject    *object,
+                               guint       prop_id,
+                               GValue     *value,
+                               GParamSpec *pspec)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      g_value_set_string (value, g_bus_name_owner_get_name (owner));
+      break;
+
+    case PROP_FLAGS:
+      g_value_set_flags (value, g_bus_name_owner_get_flags (owner));
+      break;
+
+    case PROP_OWNS_NAME:
+      g_value_set_boolean (value, g_bus_name_owner_get_owns_name (owner));
+      break;
+
+    case PROP_CONNECTION:
+      g_value_set_object (value, g_bus_name_owner_get_connection (owner));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+g_bus_name_owner_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (object);
+
+  switch (prop_id)
+    {
+    case PROP_NAME:
+      owner->priv->name = g_value_dup_string (value);
+      break;
+
+    case PROP_FLAGS:
+      owner->priv->flags = g_value_get_flags (value);
+      break;
+
+    case PROP_CONNECTION:
+      owner->priv->connection = g_value_dup_object (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+#if 0
+static void
+request_name_cb (GMessageBusConnection *bus,
+                 GAsyncResult          *res,
+                 gpointer               user_data)
+{
+  GMessageBusRequestNameFlags reply;
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
+
+  reply = g_message_bus_connection_request_name_finish (bus,
+                                                        res,
+                                                        NULL);
+  if (reply == G_MESSAGE_BUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+    {
+      owner->priv->owns_name = TRUE;
+      g_object_notify (G_OBJECT (owner), "owns-name");
+      g_signal_emit (owner, signals[NAME_ACQUIRED_SIGNAL], 0);
+    }
+  else
+    {
+      //g_signal_emit (owner, signals[FAILED_TO_ACQUIRE_NAME_SIGNAL], 0);
+    }
+
+  g_object_unref (owner);
+}
+#endif
+
+#define PRINT_MESSAGE(message)                          \
+  do {                                                  \
+    const gchar *message_type;                          \
+    switch (dbus_message_get_type (message))            \
+      {                                                 \
+      case DBUS_MESSAGE_TYPE_METHOD_CALL:               \
+        message_type = "method_call";                   \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_METHOD_RETURN:             \
+        message_type = "method_return";                 \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_ERROR:                     \
+        message_type = "error";                         \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_SIGNAL:                    \
+        message_type = "signal";                        \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_INVALID:                   \
+        message_type = "invalid";                       \
+        break;                                          \
+      default:                                          \
+        message_type = "unknown";                       \
+        break;                                          \
+      }                                                 \
+    g_print ("new message:\n"                           \
+             " type:         %s\n"                      \
+             " sender:       %s\n"                      \
+             " destination:  %s\n"                      \
+             " path:         %s\n"                      \
+             " interface:    %s\n"                      \
+             " member:       %s\n",                     \
+             message_type,                              \
+             dbus_message_get_sender (message),         \
+             dbus_message_get_destination (message),    \
+             dbus_message_get_path (message),           \
+             dbus_message_get_interface (message),      \
+             dbus_message_get_member (message));        \
+  } while (FALSE)
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+                 DBusMessage    *message,
+                 void           *user_data)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
+  DBusError dbus_error;
+  const gchar *name;
+  gboolean old_owns_name;
+
+  g_debug ("in bus-name-owner's filter_function for dbus_1_connection %p", dbus_1_connection);
+  PRINT_MESSAGE (message);
+
+  dbus_error_init (&dbus_error);
+
+  old_owns_name = owner->priv->owns_name;
+
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_DBUS,
+                              "NameLost") &&
+      g_strcmp0 (dbus_message_get_sender (message), DBUS_SERVICE_DBUS) == 0 &&
+      g_strcmp0 (dbus_message_get_path (message), DBUS_PATH_DBUS) == 0)
+    {
+      if (dbus_message_get_args (message,
+                                 &dbus_error,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_INVALID))
+        {
+          if (g_strcmp0 (name, owner->priv->name) == 0)
+            {
+              owner->priv->owns_name = FALSE;
+              if (owner->priv->owns_name != old_owns_name)
+                {
+                  g_object_notify (G_OBJECT (owner), "owns-name");
+                  g_signal_emit (owner, signals[NAME_LOST_SIGNAL], 0);
+                }
+              else
+                {
+                  /* This is not unexpected.. it can happen when releasing a name only to claim it right again */
+                  /*g_warning ("Got unexpected NameLost signal for the name %s", owner->priv->name);*/
+                }
+            }
+        }
+      else
+        {
+          g_warning ("Error extracting name for NameLost signal: %s: %s", dbus_error.name, dbus_error.message);
+          dbus_error_free (&dbus_error);
+        }
+    }
+
+  else if (dbus_message_is_signal (message,
+                                   DBUS_INTERFACE_DBUS,
+                                   "NameAcquired") &&
+           g_strcmp0 (dbus_message_get_sender (message), DBUS_SERVICE_DBUS) == 0 &&
+           g_strcmp0 (dbus_message_get_path (message), DBUS_PATH_DBUS) == 0)
+    {
+      if (dbus_message_get_args (message,
+                                 &dbus_error,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_INVALID))
+        {
+          if (g_strcmp0 (name, owner->priv->name) == 0)
+            {
+              owner->priv->owns_name = TRUE;
+              if (owner->priv->owns_name != old_owns_name)
+                {
+                  g_object_notify (G_OBJECT (owner), "owns-name");
+                  g_signal_emit (owner, signals[NAME_ACQUIRED_SIGNAL], 0);
+                }
+              else
+                {
+                  g_warning ("Got unexpected NameAcquired signal for the name %s",
+                             owner->priv->name);
+                }
+            }
+        }
+      else
+        {
+          g_warning ("Error extracting name for NameAcquired signal: %s: %s", dbus_error.name, dbus_error.message);
+          dbus_error_free (&dbus_error);
+        }
+    }
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+on_connection_opened (GDBusConnection *connection,
+                      gpointer         user_data)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
+
+  /* set up a filter function for listening on NameLost and NameAcquired messages on the DBusConnection */
+  if (!dbus_connection_add_filter (g_dbus_connection_get_dbus_1_connection (owner->priv->connection),
+                                   filter_function,
+                                   owner,
+                                   NULL))
+    _g_dbus_oom ();
+
+  if (owner->priv->in_construction_phase)
+    return;
+
+  /* ok, the bus suddenly came up.. so try to claim the name ASAP */
+
+  g_assert (!owner->priv->owns_name);
+
+  /* we don't care about the reply.. we'll know soon enough, via a NameAcquired
+   * signal, if we managed to claim the name
+   */
+  bus_request_name (owner->priv->connection,
+                    owner->priv->name,
+                    get_request_name_flags (owner->priv->flags),
+                    NULL,
+                    NULL);
+}
+
+static void
+on_connection_closed (GDBusConnection *connection,
+                      gpointer         user_data)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (user_data);
+
+  /* no need to remove filter; it is removed when the DBusConnection is destroyed */
+
+  /* if we currently own the name, well too bad, not anymore, it's up for grabs */
+  if (owner->priv->owns_name)
+    {
+      owner->priv->owns_name = FALSE;
+      g_object_notify (G_OBJECT (owner), "owns-name");
+      g_signal_emit (owner, signals[NAME_LOST_SIGNAL], 0);
+    }
+
+}
+
+static void
+g_bus_name_owner_constructed (GObject *object)
+{
+  GBusNameOwner *owner = G_BUS_NAME_OWNER (object);
+
+  g_signal_connect (owner->priv->connection, "opened", G_CALLBACK (on_connection_opened), owner);
+  g_signal_connect (owner->priv->connection, "closed", G_CALLBACK (on_connection_closed), owner);
+  if (g_dbus_connection_get_is_open (owner->priv->connection))
+    on_connection_opened (owner->priv->connection, owner);
+
+  if (G_OBJECT_CLASS (g_bus_name_owner_parent_class)->constructed != NULL)
+    G_OBJECT_CLASS (g_bus_name_owner_parent_class)->constructed (object);
+}
+
+static void
+g_bus_name_owner_class_init (GBusNameOwnerClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GBusNameOwnerPrivate));
+
+  gobject_class = G_OBJECT_CLASS (klass);
+  gobject_class->finalize     = g_bus_name_owner_finalize;
+  gobject_class->constructed  = g_bus_name_owner_constructed;
+  gobject_class->get_property = g_bus_name_owner_get_property;
+  gobject_class->set_property = g_bus_name_owner_set_property;
+
+  /**
+   * GBusNameOwner:name:
+   *
+   * The well-known name to own.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_NAME,
+                                   g_param_spec_string ("name",
+                                                        _("name"),
+                                                        _("The name to own"),
+                                                        NULL,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_WRITABLE |
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_NAME |
+                                                        G_PARAM_STATIC_BLURB |
+                                                        G_PARAM_STATIC_NICK));
+
+  /**
+   * GBusNameOwner:flags:
+   *
+   * A set of flags from the #GBusNameOwnerFlags flag enumeration
+   * detailing behavior on how to own the name.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_FLAGS,
+                                   g_param_spec_flags ("flags",
+                                                       _("flags"),
+                                                       _("Flags detailing how to own the name"),
+                                                       G_TYPE_BUS_NAME_OWNER_FLAGS,
+                                                       G_BUS_NAME_OWNER_FLAGS_NONE,
+                                                       G_PARAM_READABLE |
+                                                       G_PARAM_WRITABLE |
+                                                       G_PARAM_CONSTRUCT_ONLY |
+                                                       G_PARAM_STATIC_NAME |
+                                                       G_PARAM_STATIC_BLURB |
+                                                       G_PARAM_STATIC_NICK));
+
+  /**
+   * GBusNameOwner:owns-name:
+   *
+   * Whether the name is currently owned.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_OWNS_NAME,
+                                   g_param_spec_boolean ("owns-name",
+                                                         _("owns-name"),
+                                                         _("Whether the name is currently owned"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE |
+                                                         G_PARAM_STATIC_NAME |
+                                                         G_PARAM_STATIC_BLURB |
+                                                         G_PARAM_STATIC_NICK));
+
+  /**
+   * GBusNameOwner:connection:
+   *
+   * The #GMessageBusConnection that the name will be owned on.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_CONNECTION,
+                                   g_param_spec_object ("connection",
+                                                        _("connection"),
+                                                        _("The connection that the name will be owned on"),
+                                                        G_TYPE_DBUS_CONNECTION,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_WRITABLE |
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_NAME |
+                                                        G_PARAM_STATIC_BLURB |
+                                                        G_PARAM_STATIC_NICK));
+
+  /**
+   * GBusNameOwner::name-lost:
+   * @owner: The #GBusNameOwner emitting the signal.
+   *
+   * Emitted when @owner loses ownership of #GBusNameOwner:name.
+   **/
+  signals[NAME_LOST_SIGNAL] = g_signal_new ("name-lost",
+                                            G_TYPE_BUS_NAME_OWNER,
+                                            G_SIGNAL_RUN_LAST,
+                                            G_STRUCT_OFFSET (GBusNameOwnerClass, name_lost),
+                                            NULL,
+                                            NULL,
+                                            g_cclosure_marshal_VOID__VOID,
+                                            G_TYPE_NONE,
+                                            0);
+
+  /**
+   * GBusNameOwner::name-acquired:
+   * @owner: The #GBusNameOwner emitting the signal.
+   *
+   * Emitted when @owner acquires ownership of #GBusNameOwner:name.
+   **/
+  signals[NAME_ACQUIRED_SIGNAL] = g_signal_new ("name-acquired",
+                                                G_TYPE_BUS_NAME_OWNER,
+                                                G_SIGNAL_RUN_LAST,
+                                                G_STRUCT_OFFSET (GBusNameOwnerClass, name_acquired),
+                                                NULL,
+                                                NULL,
+                                                g_cclosure_marshal_VOID__VOID,
+                                                G_TYPE_NONE,
+                                                0);
+}
+
+static void
+g_bus_name_owner_init (GBusNameOwner *connection)
+{
+  connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection, G_TYPE_BUS_NAME_OWNER, GBusNameOwnerPrivate);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#if 0
+
+static void
+bus_release_name_cb (DBusPendingCall *pending,
+                     void            *user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+  DBusMessage *reply;
+  DBusError dbus_error;
+  GError *error;
+  dbus_uint32_t release_name_reply;
+
+  reply = dbus_pending_call_steal_reply (pending);
+  g_assert (reply != NULL);
+
+  dbus_error_init (&dbus_error);
+  if (dbus_message_get_args (reply,
+                             &dbus_error,
+                             DBUS_TYPE_UINT32, &release_name_reply,
+                             DBUS_TYPE_INVALID))
+    {
+      g_simple_async_result_set_op_res_gpointer (simple, GINT_TO_POINTER (release_name_reply), NULL);
+      goto done;
+    }
+
+  error = g_dbus_error_new_for_dbus_error (&dbus_error,
+                                           NULL,
+                                           NULL);
+  g_simple_async_result_set_from_error (simple, error);
+  g_error_free (error);
+  dbus_error_free (&dbus_error);
+
+ done:
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+  dbus_message_unref (reply);
+}
+
+static void
+bus_release_name (GDBusConnection       *connection,
+                  const gchar           *name,
+                  GAsyncReadyCallback    callback,
+                  gpointer               user_data)
+{
+  GSimpleAsyncResult *simple;
+  DBusMessage *message;
+  DBusPendingCall *pending_call;
+
+  g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
+  g_return_if_fail (name != NULL);
+
+  simple = g_simple_async_result_new (G_OBJECT (connection),
+                                      callback,
+                                      user_data,
+                                      bus_release_name);
+
+  if (g_dbus_connection_get_dbus_1_connection (connection) == NULL)
+    {
+      g_simple_async_result_set_error (simple,
+                                       G_DBUS_ERROR,
+                                       G_DBUS_ERROR_FAILED,
+                                       _("Not connected to message bus"));
+      g_simple_async_result_complete (simple);
+      g_object_unref (simple);
+      goto out;
+    }
+
+  if ((message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS,
+                                               "ReleaseName")) == NULL)
+    _g_dbus_oom ();
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_INVALID))
+    _g_dbus_oom ();
+
+  if (!dbus_connection_send_with_reply (g_dbus_connection_get_dbus_1_connection (connection),
+                                        message,
+                                        &pending_call,
+                                        -1))
+    _g_dbus_oom ();
+
+  dbus_message_unref (message);
+
+  dbus_pending_call_set_notify (pending_call,
+                                bus_release_name_cb,
+                                simple,
+                                NULL);
+
+ out:
+  ;
+}
+
+static guint
+bus_release_name_finish (GDBusConnection  *bus,
+                         GAsyncResult     *res,
+                         GError          **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  guint ret;
+
+  ret = 0;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == bus_release_name);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    goto out;
+
+  ret = GPOINTER_TO_INT (g_simple_async_result_get_op_res_gpointer (simple));
+
+ out:
+  return ret;
+}
+#endif
+
+static guint
+bus_release_name_sync (GDBusConnection       *connection,
+                       const gchar           *name,
+                       GError               **error)
+{
+  DBusMessage *message;
+  DBusMessage *reply;
+  dbus_uint32_t release_name_reply;
+  DBusError dbus_error;
+
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), 0);
+  g_return_val_if_fail (name != NULL, 0);
+
+  message = NULL;
+  reply = NULL;
+  release_name_reply = 0;
+
+  if (g_dbus_connection_get_dbus_1_connection (connection) == NULL)
+    {
+      g_set_error (error,
+                   G_DBUS_ERROR,
+                   G_DBUS_ERROR_FAILED,
+                   _("Not connected to message bus"));
+      goto out;
+    }
+
+  if ((message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS,
+                                               "ReleaseName")) == NULL)
+    _g_dbus_oom ();
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_INVALID))
+    _g_dbus_oom ();
+
+  dbus_error_init (&dbus_error);
+  reply = dbus_connection_send_with_reply_and_block (g_dbus_connection_get_dbus_1_connection (connection),
+                                                     message,
+                                                     -1,
+                                                     &dbus_error);
+  if (reply == NULL)
+    {
+      g_dbus_error_set_dbus_error (error,
+                                   &dbus_error,
+                                   NULL,
+                                   NULL);
+      dbus_error_free (&dbus_error);
+      goto out;
+    }
+
+  if (!dbus_message_get_args (reply,
+                              &dbus_error,
+                              DBUS_TYPE_UINT32, &release_name_reply,
+                              DBUS_TYPE_INVALID))
+    {
+      g_dbus_error_set_dbus_error (error,
+                                   &dbus_error,
+                                   NULL,
+                                   NULL);
+      dbus_error_free (&dbus_error);
+      goto out;
+    }
+
+ out:
+  if (message != NULL)
+    dbus_message_unref (message);
+  if (reply != NULL)
+    dbus_message_unref (reply);
+
+  return release_name_reply;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static guint
+get_request_name_flags (GBusNameOwnerFlags flags)
+{
+  guint request_name_flags;
+
+  request_name_flags = 0;
+  if (flags & G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT)
+    request_name_flags |= DBUS_NAME_FLAG_ALLOW_REPLACEMENT;
+  if (flags & G_BUS_NAME_OWNER_FLAGS_REPLACE)
+    request_name_flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
+
+  return request_name_flags;
+}
+
+static void
+bus_request_name_cb (DBusPendingCall *pending,
+                     void            *user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+  DBusMessage *reply;
+  DBusError dbus_error;
+  GError *error;
+  dbus_uint32_t request_name_reply;
+
+  reply = dbus_pending_call_steal_reply (pending);
+  g_assert (reply != NULL);
+
+  dbus_error_init (&dbus_error);
+  if (dbus_message_get_args (reply,
+                             &dbus_error,
+                             DBUS_TYPE_UINT32, &request_name_reply,
+                             DBUS_TYPE_INVALID))
+    {
+      g_simple_async_result_set_op_res_gpointer (simple, GINT_TO_POINTER (request_name_reply), NULL);
+      goto done;
+    }
+
+  error = g_dbus_error_new_for_dbus_error (&dbus_error,
+                                           NULL,
+                                           NULL);
+  g_simple_async_result_set_from_error (simple, error);
+  g_error_free (error);
+  dbus_error_free (&dbus_error);
+
+ done:
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+  dbus_message_unref (reply);
+}
+
+static void
+bus_request_name (GDBusConnection       *connection,
+                  const gchar           *name,
+                  guint                  flags,
+                  GAsyncReadyCallback    callback,
+                  gpointer               user_data)
+{
+  GSimpleAsyncResult *simple;
+  DBusMessage *message;
+  DBusPendingCall *pending_call;
+
+  g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
+  g_return_if_fail (name != NULL);
+
+  simple = g_simple_async_result_new (G_OBJECT (connection),
+                                      callback,
+                                      user_data,
+                                      bus_request_name);
+
+  if (g_dbus_connection_get_dbus_1_connection (connection) == NULL)
+    {
+      g_simple_async_result_set_error (simple,
+                                       G_DBUS_ERROR,
+                                       G_DBUS_ERROR_FAILED,
+                                       _("Not connected to message bus"));
+      g_simple_async_result_complete (simple);
+      g_object_unref (simple);
+      goto out;
+    }
+
+  if ((message = dbus_message_new_method_call (DBUS_SERVICE_DBUS,
+                                               DBUS_PATH_DBUS,
+                                               DBUS_INTERFACE_DBUS,
+                                               "RequestName")) == NULL)
+    _g_dbus_oom ();
+  if (!dbus_message_append_args (message,
+                                 DBUS_TYPE_STRING, &name,
+                                 DBUS_TYPE_UINT32, &flags,
+                                 DBUS_TYPE_INVALID))
+    _g_dbus_oom ();
+
+  if (!dbus_connection_send_with_reply (g_dbus_connection_get_dbus_1_connection (connection),
+                                        message,
+                                        &pending_call,
+                                        -1))
+    _g_dbus_oom ();
+
+  dbus_message_unref (message);
+
+  dbus_pending_call_set_notify (pending_call,
+                                bus_request_name_cb,
+                                simple,
+                                NULL);
+
+ out:
+  ;
+}
+
+static guint
+bus_request_name_finish (GDBusConnection  *bus,
+                         GAsyncResult     *res,
+                         GError          **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  guint ret;
+
+  ret = 0;
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == bus_request_name);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    goto out;
+
+  ret = GPOINTER_TO_INT (g_simple_async_result_get_op_res_gpointer (simple));
+
+ out:
+  return ret;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+typedef struct
+{
+  GAsyncReadyCallback   callback;
+  gpointer              user_data;
+  GBusNameOwner        *owner;
+  gboolean              is_for_connection;
+} ConstructData;
+
+static void
+construct_data_free (ConstructData *data)
+{
+  g_free (data);
+}
+
+static void
+request_name_cb (GDBusConnection *connection,
+                 GAsyncResult    *result,
+                 gpointer         user_data)
+{
+  ConstructData *data = user_data;
+  GSimpleAsyncResult *simple;
+  GError *error;
+  guint reply;
+
+  simple = g_simple_async_result_new (G_OBJECT (data->owner),
+                                      data->callback,
+                                      data->user_data,
+                                      data->is_for_connection ? g_bus_name_owner_new_for_connection_finish : g_bus_name_owner_new_finish);
+
+  error = NULL;
+  reply = bus_request_name_finish (connection,
+                                   result,
+                                   &error);
+  if (error != NULL)
+    {
+      g_simple_async_result_set_from_error (simple,
+                                            error);
+      g_error_free (error);
+    }
+  else
+    {
+      if (reply != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
+        {
+          g_simple_async_result_set_error (simple,
+                                           G_DBUS_ERROR,
+                                           G_DBUS_ERROR_FAILED,
+                                           _("Error acquiring name, RequestName() returned %d"),
+                                           reply);
+        }
+      else
+        {
+          data->owner->priv->owns_name = TRUE;
+          g_signal_emit (data->owner, signals[NAME_ACQUIRED_SIGNAL], 0);
+        }
+    }
+
+  data->owner->priv->in_construction_phase = FALSE;
+  g_simple_async_result_complete_in_idle (simple);
+  g_object_unref (simple);
+  construct_data_free (data);
+}
+
+static void
+get_connection_cb (GDBusConnection *connection,
+                   GAsyncResult    *result,
+                   gpointer         user_data)
+{
+  ConstructData *data = user_data;
+  GError *error;
+
+  error = NULL;
+  if (!g_dbus_connection_bus_get_finish (connection,
+                                         result,
+                                         &error))
+    {
+      GSimpleAsyncResult *simple;
+
+      /* connection is not open.. report back */
+      simple = g_simple_async_result_new (G_OBJECT (data->owner),
+                                          data->callback,
+                                          data->user_data,
+                                          g_bus_name_owner_new_finish);
+      g_simple_async_result_set_from_error (simple,
+                                            error);
+      g_error_free (error);
+
+      data->owner->priv->in_construction_phase = FALSE;
+      g_simple_async_result_complete_in_idle (simple);
+      g_object_unref (simple);
+      construct_data_free (data);
+    }
+  else
+    {
+      /* connection is open.. try to claim the name */
+
+      bus_request_name (data->owner->priv->connection,
+                        data->owner->priv->name,
+                        get_request_name_flags (data->owner->priv->flags),
+                        (GAsyncReadyCallback) request_name_cb,
+                        data);
+    }
+
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_bus_name_owner_new:
+ * @bus_type: A #GMessageBusType specifying what message bus to connect to.
+ * @name: A well-known name to acquire.
+ * @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
+ * @cancellable: %NULL or a #GCancellable.
+ * @callback: The callback function to invoke when finished acquiring the name.
+ * @user_data: User data to pass to @callback.
+ *
+ * Creates a new #GBusNameOwner and then attempts to own @name on the
+ * bus specified by @bus_type. When the attempt to own the name is
+ * finished, @callback will be invoked (on the main thread) and you
+ * can use g_bus_name_owner_new_finish() to get the result.
+ *
+ * This class is the preferred way to implement D-Bus
+ * services. The canonical example follows.
+ * <example><title>Using g_bus_name_owner_new()</title><programlisting><xi:include xmlns:xi="http://www.w3.org/2001/XInclude"; parse="text" href="../../../../gdbus/example-gbusnameowner.c"><xi:fallback>FIXME: MISSING XINCLUDE CONTENT</xi:fallback></xi:include></programlisting></example>
+ *
+ * Returns: A #GBusNameOwner object. Free with g_object_unref().
+ **/
+GBusNameOwner *
+g_bus_name_owner_new (GMessageBusType        bus_type,
+                      const gchar           *name,
+                      GBusNameOwnerFlags     flags,
+                      GCancellable          *cancellable,
+                      GAsyncReadyCallback    callback,
+                      gpointer               user_data)
+{
+  GBusNameOwner *owner;
+  GDBusConnection *connection;
+  ConstructData *data;
+
+  data = g_new0 (ConstructData, 1);
+  data->callback = callback;
+  data->user_data = user_data;
+
+  connection = g_dbus_connection_bus_get (bus_type,
+                                          cancellable,
+                                          (GAsyncReadyCallback) get_connection_cb,
+                                          data);
+
+  owner = G_BUS_NAME_OWNER (g_object_new (G_TYPE_BUS_NAME_OWNER,
+                                          "name", name,
+                                          "connection", connection,
+                                          "flags", flags,
+                                          NULL));
+
+  data->owner = owner;
+  owner->priv->in_construction_phase = TRUE;
+
+  g_object_unref (connection);
+
+  return owner;
+}
+
+/**
+ * g_bus_name_owner_new_finish:
+ * @owner: A #GBusNameOwner.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_bus_name_owner_get().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes attempting to acquire a name.
+ *
+ * Returns: %TRUE if the name was acquired, otherwise %FALSE with @error set.
+ **/
+gboolean
+g_bus_name_owner_new_finish (GBusNameOwner         *owner,
+                             GAsyncResult          *res,
+                             GError               **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+
+  g_return_val_if_fail (G_IS_BUS_NAME_OWNER (owner), FALSE);
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_bus_name_owner_new_finish);
+
+  return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_bus_name_owner_new_for_connection:
+ * @connection: A #GDBusConnection.
+ * @name: A well-known name to acquire.
+ * @flags: A set of flags from the #GBusNameOwnerFlags enumeration.
+ * @cancellable: %NULL or a #GCancellable.
+ * @callback: The callback function to invoke when finished acquiring the name.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_bus_name_owner_new() but allows you to pass in a
+ * #GDBusConnection.
+ *
+ * Returns: A #GBusNameOwner object. Free with g_object_unref().
+ **/
+GBusNameOwner *
+g_bus_name_owner_new_for_connection (GDBusConnection       *connection,
+                                     const gchar           *name,
+                                     GBusNameOwnerFlags     flags,
+                                     GCancellable          *cancellable,
+                                     GAsyncReadyCallback    callback,
+                                     gpointer               user_data)
+{
+  GBusNameOwner *owner;
+
+  owner = G_BUS_NAME_OWNER (g_object_new (G_TYPE_BUS_NAME_OWNER,
+                                          "name", name,
+                                          "connection", connection,
+                                          "flags", flags,
+                                          NULL));
+
+  if (g_dbus_connection_get_is_open (connection))
+    {
+      ConstructData *data;
+      data = g_new0 (ConstructData, 1);
+      data->callback = callback;
+      data->user_data = user_data;
+      data->is_for_connection = TRUE;
+      data->owner = owner;
+      owner->priv->in_construction_phase = TRUE;
+
+      /* connection is open.. try to claim the name */
+      bus_request_name (data->owner->priv->connection,
+                        data->owner->priv->name,
+                        get_request_name_flags (data->owner->priv->flags),
+                        (GAsyncReadyCallback) request_name_cb,
+                        data);
+    }
+  else
+    {
+      GSimpleAsyncResult *simple;
+
+      /* connection is not open.. report back in idle
+       *
+       * TODO: maybe handle g_dbus_connection_is_connecting() or something...
+       */
+      simple = g_simple_async_result_new (G_OBJECT (owner),
+                                          callback,
+                                          user_data,
+                                          g_bus_name_owner_new_for_connection_finish);
+      g_simple_async_result_set_error (simple,
+                                       G_DBUS_ERROR,
+                                       G_DBUS_ERROR_FAILED,
+                                       _("Connection is not open"));
+
+      g_simple_async_result_complete_in_idle (simple);
+      g_object_unref (simple);
+    }
+
+  return owner;
+}
+
+/**
+ * g_bus_name_owner_new_for_connection_finish:
+ * @owner: A #GBusNameOwner.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback
+ * function passed to g_bus_name_owner_get_for_connection().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes attempting to acquire a name.
+ *
+ * Returns: %TRUE if the name was acquired, otherwise %FALSE with @error set.
+ **/
+gboolean
+g_bus_name_owner_new_for_connection_finish (GBusNameOwner         *owner,
+                                            GAsyncResult          *res,
+                                            GError               **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+
+  g_return_val_if_fail (G_IS_BUS_NAME_OWNER (owner), FALSE);
+
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_bus_name_owner_new_for_connection_finish);
+
+  return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+/**
+ * g_bus_name_owner_get_owns_name:
+ * @owner: A #GBusNameOwner.
+ *
+ * Gets whether @owner currently owns the name it was constructed with.
+ *
+ * You can track changes to this value by listening to the
+ * #GBusNameOwner::name-acquired and #GBusNameOwner::name-lost signals
+ * or by listning to changes on the #GBusNameOwner:owns-name property.
+ *
+ * Returns: %TRUE if @owner owns the name it was constructed with,
+ * %FALSE otherwise.
+ **/
+gboolean
+g_bus_name_owner_get_owns_name (GBusNameOwner *owner)
+{
+  g_return_val_if_fail (G_IS_BUS_NAME_OWNER (owner), FALSE);
+
+  return owner->priv->owns_name;
+}
+
+/**
+ * g_bus_name_owner_get_name:
+ * @owner: A #GBusNameOwner.
+ *
+ * Gets the well-known name that @owner was constructed with.
+ *
+ * Returns: The well-known name for @owner. Do not free this string,
+ * it is owned by @owner.
+ **/
+const gchar *
+g_bus_name_owner_get_name (GBusNameOwner *owner)
+{
+  g_return_val_if_fail (G_IS_BUS_NAME_OWNER (owner), NULL);
+
+  return owner->priv->name;
+}
+
+/**
+ * g_bus_name_owner_get_flags:
+ * @owner: A #GBusNameOwner.
+ *
+ * Gets the flags that @owner was constructed with.
+ *
+ * Returns: Flags from the #GBusNameOwnerFlags enumeration.
+ **/
+GBusNameOwnerFlags
+g_bus_name_owner_get_flags (GBusNameOwner *owner)
+{
+  g_return_val_if_fail (G_IS_BUS_NAME_OWNER (owner), 0);
+
+  return owner->priv->flags;
+}
+
+/**
+ * g_bus_name_owner_get_connection:
+ * @owner: A #GBusNameOwner.
+ *
+ * Gets the #GDBusConnection used for @owner.
+ *
+ * Returns: A #GDBusConnection object owned by @owner. Do not unref.
+ **/
+GDBusConnection *
+g_bus_name_owner_get_connection (GBusNameOwner *owner)
+{
+  g_return_val_if_fail (G_IS_BUS_NAME_OWNER (owner), NULL);
+
+  return owner->priv->connection;
+}
+
+#define __G_BUS_NAME_OWNER_C__
+#include "gdbusaliasdef.c"
diff --git a/gdbus/gbusnameowner.h b/gdbus/gbusnameowner.h
new file mode 100644
index 0000000..1927b49
--- /dev/null
+++ b/gdbus/gbusnameowner.h
@@ -0,0 +1,114 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_BUS_NAME_OWNER_H__
+#define __G_BUS_NAME_OWNER_H__
+
+#include <gdbus/gdbustypes.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_BUS_NAME_OWNER         (g_bus_name_owner_get_type ())
+#define G_BUS_NAME_OWNER(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_BUS_NAME_OWNER, GBusNameOwner))
+#define G_BUS_NAME_OWNER_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_BUS_NAME_OWNER, GBusNameOwnerClass))
+#define G_BUS_NAME_OWNER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_BUS_NAME_OWNER, GBusNameOwnerClass))
+#define G_IS_BUS_NAME_OWNER(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_BUS_NAME_OWNER))
+#define G_IS_BUS_NAME_OWNER_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_BUS_NAME_OWNER))
+
+typedef struct _GBusNameOwnerClass   GBusNameOwnerClass;
+typedef struct _GBusNameOwnerPrivate GBusNameOwnerPrivate;
+
+/**
+ * GBusNameOwner:
+ *
+ * The #GBusNameOwner structure contains only private data and
+ * should only be accessed using the provided API.
+ */
+struct _GBusNameOwner
+{
+  /*< private >*/
+  GObject parent_instance;
+  GBusNameOwnerPrivate *priv;
+};
+
+/**
+ * GBusNameOwnerClass:
+ * @name_acquired: Signal class handler for the #GBusNameOwner::name-acquired signal.
+ * @name_lost: Signal class handler for the #GBusNameOwner::name-lost signal.
+ *
+ * Class structure for #GBusNameOwner.
+ */
+struct _GBusNameOwnerClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+
+  /*< public >*/
+
+  /* Signals */
+  void (*name_acquired) (GBusNameOwner *owner);
+  void (*name_lost)     (GBusNameOwner *owner);
+
+  /*< private >*/
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+  void (*_g_reserved7) (void);
+  void (*_g_reserved8) (void);
+};
+
+GType               g_bus_name_owner_get_type                  (void) G_GNUC_CONST;
+GBusNameOwner      *g_bus_name_owner_new                       (GMessageBusType        bus_type,
+                                                                const gchar           *name,
+                                                                GBusNameOwnerFlags     flags,
+                                                                GCancellable          *cancellable,
+                                                                GAsyncReadyCallback    callback,
+                                                                gpointer               user_data);
+gboolean            g_bus_name_owner_new_finish                (GBusNameOwner         *owner,
+                                                                GAsyncResult          *res,
+                                                                GError               **error);
+GBusNameOwner      *g_bus_name_owner_new_for_connection        (GDBusConnection       *connection,
+                                                                const gchar           *name,
+                                                                GBusNameOwnerFlags     flags,
+                                                                GCancellable          *cancellable,
+                                                                GAsyncReadyCallback    callback,
+                                                                gpointer               user_data);
+gboolean            g_bus_name_owner_new_for_connection_finish (GBusNameOwner         *owner,
+                                                                GAsyncResult          *res,
+                                                                GError               **error);
+gboolean            g_bus_name_owner_get_owns_name             (GBusNameOwner         *owner);
+const gchar        *g_bus_name_owner_get_name                  (GBusNameOwner         *owner);
+GBusNameOwnerFlags  g_bus_name_owner_get_flags                 (GBusNameOwner         *owner);
+GDBusConnection    *g_bus_name_owner_get_connection            (GBusNameOwner         *owner);
+
+G_END_DECLS
+
+#endif /* __G_BUS_NAME_OWNER_H__ */
diff --git a/gdbus/gdbus-marshal.list b/gdbus/gdbus-marshal.list
new file mode 100644
index 0000000..02fd6ad
--- /dev/null
+++ b/gdbus/gdbus-marshal.list
@@ -0,0 +1 @@
+VOID:OBJECT,OBJECT,ENUM
diff --git a/gdbus/gdbus.h b/gdbus/gdbus.h
new file mode 100644
index 0000000..6abebc3
--- /dev/null
+++ b/gdbus/gdbus.h
@@ -0,0 +1,37 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#ifndef __G_DBUS_H__
+#define __G_DBUS_H__
+
+#define __G_DBUS_G_DBUS_H_INSIDE__
+
+#include <gdbus/gdbustypes.h>
+#include <gdbus/gdbusenumtypes.h>
+#include <gdbus/gdbusmainloop.h>
+#include <gdbus/gdbusconnection.h>
+#include <gdbus/gdbuserror.h>
+#include <gdbus/gbusnameowner.h>
+
+#undef __G_DBUS_D_DBUS_H_INSIDE__
+
+#endif /* __G_DBUS_H__ */
diff --git a/gdbus/gdbus.symbols b/gdbus/gdbus.symbols
new file mode 100644
index 0000000..cf10bc3
--- /dev/null
+++ b/gdbus/gdbus.symbols
@@ -0,0 +1,73 @@
+/* This file lists all exported symbols. It is used to generate
+ * the gio.def file used to control exports on Windows and the
+ * gioalias.h/gioaliasdef.c files used to avoid PLT entries for
+ * internal uses of exported functions (see makegioalias.pl).
+ *
+ * Every symbol must be included in the right
+ * #ifdef IN_HEADER(sym) #endif and
+ * #ifdef IN_FILE(sym) #endif sections.
+ */
+
+#ifdef ALL_FILES
+#define IN_FILE(x) 1
+#define IN_HEADER(x) 1
+#endif
+
+#if IN_HEADER(__G_DBUS_CONNECTION_H__)
+#if IN_FILE(__G_DBUS_CONNECTION_C__)
+g_dbus_connection_get_type G_GNUC_CONST
+g_dbus_connection_bus_get
+g_dbus_connection_bus_get_finish
+g_dbus_connection_bus_get_private
+g_dbus_connection_bus_get_private_finish
+g_dbus_connection_get_unique_name
+g_dbus_connection_get_is_open
+g_dbus_connection_get_bus_type
+g_dbus_connection_get_dbus_1_connection
+g_dbus_connection_get_exit_on_close
+g_dbus_connection_set_exit_on_close
+#endif
+#endif
+
+#if IN_HEADER(__G_BUS_NAME_OWNER_H__)
+#if IN_FILE(__G_BUS_NAME_OWNER_C__)
+g_bus_name_owner_new
+g_bus_name_owner_new_finish
+g_bus_name_owner_new_for_connection
+g_bus_name_owner_new_for_connection_finish
+g_bus_name_owner_get_connection
+g_bus_name_owner_get_flags
+g_bus_name_owner_get_name
+g_bus_name_owner_get_owns_name
+g_bus_name_owner_get_type
+#endif
+#endif
+
+#if IN_HEADER(__G_DBUS_MAINLOOP_H__)
+#if IN_FILE(__G_DBUS_MAINLOOP_C__)
+g_dbus_integrate_dbus_1_connection
+g_dbus_unintegrate_dbus_1_connection
+g_dbus_integrate_dbus_1_server
+g_dbus_unintegrate_dbus_1_server
+#endif
+#endif
+
+#if IN_HEADER(__G_DBUS_ENUM_TYPES_H__)
+#if IN_FILE(__G_DBUS_ENUM_TYPES_C__)
+g_dbus_error_get_type G_GNUC_CONST
+g_message_bus_type_get_type G_GNUC_CONST
+g_bus_name_owner_flags_get_type
+#endif
+#endif
+
+#if IN_HEADER(__G_DBUS_ERROR_H__)
+#if IN_FILE(__G_DBUS_ERROR_C__)
+g_dbus_error_quark
+g_dbus_error_get_remote_exception
+g_dbus_error_new_for_dbus_error
+g_dbus_error_new_for_dbus_error_valist
+g_dbus_error_new_for_gerror
+g_dbus_error_set_dbus_error
+g_dbus_error_set_dbus_error_valist
+#endif
+#endif
diff --git a/gdbus/gdbusconnection.c b/gdbus/gdbusconnection.c
new file mode 100644
index 0000000..a461862
--- /dev/null
+++ b/gdbus/gdbusconnection.c
@@ -0,0 +1,964 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+
+#include "gdbusconnection.h"
+#include "gdbusmainloop.h"
+#include "gdbuserror.h"
+#include "gdbusprivate.h"
+#include "gdbusenumtypes.h"
+
+#include "gdbusalias.h"
+
+/**
+ * SECTION:gdbusconnection
+ * @short_description: D-Bus Connections
+ * @include: gdbus/gdbus.h
+ *
+ * #GDBusConnection is a thin wrapper class for the #DBusConnection
+ * type that integrates with the GLib type system. The connection
+ * state of the underlying connection is tracked and upon
+ * disconnection, #GDBusConnection instances will attempt to reconnect
+ * to the remote end.
+ *
+ * TODO: stuff about caching unix_process_id etc. when we add that.
+ */
+
+struct _GDBusConnectionPrivate
+{
+  DBusConnection *dbus_1_connection;
+
+  GMessageBusType bus_type;
+
+  guint reconnect_timer_id;
+
+  /* unfortunately there is no dbus_connection_get_exit_on_disconnect() so we need to track this ourselves */
+  gboolean exit_on_close;
+
+  gboolean is_private;
+};
+
+enum
+{
+  OPENED_SIGNAL,
+  CLOSED_SIGNAL,
+  LAST_SIGNAL,
+};
+
+enum
+{
+  PROP_0,
+  PROP_BUS_TYPE,
+  PROP_UNIQUE_NAME,
+  PROP_IS_OPEN,
+  PROP_EXIT_ON_CLOSE,
+  PROP_DBUS_1_CONNECTION,
+};
+
+G_LOCK_DEFINE_STATIC (connection_lock);
+static GDBusConnection *the_session_bus = NULL;
+static GDBusConnection *the_system_bus = NULL;
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+                 DBusMessage    *message,
+                 void           *user_data);
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+static void g_dbus_connection_set_dbus_1_connection (GDBusConnection *connection,
+                                                     DBusConnection  *dbus_1_connection);
+
+G_DEFINE_TYPE (GDBusConnection, g_dbus_connection, G_TYPE_OBJECT);
+
+static void
+g_dbus_connection_dispose (GObject *object)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (object);
+
+  G_LOCK (connection_lock);
+  if (connection == the_session_bus)
+    {
+      the_session_bus = NULL;
+    }
+  else if (connection == the_system_bus)
+    {
+      the_system_bus = NULL;
+    }
+  G_UNLOCK (connection_lock);
+
+  if (G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose != NULL)
+    G_OBJECT_CLASS (g_dbus_connection_parent_class)->dispose (object);
+}
+
+static void
+g_dbus_connection_finalize (GObject *object)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (object);
+
+  if (connection->priv->reconnect_timer_id > 0)
+    g_source_remove (connection->priv->reconnect_timer_id);
+
+  g_dbus_connection_set_dbus_1_connection (connection, NULL);
+
+  if (G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize != NULL)
+    G_OBJECT_CLASS (g_dbus_connection_parent_class)->finalize (object);
+}
+
+static void
+g_dbus_connection_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_DBUS_1_CONNECTION:
+      g_value_set_pointer (value, g_dbus_connection_get_dbus_1_connection (connection));
+      break;
+
+    case PROP_BUS_TYPE:
+      g_value_set_enum (value, g_dbus_connection_get_bus_type (connection));
+      break;
+
+    case PROP_UNIQUE_NAME:
+      g_value_set_string (value, g_dbus_connection_get_unique_name (connection));
+      break;
+
+    case PROP_IS_OPEN:
+      g_value_set_boolean (value, g_dbus_connection_get_is_open (connection));
+      break;
+
+    case PROP_EXIT_ON_CLOSE:
+      g_value_set_boolean (value, g_dbus_connection_get_exit_on_close (connection));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+g_dbus_connection_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (object);
+
+  switch (prop_id)
+    {
+    case PROP_DBUS_1_CONNECTION:
+      g_dbus_connection_set_dbus_1_connection (connection, g_value_get_pointer (value));
+      break;
+
+    case PROP_BUS_TYPE:
+      connection->priv->bus_type = g_value_get_enum (value);
+      break;
+
+    case PROP_EXIT_ON_CLOSE:
+      g_dbus_connection_set_exit_on_close (connection, g_value_get_boolean (value));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+g_dbus_connection_class_init (GDBusConnectionClass *klass)
+{
+  GObjectClass *gobject_class;
+
+  g_type_class_add_private (klass, sizeof (GDBusConnectionPrivate));
+
+  gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->finalize     = g_dbus_connection_finalize;
+  gobject_class->dispose      = g_dbus_connection_dispose;
+  gobject_class->set_property = g_dbus_connection_set_property;
+  gobject_class->get_property = g_dbus_connection_get_property;
+
+  /**
+   * GDBusConnection:dbus-1-connection:
+   *
+   * The underlying #DBusConnection object for the connection or %NULL
+   * if the connection is not open.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_DBUS_1_CONNECTION,
+                                   g_param_spec_pointer ("dbus-1-connection",
+                                                         _("dbus-1-connection"),
+                                                         _("The underlying DBusConnection object for the connection"),
+                                                         G_PARAM_WRITABLE |
+                                                         G_PARAM_READABLE |
+                                                         G_PARAM_CONSTRUCT_ONLY |
+                                                         G_PARAM_STATIC_NAME |
+                                                         G_PARAM_STATIC_BLURB |
+                                                         G_PARAM_STATIC_NICK));
+
+  /**
+   * GDBusConnection:bus-type:
+   *
+   * Type type of the message bus the connection is for or
+   * #G_MESSAGE_BUS_TYPE_NONE if the connection is not to a message
+   * bus.
+   *
+   * This property is never #G_MESSAGE_BUS_TYPE_STARTER. If
+   * #G_MESSAGE_BUS_TYPE_STARTER was passed to g_dbus_connection_get()
+   * then this property will be either #G_MESSAGE_BUS_TYPE_SESSION or
+   * #G_MESSAGE_BUS_TYPE_SYSTEM depending on what bus started the
+   * process.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_BUS_TYPE,
+                                   g_param_spec_enum ("bus-type",
+                                                      _("bus-type"),
+                                                      _("The type of message bus the connection is for"),
+                                                      G_TYPE_MESSAGE_BUS_TYPE,
+                                                      G_MESSAGE_BUS_TYPE_NONE,
+                                                      G_PARAM_READABLE |
+                                                      G_PARAM_WRITABLE |
+                                                      G_PARAM_CONSTRUCT_ONLY |
+                                                      G_PARAM_STATIC_NAME |
+                                                      G_PARAM_STATIC_BLURB |
+                                                      G_PARAM_STATIC_NICK));
+
+  /**
+   * GDBusConnection:unique-name:
+   *
+   * The unique name as assigned by the message bus or %NULL if the
+   * connection is closed or not a message bus connection.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_IS_OPEN,
+                                   g_param_spec_string ("unique-name",
+                                                        _("unique-name"),
+                                                        _("Unique name of bus connection"),
+                                                        NULL,
+                                                        G_PARAM_READABLE |
+                                                        G_PARAM_STATIC_NAME |
+                                                        G_PARAM_STATIC_BLURB |
+                                                        G_PARAM_STATIC_NICK));
+
+  /**
+   * GDBusConnection:is-open:
+   *
+   * A boolean specifying whether a connection the is open.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_IS_OPEN,
+                                   g_param_spec_boolean ("is-open",
+                                                         _("is-open"),
+                                                         _("Whether the connection is open"),
+                                                         FALSE,
+                                                         G_PARAM_READABLE |
+                                                         G_PARAM_STATIC_NAME |
+                                                         G_PARAM_STATIC_BLURB |
+                                                         G_PARAM_STATIC_NICK));
+
+  /**
+   * GDBusConnection:exit-on-close:
+   *
+   * A boolean specifying whether _exit() should be called when the
+   * connection is closed.
+   */
+  g_object_class_install_property (gobject_class,
+                                   PROP_EXIT_ON_CLOSE,
+                                   g_param_spec_boolean ("exit-on-close",
+                                                         _("exit-on-close"),
+                                                         _("Whether _exit() is called when the connection is closed"),
+                                                         TRUE,
+                                                         G_PARAM_READABLE |
+                                                         G_PARAM_WRITABLE |
+                                                         G_PARAM_CONSTRUCT |
+                                                         G_PARAM_STATIC_NAME |
+                                                         G_PARAM_STATIC_BLURB |
+                                                         G_PARAM_STATIC_NICK));
+
+  /**
+   * GDBusConnection::opened:
+   * @connection: The #GDBusConnection emitting the signal.
+   *
+   * Emitted when the connection is established.
+   **/
+  signals[OPENED_SIGNAL] = g_signal_new ("opened",
+                                         G_TYPE_DBUS_CONNECTION,
+                                         G_SIGNAL_RUN_LAST,
+                                         G_STRUCT_OFFSET (GDBusConnectionClass, opened),
+                                         NULL,
+                                         NULL,
+                                         g_cclosure_marshal_VOID__VOID,
+                                         G_TYPE_NONE,
+                                         0);
+
+  /**
+   * GDBusConnection::closed:
+   * @connection: The #GDBusConnection emitting the signal.
+   *
+   * Emitted when the connection is closed.
+   **/
+  signals[CLOSED_SIGNAL] = g_signal_new ("closed",
+                                         G_TYPE_DBUS_CONNECTION,
+                                         G_SIGNAL_RUN_LAST,
+                                         G_STRUCT_OFFSET (GDBusConnectionClass, closed),
+                                         NULL,
+                                         NULL,
+                                         g_cclosure_marshal_VOID__VOID,
+                                         G_TYPE_NONE,
+                                         0);
+}
+
+static void
+g_dbus_connection_init (GDBusConnection *connection)
+{
+  connection->priv = G_TYPE_INSTANCE_GET_PRIVATE (connection, G_TYPE_DBUS_CONNECTION, GDBusConnectionPrivate);
+}
+
+/**
+ * g_dbus_connection_get_bus_type:
+ * @connection: A #GDBusConnection.
+ *
+ * Gets the type of message bus connection, if any.
+ *
+ * This will never return #G_MESSAGE_BUS_TYPE_STARTER. If
+ * #G_MESSAGE_BUS_TYPE_STARTER was passed to g_dbus_connection_get()
+ * then the return value will be either #G_MESSAGE_BUS_TYPE_SESSION or
+ * #G_MESSAGE_BUS_TYPE_SYSTEM depending on what bus started the
+ * process.
+ *
+ * Returns: Type type of the message bus the connection is for or
+ * #G_MESSAGE_BUS_TYPE_NONE if the connection is not to a message
+ * bus.
+ **/
+GMessageBusType
+g_dbus_connection_get_bus_type (GDBusConnection *connection)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), G_MESSAGE_BUS_TYPE_NONE);
+
+  return connection->priv->bus_type;
+}
+
+
+/**
+ * g_dbus_connection_get_is_open:
+ * @connection: A #GDBusConnection.
+ *
+ * Gets whether a connection is open.
+ *
+ * To listen for changes connect to the #GDBusConnection::opened and
+ * #GDBusConnection::closed signals or listen for notifications on the
+ * #GDBusConnection:is-open property.
+ *
+ * Returns: %TRUE if the connection is open, %FALSE otherwise.
+ **/
+gboolean
+g_dbus_connection_get_is_open (GDBusConnection *connection)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+
+  return connection->priv->dbus_1_connection != NULL &&
+    dbus_connection_get_is_connected (connection->priv->dbus_1_connection);
+}
+
+/**
+ * g_dbus_connection_get_dbus_1_connection:
+ * @connection: A #GDBusConnection.
+ *
+ * Gets the underlying #DBusConnection object for @connection.
+ *
+ * Returns: %NULL if the connection is not open, otherwise a
+ * #DBusConnection object owned by @connection.
+ **/
+DBusConnection *
+g_dbus_connection_get_dbus_1_connection (GDBusConnection *connection)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+
+  return connection->priv->dbus_1_connection;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gboolean
+attempt_connect (GDBusConnection  *connection,
+                 GError          **error)
+{
+  DBusError dbus_error;
+  gboolean ret;
+  DBusConnection *dbus_1_connection;
+
+  ret = FALSE;
+
+  g_assert (connection->priv->dbus_1_connection == NULL);
+
+  dbus_error_init (&dbus_error);
+  g_assert (connection->priv->bus_type != G_MESSAGE_BUS_TYPE_NONE); // until we have constructors with @address
+  if (connection->priv->is_private)
+    {
+      dbus_1_connection = dbus_bus_get_private (connection->priv->bus_type,
+                                                &dbus_error);
+    }
+  else
+    {
+      dbus_1_connection = dbus_bus_get (connection->priv->bus_type,
+                                        &dbus_error);
+    }
+
+  if (dbus_1_connection != NULL)
+    {
+      g_dbus_connection_set_dbus_1_connection (connection, dbus_1_connection);
+      dbus_connection_unref (dbus_1_connection);
+      g_signal_emit (connection, signals[OPENED_SIGNAL], 0);
+      g_object_notify (G_OBJECT (connection), "is-open");
+      ret = TRUE;
+    }
+  else
+    {
+      g_dbus_error_set_dbus_error (error,
+                                   &dbus_error,
+                                   NULL,
+                                   NULL);
+      dbus_error_free (&dbus_error);
+    }
+
+  return ret;
+}
+
+static gboolean
+reconnect_timeout (gpointer user_data)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
+  gboolean keep_timeout;
+
+  keep_timeout = TRUE;
+  if (attempt_connect (connection, NULL))
+    {
+      keep_timeout = FALSE;
+      connection->priv->reconnect_timer_id = 0;
+    }
+
+  return keep_timeout;
+}
+
+static void
+setup_reconnect_timer (GDBusConnection *connection)
+{
+  g_assert (connection->priv->reconnect_timer_id == 0);
+
+  connection->priv->reconnect_timer_id = g_timeout_add_seconds (1,
+                                                                reconnect_timeout,
+                                                                connection);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+#define PRINT_MESSAGE(message)                          \
+  do {                                                  \
+    const gchar *message_type;                          \
+    switch (dbus_message_get_type (message))            \
+      {                                                 \
+      case DBUS_MESSAGE_TYPE_METHOD_CALL:               \
+        message_type = "method_call";                   \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_METHOD_RETURN:             \
+        message_type = "method_return";                 \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_ERROR:                     \
+        message_type = "error";                         \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_SIGNAL:                    \
+        message_type = "signal";                        \
+        break;                                          \
+      case DBUS_MESSAGE_TYPE_INVALID:                   \
+        message_type = "invalid";                       \
+        break;                                          \
+      default:                                          \
+        message_type = "unknown";                       \
+        break;                                          \
+      }                                                 \
+    g_print ("new message:\n"                           \
+             " type:         %s\n"                      \
+             " sender:       %s\n"                      \
+             " destination:  %s\n"                      \
+             " path:         %s\n"                      \
+             " interface:    %s\n"                      \
+             " member:       %s\n",                     \
+             message_type,                              \
+             dbus_message_get_sender (message),         \
+             dbus_message_get_destination (message),    \
+             dbus_message_get_path (message),           \
+             dbus_message_get_interface (message),      \
+             dbus_message_get_member (message));        \
+  } while (FALSE)
+
+static DBusHandlerResult
+filter_function (DBusConnection *dbus_1_connection,
+                 DBusMessage    *message,
+                 void           *user_data)
+{
+  GDBusConnection *connection = G_DBUS_CONNECTION (user_data);
+  DBusError dbus_error;
+
+  g_debug ("in filter_function for dbus_1_connection %p", dbus_1_connection);
+  PRINT_MESSAGE (message);
+
+  dbus_error_init (&dbus_error);
+
+  /* check if we are disconnected from the bus */
+  if (dbus_message_is_signal (message,
+                              DBUS_INTERFACE_LOCAL,
+                              "Disconnected") &&
+      dbus_message_get_sender (message) == NULL &&
+      dbus_message_get_destination (message) == NULL &&
+      g_strcmp0 (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0)
+    {
+      if (connection->priv->dbus_1_connection != NULL)
+        {
+          g_dbus_connection_set_dbus_1_connection (connection, NULL);
+
+          //g_object_notify (G_OBJECT (bus), "unique-name");
+          g_object_notify (G_OBJECT (connection), "is-open");
+          g_signal_emit (connection, signals[CLOSED_SIGNAL], 0);
+
+          /* set up timer for attempting to reconnect */
+          setup_reconnect_timer (connection);
+        }
+    }
+
+  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+}
+
+static void
+g_dbus_connection_set_dbus_1_connection (GDBusConnection *connection,
+                                         DBusConnection  *dbus_1_connection)
+{
+  g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
+
+  if (connection->priv->dbus_1_connection != NULL)
+    {
+      dbus_connection_remove_filter (connection->priv->dbus_1_connection,
+                                     filter_function,
+                                     connection);
+      g_dbus_unintegrate_dbus_1_connection (connection->priv->dbus_1_connection);
+      if (connection->priv->is_private)
+        {
+          dbus_connection_close (connection->priv->dbus_1_connection);
+        }
+      dbus_connection_unref (connection->priv->dbus_1_connection);
+    }
+
+  if (dbus_1_connection != NULL)
+    {
+      connection->priv->dbus_1_connection = dbus_connection_ref (dbus_1_connection);
+      g_dbus_integrate_dbus_1_connection (connection->priv->dbus_1_connection, NULL);
+      if (!dbus_connection_add_filter (connection->priv->dbus_1_connection,
+                                       filter_function,
+                                       connection,
+                                       NULL))
+        _g_dbus_oom ();
+      dbus_connection_set_exit_on_disconnect (connection->priv->dbus_1_connection,
+                                              connection->priv->exit_on_close);
+    }
+  else
+    {
+      connection->priv->dbus_1_connection = NULL;
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+
+static gboolean
+open_bus_connection (gpointer user_data)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data);
+  GDBusConnection *connection;
+  GError *error;
+
+  connection = G_DBUS_CONNECTION (g_simple_async_result_get_op_res_gpointer (simple));
+
+  error = NULL;
+  if (!attempt_connect (connection, &error))
+    {
+      g_simple_async_result_set_from_error (simple, error);
+      g_error_free (error);
+
+      /* set up timer for attempting to reconnect */
+      setup_reconnect_timer (connection);
+    }
+
+  g_simple_async_result_complete (simple);
+  g_object_unref (simple);
+
+  return FALSE;
+}
+
+static GDBusConnection *
+g_dbus_connection_bus_get_internal (GMessageBusType                bus_type,
+                                    gboolean                       private,
+                                    GCancellable                  *cancellable,
+                                    GAsyncReadyCallback            callback,
+                                    gpointer                       user_data)
+{
+  GDBusConnection *connection;
+  GSimpleAsyncResult *simple;
+
+  g_return_val_if_fail (bus_type != G_MESSAGE_BUS_TYPE_NONE, NULL);
+
+  connection = NULL;
+
+  /* TODO: use cancellable */
+
+  /* handle starter bus */
+  if (bus_type == G_MESSAGE_BUS_TYPE_STARTER)
+    {
+      const gchar *starter_bus;
+
+      starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE");
+      if (g_strcmp0 (starter_bus, "session") == 0)
+        {
+          bus_type = G_MESSAGE_BUS_TYPE_SESSION;
+        }
+      else if (g_strcmp0 (starter_bus, "system") == 0)
+        {
+          bus_type = G_MESSAGE_BUS_TYPE_SYSTEM;
+        }
+      else
+        {
+          g_critical ("Cannot construct a GDBusConnection object with bus_type G_MESSAGE_BUS_TYPE_STARTER "
+                      "because the DBUS_STARTER_BUS_TYPE environment variable is not set. "
+                      "This is an error in the application.");
+          goto out;
+        }
+    }
+
+  /* singleton handling */
+  if (!private)
+    {
+      G_LOCK (connection_lock);
+      if (bus_type == G_MESSAGE_BUS_TYPE_SESSION && the_session_bus != NULL)
+        {
+          connection = g_object_ref (the_session_bus);
+          simple = g_simple_async_result_new (G_OBJECT (connection),
+                                              callback,
+                                              user_data,
+                                              g_dbus_connection_bus_get_finish);
+          g_simple_async_result_complete_in_idle (simple);
+          g_object_unref (simple);
+          G_UNLOCK (connection_lock);
+          goto out;
+        }
+      else if (bus_type == G_MESSAGE_BUS_TYPE_SYSTEM && the_system_bus != NULL)
+        {
+          connection = g_object_ref (the_system_bus);
+          simple = g_simple_async_result_new (G_OBJECT (connection),
+                                              callback,
+                                              user_data,
+                                              g_dbus_connection_bus_get_finish);
+          g_simple_async_result_complete_in_idle (simple);
+          g_object_unref (simple);
+          G_UNLOCK (connection_lock);
+          goto out;
+        }
+    }
+
+  connection = G_DBUS_CONNECTION (g_object_new (G_TYPE_DBUS_CONNECTION,
+                                                "bus-type", bus_type,
+                                                NULL));
+  connection->priv->is_private = private;
+
+  if (!private)
+    {
+      /* singleton handling, part 2 */
+      if (bus_type == G_MESSAGE_BUS_TYPE_SESSION && the_session_bus == NULL)
+        {
+          the_session_bus = connection;
+        }
+      else if (bus_type == G_MESSAGE_BUS_TYPE_SYSTEM && the_system_bus == NULL)
+        {
+          the_system_bus = connection;
+        }
+      G_UNLOCK (connection_lock);
+    }
+
+  simple = g_simple_async_result_new (G_OBJECT (connection),
+                                      callback,
+                                      user_data,
+                                      private ? g_dbus_connection_bus_get_private_finish : g_dbus_connection_bus_get_finish);
+  g_simple_async_result_set_op_res_gpointer (simple,
+                                             connection,
+                                             NULL);
+  g_idle_add (open_bus_connection,
+              simple);
+
+ out:
+  return connection;
+}
+
+
+/**
+ * g_dbus_connection_bus_get:
+ * @bus_type: The bus type (can't be #G_MESSAGE_BUS_TYPE_NONE).
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: The callback function to invoke when finished attempting opening a connection.
+ * @user_data: User data to pass to @callback.
+ *
+ * <note><para>This class is rarely used directly; f you are
+ *             implementing a D-Bus service, it's often easier to use
+ *             g_bus_name_owner_new() and if you are implementing a
+ *             D-Bus client it's often easier to use TODO().
+ * </para></note>
+ * Creates a new #GDBusConnection object and then attempts to open a
+ * connection to the message bus specified by @bus_type. When the
+ * attempt to connect to the message bus is finished, @callback will
+ * be invoked (on the main thread) and you can use
+ * g_dbus_connection_bus_get_finish() to see if the connection could be
+ * opened.
+ *
+ * Note that the returned object is a singleton - i.e. it is shared
+ * among all callers of g_dbus_connection_bus_get() for the same message
+ * bus type. As such, the connection may already be open when using
+ * g_dbus_connection_bus_get(). In this case @callback will still be
+ * invoked and calls to g_dbus_connection_bus_get_finish() will not return
+ * error. Another observation is that you cannot rely on the
+ * #GDBusConnection::opened signal to fire if the connection is
+ * already open. You can however use g_dbus_connection_get_is_open()
+ * right after g_dbus_connection_bus_get() and just call the function you
+ * would normally use for the #GDBusConnection::opened signal handler.
+ *
+ * If the message bus that @connection is connected to vanishes, the
+ * #GDBusConnection::closed signal is emitted and the connection is
+ * closed. When (and if) the message bus reappears the
+ * #GDBusConnection::opened signal is emitted and the connection is
+ * open.
+ *
+ * Note that connections to message buses are created with the
+ * #GDBusConnection:exit-on-close set to %TRUE so if you intend to
+ * handle the case where the message bus is vanishing and appearing
+ * you need to change this property via
+ * e.g. g_dbus_connection_set_exit_on_close().
+ *
+ * An example of how this function typically is used can be seen in
+ * the following example.
+ * <example><title>Using g_dbus_connection_bus_get()</title><programlisting>
+ * static void
+ * on_connection_opened (GDBusConnection *connection,
+ *                       gpointer         user_data)
+ * {
+ *   /<!-- -->* the connection to the bus is now open, do something with connection *<!-- -->/
+ * }
+ *
+ * static void
+ * on_connection_closed (GDBusConnection *connection,
+ *                       gpointer         user_data)
+ * {
+ *   /<!-- -->* the connection to the message bus closed, clean up *<!-- -->/
+ * }
+ *
+ * static void
+ * get_bus_cb (GDBusConnection *connection,
+ *             GAsyncResult    *result,
+ *             gpointer         user_data)
+ * {
+ *   GError *error;
+ *
+ *   error = NULL;
+ *   if (!g_dbus_connection_bus_get_finish (connection, result, &error))
+ *     {
+ *       /<!-- -->* failed to connect to the message bus - typically apps
+ *        * want to complain on stderr and exit.
+ *        *<!-- -->/
+ *     }
+ * }
+ *
+ * void
+ * some_routine (SomeObject *data)
+ * {
+ *   data->priv->session_bus = g_dbus_connection_bus_get (G_MESSAGE_BUS_TYPE_SESSION,
+ *                                                        NULL,
+ *                                                        (GAsyncReadyCallback) get_bus_cb,
+ *                                                        data);
+ *   g_signal_connect (data->priv->session_bus, "opened", G_CALLBACK (on_connection_opened), data);
+ *   g_signal_connect (data->priv->session_bus, "closed", G_CALLBACK (on_connection_closed), data);
+ *   /<!-- -->* handle the case where the connection is already open *<!-- -->/
+ *   if (g_dbus_connection_get_is_open (data->priv->session_bus))
+ *     on_connection_opened (data->priv->session_bus, data);
+ * }
+ * </programlisting></example>
+ * If you need a private bus connection, use
+ * g_dbus_connection_bus_get_private() instead.
+ *
+ * Returns: A #GDBusConnection object. Free with g_object_unref().
+ */
+GDBusConnection *
+g_dbus_connection_bus_get (GMessageBusType                bus_type,
+                           GCancellable                  *cancellable,
+                           GAsyncReadyCallback            callback,
+                           gpointer                       user_data)
+{
+  return g_dbus_connection_bus_get_internal (bus_type,
+                                             FALSE,
+                                             cancellable,
+                                             callback,
+                                             user_data);
+}
+
+/**
+ * g_dbus_connection_bus_get_private:
+ * @bus_type: The bus type (can't be #G_MESSAGE_BUS_TYPE_NONE).
+ * @cancellable: A #GCancellable or %NULL.
+ * @callback: The callback function to invoke when finished attempting opening a connection.
+ * @user_data: User data to pass to @callback.
+ *
+ * Like g_dbus_connection_bus_get() but opens a #GDBusConnection that
+ * is not shared with anyone else.
+ *
+ * Returns: A #GDBusConnection object. Free with g_object_unref().
+ */
+GDBusConnection *
+g_dbus_connection_bus_get_private (GMessageBusType                bus_type,
+                                   GCancellable                  *cancellable,
+                                   GAsyncReadyCallback            callback,
+                                   gpointer                       user_data)
+{
+  return g_dbus_connection_bus_get_internal (bus_type,
+                                             TRUE,
+                                             cancellable,
+                                             callback,
+                                             user_data);
+}
+
+/**
+ * g_dbus_connection_bus_get_finish:
+ * @connection: A #GDBusConnection.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_connection_bus_get().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes opening a connection to a message bus.
+ *
+ * Returns: %TRUE if the @connection is open, otherwise %FALSE with @error set.
+ **/
+gboolean
+g_dbus_connection_bus_get_finish (GDBusConnection *connection,
+                                  GAsyncResult    *res,
+                                  GError         **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_bus_get_finish);
+  return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/**
+ * g_dbus_connection_bus_get_private_finish:
+ * @connection: A #GDBusConnection.
+ * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback function passed to g_dbus_connection_bus_get_private().
+ * @error: Return location for error or %NULL.
+ *
+ * Finishes opening a private connection to a message bus.
+ *
+ * Returns: %TRUE if the @connection is open, otherwise %FALSE with @error set.
+ **/
+gboolean
+g_dbus_connection_bus_get_private_finish (GDBusConnection *connection,
+                                          GAsyncResult    *res,
+                                          GError         **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+  g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == g_dbus_connection_bus_get_private_finish);
+  return !g_simple_async_result_propagate_error (simple, error);
+}
+
+/**
+ * g_dbus_connection_get_exit_on_close:
+ * @connection: A #GDBusConnection.
+ *
+ * Gets whether _exit() is called when @connection is closed.
+ *
+ * Returns: %TRUE if _exit() is called when @connection is closed.
+ **/
+gboolean
+g_dbus_connection_get_exit_on_close (GDBusConnection *connection)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), FALSE);
+
+  return connection->priv->exit_on_close;
+}
+
+/**
+ * g_dbus_connection_set_exit_on_close:
+ * @connection: A #GDBusConnection.
+ * @exit_on_close: Whether _exit() should be called when @connection is
+ * closed.
+ *
+ * Sets whether _exit() should be called when @connection is closed.
+ **/
+void
+g_dbus_connection_set_exit_on_close (GDBusConnection *connection,
+                                     gboolean         exit_on_close)
+{
+  g_return_if_fail (G_IS_DBUS_CONNECTION (connection));
+
+  connection->priv->exit_on_close = exit_on_close;
+  if (connection->priv->dbus_1_connection != NULL)
+    dbus_connection_set_exit_on_disconnect (connection->priv->dbus_1_connection,
+                                            connection->priv->exit_on_close);
+}
+
+/**
+ * g_dbus_connection_get_unique_name:
+ * @connection: A #GDBusConnection.
+ *
+ * Gets the unique name of @connection as assigned by the message bus.
+ *
+ * Returns: The unique name or %NULL if the connection is closed or
+ * @connection is not a message bus connection. Do not free this
+ * string, it is owned by @connection.
+ **/
+const gchar *
+g_dbus_connection_get_unique_name (GDBusConnection *connection)
+{
+  g_return_val_if_fail (G_IS_DBUS_CONNECTION (connection), NULL);
+
+  if (connection->priv->bus_type == G_MESSAGE_BUS_TYPE_NONE)
+    return NULL;
+
+  if (connection->priv->dbus_1_connection != NULL)
+    return dbus_bus_get_unique_name (connection->priv->dbus_1_connection);
+  else
+    return NULL;
+}
+
+
+#define __G_DBUS_CONNECTION_C__
+#include "gdbusaliasdef.c"
diff --git a/gdbus/gdbusconnection.h b/gdbus/gdbusconnection.h
new file mode 100644
index 0000000..a1688f1
--- /dev/null
+++ b/gdbus/gdbusconnection.h
@@ -0,0 +1,116 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_CONNECTION_H__
+#define __G_DBUS_CONNECTION_H__
+
+#include <gdbus/gdbustypes.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+#define G_TYPE_DBUS_CONNECTION         (g_dbus_connection_get_type ())
+#define G_DBUS_CONNECTION(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), G_TYPE_DBUS_CONNECTION, GDBusConnection))
+#define G_DBUS_CONNECTION_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), G_TYPE_DBUS_CONNECTION, GDBusConnectionClass))
+#define G_DBUS_CONNECTION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), G_TYPE_DBUS_CONNECTION, GDBusConnectionClass))
+#define G_IS_DBUS_CONNECTION(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), G_TYPE_DBUS_CONNECTION))
+#define G_IS_DBUS_CONNECTION_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), G_TYPE_DBUS_CONNECTION))
+
+typedef struct _GDBusConnectionClass   GDBusConnectionClass;
+typedef struct _GDBusConnectionPrivate GDBusConnectionPrivate;
+
+/**
+ * GDBusConnection:
+ *
+ * The #GDBusConnection structure contains only private data and
+ * should only be accessed using the provided API.
+ */
+struct _GDBusConnection
+{
+  /*< private >*/
+  GObject parent_instance;
+  GDBusConnectionPrivate *priv;
+};
+
+/**
+ * GDBusConnectionClass:
+ * @opened: Signal class handler for the #GDBusConnection::opened signal.
+ * @closed: Signal class handler for the #GDBusConnection::closed signal.
+ *
+ * Class structure for #GDBusConnection.
+ */
+struct _GDBusConnectionClass
+{
+  /*< private >*/
+  GObjectClass parent_class;
+
+  /*< public >*/
+
+  /* Signals */
+  void (*opened) (GDBusConnection *connection);
+  void (*closed) (GDBusConnection *connection);
+
+  /*< private >*/
+  /* Padding for future expansion */
+  void (*_g_reserved1) (void);
+  void (*_g_reserved2) (void);
+  void (*_g_reserved3) (void);
+  void (*_g_reserved4) (void);
+  void (*_g_reserved5) (void);
+  void (*_g_reserved6) (void);
+  void (*_g_reserved7) (void);
+  void (*_g_reserved8) (void);
+};
+
+GType            g_dbus_connection_get_type               (void) G_GNUC_CONST;
+
+GDBusConnection *g_dbus_connection_bus_get                (GMessageBusType      bus_type,
+                                                           GCancellable        *cancellable,
+                                                           GAsyncReadyCallback  callback,
+                                                           gpointer             user_data);
+gboolean         g_dbus_connection_bus_get_finish         (GDBusConnection     *connection,
+                                                           GAsyncResult        *res,
+                                                           GError             **error);
+
+GDBusConnection *g_dbus_connection_bus_get_private        (GMessageBusType      bus_type,
+                                                           GCancellable        *cancellable,
+                                                           GAsyncReadyCallback  callback,
+                                                           gpointer             user_data);
+gboolean         g_dbus_connection_bus_get_private_finish (GDBusConnection     *connection,
+                                                           GAsyncResult        *res,
+                                                           GError             **error);
+
+GMessageBusType  g_dbus_connection_get_bus_type           (GDBusConnection *connection);
+gboolean         g_dbus_connection_get_is_open            (GDBusConnection *connection);
+DBusConnection  *g_dbus_connection_get_dbus_1_connection  (GDBusConnection *connection);
+const gchar     *g_dbus_connection_get_unique_name        (GDBusConnection *connection);
+gboolean         g_dbus_connection_get_exit_on_close      (GDBusConnection *connection);
+void             g_dbus_connection_set_exit_on_close      (GDBusConnection *connection,
+                                                           gboolean         exit_on_close);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_CONNECTION_H__ */
diff --git a/gdbus/gdbusenums.h b/gdbus/gdbusenums.h
new file mode 100644
index 0000000..05af006
--- /dev/null
+++ b/gdbus/gdbusenums.h
@@ -0,0 +1,225 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_ENUMS_H__
+#define __G_DBUS_ENUMS_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+/**
+ * GMessageBusType:
+ * @G_MESSAGE_BUS_TYPE_NONE: Not a message bus connection.
+ * @G_MESSAGE_BUS_TYPE_SESSION: The login session message bus.
+ * @G_MESSAGE_BUS_TYPE_SYSTEM: The system-wide message bus.
+ * @G_MESSAGE_BUS_TYPE_STARTER: Connect to the bus that activated the program.
+ *
+ * An enumeration to specify the type of a #GDBusConnection.
+ */
+typedef enum
+{
+  G_MESSAGE_BUS_TYPE_NONE    = -1,
+  G_MESSAGE_BUS_TYPE_SESSION = DBUS_BUS_SESSION,
+  G_MESSAGE_BUS_TYPE_SYSTEM  = DBUS_BUS_SYSTEM,
+  G_MESSAGE_BUS_TYPE_STARTER = DBUS_BUS_STARTER,
+} GMessageBusType;
+
+/**
+ * GBusNameOwnerFlags:
+ * @G_BUS_NAME_OWNER_FLAGS_NONE: No flags set.
+ * @G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT: Allow another message connection to take the name.
+ * @G_BUS_NAME_OWNER_FLAGS_REPLACE: If another message bus connection
+ * owns the name and have specified #G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT, then
+ * take the name from the other connection.
+ *
+ * Flags used when constructing a #GBusNameOwner.
+ */
+typedef enum
+{
+  G_BUS_NAME_OWNER_FLAGS_NONE = 0,                    /*< nick=none >*/
+  G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT = (1<<0),  /*< nick=allow-replacement >*/
+  G_BUS_NAME_OWNER_FLAGS_REPLACE = (1<<1),            /*< nick=replace >*/
+} GBusNameOwnerFlags;
+
+/**
+ * GDBusError:
+ * @G_DBUS_ERROR_FAILED: The operation failed.
+ * @G_DBUS_ERROR_CANCELLED: The operation was cancelled.
+ * @G_DBUS_ERROR_REMOTE_EXCEPTION: A remote exception that couldn't be
+ * mapped to a #GError. Use g_dbus_error_get_remote_exception()
+ * to extract the D-Bus error name.
+ * @G_DBUS_ERROR_DBUS_FAILED:
+ * A generic error; "something went wrong" - see the error message for
+ * more.
+ * @G_DBUS_ERROR_NO_MEMORY:
+ * There was not enough memory to complete an operation.
+ * @G_DBUS_ERROR_SERVICE_UNKNOWN:
+ * The bus doesn't know how to launch a service to supply the bus name
+ * you wanted.
+ * @G_DBUS_ERROR_NAME_HAS_NO_OWNER:
+ * The bus name you referenced doesn't exist (i.e. no application owns
+ * it).
+ * @G_DBUS_ERROR_NO_REPLY:
+ * No reply to a message expecting one, usually means a timeout occurred.
+ * @G_DBUS_ERROR_IO_ERROR:
+ * Something went wrong reading or writing to a socket, for example.
+ * @G_DBUS_ERROR_BAD_ADDRESS:
+ * A D-Bus bus address was malformed.
+ * @G_DBUS_ERROR_NOT_SUPPORTED:
+ * Requested operation isn't supported (like ENOSYS on UNIX).
+ * @G_DBUS_ERROR_LIMITS_EXCEEDED:
+ * Some limited resource is exhausted.
+ * @G_DBUS_ERROR_ACCESS_DENIED:
+ * Security restrictions don't allow doing what you're trying to do.
+ * @G_DBUS_ERROR_AUTH_FAILED:
+ * Authentication didn't work.
+ * @G_DBUS_ERROR_NO_SERVER:
+ * Unable to connect to server (probably caused by ECONNREFUSED on a
+ * socket).
+ * @G_DBUS_ERROR_TIMEOUT:
+ * Certain timeout errors, possibly ETIMEDOUT on a socket.  Note that
+ * #G_DBUS_ERROR_NO_REPLY is used for message reply timeouts. Warning:
+ * this is confusingly-named given that #G_DBUS_ERROR_TIMED_OUT also
+ * exists. We can't fix it for compatibility reasons so just be
+ * careful.
+ * @G_DBUS_ERROR_NO_NETWORK:
+ * No network access (probably ENETUNREACH on a socket).
+ * @G_DBUS_ERROR_ADDRESS_IN_USE:
+ * Can't bind a socket since its address is in use (i.e. EADDRINUSE).
+ * @G_DBUS_ERROR_DISCONNECTED:
+ * The connection is disconnected and you're trying to use it.
+ * @G_DBUS_ERROR_INVALID_ARGS:
+ * Invalid arguments passed to a method call.
+ * @G_DBUS_ERROR_FILE_NOT_FOUND:
+ * Missing file.
+ * @G_DBUS_ERROR_FILE_EXISTS:
+ * Existing file and the operation you're using does not silently overwrite.
+ * @G_DBUS_ERROR_UNKNOWN_METHOD:
+ * Method name you invoked isn't known by the object you invoked it on.
+ * @G_DBUS_ERROR_TIMED_OUT:
+ * Certain timeout errors, e.g. while starting a service. Warning: this is
+ * confusingly-named given that #G_DBUS_ERROR_TIMEOUT also exists. We
+ * can't fix it for compatibility reasons so just be careful.
+ * @G_DBUS_ERROR_MATCH_RULE_NOT_FOUND:
+ * Tried to remove or modify a match rule that didn't exist.
+ * @G_DBUS_ERROR_MATCH_RULE_INVALID:
+ * The match rule isn't syntactically valid.
+ * @G_DBUS_ERROR_SPAWN_EXEC_FAILED:
+ * While starting a new process, the exec() call failed.
+ * @G_DBUS_ERROR_SPAWN_FORK_FAILED:
+ * While starting a new process, the fork() call failed.
+ * @G_DBUS_ERROR_SPAWN_CHILD_EXITED:
+ * While starting a new process, the child exited with a status code.
+ * @G_DBUS_ERROR_SPAWN_CHILD_SIGNALED:
+ * While starting a new process, the child exited on a signal.
+ * @G_DBUS_ERROR_SPAWN_FAILED:
+ * While starting a new process, something went wrong.
+ * @G_DBUS_ERROR_SPAWN_SETUP_FAILED:
+ * We failed to setup the environment correctly.
+ * @G_DBUS_ERROR_SPAWN_CONFIG_INVALID:
+ * We failed to setup the config parser correctly.
+ * @G_DBUS_ERROR_SPAWN_SERVICE_INVALID:
+ * Bus name was not valid.
+ * @G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND:
+ * Service file not found in system-services directory.
+ * @G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID:
+ * Permissions are incorrect on the setuid helper.
+ * @G_DBUS_ERROR_SPAWN_FILE_INVALID:
+ * Service file invalid (Name, User or Exec missing).
+ * @G_DBUS_ERROR_SPAWN_NO_MEMORY:
+ * Tried to get a UNIX process ID and it wasn't available.
+ * @G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN:
+ * Tried to get a UNIX process ID and it wasn't available.
+ * @G_DBUS_ERROR_INVALID_SIGNATURE:
+ * A type signature is not valid.
+ * @G_DBUS_ERROR_INVALID_FILE_CONTENT:
+ * A file contains invalid syntax or is otherwise broken.
+ * @G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN:
+ * Asked for SELinux security context and it wasn't available.
+ * @G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN:
+ * Asked for ADT audit data and it wasn't available.
+ * @G_DBUS_ERROR_OBJECT_PATH_IN_USE:
+ * There's already an object with the requested object path.
+ *
+ * Error codes.
+ */
+typedef enum
+{
+  G_DBUS_ERROR_FAILED,                           /*< nick=org.gtk.GDBus.Error.Failed >*/
+  G_DBUS_ERROR_CANCELLED,                        /*< nick=org.gtk.GDBus.Error.Cancelled >*/
+  G_DBUS_ERROR_REMOTE_EXCEPTION,                 /*< nick=org.gtk.GDBus.Error.RemoteException >*/
+
+  /* Well-known errors in the org.freedesktop.DBus.Error namespace */
+  G_DBUS_ERROR_DBUS_FAILED            = 1000,    /*< nick=org.freedesktop.DBus.Error.Failed >*/
+  G_DBUS_ERROR_NO_MEMORY,                        /*< nick=org.freedesktop.DBus.Error.NoMemory >*/
+  G_DBUS_ERROR_SERVICE_UNKNOWN,                  /*< nick=org.freedesktop.DBus.Error.ServiceUnknown >*/
+  G_DBUS_ERROR_NAME_HAS_NO_OWNER,                /*< nick=org.freedesktop.DBus.Error.NameHasNoOwner >*/
+  G_DBUS_ERROR_NO_REPLY,                         /*< nick=org.freedesktop.DBus.Error.NoReply >*/
+  G_DBUS_ERROR_IO_ERROR,                         /*< nick=org.freedesktop.DBus.Error.IOError >*/
+  G_DBUS_ERROR_BAD_ADDRESS,                      /*< nick=org.freedesktop.DBus.Error.BadAddress >*/
+  G_DBUS_ERROR_NOT_SUPPORTED,                    /*< nick=org.freedesktop.DBus.Error.NotSupported >*/
+  G_DBUS_ERROR_LIMITS_EXCEEDED,                  /*< nick=org.freedesktop.DBus.Error.LimitsExceeded >*/
+  G_DBUS_ERROR_ACCESS_DENIED,                    /*< nick=org.freedesktop.DBus.Error.AccessDenied >*/
+  G_DBUS_ERROR_AUTH_FAILED,                      /*< nick=org.freedesktop.DBus.Error.AuthFailed >*/
+  G_DBUS_ERROR_NO_SERVER,                        /*< nick=org.freedesktop.DBus.Error.NoServer >*/
+  G_DBUS_ERROR_TIMEOUT,                          /*< nick=org.freedesktop.DBus.Error.Timeout >*/
+  G_DBUS_ERROR_NO_NETWORK,                       /*< nick=org.freedesktop.DBus.Error.NoNetwork >*/
+  G_DBUS_ERROR_ADDRESS_IN_USE,                   /*< nick=org.freedesktop.DBus.Error.AddressInUse >*/
+  G_DBUS_ERROR_DISCONNECTED,                     /*< nick=org.freedesktop.DBus.Error.Disconnected >*/
+  G_DBUS_ERROR_INVALID_ARGS,                     /*< nick=org.freedesktop.DBus.Error.InvalidArgs >*/
+  G_DBUS_ERROR_FILE_NOT_FOUND,                   /*< nick=org.freedesktop.DBus.Error.FileNotFound >*/
+  G_DBUS_ERROR_FILE_EXISTS,                      /*< nick=org.freedesktop.DBus.Error.FileExists >*/
+  G_DBUS_ERROR_UNKNOWN_METHOD,                   /*< nick=org.freedesktop.DBus.Error.UnknownMethod >*/
+  G_DBUS_ERROR_TIMED_OUT,                        /*< nick=org.freedesktop.DBus.Error.TimedOut >*/
+  G_DBUS_ERROR_MATCH_RULE_NOT_FOUND,             /*< nick=org.freedesktop.DBus.Error.MatchRuleNotFound >*/
+  G_DBUS_ERROR_MATCH_RULE_INVALID,               /*< nick=org.freedesktop.DBus.Error.MatchRuleInvalid >*/
+  G_DBUS_ERROR_SPAWN_EXEC_FAILED,                /*< nick=org.freedesktop.DBus.Error.Spawn.ExecFailed >*/
+  G_DBUS_ERROR_SPAWN_FORK_FAILED,                /*< nick=org.freedesktop.DBus.Error.Spawn.ForkFailed >*/
+  G_DBUS_ERROR_SPAWN_CHILD_EXITED,               /*< nick=org.freedesktop.DBus.Error.Spawn.ChildExited >*/
+  G_DBUS_ERROR_SPAWN_CHILD_SIGNALED,             /*< nick=org.freedesktop.DBus.Error.Spawn.ChildSignaled >*/
+  G_DBUS_ERROR_SPAWN_FAILED,                     /*< nick=org.freedesktop.DBus.Error.Spawn.Failed >*/
+  G_DBUS_ERROR_SPAWN_SETUP_FAILED,               /*< nick=org.freedesktop.DBus.Error.Spawn.FailedToSetup >*/
+  G_DBUS_ERROR_SPAWN_CONFIG_INVALID,             /*< nick=org.freedesktop.DBus.Error.Spawn.ConfigInvalid >*/
+  G_DBUS_ERROR_SPAWN_SERVICE_INVALID,            /*< nick=org.freedesktop.DBus.Error.Spawn.ServiceNotValid >*/
+  G_DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND,          /*< nick=org.freedesktop.DBus.Error.Spawn.ServiceNotFound >*/
+  G_DBUS_ERROR_SPAWN_PERMISSIONS_INVALID,        /*< nick=org.freedesktop.DBus.Error.Spawn.PermissionsInvalid >*/
+  G_DBUS_ERROR_SPAWN_FILE_INVALID,               /*< nick=org.freedesktop.DBus.Error.Spawn.FileInvalid >*/
+  G_DBUS_ERROR_SPAWN_NO_MEMORY,                  /*< nick=org.freedesktop.DBus.Error.Spawn.NoMemory >*/
+  G_DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,          /*< nick=org.freedesktop.DBus.Error.UnixProcessIdUnknown >*/
+  G_DBUS_ERROR_INVALID_SIGNATURE,                /*< nick=org.freedesktop.DBus.Error.InvalidSignature >*/
+  G_DBUS_ERROR_INVALID_FILE_CONTENT,             /*< nick=org.freedesktop.DBus.Error.InvalidFileContent >*/
+  G_DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN, /*< nick=org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown >*/
+  G_DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,           /*< nick=org.freedesktop.DBus.Error.AdtAuditDataUnknown >*/
+  G_DBUS_ERROR_OBJECT_PATH_IN_USE,               /*< nick=org.freedesktop.DBus.Error.ObjectPathInUse >*/
+} GDBusError;
+
+
+G_END_DECLS
+
+#endif /* __G_DBUS_ENUMS_H__ */
diff --git a/gdbus/gdbusenumtypes.c.template b/gdbus/gdbusenumtypes.c.template
new file mode 100644
index 0000000..f4aff8a
--- /dev/null
+++ b/gdbus/gdbusenumtypes.c.template
@@ -0,0 +1,42 @@
+/*** BEGIN file-header ***/
+#include <gdbus.h>
+#include "gdbusalias.h"
+
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType
+ enum_name@_get_type (void)
+{
+  static volatile gsize g_define_type_id__volatile = 0;
+
+  if (g_once_init_enter (&g_define_type_id__volatile))
+    {
+      static const G Type@Value values[] = {
+/*** END value-header ***/
+
+/*** BEGIN value-production ***/
+        { @VALUENAME@, "@VALUENAME@", "@valuenick@" },
+/*** END value-production ***/
+
+/*** BEGIN value-tail ***/
+        { 0, NULL, NULL }
+      };
+      GType g_define_type_id =
+        g_ type@_register_static (g_intern_static_string ("@EnumName@"), values);
+      g_once_init_leave (&g_define_type_id__volatile, g_define_type_id);
+    }
+
+  return g_define_type_id__volatile;
+}
+
+/*** END value-tail ***/
+
+/*** BEGIN file-tail ***/
+#define __G_DBUS_ENUM_TYPES_C__
+#include "gdbusaliasdef.c"
+/*** END file-tail ***/
diff --git a/gdbus/gdbusenumtypes.h.template b/gdbus/gdbusenumtypes.h.template
new file mode 100644
index 0000000..b905a8f
--- /dev/null
+++ b/gdbus/gdbusenumtypes.h.template
@@ -0,0 +1,24 @@
+/*** BEGIN file-header ***/
+#ifndef __G_DBUS_ENUM_TYPES_H__
+#define __G_DBUS_ENUM_TYPES_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+/*** END file-header ***/
+
+/*** BEGIN file-production ***/
+
+/* enumerations from "@filename@" */
+/*** END file-production ***/
+
+/*** BEGIN value-header ***/
+GType @enum_name _get_type (void) G_GNUC_CONST;
+#define @ENUMPREFIX _TYPE_@ENUMSHORT@ (@enum_name _get_type ())
+/*** END value-header ***/
+
+/*** BEGIN file-tail ***/
+G_END_DECLS
+
+#endif /* __G_DBUS_ENUM_TYPES_H__ */
+/*** END file-tail ***/
diff --git a/gdbus/gdbuserror.c b/gdbus/gdbuserror.c
new file mode 100644
index 0000000..a76b375
--- /dev/null
+++ b/gdbus/gdbuserror.c
@@ -0,0 +1,507 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+
+#include "gdbuserror.h"
+#include "gdbusenumtypes.h"
+
+#include "gdbusalias.h"
+
+/**
+ * SECTION:gdbuserror
+ * @title: GDBusError
+ * @short_description: Error helper functions
+ * @include: gdbus/gdbus.h
+ *
+ * Contains error helper functions for GDBus.
+ */
+
+/**
+ * g_dbus_error_quark:
+ *
+ * Gets the GDBus Error Quark.
+ *
+ * Return value: a #GQuark.
+ **/
+GQuark
+g_dbus_error_quark (void)
+{
+  return g_quark_from_static_string ("g-dbus-error-quark");
+}
+
+/**
+ * g_dbus_error_get_remote_exception:
+ * @error: A #GError.
+ * @out_name: Return location for D-Bus error name or %NULL.
+ * @out_message: Return location for D-Bus error message or %NULL.
+ *
+ * Analyzes @error and if the error domain is #G_DBUS_ERROR and
+ * error code is #G_DBUS_ERROR_REMOTE_EXCEPTION, extracts the D-Bus
+ * error name (e.g. <literal>com.example.Acme.Error.Failed</literal>)
+ * in @out_name and the D-Bus error message in @out_message and
+ * returns %TRUE.
+ *
+ * Note that this function will not warn if @error isn't a
+ * #G_DBUS_ERROR_REMOTE_EXCEPTION (it will just return %FALSE) so it
+ * can be used to test if @error is really a
+ * #G_DBUS_ERROR_REMOTE_EXCEPTION.
+ *
+ * Returns: %TRUE if @out_name and @out_message is set (caller must
+ * free these using g_free()), %FALSE if error is not a
+ * #G_DBUS_ERROR_REMOTE_EXCEPTION.
+ **/
+gboolean
+g_dbus_error_get_remote_exception (GError  *error,
+                                   gchar  **out_name,
+                                   gchar  **out_message)
+{
+  gchar *s;
+  gchar *p;
+
+  g_return_val_if_fail (error != NULL, FALSE);
+
+  if (error->domain != G_DBUS_ERROR ||
+      error->code != G_DBUS_ERROR_REMOTE_EXCEPTION)
+    return FALSE;
+
+  if (out_name != NULL)
+    *out_name = NULL;
+  if (out_message != NULL)
+    *out_message = NULL;
+
+  s = strrchr (error->message, ' ');
+  if (s == NULL || s == error->message)
+    {
+      g_warning ("message '%s' is malformed", error->message);
+      goto out;
+    }
+  if (out_message != NULL)
+    *out_message = g_uri_unescape_string (s + 1, NULL);
+
+  p = s;
+  s--;
+  while (*s != ' ')
+    {
+      if (s < error->message)
+        {
+          g_warning ("message '%s' is malformed.", error->message);
+          goto out;
+        }
+      s--;
+    }
+  if (out_name != NULL)
+    *out_name = g_uri_unescape_segment (s + 1, p, NULL);
+
+ out:
+
+  return TRUE;
+}
+
+/**
+ * g_dbus_error_new_for_gerror:
+ * @error: A #GError.
+ * @dbus_error: Return location for #DBusError.
+ *
+ * Utility function to map a #GError to a #DBusError by getting the
+ * D-Bus error name from the nick of the element of the registered
+ * enumeration type for the error domain for @error.
+ *
+ * If the nick is not a valid D-Bus error name or the enumeration for
+ * the error domain for @error is not registered with the type system,
+ * the returned #DBusError will be of the form
+ * org.gtk.GDBus.UnmappedGError.Quark_HEXENCODED_QUARK_NAME_.Code_ERROR_CODE. This
+ * allows other GDBus applications to map the #DBusError back to the
+ * #GError using g_dbus_error_new_for_dbus_error().
+ *
+ * This function is intended for use by object mappings only.
+ */
+void
+g_dbus_error_new_for_gerror (GError    *error,
+                             DBusError *dbus_error)
+{
+  const gchar *domain_as_string;
+  gchar *error_name;
+  GString *s;
+  guint n;
+  GType enum_type;
+
+  error_name = NULL;
+
+  /* We can't assume that two different processes use the same Quark integer
+   * value for a given string. So send the string across the wire.
+   */
+  domain_as_string = g_quark_to_string (error->domain);
+
+  /* Also use the nick-name to produce error names compatible with
+   * non-GLib applications; note that GDBusError may not have
+   * been initialized so special case that.
+   */
+  if (strcmp (domain_as_string, "GDBusError") == 0)
+    enum_type = G_TYPE_DBUS_ERROR;
+  else
+    enum_type = g_type_from_name (domain_as_string);
+  if (enum_type != 0)
+    {
+      GEnumClass *enum_klass;
+      GEnumValue *enum_value;
+
+      enum_klass = g_type_class_ref (enum_type);
+      enum_value = g_enum_get_value (enum_klass, error->code);
+      g_type_class_unref (enum_klass);
+      if (enum_value != NULL)
+        {
+          /* TODO: it's the users own problem if value_nick isn't a proper D-Bus
+           * error name. Or is it? We should probably validate it...
+           */
+          error_name = g_strdup (enum_value->value_nick);
+          goto out;
+        }
+    }
+
+  /* We can't make a lot of assumptions about what domain_as_string
+   * looks like and D-Bus is extremely picky about error names so
+   * hex-encode it for transport across the wire.
+   */
+
+  s = g_string_new ("org.gtk.GDBus.UnmappedGError.Quark0x");
+  for (n = 0; domain_as_string[n] != 0; n++)
+    {
+      guint nibble_top;
+      guint nibble_bottom;
+
+      nibble_top = ((int) domain_as_string[n]) >> 4;
+      nibble_bottom = ((int) domain_as_string[n]) & 0x0f;
+
+      if (nibble_top < 10)
+        nibble_top += '0';
+      else
+        nibble_top += 'a' - 10;
+
+      if (nibble_bottom < 10)
+        nibble_bottom += '0';
+      else
+        nibble_bottom += 'a' - 10;
+
+      g_string_append_c (s, nibble_top);
+      g_string_append_c (s, nibble_bottom);
+    }
+  g_string_append_printf (s, ".Code%d", error->code);
+
+  error_name = g_string_free (s, FALSE);
+
+ out:
+  dbus_error_init (dbus_error);
+  dbus_set_error (dbus_error,
+                  error_name,
+                  "%s",
+                  error->message);
+}
+
+static gboolean
+_g_dbus_error_decode_gerror (const gchar *dbus_name,
+                             GQuark      *out_error_domain,
+                             gint        *out_error_code)
+{
+  gboolean ret;
+  guint n;
+  GString *s;
+  gchar *domain_quark_string;
+
+  ret = FALSE;
+  s = NULL;
+
+  if (g_str_has_prefix (dbus_name, "org.gtk.GDBus.UnmappedGError.Quark0x"))
+    {
+      s = g_string_new (NULL);
+
+      for (n = sizeof "org.gtk.GDBus.UnmappedGError.Quark0x" - 1;
+           dbus_name[n] != '.' && dbus_name[n] != '\0';
+           n++)
+        {
+          guint nibble_top;
+          guint nibble_bottom;
+
+          nibble_top = dbus_name[n];
+          if (nibble_top >= '0' && nibble_top <= '9')
+            nibble_top -= '0';
+          else if (nibble_top >= 'a' && nibble_top <= 'f')
+            nibble_top -= ('a' - 10);
+          else
+            goto not_mapped;
+
+          n++;
+
+          nibble_bottom = dbus_name[n];
+          if (nibble_bottom >= '0' && nibble_bottom <= '9')
+            nibble_bottom -= '0';
+          else if (nibble_bottom >= 'a' && nibble_bottom <= 'f')
+            nibble_bottom -= ('a' - 10);
+          else
+            goto not_mapped;
+
+          g_string_append_c (s, (nibble_top<<4) | nibble_bottom);
+
+        }
+
+      if (!g_str_has_prefix (dbus_name + n, ".Code"))
+        goto not_mapped;
+
+      domain_quark_string = g_string_free (s, FALSE);
+      s = NULL;
+
+      if (out_error_domain != NULL)
+        *out_error_domain = g_quark_from_string (domain_quark_string);
+      g_free (domain_quark_string);
+
+      if (out_error_code != NULL)
+        *out_error_code = atoi (dbus_name + n + sizeof ".Code" - 1);
+
+      ret = TRUE;
+    }
+
+ not_mapped:
+
+  if (s != NULL)
+    g_string_free (s, TRUE);
+
+  return ret;
+}
+
+/**
+ * g_dbus_error_new_for_dbus_error_valist:
+ * @dbus_error: A #DBusError.
+ * @error_types: %NULL or a #G_TYPE_INVALID terminated array of #GType<!-- -->s for error domains to consider.
+ * @prepend_format: %NULL or format for message to prepend to the D-Bus error message.
+ * @va_args: Arguments for @prepend_format.
+ *
+ * Like g_dbus_error_new_for_dbus_error() but intended for language
+ * bindings.
+ *
+ * This function is intended for use by object mappings only.
+ *
+ * Returns: A newly allocated #GError. Free with g_error_free().
+ **/
+GError *
+g_dbus_error_new_for_dbus_error_valist (DBusError   *dbus_error,
+                                        GType       *error_types,
+                                        const gchar *prepend_format,
+                                        va_list      va_args)
+{
+  GString *literal_error;
+  gchar *name_escaped;
+  gchar *message_escaped;
+  GError *error;
+  GQuark error_domain;
+  gint error_code;
+  GEnumClass *enum_klass;
+  GEnumValue *enum_value;
+  guint n;
+
+  g_return_val_if_fail (dbus_error != NULL, NULL);
+
+  literal_error = g_string_new (NULL);
+  if (prepend_format != NULL)
+    g_string_append_vprintf (literal_error, prepend_format, va_args);
+  g_string_append (literal_error, dbus_error->message);
+
+  /* Unmapped GError's from GLib peers are encoded in a special format can be mapped
+   * back to the right domain and code; see _g_dbus_error_encode_gerror()
+   */
+  if (_g_dbus_error_decode_gerror (dbus_error->name, &error_domain, &error_code))
+    goto mapped;
+
+  error_domain = G_DBUS_ERROR;
+
+  /* Otherwise lookup our registered error types
+   *
+   *   TODO: reading the GObject sources, g_enum_get_value_by_nick is O(n); maybe cache in a hash
+   *         table if performance is a concern? It probably isn't; errors should be rare...
+   *
+   * First check our built-in error type...
+   */
+  enum_klass = g_type_class_ref (G_TYPE_DBUS_ERROR);
+  enum_value = g_enum_get_value_by_nick (enum_klass, dbus_error->name);
+  g_type_class_unref (enum_klass);
+  if (enum_value != NULL)
+    {
+      error_code = enum_value->value;
+      goto mapped;
+    }
+  /* then check all error domains the user passed in (via e.g. g_dbus_connection_send_message_with_reply()) */
+  for (n = 0; error_types != NULL && error_types[n] != G_TYPE_INVALID; n++)
+    {
+      enum_klass = g_type_class_ref (error_types[n]);
+      enum_value = g_enum_get_value_by_nick (enum_klass, dbus_error->name);
+      g_type_class_unref (enum_klass);
+      if (enum_value != NULL)
+        {
+          error_domain = g_quark_from_static_string (g_type_name (error_types[n]));
+          error_code = enum_value->value;
+          goto mapped;
+        }
+    }
+
+  /* Otherwise we fall back to returning a G_DBUS_ERROR_REMOTE_EXCEPTION error with enough
+   * detail such that the D-Bus error name and error message can be decoded using the
+   * g_dbus_error_get_remote_exception() function.
+   */
+  error_code = G_DBUS_ERROR_REMOTE_EXCEPTION;
+
+  name_escaped = g_uri_escape_string (dbus_error->name, NULL, TRUE);
+  message_escaped = g_uri_escape_string (dbus_error->message, NULL, TRUE);
+
+  g_string_append_c (literal_error, ' ');
+  g_string_append (literal_error, name_escaped);
+  g_string_append_c (literal_error, ' ');
+  g_string_append (literal_error, message_escaped);
+
+ mapped:
+
+  error = g_error_new_literal (error_domain,
+                               error_code,
+                               literal_error->str);
+
+  g_string_free (literal_error, TRUE);
+
+  return error;
+}
+
+/**
+ * g_dbus_error_new_for_dbus_error:
+ * @dbus_error: A #DBusError.
+ * @error_types: %NULL or a #G_TYPE_INVALID terminated array of #GType<!-- -->s for error domains to consider.
+ * @prepend_format: %NULL or format for message to prepend to the D-Bus error message.
+ * @...: Arguments for @prepend_format.
+ *
+ * Utility function to map a #DBusError to a #GError by matching the
+ * name of @dbus_error with the nick names in the enumerations
+ * specified by the @error_types array.
+ *
+ * This function also handles unmapped #GError<!-- -->'s as described
+ * in g_dbus_error_new_for_gerror().
+ *
+ * If no suitable error code is found, then
+ * #G_DBUS_ERROR_REMOTE_EXCEPTION in the #G_DBUS_ERROR domain is used
+ * and an encoded form of the name and message from @dbus_error is
+ * appended to the message text such that the user can get this back
+ * via g_dbus_error_get_remote_exception().
+ *
+ * This function is intended for use by object mappings only.
+ *
+ * Returns: A newly allocated #GError. Free with g_error_free().
+ */
+GError *
+g_dbus_error_new_for_dbus_error (DBusError   *dbus_error,
+                                 GType       *error_types,
+                                 const gchar *prepend_format,
+                                 ...)
+{
+  va_list va_args;
+  GError *new_error;
+
+  va_start (va_args, prepend_format);
+  new_error = g_dbus_error_new_for_dbus_error_valist (dbus_error,
+                                                      error_types,
+                                                      prepend_format,
+                                                      va_args);
+  va_end (va_args);
+
+  return new_error;
+}
+
+/**
+ * g_dbus_error_set_dbus_error:
+ * @error: %NULL or a #GError to set.
+ * @dbus_error: A #DBusError.
+ * @error_types: %NULL or a #G_TYPE_INVALID terminated array of #GType<!-- -->s for error domains to consider.
+ * @prepend_format: %NULL or format for message to prepend to the D-Bus error message.
+ * @...: Arguments for @prepend_format.
+ *
+ * Does nothing if @error is %NULL; if @error is non-%NULL, then
+ * * error must be NULL. A new #GError is created and assigned to
+ * * error using g_dbus_error_new_for_dbus_error().
+ *
+ * This function is intended for use by object mappings only.
+ */
+void
+g_dbus_error_set_dbus_error (GError      **error,
+                             DBusError    *dbus_error,
+                             GType        *error_types,
+                             const gchar  *prepend_format,
+                             ...)
+{
+  va_list va_args;
+  GError *new_error;
+
+  if (error == NULL)
+    return;
+
+  va_start (va_args, prepend_format);
+  new_error = g_dbus_error_new_for_dbus_error_valist (dbus_error,
+                                                      error_types,
+                                                      prepend_format,
+                                                      va_args);
+  *error = new_error;
+  va_end (va_args);
+}
+
+/**
+ * g_dbus_error_set_dbus_error_valist:
+ * @error: %NULL or a #GError to set.
+ * @dbus_error: A #DBusError.
+ * @error_types: %NULL or a #G_TYPE_INVALID terminated array of #GType<!-- -->s for error domains to consider.
+ * @prepend_format: %NULL or format for message to prepend to the D-Bus error message.
+ * @va_args: Arguments for @prepend_format.
+ *
+ * Like g_dbus_error_set_dbus_error() but intended for language
+ * bindings.
+ *
+ * This function is intended for use by object mappings only.
+ */
+void
+g_dbus_error_set_dbus_error_valist (GError      **error,
+                                    DBusError    *dbus_error,
+                                    GType        *error_types,
+                                    const gchar  *prepend_format,
+                                    va_list       va_args)
+{
+  GError *new_error;
+
+  if (error == NULL)
+    return;
+
+  new_error = g_dbus_error_new_for_dbus_error_valist (dbus_error,
+                                                      error_types,
+                                                      prepend_format,
+                                                      va_args);
+  *error = new_error;
+}
+
+
+
+#define __G_DBUS_ERROR_C__
+#include "gdbusaliasdef.c"
diff --git a/gdbus/gdbuserror.h b/gdbus/gdbuserror.h
new file mode 100644
index 0000000..3922ad6
--- /dev/null
+++ b/gdbus/gdbuserror.h
@@ -0,0 +1,80 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_ERROR_H__
+#define __G_DBUS_ERROR_H__
+
+#include <gdbus/gdbustypes.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+/**
+ * G_DBUS_ERROR:
+ *
+ * Error domain for GDBus. Errors in this domain will be from the #GDBusError enumeration.
+ * See #GError for more information on error domains.
+ **/
+#define G_DBUS_ERROR g_dbus_error_quark()
+
+GQuark g_dbus_error_quark (void);
+
+gboolean g_dbus_error_get_remote_exception (GError  *error,
+                                            gchar  **out_name,
+                                            gchar  **out_message);
+
+/* Map DBusError to GError (only intended for object mappings) */
+
+GError *g_dbus_error_new_for_dbus_error_valist (DBusError   *dbus_error,
+                                                GType       *error_types,
+                                                const gchar *prepend_format,
+                                                va_list      va_args);
+
+GError *g_dbus_error_new_for_dbus_error (DBusError   *dbus_error,
+                                         GType       *error_types,
+                                         const gchar *prepend_format,
+                                         ...);
+
+void g_dbus_error_set_dbus_error (GError      **error,
+                                  DBusError    *dbus_error,
+                                  GType        *error_types,
+                                  const gchar  *prepend_format,
+                                  ...);
+
+void g_dbus_error_set_dbus_error_valist (GError      **error,
+                                         DBusError    *dbus_error,
+                                         GType        *error_types,
+                                         const gchar  *prepend_format,
+                                         va_list       va_args);
+
+/* Map GError to DBusError (only intended for object mappings) */
+
+void g_dbus_error_new_for_gerror (GError    *error,
+                                  DBusError *dbus_error);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_ERROR_H__ */
diff --git a/gdbus/gdbusmainloop.c b/gdbus/gdbusmainloop.c
new file mode 100644
index 0000000..5347585
--- /dev/null
+++ b/gdbus/gdbusmainloop.c
@@ -0,0 +1,782 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+
+#include "gdbusmainloop.h"
+#include "gdbusprivate.h"
+
+#include "gdbusalias.h"
+
+/**
+ * SECTION:gdbusmainloop
+ * @title: Main-loop integration
+ * @short_description: Main-loop integration routines
+ * @include: gdbus/gdbus.h
+ *
+ * Routines for integration #DBusConnection and #DBusServer objects
+ * with the GLib main loop.
+ */
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* The following code is adopted from dbus/dbus-gmain.c in dbus-glib. Copright notices
+ * and license:
+ *
+ * Copyright (C) 2002, 2003 CodeFactory AB
+ * Copyright (C) 2005 Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * 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.
+ */
+
+typedef struct
+{
+  GSource source; /**< the parent GSource */
+  DBusConnection *connection; /**< the connection to dispatch */
+} DBusGMessageQueue;
+
+static gboolean message_queue_prepare  (GSource     *source,
+                                        gint        *timeout);
+static gboolean message_queue_check    (GSource     *source);
+static gboolean message_queue_dispatch (GSource     *source,
+                                        GSourceFunc  callback,
+                                        gpointer     user_data);
+
+static const GSourceFuncs message_queue_funcs = {
+  message_queue_prepare,
+  message_queue_check,
+  message_queue_dispatch,
+  NULL
+};
+
+static gboolean
+message_queue_prepare (GSource *source,
+                       gint    *timeout)
+{
+  DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+
+  *timeout = -1;
+
+  return (dbus_connection_get_dispatch_status (connection) == DBUS_DISPATCH_DATA_REMAINS);
+}
+
+static gboolean
+message_queue_check (GSource *source)
+{
+  return FALSE;
+}
+
+static gboolean
+message_queue_dispatch (GSource     *source,
+                        GSourceFunc  callback,
+                        gpointer     user_data)
+{
+  DBusConnection *connection = ((DBusGMessageQueue *)source)->connection;
+
+  dbus_connection_ref (connection);
+
+  /* Only dispatch once - we don't want to starve other GSource */
+  dbus_connection_dispatch (connection);
+
+  dbus_connection_unref (connection);
+
+  return TRUE;
+}
+
+typedef struct
+{
+  GMainContext *context;      /**< the main context */
+  GSList *ios;                /**< all IOHandler */
+  GSList *timeouts;           /**< all TimeoutHandler */
+  DBusConnection *connection; /**< NULL if this is really for a server not a connection */
+  GSource *message_queue_source; /**< DBusGMessageQueue */
+} ConnectionSetup;
+
+
+typedef struct
+{
+  ConnectionSetup *cs;
+  GSource *source;
+  DBusWatch *watch;
+} IOHandler;
+
+typedef struct
+{
+  ConnectionSetup *cs;
+  GSource *source;
+  DBusTimeout *timeout;
+} TimeoutHandler;
+
+G_LOCK_DEFINE_STATIC (main_loop_lock);
+
+dbus_int32_t _dbus_gmain_connection_slot = -1;
+static dbus_int32_t server_slot = -1;
+
+static ConnectionSetup*
+connection_setup_new (GMainContext   *context,
+                      DBusConnection *connection)
+{
+  ConnectionSetup *cs;
+
+  cs = g_new0 (ConnectionSetup, 1);
+
+  g_assert (context != NULL);
+
+  cs->context = context;
+  g_main_context_ref (cs->context);
+
+  if (connection)
+    {
+      cs->connection = connection;
+
+      cs->message_queue_source = g_source_new ((GSourceFuncs *) &message_queue_funcs,
+                                               sizeof (DBusGMessageQueue));
+      ((DBusGMessageQueue*)cs->message_queue_source)->connection = connection;
+      g_source_attach (cs->message_queue_source, cs->context);
+    }
+
+  return cs;
+}
+
+static void
+io_handler_source_finalized (gpointer data)
+{
+  IOHandler *handler;
+
+  handler = data;
+
+  if (handler->watch)
+    dbus_watch_set_data (handler->watch, NULL, NULL);
+
+  g_free (handler);
+}
+
+static void
+io_handler_destroy_source (void *data)
+{
+  IOHandler *handler;
+
+  handler = data;
+
+  if (handler->source)
+    {
+      GSource *source = handler->source;
+      handler->source = NULL;
+      handler->cs->ios = g_slist_remove (handler->cs->ios, handler);
+      g_source_destroy (source);
+      g_source_unref (source);
+    }
+}
+
+static void
+io_handler_watch_freed (void *data)
+{
+  IOHandler *handler;
+
+  handler = data;
+
+  handler->watch = NULL;
+
+  io_handler_destroy_source (handler);
+}
+
+static gboolean
+io_handler_dispatch (GIOChannel   *source,
+                     GIOCondition  condition,
+                     gpointer      data)
+{
+  IOHandler *handler;
+  guint dbus_condition = 0;
+  DBusConnection *connection;
+
+  handler = data;
+
+  connection = handler->cs->connection;
+
+  if (connection)
+    dbus_connection_ref (connection);
+
+  if (condition & G_IO_IN)
+    dbus_condition |= DBUS_WATCH_READABLE;
+  if (condition & G_IO_OUT)
+    dbus_condition |= DBUS_WATCH_WRITABLE;
+  if (condition & G_IO_ERR)
+    dbus_condition |= DBUS_WATCH_ERROR;
+  if (condition & G_IO_HUP)
+    dbus_condition |= DBUS_WATCH_HANGUP;
+
+  /* Note that we don't touch the handler after this, because
+   * dbus may have disabled the watch and thus killed the
+   * handler.
+   */
+  dbus_watch_handle (handler->watch, dbus_condition);
+  handler = NULL;
+
+  if (connection)
+    dbus_connection_unref (connection);
+
+  return TRUE;
+}
+
+static void
+connection_setup_add_watch (ConnectionSetup *cs,
+                            DBusWatch       *watch)
+{
+  guint flags;
+  GIOCondition condition;
+  GIOChannel *channel;
+  IOHandler *handler;
+
+  if (!dbus_watch_get_enabled (watch))
+    return;
+
+  g_assert (dbus_watch_get_data (watch) == NULL);
+
+  flags = dbus_watch_get_flags (watch);
+
+  condition = G_IO_ERR | G_IO_HUP;
+  if (flags & DBUS_WATCH_READABLE)
+    condition |= G_IO_IN;
+  if (flags & DBUS_WATCH_WRITABLE)
+    condition |= G_IO_OUT;
+
+  handler = g_new0 (IOHandler, 1);
+  handler->cs = cs;
+  handler->watch = watch;
+
+  channel = g_io_channel_unix_new (dbus_watch_get_unix_fd (watch));
+
+  handler->source = g_io_create_watch (channel, condition);
+  g_source_set_callback (handler->source, (GSourceFunc) io_handler_dispatch, handler,
+                         io_handler_source_finalized);
+  g_source_attach (handler->source, cs->context);
+
+  cs->ios = g_slist_prepend (cs->ios, handler);
+
+  dbus_watch_set_data (watch, handler, io_handler_watch_freed);
+  g_io_channel_unref (channel);
+}
+
+static void
+connection_setup_remove_watch (ConnectionSetup *cs,
+                               DBusWatch       *watch)
+{
+  IOHandler *handler;
+
+  handler = dbus_watch_get_data (watch);
+
+  if (handler == NULL)
+    return;
+
+  io_handler_destroy_source (handler);
+}
+
+static void
+timeout_handler_source_finalized (gpointer data)
+{
+  TimeoutHandler *handler;
+
+  handler = data;
+
+  if (handler->timeout)
+    dbus_timeout_set_data (handler->timeout, NULL, NULL);
+
+  g_free (handler);
+}
+
+static void
+timeout_handler_destroy_source (void *data)
+{
+  TimeoutHandler *handler;
+
+  handler = data;
+
+  if (handler->source)
+    {
+      GSource *source = handler->source;
+      handler->source = NULL;
+      handler->cs->timeouts = g_slist_remove (handler->cs->timeouts, handler);
+      g_source_destroy (source);
+      g_source_unref (source);
+    }
+}
+
+static void
+timeout_handler_timeout_freed (void *data)
+{
+  TimeoutHandler *handler;
+
+  handler = data;
+
+  handler->timeout = NULL;
+
+  timeout_handler_destroy_source (handler);
+}
+
+static gboolean
+timeout_handler_dispatch (gpointer      data)
+{
+  TimeoutHandler *handler;
+
+  handler = data;
+
+  dbus_timeout_handle (handler->timeout);
+
+  return TRUE;
+}
+
+static void
+connection_setup_add_timeout (ConnectionSetup *cs,
+                              DBusTimeout     *timeout)
+{
+  TimeoutHandler *handler;
+
+  if (!dbus_timeout_get_enabled (timeout))
+    return;
+
+  g_assert (dbus_timeout_get_data (timeout) == NULL);
+
+  handler = g_new0 (TimeoutHandler, 1);
+  handler->cs = cs;
+  handler->timeout = timeout;
+
+  handler->source = g_timeout_source_new (dbus_timeout_get_interval (timeout));
+  g_source_set_callback (handler->source, timeout_handler_dispatch, handler,
+                         timeout_handler_source_finalized);
+  g_source_attach (handler->source, handler->cs->context);
+
+  cs->timeouts = g_slist_prepend (cs->timeouts, handler);
+
+  dbus_timeout_set_data (timeout, handler, timeout_handler_timeout_freed);
+}
+
+static void
+connection_setup_remove_timeout (ConnectionSetup *cs,
+                                 DBusTimeout       *timeout)
+{
+  TimeoutHandler *handler;
+
+  handler = dbus_timeout_get_data (timeout);
+
+  if (handler == NULL)
+    return;
+
+  timeout_handler_destroy_source (handler);
+}
+
+static void
+connection_setup_free (ConnectionSetup *cs)
+{
+  while (cs->ios)
+    io_handler_destroy_source (cs->ios->data);
+
+  while (cs->timeouts)
+    timeout_handler_destroy_source (cs->timeouts->data);
+
+  if (cs->message_queue_source)
+    {
+      GSource *source;
+
+      source = cs->message_queue_source;
+      cs->message_queue_source = NULL;
+
+      g_source_destroy (source);
+      g_source_unref (source);
+    }
+
+  g_main_context_unref (cs->context);
+  g_free (cs);
+}
+
+static dbus_bool_t
+add_watch (DBusWatch *watch,
+           gpointer   data)
+{
+  ConnectionSetup *cs;
+
+  cs = data;
+
+  connection_setup_add_watch (cs, watch);
+
+  return TRUE;
+}
+
+static void
+remove_watch (DBusWatch *watch,
+              gpointer   data)
+{
+  ConnectionSetup *cs;
+
+  cs = data;
+
+  connection_setup_remove_watch (cs, watch);
+}
+
+static void
+watch_toggled (DBusWatch *watch,
+               void      *data)
+{
+  /* Because we just exit on OOM, enable/disable is
+   * no different from add/remove
+   */
+  if (dbus_watch_get_enabled (watch))
+    add_watch (watch, data);
+  else
+    remove_watch (watch, data);
+}
+
+static dbus_bool_t
+add_timeout (DBusTimeout *timeout,
+             void        *data)
+{
+  ConnectionSetup *cs;
+
+  cs = data;
+
+  if (!dbus_timeout_get_enabled (timeout))
+    return TRUE;
+
+  connection_setup_add_timeout (cs, timeout);
+
+  return TRUE;
+}
+
+static void
+remove_timeout (DBusTimeout *timeout,
+                void        *data)
+{
+  ConnectionSetup *cs;
+
+  cs = data;
+
+  connection_setup_remove_timeout (cs, timeout);
+}
+
+static void
+timeout_toggled (DBusTimeout *timeout,
+                 void        *data)
+{
+  /* Because we just exit on OOM, enable/disable is
+   * no different from add/remove
+   */
+  if (dbus_timeout_get_enabled (timeout))
+    add_timeout (timeout, data);
+  else
+    remove_timeout (timeout, data);
+}
+
+static void
+wakeup_main (void *data)
+{
+  ConnectionSetup *cs = data;
+
+  g_main_context_wakeup (cs->context);
+}
+
+
+/* Move to a new context */
+static ConnectionSetup*
+connection_setup_new_from_old (GMainContext    *context,
+                               ConnectionSetup *old)
+{
+  GSList *tmp;
+  ConnectionSetup *cs;
+
+  g_assert (old->context != context);
+
+  cs = connection_setup_new (context, old->connection);
+
+  tmp = old->ios;
+  while (tmp != NULL)
+    {
+      IOHandler *handler = tmp->data;
+
+      connection_setup_add_watch (cs, handler->watch);
+
+      tmp = tmp->next;
+    }
+
+  tmp = old->timeouts;
+  while (tmp != NULL)
+    {
+      TimeoutHandler *handler = tmp->data;
+
+      connection_setup_add_timeout (cs, handler->timeout);
+
+      tmp = tmp->next;
+    }
+
+  return cs;
+}
+
+static void
+ensure_slots (void)
+{
+  G_LOCK (main_loop_lock);
+  if (_dbus_gmain_connection_slot < 0)
+    {
+      dbus_connection_allocate_data_slot (&_dbus_gmain_connection_slot);
+      if (_dbus_gmain_connection_slot < 0)
+        {
+          G_UNLOCK (main_loop_lock);
+          _g_dbus_oom ();
+        }
+    }
+  if (server_slot < 0)
+    {
+      dbus_server_allocate_data_slot (&server_slot);
+      if (server_slot < 0)
+        {
+          G_UNLOCK (main_loop_lock);
+          _g_dbus_oom ();
+        }
+    }
+  G_UNLOCK (main_loop_lock);
+}
+
+/**
+ * g_dbus_integrate_dbus_1_connection:
+ * @connection: A #DBusConnection.
+ * @context: the #GMainContext or #NULL for default context
+ *
+ * Sets the watch and timeout functions of @connection to integrate
+ * the connection with the GLib main loop.  Pass in #NULL for the
+ * #GMainContext unless you're doing something specialized.
+ *
+ * If called twice for the same context, does nothing the second
+ * time. If called once with context A and once with context B,
+ * context B replaces context A as the context monitoring the
+ * connection.
+ */
+void
+g_dbus_integrate_dbus_1_connection (DBusConnection *connection,
+                                    GMainContext   *context)
+{
+  ConnectionSetup *old_setup;
+  ConnectionSetup *cs;
+
+  ensure_slots ();
+
+  if (context == NULL)
+    context = g_main_context_default ();
+
+  cs = NULL;
+
+  old_setup = dbus_connection_get_data (connection, _dbus_gmain_connection_slot);
+  if (old_setup != NULL)
+    {
+      if (old_setup->context == context)
+        return; /* nothing to do */
+
+      cs = connection_setup_new_from_old (context, old_setup);
+
+      /* Nuke the old setup */
+      dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL, NULL);
+      old_setup = NULL;
+    }
+
+  if (cs == NULL)
+    cs = connection_setup_new (context, connection);
+
+  if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, cs,
+                                 (DBusFreeFunction)connection_setup_free))
+    goto nomem;
+
+  if (!dbus_connection_set_watch_functions (connection,
+                                            add_watch,
+                                            remove_watch,
+                                            watch_toggled,
+                                            cs, NULL))
+    goto nomem;
+
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              add_timeout,
+                                              remove_timeout,
+                                              timeout_toggled,
+                                              cs, NULL))
+    goto nomem;
+
+  dbus_connection_set_wakeup_main_function (connection,
+                                            wakeup_main,
+                                            cs, NULL);
+
+  return;
+
+ nomem:
+  _g_dbus_oom ();
+}
+
+/**
+ * g_dbus_unintegrate_dbus_1_connection:
+ * @connection: A #DBusConnection.
+ *
+ * Removes mainloop integration for @connection.
+ **/
+void
+g_dbus_unintegrate_dbus_1_connection (DBusConnection *connection)
+{
+  ensure_slots ();
+
+  if (!dbus_connection_set_data (connection, _dbus_gmain_connection_slot, NULL,
+                                 NULL))
+    goto nomem;
+
+  if (!dbus_connection_set_watch_functions (connection,
+                                            NULL,
+                                            NULL,
+                                            NULL,
+                                            NULL, NULL))
+    goto nomem;
+
+  if (!dbus_connection_set_timeout_functions (connection,
+                                              NULL,
+                                              NULL,
+                                              NULL,
+                                              NULL, NULL))
+    goto nomem;
+
+  dbus_connection_set_wakeup_main_function (connection,
+                                            NULL,
+                                            NULL, NULL);
+
+  return;
+
+ nomem:
+  _g_dbus_oom ();
+}
+
+/**
+ * g_dbus_integrate_dbus_1_server:
+ * @server: A #DBusServer.
+ * @context: the #GMainContext or #NULL for default
+ *
+ * Sets the watch and timeout functions of a #DBusServer
+ * to integrate the server with the GLib main loop.
+ * In most cases the context argument should be #NULL.
+ *
+ * If called twice for the same context, does nothing the second
+ * time. If called once with context A and once with context B,
+ * context B replaces context A as the context monitoring the
+ * connection.
+ */
+void
+g_dbus_integrate_dbus_1_server (DBusServer   *server,
+                                GMainContext *context)
+{
+  ConnectionSetup *old_setup;
+  ConnectionSetup *cs;
+
+  ensure_slots ();
+
+  dbus_server_allocate_data_slot (&server_slot);
+  if (server_slot < 0)
+    goto nomem;
+
+  if (context == NULL)
+    context = g_main_context_default ();
+
+  cs = NULL;
+
+  old_setup = dbus_server_get_data (server, server_slot);
+  if (old_setup != NULL)
+    {
+      if (old_setup->context == context)
+        return; /* nothing to do */
+
+      cs = connection_setup_new_from_old (context, old_setup);
+
+      /* Nuke the old setup */
+      dbus_server_set_data (server, server_slot, NULL, NULL);
+      old_setup = NULL;
+    }
+
+  if (cs == NULL)
+    cs = connection_setup_new (context, NULL);
+
+  if (!dbus_server_set_data (server, server_slot, cs,
+                             (DBusFreeFunction)connection_setup_free))
+    goto nomem;
+
+  if (!dbus_server_set_watch_functions (server,
+                                        add_watch,
+                                        remove_watch,
+                                        watch_toggled,
+                                        cs, NULL))
+    goto nomem;
+
+  if (!dbus_server_set_timeout_functions (server,
+                                          add_timeout,
+                                          remove_timeout,
+                                          timeout_toggled,
+                                          cs, NULL))
+    goto nomem;
+
+  return;
+
+ nomem:
+  _g_dbus_oom ();
+}
+
+/**
+ * g_dbus_unintegrate_dbus_1_server:
+ * @server: A #DBusServer.
+ *
+ * Removes mainloop integration for @server.
+ **/
+void
+g_dbus_unintegrate_dbus_1_server (DBusServer *server)
+{
+  ensure_slots ();
+
+  if (!dbus_server_set_data (server, server_slot, NULL,
+                             NULL))
+    goto nomem;
+
+  if (!dbus_server_set_watch_functions (server,
+                                        NULL,
+                                        NULL,
+                                        NULL,
+                                        NULL, NULL))
+    goto nomem;
+
+  if (!dbus_server_set_timeout_functions (server,
+                                          NULL,
+                                          NULL,
+                                          NULL,
+                                          NULL, NULL))
+    goto nomem;
+
+  return;
+
+ nomem:
+  _g_dbus_oom ();
+}
+
+
+#define __G_DBUS_MAINLOOP_C__
+#include "gdbusaliasdef.c"
diff --git a/gdbus/gdbusmainloop.h b/gdbus/gdbusmainloop.h
new file mode 100644
index 0000000..77bb0f0
--- /dev/null
+++ b/gdbus/gdbusmainloop.h
@@ -0,0 +1,45 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_MAINLOOP_H__
+#define __G_DBUS_MAINLOOP_H__
+
+#include <gdbus/gdbustypes.h>
+#include <dbus/dbus.h>
+
+G_BEGIN_DECLS
+
+void g_dbus_integrate_dbus_1_connection   (DBusConnection *connection,
+                                           GMainContext   *context);
+void g_dbus_unintegrate_dbus_1_connection (DBusConnection *connection);
+
+void g_dbus_integrate_dbus_1_server       (DBusServer   *server,
+                                           GMainContext *context);
+void g_dbus_unintegrate_dbus_1_server     (DBusServer   *server);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_CONNECTION_H__ */
diff --git a/gdbus/gdbusprivate.c b/gdbus/gdbusprivate.c
new file mode 100644
index 0000000..f6e7d75
--- /dev/null
+++ b/gdbus/gdbusprivate.c
@@ -0,0 +1,37 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include "config.h"
+
+#include <stdlib.h>
+
+#include <glib/gi18n.h>
+
+#include "gdbustypes.h"
+
+void
+_g_dbus_oom (void)
+{
+  /* TODO: print stack trace etc. */
+  g_error ("OOM from libdbus");
+  abort ();
+}
diff --git a/gdbus/gdbusprivate.h b/gdbus/gdbusprivate.h
new file mode 100644
index 0000000..90d1278
--- /dev/null
+++ b/gdbus/gdbusprivate.h
@@ -0,0 +1,38 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (G_DBUS_COMPILATION)
+#error "gdbusprivate.h is a private header file."
+#endif
+
+#ifndef __G_DBUS_PRIVATE_H__
+#define __G_DBUS_PRIVATE_H__
+
+#include <gdbus/gdbustypes.h>
+
+G_BEGIN_DECLS
+
+void _g_dbus_oom (void);
+
+G_END_DECLS
+
+#endif /* __G_DBUS_TYPES_H__ */
diff --git a/gdbus/gdbustypes.h b/gdbus/gdbustypes.h
new file mode 100644
index 0000000..21dacb2
--- /dev/null
+++ b/gdbus/gdbustypes.h
@@ -0,0 +1,39 @@
+/* GDBus - GLib D-Bus Library
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#if !defined (__G_DBUS_G_DBUS_H_INSIDE__) && !defined (G_DBUS_COMPILATION)
+#error "Only <gdbus/gdbus.h> can be included directly."
+#endif
+
+#ifndef __G_DBUS_TYPES_H__
+#define __G_DBUS_TYPES_H__
+
+#include <gdbus/gdbusenums.h>
+
+G_BEGIN_DECLS
+
+typedef struct _GDBusConnection       GDBusConnection;
+typedef struct _GBusNameOwner         GBusNameOwner;
+
+G_END_DECLS
+
+#endif /* __G_DBUS_TYPES_H__ */
diff --git a/gdbus/makegdbusalias.pl b/gdbus/makegdbusalias.pl
new file mode 100755
index 0000000..a46bb8e
--- /dev/null
+++ b/gdbus/makegdbusalias.pl
@@ -0,0 +1,137 @@
+#!/usr/bin/perl -w
+
+my $do_def = 0;
+
+if (($#ARGV >= 0) && ($ARGV[0] eq "-def")) {
+    shift;
+    $do_def = 1;
+}
+
+print <<EOF;
+/* Generated by makegdbusalias.pl */
+
+#ifndef DISABLE_VISIBILITY
+
+#include "glib.h"
+
+#ifdef G_HAVE_GNUC_VISIBILITY
+
+EOF
+
+if ($do_def) {
+    print <<EOF
+#undef IN_FILE
+#define IN_FILE defined
+
+#undef IN_HEADER
+#define IN_HEADER(x) 1
+
+EOF
+} 
+else { 
+    print <<EOF
+#define IN_FILE(x) 1
+#define IN_HEADER defined
+
+EOF
+}
+
+my $in_comment = 0;
+my $in_skipped_section = 0;
+
+while (<>) {
+
+  # ignore empty lines
+  next if /^\s*$/;
+
+  # skip comments
+  if ($_ =~ /^\s*\/\*/)
+  {
+      $in_comment = 1;
+  }
+  
+  if ($in_comment)
+  {
+      if ($_ =~  /\*\/\s$/)
+      {
+	  $in_comment = 0;
+      }
+      
+      next;
+  }
+
+  # handle ifdefs
+  if ($_ =~ /^\#endif/)
+  {
+      if (!$in_skipped_section)
+      {
+	  print $_;
+      }
+
+      $in_skipped_section = 0;
+
+      next;
+  }
+
+  if ($_ =~ /^\#ifdef\s+(INCLUDE_VARIABLES|INCLUDE_INTERNAL_SYMBOLS|ALL_FILES)/)
+  {
+      $in_skipped_section = 1;
+  }
+
+  if ($in_skipped_section)
+  {
+      next;
+  }
+
+  if ($_ =~ /^\#ifn?def\s+G/)
+  {
+      print $_;
+      
+      next;
+  }
+ 
+  if ($_ =~ /^\#if.*(IN_FILE|IN_HEADER)/)
+  {
+      print $_;
+      
+      next;
+  }
+
+  chop;
+  my $str = $_;
+  my @words;
+  my $attributes = "";
+
+  @words = split(/ /, $str);
+  $str = shift(@words);
+  chomp($str);
+  my $alias = "IA__".$str;
+  
+  # Drop any Win32 specific .def file syntax,  but keep attributes
+  foreach $word (@words) {
+      $attributes = "$attributes $word" unless $word eq "PRIVATE";
+  }
+  
+  if (!$do_def) {
+    print <<EOF
+extern __typeof ($str) $alias __attribute((visibility("hidden")))$attributes;
+\#define $str $alias
+
+EOF
+  }
+  else {
+    print <<EOF
+\#undef $str 
+extern __typeof ($str) $str __attribute((alias("$alias"), visibility("default")));
+
+EOF
+  }
+}
+
+print <<EOF;
+
+#endif /* G_HAVE_GNUC_VISIBILITY */
+#endif /* DISABLE_VISIBILITY */
+EOF
+
+
diff --git a/gdbus/pltcheck.sh b/gdbus/pltcheck.sh
new file mode 100755
index 0000000..4461304
--- /dev/null
+++ b/gdbus/pltcheck.sh
@@ -0,0 +1,19 @@
+#!/bin/sh
+
+LANG=C
+
+status=0
+
+if ! which readelf 2>/dev/null >/dev/null; then
+	echo "'readelf' not found; skipping test"
+	exit 0
+fi
+
+SKIP='\<g_'
+
+for so in .libs/lib*.so; do
+	echo Checking $so for local PLT entries
+	readelf -r $so | grep 'JU\?MP_SLOT\?' | grep '\<g_' | grep -v $SKIP && status=1
+done
+
+exit $status
diff --git a/gdbus/tests/Makefile.am b/gdbus/tests/Makefile.am
new file mode 100644
index 0000000..1a6d855
--- /dev/null
+++ b/gdbus/tests/Makefile.am
@@ -0,0 +1,30 @@
+include $(top_srcdir)/Makefile.decl
+
+NULL =
+
+INCLUDES =                      \
+        -g                      \
+        -I$(top_srcdir)         \
+        -I$(top_srcdir)/glib    \
+        -I$(top_srcdir)/gmodule \
+        -I$(top_srcdir)/gobject \
+        -I$(top_srcdir)/gio     \
+        -I$(top_srcdir)/gdbus   \
+        $(GLIB_DEBUG_FLAGS)	\
+	$(DBUS_CFLAGS)		\
+	$(NULL)
+
+check_PROGRAMS = $(TEST_PROGS)
+progs_ldadd     =                                       \
+        $(top_builddir)/glib/libglib-2.0.la             \
+        $(top_builddir)/gobject/libgobject-2.0.la       \
+        $(top_builddir)/gio/libgio-2.0.la		\
+        $(top_builddir)/gdbus/libgdbus-2.0.la		\
+	$(NULL)
+
+TEST_PROGS +=				\
+        connection			\
+	$(NULL)
+
+connection_SOURCES = connection.c
+connection_LDADD = $(progs_ldadd)
diff --git a/gdbus/tests/connection.c b/gdbus/tests/connection.c
new file mode 100644
index 0000000..58f08c2
--- /dev/null
+++ b/gdbus/tests/connection.c
@@ -0,0 +1,904 @@
+/* GLib testing framework examples and tests
+ *
+ * Copyright (C) 2008-2009 Red Hat, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General
+ * Public License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: David Zeuthen <davidz redhat com>
+ */
+
+#include <gdbus/gdbus.h>
+
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <signal.h>
+#include <stdio.h>
+
+/* all tests rely on a shared mainloop */
+static GMainLoop *loop = NULL;
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* Utilities for bringing up and tearing down session message bus instances */
+
+static void
+watch_parent (gint fd)
+{
+  GPollFD fds[1];
+  gint num_events;
+  gchar buf[512];
+  guint bytes_read;
+  GArray *buses_to_kill_array;
+
+  fds[0].fd = fd;
+  fds[0].events = G_IO_HUP | G_IO_IN;
+  fds[0].revents = 0;
+
+  buses_to_kill_array = g_array_new (FALSE, TRUE, sizeof (guint));
+
+  do
+    {
+      guint pid;
+      guint n;
+
+      num_events = g_poll (fds, 1, -1);
+      if (num_events == 0)
+        continue;
+
+      if (fds[0].revents == G_IO_HUP)
+        {
+          for (n = 0; n < buses_to_kill_array->len; n++)
+            {
+              pid = g_array_index (buses_to_kill_array, guint, n);
+              g_print ("cleaning up bus with pid %d\n", pid);
+              kill (pid, SIGTERM);
+            }
+          g_array_free (buses_to_kill_array, TRUE);
+          exit (0);
+        }
+
+      //g_debug ("data from parent");
+
+      memset (buf, '\0', sizeof buf);
+    again:
+      bytes_read = read (fds[0].fd, buf, sizeof buf);
+      if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+        goto again;
+
+      if (sscanf (buf, "add %d\n", &pid) == 1)
+        {
+          g_array_append_val (buses_to_kill_array, pid);
+        }
+      else if (sscanf (buf, "remove %d\n", &pid) == 1)
+        {
+          for (n = 0; n < buses_to_kill_array->len; n++)
+            {
+              if (g_array_index (buses_to_kill_array, guint, n) == pid)
+                {
+                  g_array_remove_index (buses_to_kill_array, n);
+                  pid = 0;
+                  break;
+                }
+            }
+          if (pid != 0)
+            {
+              g_warning ("unknown pid %d to remove", pid);
+            }
+        }
+      else
+        {
+          g_warning ("unknown command from parent '%s'", buf);
+        }
+    }
+  while (TRUE);
+
+}
+
+static GHashTable *session_bus_address_to_pid = NULL;
+static gint pipe_fds[2];
+
+static const gchar *
+session_bus_up_with_address (const gchar *given_address)
+{
+  gchar *address;
+  int stdout_fd;
+  GError *error;
+  gchar *argv[] = {"dbus-daemon", "--print-address", "--config-file=foo", NULL};
+  GPid pid;
+  gchar buf[512];
+  ssize_t bytes_read;
+  gchar *config_file_name;
+  gint config_file_fd;
+  GString *config_file_contents;
+
+  address = NULL;
+  error = NULL;
+  config_file_name = NULL;
+  config_file_fd = -1;
+  argv[2] = NULL;
+
+  config_file_fd = g_file_open_tmp ("g-dbus-tests-XXXXXX",
+                                    &config_file_name,
+                                    &error);
+  if (config_file_fd < 0)
+    {
+      g_warning ("Error creating temporary config file: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  config_file_contents = g_string_new (NULL);
+  g_string_append        (config_file_contents, "<busconfig>\n");
+  g_string_append        (config_file_contents, "  <type>session</type>\n");
+  g_string_append_printf (config_file_contents, "  <listen>%s</listen>\n", given_address);
+  g_string_append        (config_file_contents,
+                          "  <policy context=\"default\">\n"
+                          "    <!-- Allow everything to be sent -->\n"
+                          "    <allow send_destination=\"*\" eavesdrop=\"true\"/>\n"
+                          "    <!-- Allow everything to be received -->\n"
+                          "    <allow eavesdrop=\"true\"/>\n"
+                          "    <!-- Allow anyone to own anything -->\n"
+                          "    <allow own=\"*\"/>\n"
+                          "  </policy>\n");
+  g_string_append        (config_file_contents, "</busconfig>\n");
+
+  if (write (config_file_fd, config_file_contents->str, config_file_contents->len) != config_file_contents->len)
+    {
+      g_warning ("Error writing %d bytes to config file: %m", (gint) config_file_contents->len);
+      g_string_free (config_file_contents, TRUE);
+      goto out;
+    }
+  g_string_free (config_file_contents, TRUE);
+
+  argv[2] = g_strdup_printf ("--config-file=%s", config_file_name);
+
+  if (session_bus_address_to_pid == NULL)
+    {
+      /* keep a mapping from session bus address to the pid */
+      session_bus_address_to_pid = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+
+      /* fork a child to clean up session buses when we are killed */
+      if (pipe (pipe_fds) != 0)
+        {
+          g_warning ("pipe() failed: %m");
+          g_assert_not_reached ();
+        }
+      switch (fork ())
+        {
+        case -1:
+          g_warning ("fork() failed: %m");
+          g_assert_not_reached ();
+          break;
+
+        case 0:
+          /* child */
+          close (pipe_fds[1]);
+          watch_parent (pipe_fds[0]);
+          break;
+
+        default:
+          /* parent */
+          close (pipe_fds[0]);
+          break;
+        }
+
+      //atexit (cleanup_session_buses);
+      /* TODO: need to handle the cases where we crash */
+    }
+  else
+    {
+      /* check if we already have a bus running for this address */
+      if (g_hash_table_lookup (session_bus_address_to_pid, given_address) != NULL)
+        {
+          g_warning ("Already have a bus instance for the given address %s", given_address);
+          goto out;
+        }
+    }
+
+  if (!g_spawn_async_with_pipes (NULL,
+                                 argv,
+                                 NULL,
+                                 G_SPAWN_SEARCH_PATH,
+                                 NULL,
+                                 NULL,
+                                 &pid,
+                                 NULL,
+                                 &stdout_fd,
+                                 NULL,
+                                 &error))
+    {
+      g_warning ("Error spawning dbus-daemon: %s", error->message);
+      g_error_free (error);
+      goto out;
+    }
+
+  memset (buf, '\0', sizeof buf);
+ again:
+  bytes_read = read (stdout_fd, buf, sizeof buf);
+  if (bytes_read < 0 && (errno == EAGAIN || errno == EINTR))
+    goto again;
+  close (stdout_fd);
+
+  if (bytes_read == 0 || bytes_read == sizeof buf)
+    {
+      g_warning ("Error reading address from dbus daemon, %d bytes read", (gint) bytes_read);
+      kill (SIGTERM, pid);
+      goto out;
+    }
+
+  address = g_strdup (buf);
+  g_strstrip (address);
+
+  /* write the pid to the child so it can kill it when we die */
+  g_snprintf (buf, sizeof buf, "add %d\n", (guint) pid);
+  write (pipe_fds[1], buf, strlen (buf));
+
+  g_hash_table_insert (session_bus_address_to_pid, address, GUINT_TO_POINTER (pid));
+
+ out:
+  if (config_file_fd > 0)
+    {
+      if (close (config_file_fd) != 0)
+        {
+          g_warning ("Error closing fd for config file %s: %m", config_file_name);
+        }
+      g_assert (config_file_name != NULL);
+      if (unlink (config_file_name) != 0)
+        {
+          g_warning ("Error unlinking config file %s: %m", config_file_name);
+        }
+    }
+  g_free (argv[2]);
+  g_free (config_file_name);
+  return address;
+}
+
+static void
+session_bus_down_with_address (const gchar *address)
+{
+  gpointer value;
+  GPid pid;
+  gchar buf[512];
+
+  g_assert (address != NULL);
+  g_assert (session_bus_address_to_pid != NULL);
+
+  value = g_hash_table_lookup (session_bus_address_to_pid, address);
+  g_assert (value != NULL);
+
+  pid = GPOINTER_TO_UINT (g_hash_table_lookup (session_bus_address_to_pid, address));
+
+  kill (pid, SIGTERM);
+
+  /* write the pid to the child so it won't kill it when we die */
+  g_snprintf (buf, sizeof buf, "remove %d\n", (guint) pid);
+  write (pipe_fds[1], buf, strlen (buf));
+
+  g_hash_table_remove (session_bus_address_to_pid, address);
+}
+
+static gchar *temporary_address = NULL;
+static gchar *temporary_address_used_by_bus = NULL;
+
+static const gchar *
+session_bus_get_temporary_address (void)
+{
+  if (temporary_address == NULL)
+    {
+      /* TODO: maybe use a more random name etc etc */
+      temporary_address = g_strdup_printf ("unix:path=/tmp/g-dbus-tests-pid-%d", getpid ());
+    }
+
+  return temporary_address;
+}
+
+static const gchar *
+session_bus_up (void)
+{
+  if (temporary_address_used_by_bus != NULL)
+    {
+      g_warning ("There is already a session bus up");
+      goto out;
+    }
+
+  temporary_address_used_by_bus = g_strdup (session_bus_up_with_address (session_bus_get_temporary_address ()));
+
+ out:
+  return temporary_address_used_by_bus;
+}
+
+static void
+session_bus_down (void)
+{
+  if (temporary_address_used_by_bus == NULL)
+    {
+      g_warning ("There is not a session bus up");
+    }
+  else
+    {
+      session_bus_down_with_address (temporary_address_used_by_bus);
+      g_free (temporary_address_used_by_bus);
+      temporary_address_used_by_bus = NULL;
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* Message Bus tests - check all aspects of connecting and reconnecting to bus instances                */
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_opened_no_bus_exists (GDBusConnection *connection,
+                         gpointer         user_data)
+{
+  g_assert_not_reached ();
+}
+
+static void
+on_closed_no_bus_exists (GDBusConnection *connection,
+                         gpointer         user_data)
+{
+  g_assert_not_reached ();
+}
+
+static void
+get_connection_callback_no_bus_exists (GDBusConnection *connection,
+                                       GAsyncResult    *result,
+                                       gpointer         user_data)
+{
+  GError *error;
+  gboolean ret;
+
+  error = NULL;
+  ret = g_dbus_connection_bus_get_finish (connection,
+                                          result,
+                                          &error);
+  g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FILE_NOT_FOUND);
+  g_error_free (error);
+  g_assert (!ret);
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_opened_bus_exists (GDBusConnection *connection,
+                      gpointer         user_data)
+{
+  gboolean *val = user_data;
+  *val = TRUE;
+}
+
+static void
+on_opened_bus_exists_reconnect (GDBusConnection *connection,
+                                gpointer         user_data)
+{
+  gboolean *val = user_data;
+  *val = TRUE;
+  g_main_loop_quit (loop);
+}
+
+static void
+on_closed_bus_exists (GDBusConnection *connection,
+                      gpointer         user_data)
+{
+  gboolean *val = user_data;
+  *val = FALSE;
+
+  g_main_loop_quit (loop);
+}
+
+static void
+get_connection_callback_bus_exists (GDBusConnection *connection,
+                                    GAsyncResult    *result,
+                                    gpointer         user_data)
+{
+  GError *error;
+  gboolean ret;
+  gboolean *val = user_data;
+
+  /* check we get the ::opened signal before the callback */
+  g_assert (*val);
+
+  error = NULL;
+  ret = g_dbus_connection_bus_get_finish (connection,
+                                          result,
+                                          &error);
+  g_assert_no_error (error);
+  g_assert (ret);
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+get_connection_callback_singleton (GDBusConnection *connection,
+                                   GAsyncResult    *result,
+                                   gpointer         user_data)
+{
+  GError *error;
+  gboolean ret;
+
+  error = NULL;
+  ret = g_dbus_connection_bus_get_finish (connection,
+                                          result,
+                                          &error);
+  g_assert_no_error (error);
+  g_assert (ret);
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+get_connection_callback_private (GDBusConnection *connection,
+                                 GAsyncResult    *result,
+                                 gpointer         user_data)
+{
+  GError *error;
+  gboolean ret;
+
+  error = NULL;
+  ret = g_dbus_connection_bus_get_private_finish (connection,
+                                                  result,
+                                                  &error);
+  g_assert_no_error (error);
+  g_assert (ret);
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+test_message_bus_connections (void)
+{
+  GDBusConnection *c;
+  GDBusConnection *c2;
+  gboolean val;
+
+  /* Check for correct behavior when no bus is present */
+  c = g_dbus_connection_bus_get (G_MESSAGE_BUS_TYPE_SESSION,
+                                 NULL,
+                                 (GAsyncReadyCallback) get_connection_callback_no_bus_exists,
+                                 NULL);
+  g_signal_connect (c, "opened", G_CALLBACK (on_opened_no_bus_exists), NULL);
+  g_signal_connect (c, "closed", G_CALLBACK (on_closed_no_bus_exists), NULL);
+  g_assert (!g_dbus_connection_get_is_open (c));
+  g_main_loop_run (loop);
+  g_assert (!g_dbus_connection_get_is_open (c));
+  g_object_unref (c);
+
+  /* Check for correct behavior if a bus is present and that we get the ::opened signal
+   *
+   * Then check that get the ::closed signal when tearing down the bus.
+   */
+  session_bus_up ();
+  val = FALSE;
+  c = g_dbus_connection_bus_get (G_MESSAGE_BUS_TYPE_SESSION,
+                                 NULL,                            /* cancellable */
+                                 (GAsyncReadyCallback) get_connection_callback_bus_exists,
+                                 &val);                           /* user_data */
+  g_signal_connect (c, "opened", G_CALLBACK (on_opened_bus_exists), &val);
+  g_signal_connect (c, "closed", G_CALLBACK (on_closed_bus_exists), &val);
+  g_assert (!g_dbus_connection_get_is_open (c));
+  g_main_loop_run (loop);
+  g_assert (g_dbus_connection_get_is_open (c));
+  g_assert (val);
+  g_dbus_connection_set_exit_on_close (c, FALSE);
+  session_bus_down ();
+  g_main_loop_run (loop);
+  g_assert (!g_dbus_connection_get_is_open (c));
+  g_assert (!val);
+
+  /* Now check that we get the ::opened signal on the existing connection object when
+   * bringing up the bus.. this checks that the reconnect logic in GDBusConnection works.
+   *
+   * We replace the ::opened signal handler since we want to break out of the mainloop.
+   */
+  g_signal_handlers_disconnect_by_func (c, on_opened_bus_exists, &val);
+  g_signal_connect (c, "opened", G_CALLBACK (on_opened_bus_exists_reconnect), &val);
+  session_bus_up ();
+  g_main_loop_run (loop);
+  g_assert (g_dbus_connection_get_is_open (c));
+  g_dbus_connection_set_exit_on_close (c, FALSE);
+  g_assert (val);
+
+  /* Check that singleton handling works, e.g. we get the same object for the same bus type */
+  c2 = g_dbus_connection_bus_get (G_MESSAGE_BUS_TYPE_SESSION,
+                                  NULL,                            /* cancellable */
+                                  (GAsyncReadyCallback) get_connection_callback_singleton,
+                                  NULL);                           /* user_data */
+  g_assert (c == c2);
+  g_main_loop_run (loop);
+  g_object_unref (c2);
+
+  /* Check that we get a distinct connection, with a distinct unique name, for private connections */
+  c2 = g_dbus_connection_bus_get_private (G_MESSAGE_BUS_TYPE_SESSION,
+                                          NULL,                            /* cancellable */
+                                          (GAsyncReadyCallback) get_connection_callback_private,
+                                          NULL);                           /* user_data */
+  g_assert (c != c2);
+  g_main_loop_run (loop);
+  g_assert_cmpstr (g_dbus_connection_get_unique_name (c),
+                   !=,
+                   g_dbus_connection_get_unique_name (c2));
+  g_object_unref (c2);
+
+  /* Try to bring the bus down and check we get the ::closed signal.
+   *
+   * The existing signal handler does the right thing here.
+   */
+  session_bus_down ();
+  g_main_loop_run (loop);
+  g_assert (!g_dbus_connection_get_is_open (c));
+  g_assert (!val);
+
+  g_object_unref (c);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+/* Test that GBusNameOwner works correctly */
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_name_acquired_expect_failure (GBusNameOwner *owner,
+                                 gpointer       user_data)
+{
+  g_assert_not_reached ();
+}
+
+static void
+on_name_lost_expect_failure (GBusNameOwner *owner,
+                             gpointer       user_data)
+{
+  g_assert_not_reached ();
+}
+
+static void
+on_owner_cb_expect_failure (GBusNameOwner *owner,
+                            GAsyncResult  *result,
+                            gpointer       user_data)
+{
+  gboolean *val = user_data;
+  gboolean ret;
+  GError *error;
+
+  error = NULL;
+  ret = g_bus_name_owner_new_finish (owner,
+                                     result,
+                                     &error);
+  g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FILE_NOT_FOUND);
+  g_error_free (error);
+  g_assert (!ret);
+
+  *val = TRUE;
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_name_acquired_expect_success (GBusNameOwner *owner,
+                                 gpointer       user_data)
+{
+  gboolean *val2 = user_data;
+
+  *val2 = TRUE;
+}
+
+static void
+on_name_lost_expect_success (GBusNameOwner *owner,
+                             gpointer       user_data)
+{
+  g_assert_not_reached ();
+}
+
+static void
+on_owner_cb_expect_success (GBusNameOwner *owner,
+                            GAsyncResult  *result,
+                            gpointer       user_data)
+{
+  gboolean *val = user_data;
+  gboolean ret;
+  GError *error;
+
+  error = NULL;
+  ret = g_bus_name_owner_new_finish (owner,
+                                     result,
+                                     &error);
+  g_assert_no_error (error);
+  g_assert (ret);
+
+  *val = TRUE;
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_name_lost_bringing_down_the_bus (GBusNameOwner *owner,
+                                    gpointer       user_data)
+{
+  gboolean *val = user_data;
+
+  *val = TRUE;
+
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_name_acquired_bringing_up_the_bus (GBusNameOwner *owner,
+                                      gpointer       user_data)
+{
+  gboolean *val = user_data;
+
+  *val = TRUE;
+
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_owner_cb_expect_failure2 (GBusNameOwner *owner,
+                             GAsyncResult  *result,
+                             gpointer       user_data)
+{
+  gboolean *val = user_data;
+  gboolean ret;
+  GError *error;
+
+  error = NULL;
+  ret = g_bus_name_owner_new_finish (owner,
+                                     result,
+                                     &error);
+  g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED);
+  g_error_free (error);
+  g_assert (!ret);
+
+  *val = TRUE;
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_owner_for_connection_cb_expect_failure (GBusNameOwner *owner,
+                                           GAsyncResult  *result,
+                                           gpointer       user_data)
+{
+  gboolean *val = user_data;
+  gboolean ret;
+  GError *error;
+
+  error = NULL;
+  ret = g_bus_name_owner_new_for_connection_finish (owner,
+                                                    result,
+                                                    &error);
+  g_assert_error (error, G_DBUS_ERROR, G_DBUS_ERROR_FAILED);
+  g_error_free (error);
+  g_assert (!ret);
+
+  *val = TRUE;
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_name_acquired_for_o2 (GBusNameOwner *owner,
+                         gpointer       user_data)
+{
+  gboolean *val = user_data;
+
+  *val = TRUE;
+
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+on_name_lost_for_o2 (GBusNameOwner *owner,
+                     gpointer       user_data)
+{
+  gboolean *val = user_data;
+
+  *val = TRUE;
+
+  g_main_loop_quit (loop);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+test_bus_name_owner (void)
+{
+  GDBusConnection *private_connection;
+  GBusNameOwner *o;
+  GBusNameOwner *o2;
+  gboolean val;
+  gboolean val2;
+
+  /* first try to own a name when there is no bus */
+  val = FALSE;
+  o = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                            "org.gtk.Test.Name1",
+                            G_BUS_NAME_OWNER_FLAGS_NONE,
+                            NULL,
+                            (GAsyncReadyCallback) on_owner_cb_expect_failure,
+                            &val);
+  g_signal_connect (o, "name-acquired", G_CALLBACK (on_name_acquired_expect_failure), NULL);
+  g_signal_connect (o, "name-lost", G_CALLBACK (on_name_lost_expect_failure), NULL);
+  g_main_loop_run (loop);
+  g_assert (val);
+  g_object_unref (o);
+
+  /* try again, this time with a bus instance - the ::name-acquired signal should fire before the async reply */
+  session_bus_up ();
+  val = FALSE;
+  val2 = FALSE;
+  o = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                            "org.gtk.Test.Name1",
+                            G_BUS_NAME_OWNER_FLAGS_NONE,
+                            NULL,
+                            (GAsyncReadyCallback) on_owner_cb_expect_success,
+                            &val);
+  g_signal_connect (o, "name-acquired", G_CALLBACK (on_name_acquired_expect_success), &val2);
+  g_signal_connect (o, "name-lost", G_CALLBACK (on_name_lost_expect_success), NULL);
+  g_main_loop_run (loop);
+  g_assert (val);
+  g_assert (val2);
+
+  /* try owning the same name again... the should fail because o is still alive */
+  o2 = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                             "org.gtk.Test.Name1",
+                             G_BUS_NAME_OWNER_FLAGS_NONE,
+                             NULL,
+                             (GAsyncReadyCallback) on_owner_cb_expect_failure2,
+                             &val);
+  g_main_loop_run (loop);
+  g_assert (val);
+  g_object_unref (o2);
+
+  /* now kill o.. and then attempt to own the same name again.. */
+  g_object_unref (o);
+  val = FALSE;
+  val2 = FALSE;
+  o = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                            "org.gtk.Test.Name1",
+                            G_BUS_NAME_OWNER_FLAGS_NONE,
+                            NULL,
+                            (GAsyncReadyCallback) on_owner_cb_expect_success,
+                            &val);
+  g_signal_connect (o, "name-acquired", G_CALLBACK (on_name_acquired_expect_success), &val2);
+  g_main_loop_run (loop);
+  g_assert (val);
+  g_assert (val2);
+
+  /* now bring down the bus.. this should trigger the ::name-lost signal */
+  val = FALSE;
+  g_signal_connect (o, "name-lost", G_CALLBACK (on_name_lost_bringing_down_the_bus), &val);
+  g_dbus_connection_set_exit_on_close (g_bus_name_owner_get_connection (o), FALSE);
+  session_bus_down ();
+  g_main_loop_run (loop);
+  g_assert (val);
+
+  /* bring the bus back up... then we should get the ::name-acquired signal
+   *
+   * Can't use existing signal handler since it doesn't quit the main loop.
+   */
+  val = FALSE;
+  g_signal_handlers_disconnect_by_func (o, on_name_acquired_expect_success, &val2);
+  g_signal_connect (o, "name-acquired", G_CALLBACK (on_name_acquired_bringing_up_the_bus), &val);
+  session_bus_up ();
+  g_main_loop_run (loop);
+  g_assert (val);
+
+  /* Create a private connection and a bus name owner for that connection, o2, that tries to own
+   * the name with _REPLACE and _ALLOW_REPLACEMENT. This should fail because o already owns the name
+   * and didn't specify ALLOW_REPLACEMENT.
+   */
+  private_connection = g_dbus_connection_bus_get_private (G_MESSAGE_BUS_TYPE_SESSION,
+                                                          NULL,                            /* cancellable */
+                                                          (GAsyncReadyCallback) get_connection_callback_private,
+                                                          NULL);                           /* user_data */
+  g_main_loop_run (loop);
+  val = FALSE;
+  o2 = g_bus_name_owner_new_for_connection (private_connection,
+                                            "org.gtk.Test.Name1",
+                                            G_BUS_NAME_OWNER_FLAGS_REPLACE |
+                                            G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT,
+                                            NULL,
+                                            (GAsyncReadyCallback) on_owner_for_connection_cb_expect_failure,
+                                            &val);
+  g_object_unref (private_connection);
+  g_main_loop_run (loop);
+  g_assert (!g_bus_name_owner_get_owns_name (o2));
+  g_assert (val);
+
+  /* OK, so o is owning the name and o2 is in queue. Kill o and check that o2 acquires the name. */
+  val = FALSE;
+  g_signal_connect (o2, "name-acquired", G_CALLBACK (on_name_acquired_for_o2), &val);
+  g_object_unref (o);
+  g_main_loop_run (loop);
+  g_assert (g_bus_name_owner_get_owns_name (o2));
+  g_assert (val);
+
+  /* Since o2 specified ALLOW_REPLACEMENT, check that o can claim the name only when using REPLACE */
+  val = FALSE;
+  o = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                            "org.gtk.Test.Name1",
+                            G_BUS_NAME_OWNER_FLAGS_NONE,
+                            NULL,
+                            (GAsyncReadyCallback) on_owner_cb_expect_failure2,
+                            &val);
+  g_main_loop_run (loop);
+  g_assert (val);
+  g_assert (!g_bus_name_owner_get_owns_name (o));
+  g_assert (g_bus_name_owner_get_owns_name (o2));
+  g_object_unref (o);
+  /* and now with REPLACE */
+  val = FALSE;
+  o = g_bus_name_owner_new (G_MESSAGE_BUS_TYPE_SESSION,
+                            "org.gtk.Test.Name1",
+                            G_BUS_NAME_OWNER_FLAGS_REPLACE,
+                            NULL,
+                            (GAsyncReadyCallback) on_owner_cb_expect_success,
+                            &val);
+  g_main_loop_run (loop);
+  g_assert (val);
+  g_assert (g_bus_name_owner_get_owns_name (o));
+  /* we might not have gotten the signal for o2 yet */
+  if (g_bus_name_owner_get_owns_name (o2))
+    {
+      val = FALSE;
+      g_signal_connect (o2, "name-lost", G_CALLBACK (on_name_lost_for_o2), &val);
+      g_main_loop_run (loop);
+      g_assert (val);
+      g_assert (!g_bus_name_owner_get_owns_name (o2));
+    }
+  g_object_unref (o2);
+  g_object_unref (o);
+
+  session_bus_down ();
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+int
+main (int   argc,
+      char *argv[])
+{
+  g_type_init ();
+  g_test_init (&argc, &argv, NULL);
+
+  /* all the tests rely on a shared main loop */
+  loop = g_main_loop_new (NULL, FALSE);
+
+  /* all the tests use a session bus with a well-known address that we can bring up and down
+   * using session_bus_up() and session_bus_down().
+   */
+  g_unsetenv ("DISPLAY");
+  g_setenv ("DBUS_SESSION_BUS_ADDRESS", session_bus_get_temporary_address (), TRUE);
+
+  g_test_add_func ("/gdbus/message-bus-connections", test_message_bus_connections);
+  g_test_add_func ("/gdbus/bus-name-owner", test_bus_name_owner);
+  return g_test_run();
+}



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