[gvfs/gdbus-core: 1/49] gdbus: Core daemon and client port



commit 622a5c0d167556188c38fcde40a42a0dfad9c625
Author: Tomas Bzatek <tbzatek redhat com>
Date:   Tue Jul 31 11:58:09 2012 +0200

    gdbus: Core daemon and client port
    
    Port of most of the gvfs core, few bits still missing. Lot of debug prints around,
    will be removed in further commits. Same amount of TODOs and FIXMEs.
    
    Notes:
     * kill serials?
     * get rid of mainloops where applicable (copy/move progress callback, enumerator)
     * fix keyring integration
     * use gdbus builtin fd passing within gvfsdaemon.c, kill the extra_fd stuff

 .gitignore                       |    1 +
 client/gdaemonfile.c             | 3183 +++++++++++++++++++++-----------------
 client/gdaemonfileenumerator.c   |  319 +++--
 client/gdaemonfileenumerator.h   |    3 +-
 client/gdaemonmount.c            |  198 ++-
 client/gdaemonvfs.c              |  399 +++---
 client/gdaemonvfs.h              |    7 +-
 client/gvfsdaemondbus.c          |  885 +++--------
 client/gvfsdaemondbus.h          |   41 +-
 common/Makefile.am               |   20 +
 common/dbus-interfaces.xml       |  351 +++++
 common/gmountoperationdbus.c     |  506 +++----
 common/gmountoperationdbus.h     |    2 +-
 common/gmountsource.c            |  476 +++---
 common/gmountsource.h            |    4 +-
 common/gmountspec.c              |  106 +-
 common/gmountspec.h              |   28 +-
 common/gmounttracker.c           |  255 ++--
 common/gmounttracker.h           |    4 +-
 common/gvfsdaemonprotocol.c      |  558 ++-----
 common/gvfsdaemonprotocol.h      |   16 +-
 daemon/daemon-main.c             |  295 +++--
 daemon/gvfsbackend.c             |  386 +++---
 daemon/gvfsbackend.h             |   10 +-
 daemon/gvfsdaemon.c              |  719 +++++----
 daemon/gvfsdaemon.h              |   16 +-
 daemon/gvfsdaemonutils.c         |   75 -
 daemon/gvfsdaemonutils.h         |    7 -
 daemon/gvfsjob.c                 |    1 -
 daemon/gvfsjobcopy.c             |  165 ++-
 daemon/gvfsjobcopy.h             |   10 +-
 daemon/gvfsjobcreatemonitor.c    |  111 +-
 daemon/gvfsjobcreatemonitor.h    |   15 +-
 daemon/gvfsjobdbus.c             |   83 +-
 daemon/gvfsjobdbus.h             |   19 +-
 daemon/gvfsjobdelete.c           |   69 +-
 daemon/gvfsjobdelete.h           |    8 +-
 daemon/gvfsjobenumerate.c        |  226 ++--
 daemon/gvfsjobenumerate.h        |   16 +-
 daemon/gvfsjobmakedirectory.c    |   67 +-
 daemon/gvfsjobmakedirectory.h    |    8 +-
 daemon/gvfsjobmakesymlink.c      |   72 +-
 daemon/gvfsjobmakesymlink.h      |    8 +-
 daemon/gvfsjobmount.c            |   72 +-
 daemon/gvfsjobmount.h            |    8 +-
 daemon/gvfsjobmountmountable.c   |  113 +-
 daemon/gvfsjobmountmountable.h   |   10 +-
 daemon/gvfsjobmove.c             |  172 ++-
 daemon/gvfsjobmove.h             |   10 +-
 daemon/gvfsjobopenforread.c      |  103 +-
 daemon/gvfsjobopenforread.h      |   10 +-
 daemon/gvfsjobopenforwrite.c     |  133 +-
 daemon/gvfsjobopenforwrite.h     |   14 +-
 daemon/gvfsjobpollmountable.c    |   71 +-
 daemon/gvfsjobpollmountable.h    |    5 +-
 daemon/gvfsjobpull.c             |  185 ++-
 daemon/gvfsjobpull.h             |   12 +-
 daemon/gvfsjobpush.c             |  185 ++-
 daemon/gvfsjobpush.h             |   12 +-
 daemon/gvfsjobqueryattributes.c  |  109 +-
 daemon/gvfsjobqueryattributes.h  |   12 +-
 daemon/gvfsjobqueryfsinfo.c      |   76 +-
 daemon/gvfsjobqueryfsinfo.h      |    8 +-
 daemon/gvfsjobqueryinfo.c        |  106 +-
 daemon/gvfsjobqueryinfo.h        |   11 +-
 daemon/gvfsjobsetattribute.c     |   91 +-
 daemon/gvfsjobsetattribute.h     |    9 +-
 daemon/gvfsjobsetdisplayname.c   |   75 +-
 daemon/gvfsjobsetdisplayname.h   |    8 +-
 daemon/gvfsjobstartmountable.c   |   78 +-
 daemon/gvfsjobstartmountable.h   |    9 +-
 daemon/gvfsjobstopmountable.c    |   85 +-
 daemon/gvfsjobstopmountable.h    |    8 +-
 daemon/gvfsjobtrash.c            |   66 +-
 daemon/gvfsjobtrash.h            |    8 +-
 daemon/gvfsjobunmount.c          |  107 +-
 daemon/gvfsjobunmount.h          |    9 +-
 daemon/gvfsjobunmountmountable.c |  125 +-
 daemon/gvfsjobunmountmountable.h |   19 +-
 daemon/main.c                    |  156 ++-
 daemon/mount.c                   | 1215 ++++++---------
 81 files changed, 6526 insertions(+), 6727 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 0a044dd..95ffa73 100644
--- a/.gitignore
+++ b/.gitignore
@@ -40,3 +40,4 @@ gtk-doc.make
 *.enums.xml
 monitor/proxy/gvfsvolumemonitordbus.*
 metadata/metadata-dbus.*
+common/gvfsdbus.*
diff --git a/client/gdaemonfile.c b/client/gdaemonfile.c
index 27e8695..bc0afbe 100644
--- a/client/gdaemonfile.c
+++ b/client/gdaemonfile.c
@@ -38,11 +38,12 @@
 #include <gdaemonfilemonitor.h>
 #include <gdaemonfileenumerator.h>
 #include <glib/gi18n-lib.h>
-#include "gvfsdbusutils.h"
 #include "gmountoperationdbus.h"
 #include <gio/gio.h>
 #include "metatree.h"
 #include <metadata-dbus.h>
+#include <gvfsdbus.h>
+#include <gio/gunixfdlist.h>
 
 static void g_daemon_file_file_iface_init (GFileIface       *iface);
 
@@ -179,6 +180,7 @@ g_daemon_file_get_path (GFile *file)
   
   mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
 						  daemon_file->path,
+						  NULL,  /* TODO: cancellable */
 						  NULL);
 
   if (mount_info == NULL)
@@ -370,210 +372,130 @@ g_daemon_file_resolve_relative_path (GFile *file,
   return child;
 }
 
-static DBusMessage *
-create_empty_message (GFile *file,
-		      const char *op,
-		      GMountInfo **mount_info_out,
-		      GError **error)
-{
-  GDaemonFile *daemon_file = G_DAEMON_FILE (file);
-  DBusMessage *message;
-  GMountInfo *mount_info;
-  const char *path;
-
-  mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
-						  daemon_file->path,
-						  error);
-  if (mount_info == NULL)
-    return NULL;
-
-  if (mount_info_out)
-    *mount_info_out = g_mount_info_ref (mount_info);
-  
-  message =
-    dbus_message_new_method_call (mount_info->dbus_id,
-				  mount_info->object_path,
-				  G_VFS_DBUS_MOUNT_INTERFACE,
-				  op);
-
-  path = g_mount_info_resolve_path (mount_info,
-				    daemon_file->path);
-  _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0);
-
-  g_mount_info_unref (mount_info);
-  return message;
-}
-
-static DBusMessage *
-do_sync_path_call (GFile *file,
-		   const char *op,
-		   GMountInfo **mount_info_out,
-		   DBusConnection **connection_out,
-		   GCancellable *cancellable,
-		   GError **error,
-		   int first_arg_type,
-		   ...)
-{
-  DBusMessage *message, *reply;
-  va_list var_args;
-  GError *my_error;
-
- retry:
-  
-  message = create_empty_message (file, op, mount_info_out, error);
-  if (!message)
-    return NULL;
-
-  va_start (var_args, first_arg_type);
-  _g_dbus_message_append_args_valist (message,
-				      first_arg_type,
-				      var_args);
-  va_end (var_args);
-
-
-  my_error = NULL;
-  reply = _g_vfs_daemon_call_sync (message,
-				   connection_out,
-				   NULL, NULL, NULL,
-				   cancellable, &my_error);
-  dbus_message_unref (message);
-
-  if (reply == NULL)
-    {
-      if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
-	{
-	  g_error_free (my_error);
-	  goto retry;
-	}
-      g_propagate_error (error, my_error);
-    }
-
-  return reply;
-}
-
-static DBusMessage *
-do_sync_2_path_call (GFile *file1,
-		     GFile *file2,
-		     const char *op,
-		     const char *callback_obj_path,
-		     DBusObjectPathMessageFunction callback,
-		     gpointer callback_user_data, 
-		     DBusConnection **connection_out,
-		     GCancellable *cancellable,
-		     GError **error,
-		     int first_arg_type,
-		     ...)
+static GVfsDBusMount *
+create_proxy_for_file2 (GFile *file1,
+                        GFile *file2,
+                        GMountInfo **mount_info1_out,
+                        GMountInfo **mount_info2_out,
+                        gchar **path1_out,
+                        gchar **path2_out,
+                        GDBusConnection **connection_out,
+                        GCancellable *cancellable,
+                        GError **error)
 {
+  GVfsDBusMount *proxy;
   GDaemonFile *daemon_file1 = G_DAEMON_FILE (file1);
   GDaemonFile *daemon_file2 = G_DAEMON_FILE (file2);
-  DBusMessage *message, *reply;
   GMountInfo *mount_info1, *mount_info2;
-  const char *path1, *path2;
-  va_list var_args;
-  GError *my_error;
+  GDBusConnection *connection;
 
- retry:
+  proxy = NULL;
+  mount_info2 = NULL;
   
   mount_info1 = _g_daemon_vfs_get_mount_info_sync (daemon_file1->mount_spec,
-						   daemon_file1->path,
-						   error);
+                                                   daemon_file1->path,
+                                                   cancellable,
+                                                   error);
+  
   if (mount_info1 == NULL)
-    return NULL;
+    goto out;
 
-  mount_info2 = NULL;
   if (daemon_file2)
     {
       mount_info2 = _g_daemon_vfs_get_mount_info_sync (daemon_file2->mount_spec,
-						       daemon_file2->path,
-						       error);
+                                                       daemon_file2->path,
+                                                       cancellable,
+                                                       error);
       if (mount_info2 == NULL)
-	{
-	  g_mount_info_unref (mount_info1);
-	  return NULL;
-	}
+        goto out;
 
-      if (mount_info1 != mount_info2)
-	{
-	  g_mount_info_unref (mount_info1);
-	  /* For copy this will cause the fallback code to be involved */
-	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
-			       _("Operation not supported, files on different mounts"));
-	  return NULL;
-	}
+      if (! g_mount_info_equal (mount_info1, mount_info2))
+        {
+          /* For copy this will cause the fallback code to be involved */
+          g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
+                               _("Operation not supported, files on different mounts"));
+          goto out;
+        }
     }
-      
-  message =
-    dbus_message_new_method_call (mount_info1->dbus_id,
-				  mount_info1->object_path,
-				  G_VFS_DBUS_MOUNT_INTERFACE,
-				  op);
 
-  path1 = g_mount_info_resolve_path (mount_info1,
-				     daemon_file1->path);
-  _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path1, 0);
+  connection = _g_dbus_connection_get_sync (mount_info1->dbus_id, cancellable, error);
+  if (connection == NULL)
+    goto out;
 
-  if (daemon_file2)
-    {
-      path2 = g_mount_info_resolve_path (mount_info2,
-					 daemon_file2->path);
-      _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path2, 0);
-    }
+  proxy = gvfs_dbus_mount_proxy_new_sync (connection,
+                                          G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                          mount_info1->dbus_id,
+                                          mount_info1->object_path,
+                                          cancellable,
+                                          error);
   
-  va_start (var_args, first_arg_type);
-  _g_dbus_message_append_args_valist (message,
-				      first_arg_type,
-				      var_args);
-  va_end (var_args);
+  if (proxy == NULL)
+    goto out;
+  
+  _g_dbus_connect_vfs_filters (connection);
 
-  my_error = NULL;
-  reply = _g_vfs_daemon_call_sync (message,
-				   connection_out,
-				   callback_obj_path,
-				   callback,
-				   callback_user_data, 
-				   cancellable, &my_error);
-  dbus_message_unref (message);
+  if (mount_info1_out)
+    *mount_info1_out = g_mount_info_ref (mount_info1);
+  if (mount_info2_out && mount_info2)
+    *mount_info2_out = g_mount_info_ref (mount_info2);
+  if (path1_out)
+    *path1_out = g_strdup (g_mount_info_resolve_path (mount_info1, daemon_file1->path));
+  if (path2_out && mount_info2)
+    *path2_out = g_strdup (g_mount_info_resolve_path (mount_info2, daemon_file2->path));
+  if (connection_out)
+    *connection_out = connection;
 
+ out:
   g_mount_info_unref (mount_info1);
   if (mount_info2)
     g_mount_info_unref (mount_info2);
+ 
+  return proxy;
+}
 
-  if (reply == NULL)
-    {
-      if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
-	{
-	  g_error_free (my_error);
-	  goto retry;
-	}
-      g_propagate_error (error, my_error);
-    }
-  
-  return reply;
+static GVfsDBusMount *
+create_proxy_for_file (GFile *file,
+                       GMountInfo **mount_info_out,
+                       gchar **path_out,
+                       GDBusConnection **connection_out,
+                       GCancellable *cancellable,
+                       GError **error)
+{
+  return create_proxy_for_file2 (file, NULL,
+                                 mount_info_out, NULL,
+                                 path_out, NULL,
+                                 connection_out,
+                                 cancellable,
+                                 error);
 }
 
-typedef void (*AsyncPathCallCallback) (DBusMessage *reply,
-				       DBusConnection *connection,
-				       GMountInfo *mount_info,
-				       GSimpleAsyncResult *result,
-				       GCancellable *cancellable,
-				       gpointer callback_data);
 
+typedef void (*CreateProxyAsyncCallback) (GVfsDBusMount *proxy,
+                                          GDBusConnection *connection,
+                                          GMountInfo *mount_info,
+                                          const gchar *path,
+                                          GSimpleAsyncResult *result,
+                                          GError *error,
+                                          GCancellable *cancellable,
+                                          gpointer callback_data);
 
 typedef struct {
   GSimpleAsyncResult *result;
   GFile *file;
   char *op;
   GCancellable *cancellable;
-  DBusMessage *args;
-  AsyncPathCallCallback callback;
+  CreateProxyAsyncCallback callback;
   gpointer callback_data;
   GDestroyNotify notify;
   GMountInfo *mount_info;
-} AsyncPathCall;
+  GDBusConnection *connection;
+  GVfsDBusMount *proxy;
+} AsyncProxyCreate;
 
 static void
-async_path_call_free (AsyncPathCall *data)
+async_proxy_create_free (AsyncProxyCreate *data)
 {
+  g_print ("async_proxy_create_free\n");
   if (data->notify)
     data->notify (data->callback_data);
 
@@ -583,144 +505,176 @@ async_path_call_free (AsyncPathCall *data)
   g_free (data->op);
   if (data->cancellable)
     g_object_unref (data->cancellable);
-  if (data->args)
-    dbus_message_unref (data->args);
   if (data->mount_info)
     g_mount_info_unref (data->mount_info);
+  if (data->connection)
+    g_object_unref (data->connection);
+  if (data->proxy)
+    g_object_unref (data->proxy);
   g_free (data);
 }
 
 static void
-async_path_call_done (DBusMessage *reply,
-		      DBusConnection *connection,
-		      GError *io_error,
-		      gpointer _data)
+async_proxy_new_cb (GObject *source_object,
+                    GAsyncResult *res,
+                    gpointer user_data)
 {
-  AsyncPathCall *data = _data;
+  AsyncProxyCreate *data = user_data;
+  GDaemonFile *daemon_file = G_DAEMON_FILE (data->file);
+  const char *path;
+  GVfsDBusMount *proxy;
+  GError *error = NULL;
   GSimpleAsyncResult *result;
-
-  if (io_error != NULL)
+  
+  proxy = gvfs_dbus_mount_proxy_new_finish (res, &error);
+  g_print ("async_proxy_new_cb, proxy = %p\n", proxy);
+  if (proxy == NULL)
     {
-      g_simple_async_result_set_from_error (data->result, io_error);
+      g_simple_async_result_take_error (data->result, error);      
       _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
-      async_path_call_free (data);
-    }
-  else
-    {
-      result = data->result;
-      g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_path_call_free, data);
-      data->result = NULL;
-      
-      data->callback (reply,
-                      connection,
-                      data->mount_info,
-		      result,
-		      data->cancellable,
-		      data->callback_data);
-
-      /* Free data here, or later if callback ref:ed the result */
-      g_object_unref (result);
+      async_proxy_create_free (data);
+      return;
     }
+  
+  data->proxy = proxy;
+  _g_dbus_connect_vfs_filters (data->connection);
+  path = g_mount_info_resolve_path (data->mount_info, daemon_file->path);
+
+  /* Complete the create_proxy_for_file_async() call */
+  result = data->result;
+  g_object_weak_ref (G_OBJECT (result), (GWeakNotify)async_proxy_create_free, data);
+  data->result = NULL;
+  
+  data->callback (proxy,
+                  data->connection,
+                  data->mount_info,
+                  path,
+                  result,
+                  NULL,
+                  data->cancellable,
+                  data->callback_data);
+
+  /* Free data here, or later if callback ref:ed the result */
+  g_object_unref (result);
 }
 
 static void
-do_async_path_call_callback (GMountInfo *mount_info,
-			     gpointer _data,
-			     GError *error)
+async_construct_proxy (GDBusConnection *connection,
+                       AsyncProxyCreate *data)
 {
-  AsyncPathCall *data = _data;
-  GDaemonFile *daemon_file = G_DAEMON_FILE (data->file);
-  const char *path;
-  DBusMessage *message;
-  DBusMessageIter arg_source, arg_dest;
+  data->connection = g_object_ref (connection);
+  gvfs_dbus_mount_proxy_new (connection,
+                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                             data->mount_info->dbus_id,
+                             data->mount_info->object_path,
+                             data->cancellable,
+                             async_proxy_new_cb,
+                             data);
+}
+
+static void
+bus_get_cb (GObject *source_object,
+            GAsyncResult *res,
+            gpointer user_data)
+{
+  AsyncProxyCreate *data = user_data;
+  GDBusConnection *connection;
+  GError *error = NULL;
   
-  if (error != NULL)
+  connection = g_bus_get_finish (res, &error);
+  
+  if (connection == NULL)
     {
-      g_simple_async_result_set_from_error (data->result, error);      
+      g_simple_async_result_set_from_error (data->result, error);
       _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
-      async_path_call_free (data);
+      async_proxy_create_free (data);
       return;
     }
 
-  data->mount_info = g_mount_info_ref (mount_info);
+  async_construct_proxy (connection, data);
+}
 
-  message =
-    dbus_message_new_method_call (mount_info->dbus_id,
-				  mount_info->object_path,
-				  G_VFS_DBUS_MOUNT_INTERFACE,
-				  data->op);
+static void
+async_got_connection_cb (GDBusConnection *connection,
+                         GError *io_error,
+                         gpointer callback_data)
+{
+  AsyncProxyCreate *data = callback_data;
+  
+  g_print ("async_got_connection_cb, connection = %p\n", connection);
   
-  path = g_mount_info_resolve_path (mount_info, daemon_file->path);
-  _g_dbus_message_append_args (message, G_DBUS_TYPE_CSTRING, &path, 0);
+  if (connection == NULL)
+    {
+      /* TODO: we should probably test if we really want a session bus;
+       *       for now, this code is on par with the old dbus code */ 
+      g_bus_get (G_BUS_TYPE_SESSION,
+                 data->cancellable,
+                 bus_get_cb,
+                 data);
+      return;
+    }
+  
+  async_construct_proxy (connection, data);
+}
 
-  /* Append more args from data->args */
+static void
+async_got_mount_info (GMountInfo *mount_info,
+                      gpointer _data,
+                      GError *error)
+{
+  AsyncProxyCreate *data = _data;
+ 
+  g_print ("async_got_mount_info, mount_info = %p\n", mount_info);
 
-  if (data->args)
+  if (error != NULL)
     {
-      dbus_message_iter_init (data->args, &arg_source);
-      dbus_message_iter_init_append (message, &arg_dest);
-
-      _g_dbus_message_iter_copy (&arg_dest, &arg_source);
+      g_simple_async_result_set_from_error (data->result, error);      
+      _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
+      async_proxy_create_free (data);
+      return;
     }
 
-  _g_vfs_daemon_call_async (message,
-			    async_path_call_done, data,
-			    data->cancellable);
-  
-  dbus_message_unref (message);
+  data->mount_info = g_mount_info_ref (mount_info);
+
+  _g_dbus_connection_get_for_async (mount_info->dbus_id,
+                                    async_got_connection_cb,
+                                    data,
+                                    data->cancellable);
 }
 
 static void
-do_async_path_call (GFile *file,
-		    const char *op,
-		    GCancellable *cancellable,
-		    GAsyncReadyCallback op_callback,
-		    gpointer op_callback_data,
-		    AsyncPathCallCallback callback,
-		    gpointer callback_data,
-		    GDestroyNotify notify,
-		    int first_arg_type,
-		    ...)
+create_proxy_for_file_async (GFile *file,
+                             GCancellable *cancellable,
+                             GAsyncReadyCallback op_callback,
+                             gpointer op_callback_data,
+                             CreateProxyAsyncCallback callback,
+                             gpointer callback_data,
+                             GDestroyNotify notify)
 {
   GDaemonFile *daemon_file = G_DAEMON_FILE (file);
-  va_list var_args;
-  AsyncPathCall *data;
+  AsyncProxyCreate *data;
 
-  data = g_new0 (AsyncPathCall, 1);
+  g_print ("create_proxy_for_file_async\n");
+  
+  data = g_new0 (AsyncProxyCreate, 1);
 
   data->result = g_simple_async_result_new (G_OBJECT (file),
-					    op_callback, op_callback_data,
-					    NULL);
+                                            op_callback, op_callback_data,
+                                            NULL);
 
   data->file = g_object_ref (file);
-  data->op = g_strdup (op);
   if (cancellable)
     data->cancellable = g_object_ref (cancellable);
   data->callback = callback;
   data->callback_data = callback_data;
   data->notify = notify;
   
-  if (first_arg_type != 0)
-    {
-      data->args = dbus_message_new (DBUS_MESSAGE_TYPE_METHOD_CALL);
-      if (data->args == NULL)
-	_g_dbus_oom ();
-      
-      va_start (var_args, first_arg_type);
-      _g_dbus_message_append_args_valist (data->args,
-					  first_arg_type,
-					  var_args);
-      va_end (var_args);
-    }
-  
-  
   _g_daemon_vfs_get_mount_info_async (daemon_file->mount_spec,
-				     daemon_file->path,
-				     do_async_path_call_callback,
-				     data);
+                                      daemon_file->path,
+                                      async_got_mount_info,
+                                      data);
 }
 
-
 static GFileEnumerator *
 g_daemon_file_enumerate_children (GFile      *file,
 				  const char *attributes,
@@ -728,47 +682,51 @@ g_daemon_file_enumerate_children (GFile      *file,
 				  GCancellable *cancellable,
 				  GError **error)
 {
-  DBusMessage *reply;
-  dbus_uint32_t flags_dbus;
   char *obj_path;
+  char *path;
   GDaemonFileEnumerator *enumerator;
-  DBusConnection *connection;
+  GDBusConnection *connection;
   char *uri;
-
+  GVfsDBusMount *proxy;
+  gboolean res;
+  
+  g_print ("g_daemon_file_enumerate_children\n");
+  
   enumerator = g_daemon_file_enumerator_new (file, attributes);
-  obj_path = g_daemon_file_enumerator_get_object_path (enumerator);
-
 
+  proxy = create_proxy_for_file (file, NULL, &path, &connection, cancellable, error);
+  if (proxy == NULL)
+    goto out;
+ 
+  obj_path = g_daemon_file_enumerator_get_object_path (enumerator);
   uri = g_file_get_uri (file);
+
+  res = gvfs_dbus_mount_call_enumerate_sync (proxy,
+                                             path,
+                                             obj_path,
+                                             attributes ? attributes : "",
+                                             flags,
+                                             uri,
+                                             cancellable,
+                                             error);
+  
+  g_print ("g_daemon_file_enumerate_children: done, res = %d\n", res);
   
-  if (attributes == NULL)
-    attributes = "";
-  flags_dbus = flags;
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_ENUMERATE,
-			     NULL, &connection,
-			     cancellable, error,
-			     DBUS_TYPE_STRING, &obj_path,
-			     DBUS_TYPE_STRING, &attributes,
-			     DBUS_TYPE_UINT32, &flags_dbus,
-			     DBUS_TYPE_STRING, &uri,
-			     0);
+  g_free (path);
   g_free (uri);
   g_free (obj_path);
+  g_object_unref (proxy);
 
-  if (reply == NULL)
-    goto error;
-
-  dbus_message_unref (reply);
-
+  if (! res)
+    goto out;
+  
   g_daemon_file_enumerator_set_sync_connection (enumerator, connection);
   
   return G_FILE_ENUMERATOR (enumerator);
-
- error:
-  if (reply)
-    dbus_message_unref (reply);
-  g_object_unref (enumerator);
+  
+out:
+  if (enumerator != NULL)
+    g_object_unref (enumerator);
   return NULL;
 }
 
@@ -843,94 +801,143 @@ g_daemon_file_query_info (GFile                *file,
 			  GCancellable         *cancellable,
 			  GError              **error)
 {
-  DBusMessage *reply;
-  dbus_uint32_t flags_dbus;
-  DBusMessageIter iter;
+  char *path;
   GFileInfo *info;
   char *uri;
+  GVfsDBusMount *proxy;
+  GVariant *iter_info;
+  gboolean res;
+
+  g_print ("g_daemon_file_query_info\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return NULL;
 
   uri = g_file_get_uri (file);
 
-  if (attributes == NULL)
-    attributes = "";
-  flags_dbus = flags;
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_QUERY_INFO,
-			     NULL, NULL,
-			     cancellable, error,
-			     DBUS_TYPE_STRING, &attributes,
-			     DBUS_TYPE_UINT32, &flags_dbus,
-			     DBUS_TYPE_STRING, &uri,
-			     0);
+  iter_info = NULL;
+  res = gvfs_dbus_mount_call_query_info_sync (proxy,
+                                              path,
+                                              attributes ? attributes : "",
+                                              flags,
+                                              uri,
+                                              &iter_info,
+                                              cancellable,
+                                              error);
+
+  g_print ("g_daemon_file_query_info: done, res = %d\n", res);
 
+  g_free (path);
   g_free (uri);
-  
-  if (reply == NULL)
-    return NULL;
+  g_object_unref (proxy);
 
-  info = NULL;
-  
-  if (!dbus_message_iter_init (reply, &iter) ||
-      (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   /* Translators: %s is the name of a programming function */
-			   _("Invalid return value from %s"), "get_info");
-      goto out;
-    }
+  if (! res)
+    return NULL;
 
-  info = _g_dbus_get_file_info (&iter, error);
+  info = _g_dbus_get_file_info (iter_info, error);
+  g_variant_unref (iter_info);
 
   if (info)
     add_metadata (file, attributes, info);
-
- out:
-  dbus_message_unref (reply);
+  
   return info;
 }
 
+
+typedef struct {
+  GFile *file;
+  char *attributes;
+  GFileQueryInfoFlags flags;
+  int io_priority;
+  GSimpleAsyncResult *result;
+  GCancellable *cancellable;
+} AsyncCallQueryInfo;
+
 static void
-query_info_async_cb (DBusMessage *reply,
-		     DBusConnection *connection,
-                     GMountInfo *mount_info,
-		     GSimpleAsyncResult *result,
-		     GCancellable *cancellable,
-		     gpointer callback_data)
+async_call_query_info_free (AsyncCallQueryInfo *data)
 {
-  const char *attributes = callback_data;
-  DBusMessageIter iter;
+  if (data->file)
+    g_object_unref (data->file);
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  g_free (data->attributes);
+  g_free (data);
+}
+
+static void
+query_info_async_cb (GVfsDBusMount *proxy,
+                     GAsyncResult *res,
+                     gpointer user_data)
+{
+  AsyncCallQueryInfo *data = user_data;
+  GError *error = NULL;
+  GSimpleAsyncResult *orig_result;
+  GVariant *iter_info;
   GFileInfo *info;
-  GError *error;
   GFile *file;
-
-  info = NULL;
   
-  if (!dbus_message_iter_init (reply, &iter) ||
-      (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
+  g_print ("query_info_async_cb\n");
+  orig_result = data->result;
+  
+  if (! gvfs_dbus_mount_call_query_info_finish (proxy, &iter_info, res, &error))
     {
-      g_simple_async_result_set_error (result,
-				       G_IO_ERROR, G_IO_ERROR_FAILED,
-				       _("Invalid return value from %s"), "query_info");
-      _g_simple_async_result_complete_with_cancellable (result, cancellable);
-      return;
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
     }
+  
+  info = _g_dbus_get_file_info (iter_info, &error);
+  g_variant_unref (iter_info);
 
-  error = NULL;
-  info = _g_dbus_get_file_info (&iter, &error);
   if (info == NULL)
     {
-      g_simple_async_result_set_from_error (result, error);
-      g_error_free (error);
-      _g_simple_async_result_complete_with_cancellable (result, cancellable);
-      return;
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
     }
 
-  file = G_FILE (g_async_result_get_source_object (G_ASYNC_RESULT (result)));
-  add_metadata (file, attributes, info);
+  file = G_FILE (g_async_result_get_source_object (G_ASYNC_RESULT (orig_result)));
+  add_metadata (file, data->attributes, info);
   g_object_unref (file);
 
-  g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref);
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  g_simple_async_result_set_op_res_gpointer (orig_result, info, g_object_unref);
+  
+out:
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+query_info_async_get_proxy_cb (GVfsDBusMount *proxy,
+                               GDBusConnection *connection,
+                               GMountInfo *mount_info,
+                               const gchar *path,
+                               GSimpleAsyncResult *result,
+                               GError *error,
+                               GCancellable *cancellable,
+                               gpointer callback_data)
+{
+  AsyncCallQueryInfo *data = callback_data;
+  char *uri;
+
+  g_print ("query_info_async_get_proxy_cb, proxy = %p\n", proxy);
+  
+  uri = g_file_get_uri (data->file);
+  
+  data->result = g_object_ref (result);
+  
+  gvfs_dbus_mount_call_query_info (proxy,
+                                   path,
+                                   data->attributes ? data->attributes : "",
+                                   data->flags,
+                                   uri,
+                                   cancellable,
+                                   (GAsyncReadyCallback) query_info_async_cb,
+                                   data);
+  
+  g_free (uri);
 }
 
 static void
@@ -942,23 +949,23 @@ g_daemon_file_query_info_async (GFile                      *file,
 				GAsyncReadyCallback         callback,
 				gpointer                    user_data)
 {
-  guint32 dbus_flags;
-  char *uri;
+  AsyncCallQueryInfo *data;
 
-  uri = g_file_get_uri (file);
-
-  dbus_flags = flags;
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_QUERY_INFO,
-		      cancellable,
-		      callback, user_data,
-		      query_info_async_cb, g_strdup (attributes), g_free,
-		      DBUS_TYPE_STRING, &attributes,
-		      DBUS_TYPE_UINT32, &dbus_flags,
-		      DBUS_TYPE_STRING, &uri,
-		      0);
+  g_print ("g_daemon_file_query_info_async\n");
+  
+  data = g_new0 (AsyncCallQueryInfo, 1);
+  data->file = g_object_ref (file);
+  data->attributes = g_strdup (attributes);
+  data->flags = flags;
+  data->io_priority = io_priority;
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  g_free (uri);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               query_info_async_get_proxy_cb,
+                               data, (GDestroyNotify) async_call_query_info_free);
 }
 
 static GFileInfo *
@@ -976,67 +983,100 @@ g_daemon_file_query_info_finish (GFile                      *file,
   return NULL;
 }
 
+
 typedef struct {
+  GFile *file;
+  guint16 mode;
+  int io_priority;
+  gchar *etag;
+  gboolean make_backup;
+  GFileCreateFlags flags;
   GSimpleAsyncResult *result;
   GCancellable *cancellable;
-  gboolean can_seek;
-} GetFDData;
+} AsyncCallFileReadWrite;
+
+static void
+async_call_file_read_write_free (AsyncCallFileReadWrite *data)
+{
+  if (data->file)
+    g_object_unref (data->file);
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  g_free (data->etag);
+  g_free (data);
+}
 
 static void
-read_async_get_fd_cb (int fd,
-		      gpointer callback_data)
+read_async_cb (GVfsDBusMount *proxy,
+               GAsyncResult *res,
+               gpointer user_data)
 {
-  GetFDData *data = callback_data;
+  AsyncCallFileReadWrite *data = user_data;
+  GError *error = NULL;
+  GSimpleAsyncResult *orig_result;
+  gboolean can_seek;
+  GUnixFDList *fd_list;
+  int fd;
+  guint fd_id;
   GFileInputStream *stream;
+
+  g_print ("read_async_cb\n");
+  orig_result = data->result;
   
-  if (fd == -1)
+  if (! gvfs_dbus_mount_call_open_for_read_finish (proxy, &fd_id, &can_seek, &fd_list, res, &error))
+    {
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
+    }
+
+  if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 ||
+      (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1)
     {
-      g_simple_async_result_set_error (data->result,
-				       G_IO_ERROR, G_IO_ERROR_FAILED,
-				       _("Couldn't get stream file descriptor"));
+      g_simple_async_result_set_error (orig_result,
+                                       G_IO_ERROR, G_IO_ERROR_FAILED,
+                                       _("Couldn't get stream file descriptor"));
     }
   else
     {
-      stream = g_daemon_file_input_stream_new (fd, data->can_seek);
-      g_simple_async_result_set_op_res_gpointer (data->result, stream, g_object_unref);
+      stream = g_daemon_file_input_stream_new (fd, can_seek);
+      g_simple_async_result_set_op_res_gpointer (orig_result, stream, g_object_unref);
+      g_object_unref (fd_list);
     }
 
-  _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
-
-  g_object_unref (data->result);
-  g_free (data);
+out:
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
 
 static void
-read_async_cb (DBusMessage *reply,
-	       DBusConnection *connection,
-               GMountInfo *mount_info,
-	       GSimpleAsyncResult *result,
-	       GCancellable *cancellable,
-	       gpointer callback_data)
-{
-  guint32 fd_id;
-  dbus_bool_t can_seek;
-  GetFDData *get_fd_data;
-  
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &can_seek,
-			      DBUS_TYPE_INVALID))
-    {
-      g_simple_async_result_set_error (result,
-				       G_IO_ERROR, G_IO_ERROR_FAILED,
-				       _("Invalid return value from %s"), "open");
-      _g_simple_async_result_complete_with_cancellable (result, cancellable);
-      return;
-    }
+file_read_async_get_proxy_cb (GVfsDBusMount *proxy,
+                               GDBusConnection *connection,
+                               GMountInfo *mount_info,
+                               const gchar *path,
+                               GSimpleAsyncResult *result,
+                               GError *error,
+                               GCancellable *cancellable,
+                               gpointer callback_data)
+{
+  AsyncCallFileReadWrite *data = callback_data;
+  guint32 pid;
+
+  g_print ("file_read_async_get_proxy_cb, proxy = %p\n", proxy);
+
+  pid = get_pid_for_file (data->file);
   
-  get_fd_data = g_new0 (GetFDData, 1);
-  get_fd_data->result = g_object_ref (result);
-  get_fd_data->can_seek = can_seek;
+  data->result = g_object_ref (result);
   
-  _g_dbus_connection_get_fd_async (connection, fd_id,
-				   read_async_get_fd_cb, get_fd_data);
+  gvfs_dbus_mount_call_open_for_read (proxy,
+                                     path,
+                                     pid,
+                                     NULL,
+                                     cancellable,
+                                     (GAsyncReadyCallback) read_async_cb,
+                                     data);
 }
 
 static void
@@ -1046,17 +1086,21 @@ g_daemon_file_read_async (GFile *file,
 			  GAsyncReadyCallback callback,
 			  gpointer callback_data)
 {
-  guint32 pid;
+  AsyncCallFileReadWrite *data;
 
-  pid = get_pid_for_file (file);
+  g_print ("g_daemon_file_read_async\n");
+  
+  data = g_new0 (AsyncCallFileReadWrite, 1);
+  data->file = g_object_ref (file);
+  data->io_priority = io_priority;
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ,
-		      cancellable,
-		      callback, callback_data,
-		      read_async_cb, NULL, NULL,
-                      DBUS_TYPE_UINT32, &pid,
-		      0);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, callback_data,
+                               file_read_async_get_proxy_cb,
+                               data, (GDestroyNotify) async_call_file_read_write_free);
 }
 
 static GFileInputStream *
@@ -1074,178 +1118,143 @@ g_daemon_file_read_finish (GFile                  *file,
   return NULL;
 }
 
-
 static GFileInputStream *
 g_daemon_file_read (GFile *file,
 		    GCancellable *cancellable,
 		    GError **error)
 {
-  DBusConnection *connection;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
+  gboolean can_seek;
+  GUnixFDList *fd_list;
   int fd;
-  DBusMessage *reply;
-  guint32 fd_id;
-  dbus_bool_t can_seek;
+  guint fd_id;
   guint32 pid;
 
+  g_print ("g_daemon_file_read\n");
+
   pid = get_pid_for_file (file);
 
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ,
-			     NULL, &connection,
-			     cancellable, error,
-                             DBUS_TYPE_UINT32, &pid,
-			     0);
-  if (reply == NULL)
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return NULL;
 
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &can_seek,
-			      DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (reply);
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "open");
-      return NULL;
-    }
+  res = gvfs_dbus_mount_call_open_for_read_sync (proxy,
+                                                 path,
+                                                 pid,
+                                                 NULL,
+                                                 &fd_id,
+                                                 &can_seek,
+                                                 &fd_list,
+                                                 cancellable,
+                                                 error);
   
-  dbus_message_unref (reply);
+  g_print ("g_daemon_file_read: done, res = %d\n", res);
+  
+  g_free (path);
+  g_object_unref (proxy);
 
-  fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
-  if (fd == -1)
+  if (! res)
+    return NULL;
+  
+  if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 ||
+      (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1)
     {
       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 			   _("Didn't get stream file descriptor"));
       return NULL;
     }
+
+  g_object_unref (fd_list);
   
   return g_daemon_file_input_stream_new (fd, can_seek);
 }
 
 static GFileOutputStream *
-g_daemon_file_append_to (GFile *file,
-			 GFileCreateFlags flags,
-			 GCancellable *cancellable,
-			 GError **error)
-{
-  DBusConnection *connection;
+file_open_write (GFile *file,
+		 guint16 mode,
+                 const char *etag,
+                 gboolean make_backup,
+                 GFileCreateFlags flags,
+		 GCancellable *cancellable,
+		 GError **error)
+{
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
+  gboolean can_seek;
+  GUnixFDList *fd_list;
   int fd;
-  DBusMessage *reply;
   guint32 fd_id;
-  dbus_bool_t can_seek;
-  guint16 mode;
-  guint64 initial_offset;
-  dbus_bool_t make_backup;
-  guint32 dbus_flags;
-  char *etag;
   guint32 pid;
+  guint64 initial_offset;
 
   pid = get_pid_for_file (file);
 
-  mode = 1;
-  etag = "";
-  make_backup = FALSE;
-  dbus_flags = flags;
-  
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
-			     NULL, &connection,
-			     cancellable, error,
-			     DBUS_TYPE_UINT16, &mode,
-			     DBUS_TYPE_STRING, &etag,
-			     DBUS_TYPE_BOOLEAN, &make_backup,
-			     DBUS_TYPE_UINT32, &dbus_flags,
-                             DBUS_TYPE_UINT32, &pid,
-			     0);
-  if (reply == NULL)
+  if (etag == NULL)
+    etag = "";
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return NULL;
 
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &can_seek,
-			      DBUS_TYPE_UINT64, &initial_offset,
-			      DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (reply);
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "open");
-      return NULL;
-    }
+  res = gvfs_dbus_mount_call_open_for_write_sync (proxy,
+                                                  path,
+                                                  mode,
+                                                  etag,
+                                                  make_backup,
+                                                  flags,
+                                                  pid,
+                                                  NULL,
+                                                  &fd_id,
+                                                  &can_seek,
+                                                  &initial_offset,
+                                                  &fd_list,
+                                                  cancellable,
+                                                  error);
+  
+  g_print ("file_open_write: done, res = %d\n", res);
   
-  dbus_message_unref (reply);
+  g_free (path);
+  g_object_unref (proxy);
 
-  fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
-  if (fd == -1)
+  if (! res)
+    return NULL;
+  
+  if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 ||
+      (fd = g_unix_fd_list_get (fd_list, 0, NULL)) == -1)
     {
       g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Didn't get stream file descriptor"));
+                           _("Didn't get stream file descriptor"));
       return NULL;
     }
+
+  g_object_unref (fd_list);
   
   return g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
 }
 
 static GFileOutputStream *
+g_daemon_file_append_to (GFile *file,
+                         GFileCreateFlags flags,
+                         GCancellable *cancellable,
+                         GError **error)
+{
+  g_print ("g_daemon_file_append_to\n");
+
+  return file_open_write (file, 1, "", FALSE, flags, cancellable, error);
+}
+
+static GFileOutputStream *
 g_daemon_file_create (GFile *file,
 		      GFileCreateFlags flags,
 		      GCancellable *cancellable,
 		      GError **error)
 {
-  DBusConnection *connection;
-  int fd;
-  DBusMessage *reply;
-  guint32 fd_id;
-  dbus_bool_t can_seek;
-  guint16 mode;
-  guint64 initial_offset;
-  dbus_bool_t make_backup;
-  char *etag;
-  guint32 dbus_flags;
-  guint32 pid;
-
-  pid = get_pid_for_file (file);
+  g_print ("g_daemon_file_create\n");
 
-  mode = 0;
-  etag = "";
-  make_backup = FALSE;
-  dbus_flags = flags;
-  
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
-			     NULL, &connection,
-			     cancellable, error,
-			     DBUS_TYPE_UINT16, &mode,
-			     DBUS_TYPE_STRING, &etag,
-			     DBUS_TYPE_BOOLEAN, &make_backup,
-			     DBUS_TYPE_UINT32, &dbus_flags,
-                             DBUS_TYPE_UINT32, &pid,
-			     0);
-  if (reply == NULL)
-    return NULL;
-
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &can_seek,
-			      DBUS_TYPE_UINT64, &initial_offset,
-			      DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (reply);
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "open");
-      return NULL;
-    }
-  
-  dbus_message_unref (reply);
-
-  fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
-  if (fd == -1)
-    {
-      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Didn't get stream file descriptor"));
-      return NULL;
-    }
-  
-  return g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
+  return file_open_write (file, 0, "", FALSE, flags, cancellable, error);
 }
 
 static GFileOutputStream *
@@ -1256,62 +1265,29 @@ g_daemon_file_replace (GFile *file,
 		       GCancellable *cancellable,
 		       GError **error)
 {
-  DBusConnection *connection;
-  int fd;
-  DBusMessage *reply;
-  guint32 fd_id;
-  dbus_bool_t can_seek;
-  guint16 mode;
-  guint64 initial_offset;
-  dbus_bool_t dbus_make_backup;
-  guint32 dbus_flags;
-  guint32 pid;
+  g_print ("g_daemon_file_replace\n");
 
-  pid = get_pid_for_file (file);
-
-  mode = 2;
-  dbus_make_backup = make_backup;
-  dbus_flags = flags;
+  return file_open_write (file, 2, etag, make_backup, flags, cancellable, error);
+}
 
-  if (etag == NULL)
-    etag = "";
-  
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
-			     NULL, &connection,
-			     cancellable, error,
-			     DBUS_TYPE_UINT16, &mode,
-			     DBUS_TYPE_STRING, &etag,
-			     DBUS_TYPE_BOOLEAN, &dbus_make_backup,
-			     DBUS_TYPE_UINT32, &dbus_flags,
-                             DBUS_TYPE_UINT32, &pid,
-			     0);
-  if (reply == NULL)
-    return NULL;
 
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &can_seek,
-			      DBUS_TYPE_UINT64, &initial_offset,
-			      DBUS_TYPE_INVALID))
-    {
-      dbus_message_unref (reply);
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "open");
-      return NULL;
-    }
-  
-  dbus_message_unref (reply);
+typedef struct {
+  GSimpleAsyncResult *result;
+  GCancellable *cancellable;
+  guint32 flags;
+  GMountOperation *mount_operation;
+} AsyncMountOp;
 
-  fd = _g_dbus_connection_get_fd_sync (connection, fd_id);
-  if (fd == -1)
-    {
-      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Didn't get stream file descriptor"));
-      return NULL;
-    }
-  
-  return g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
+static void
+free_async_mount_op (AsyncMountOp *data)
+{
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  if (data->mount_operation)
+    g_object_unref (data->mount_operation);
+  g_free (data);
 }
 
 static void
@@ -1321,7 +1297,9 @@ mount_mountable_location_mounted_cb (GObject *source_object,
 {
   GSimpleAsyncResult *result = user_data;
   GError *error = NULL;
-  
+
+  g_print ("mount_mountable_location_mounted_cb\n");
+
   if (!g_file_mount_enclosing_volume_finish (G_FILE (source_object), res, &error))
     {
       g_simple_async_result_set_from_error (result, error);
@@ -1330,77 +1308,115 @@ mount_mountable_location_mounted_cb (GObject *source_object,
 
   g_simple_async_result_complete (result);
   g_object_unref (result);
-
 }
 
 static void
-mount_mountable_async_cb (DBusMessage *reply,
-			  DBusConnection *connection,
-                          GMountInfo *mount_info,
-			  GSimpleAsyncResult *result,
-			  GCancellable *cancellable,
-			  gpointer callback_data)
+mount_mountable_async_cb (GVfsDBusMount *proxy,
+                          GAsyncResult *res,
+                          gpointer user_data)
 {
-  GMountOperation *mount_operation = callback_data;
-  GMountSpec *mount_spec;
-  char *path;
-  DBusMessageIter iter;
+  AsyncMountOp *data = user_data;
+  GSimpleAsyncResult *orig_result;
+  GError *error = NULL;
+  gboolean is_uri;
+  gchar *out_path;
+  gboolean must_mount_location;
+  GVariant *iter_mountspec;
   GFile *file;
-  dbus_bool_t must_mount_location, is_uri;
-
-  path = NULL;
-
-  dbus_message_iter_init (reply, &iter);
+  GMountSpec *mount_spec;
   
-  if (!_g_dbus_message_iter_get_args (&iter, NULL,
-				      DBUS_TYPE_BOOLEAN, &is_uri,
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_BOOLEAN, &must_mount_location,
-				      0))
-    {
-      g_simple_async_result_set_error (result,
-				       G_IO_ERROR, G_IO_ERROR_FAILED,
-				       _("Invalid return value from %s"), "call");
-      _g_simple_async_result_complete_with_cancellable (result, cancellable);
-
-      return;
+  g_print ("mount_mountable_async_cb\n");
+  orig_result = data->result;
+  data->result = NULL;
+
+  is_uri = FALSE;
+  out_path = NULL;
+  must_mount_location = FALSE;
+  iter_mountspec = NULL;
+  if (! gvfs_dbus_mount_call_mount_mountable_finish (proxy,
+                                                     &is_uri,
+                                                     &out_path,
+                                                     &must_mount_location,
+                                                     &iter_mountspec,
+                                                     res,
+                                                     &error))
+    {
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
     }
-
+  
   if (is_uri)
     {
-      file = g_file_new_for_uri (path);
+      file = g_file_new_for_uri (out_path);
     }
   else
     {
-      mount_spec = g_mount_spec_from_dbus (&iter);
+      mount_spec = g_mount_spec_from_dbus (iter_mountspec);
+      g_variant_unref (iter_mountspec);
+      
       if (mount_spec == NULL)
-	{
-	  g_simple_async_result_set_error (result,
-					   G_IO_ERROR, G_IO_ERROR_FAILED,
-					   _("Invalid return value from %s"), "call");
-          _g_simple_async_result_complete_with_cancellable (result, cancellable);
-	  return;
-	}
+        {
+          g_simple_async_result_set_error (orig_result,
+                                           G_IO_ERROR, G_IO_ERROR_FAILED,
+                                           _("Invalid return value from %s"), "call");
+          goto out;
+        }
       
-      file = g_daemon_file_new (mount_spec, path);
+      file = g_daemon_file_new (mount_spec, out_path);
       g_mount_spec_unref (mount_spec);
     }
   
-  g_free (path);
-  g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref);
+  g_free (out_path);
+  g_simple_async_result_set_op_res_gpointer (orig_result, file, g_object_unref);
 
   if (must_mount_location)
     {
       g_file_mount_enclosing_volume (file,
-				     0,
-				     mount_operation,
-				     cancellable,
-				     mount_mountable_location_mounted_cb,
-				     g_object_ref (result));
-      
+                                     0,
+                                     data->mount_operation,
+                                     data->cancellable,
+                                     mount_mountable_location_mounted_cb,
+                                     orig_result);
+      return;
     }
-  else
-    _g_simple_async_result_complete_with_cancellable (result, cancellable);
+
+out:
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+mount_mountable_got_proxy_cb (GVfsDBusMount *proxy,
+                              GDBusConnection *connection,
+                              GMountInfo *mount_info,
+                              const gchar *path,
+                              GSimpleAsyncResult *result,
+                              GError *error,
+                              GCancellable *cancellable,
+                              gpointer callback_data)
+{
+  AsyncMountOp *data = callback_data;
+  GMountSource *mount_source;
+  const char *dbus_id, *obj_path;
+
+  g_print ("mount_mountable_got_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
+
+  dbus_id = g_mount_source_get_dbus_id (mount_source);
+  obj_path = g_mount_source_get_obj_path (mount_source);
+  
+  gvfs_dbus_mount_call_mount_mountable (proxy,
+                                        path,
+                                        dbus_id,
+                                        obj_path,
+                                        cancellable,
+                                        (GAsyncReadyCallback) mount_mountable_async_cb,
+                                        data);
+  
+  g_object_unref (mount_source);
 }
 
 static void
@@ -1411,28 +1427,21 @@ g_daemon_file_mount_mountable (GFile               *file,
 			       GAsyncReadyCallback  callback,
 			       gpointer             user_data)
 {
-  GMountSource *mount_source;
-  const char *dbus_id, *obj_path;
+  AsyncMountOp *data;
   
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
-  
-  dbus_id = g_mount_source_get_dbus_id (mount_source);
-  obj_path = g_mount_source_get_obj_path (mount_source);
-
-  if (mount_operation)
-    g_object_ref (mount_operation);
-  
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE,
-		      cancellable,
-		      callback, user_data,
-		      mount_mountable_async_cb,
-		      mount_operation, mount_operation ? g_object_unref : NULL,
-		      DBUS_TYPE_STRING, &dbus_id,
-		      DBUS_TYPE_OBJECT_PATH, &obj_path,
-		      0);
+  g_print ("g_daemon_file_mount_mountable\n");
+ 
+  data = g_new0 (AsyncMountOp, 1);
+  data->flags = flags;
+  data->mount_operation = g_object_ref (mount_operation);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  g_object_unref (mount_source);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               mount_mountable_got_proxy_cb,
+                               data, (GDestroyNotify) free_async_mount_op);
 }
 
 static GFile *
@@ -1451,46 +1460,82 @@ g_daemon_file_mount_mountable_finish (GFile               *file,
 }
 
 static void
-start_mountable_async_cb (DBusMessage *reply,
-			  DBusConnection *connection,
-                          GMountInfo *mount_info,
-			  GSimpleAsyncResult *result,
-			  GCancellable *cancellable,
-			  gpointer callback_data)
+start_mountable_async_cb (GVfsDBusMount *proxy,
+                          GAsyncResult *res,
+                          gpointer user_data)
 {
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  AsyncMountOp *data = user_data;
+  GSimpleAsyncResult *orig_result;
+  GError *error = NULL;
+
+  g_print ("start_mountable_async_cb\n");
+  orig_result = data->result;
+
+  if (! gvfs_dbus_mount_call_start_mountable_finish (proxy, res, &error))
+    g_simple_async_result_take_error (orig_result, error);
+
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
 
 static void
-g_daemon_file_start_mountable (GFile               *file,
-			       GDriveStartFlags     flags,
-			       GMountOperation     *mount_operation,
-			       GCancellable        *cancellable,
-			       GAsyncReadyCallback  callback,
-			       gpointer             user_data)
-{
+start_mountable_got_proxy_cb (GVfsDBusMount *proxy,
+                              GDBusConnection *connection,
+                              GMountInfo *mount_info,
+                              const gchar *path,
+                              GSimpleAsyncResult *result,
+                              GError *error,
+                              GCancellable *cancellable,
+                              gpointer callback_data)
+{
+  AsyncMountOp *data = callback_data;
   GMountSource *mount_source;
   const char *dbus_id, *obj_path;
 
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
+  g_print ("start_mountable_got_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
 
   dbus_id = g_mount_source_get_dbus_id (mount_source);
   obj_path = g_mount_source_get_obj_path (mount_source);
+  
+  gvfs_dbus_mount_call_start_mountable (proxy,
+                                        path,
+                                        dbus_id,
+                                        obj_path,
+                                        cancellable,
+                                        (GAsyncReadyCallback) start_mountable_async_cb,
+                                        data);
+  
+  g_object_unref (mount_source);
+}
 
-  if (mount_operation)
-    g_object_ref (mount_operation);
-
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_START_MOUNTABLE,
-		      cancellable,
-		      callback, user_data,
-		      start_mountable_async_cb,
-		      mount_operation, mount_operation ? g_object_unref : NULL,
-		      DBUS_TYPE_STRING, &dbus_id,
-		      DBUS_TYPE_OBJECT_PATH, &obj_path,
-		      0);
+static void
+g_daemon_file_start_mountable (GFile               *file,
+			       GDriveStartFlags     flags,
+			       GMountOperation     *mount_operation,
+			       GCancellable        *cancellable,
+			       GAsyncReadyCallback  callback,
+			       gpointer             user_data)
+{
+  AsyncMountOp *data;
+  
+  g_print ("g_daemon_file_start_mountable\n");
+ 
+  data = g_new0 (AsyncMountOp, 1);
+  data->flags = flags;
+  data->mount_operation = g_object_ref (mount_operation);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  g_object_unref (mount_source);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               start_mountable_got_proxy_cb,
+                               data, (GDestroyNotify) free_async_mount_op);
 }
 
 static gboolean
@@ -1502,14 +1547,58 @@ g_daemon_file_start_mountable_finish (GFile               *file,
 }
 
 static void
-stop_mountable_async_cb (DBusMessage *reply,
-                         DBusConnection *connection,
-                         GMountInfo *mount_info,
-                         GSimpleAsyncResult *result,
-                         GCancellable *cancellable,
-                         gpointer callback_data)
+stop_mountable_async_cb (GVfsDBusMount *proxy,
+                          GAsyncResult *res,
+                          gpointer user_data)
 {
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  AsyncMountOp *data = user_data;
+  GSimpleAsyncResult *orig_result;
+  GError *error = NULL;
+
+  g_print ("stop_mountable_async_cb\n");
+  orig_result = data->result;
+
+  if (! gvfs_dbus_mount_call_stop_mountable_finish (proxy, res, &error))
+    g_simple_async_result_take_error (orig_result, error);
+
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+stop_mountable_got_proxy_cb (GVfsDBusMount *proxy,
+                             GDBusConnection *connection,
+                             GMountInfo *mount_info,
+                             const gchar *path,
+                             GSimpleAsyncResult *result,
+                             GError *error,
+                             GCancellable *cancellable,
+                             gpointer callback_data)
+{
+  AsyncMountOp *data = callback_data;
+  GMountSource *mount_source;
+  const char *dbus_id, *obj_path;
+
+  g_print ("stop_mountable_got_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
+
+  dbus_id = g_mount_source_get_dbus_id (mount_source);
+  obj_path = g_mount_source_get_obj_path (mount_source);
+ 
+  gvfs_dbus_mount_call_stop_mountable (proxy,
+                                       path,
+                                       data->flags,
+                                       dbus_id,
+                                       obj_path,
+                                       cancellable,
+                                       (GAsyncReadyCallback) stop_mountable_async_cb,
+                                       data);
+
+  g_object_unref (mount_source);
 }
 
 static void
@@ -1520,52 +1609,86 @@ g_daemon_file_stop_mountable (GFile               *file,
                               GAsyncReadyCallback  callback,
                               gpointer             user_data)
 {
-  guint32 dbus_flags;
+  AsyncMountOp *data;
+  
+  g_print ("g_daemon_file_stop_mountable\n");
+ 
+  data = g_new0 (AsyncMountOp, 1);
+  data->flags = flags;
+  data->mount_operation = g_object_ref (mount_operation);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
+
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               stop_mountable_got_proxy_cb,
+                               data, (GDestroyNotify) free_async_mount_op);
+}
+
+static gboolean
+g_daemon_file_stop_mountable_finish (GFile               *file,
+                                     GAsyncResult        *result,
+                                     GError             **error)
+{
+  return TRUE;
+}
+
+static void
+eject_mountable_async_cb (GVfsDBusMount *proxy,
+                          GAsyncResult *res,
+                          gpointer user_data)
+{
+  AsyncMountOp *data = user_data;
+  GSimpleAsyncResult *orig_result;
+  GError *error = NULL;
+
+  g_print ("eject_mountable_async_cb\n");
+  orig_result = data->result;
+
+  if (! gvfs_dbus_mount_call_eject_mountable_finish (proxy, res, &error))
+    g_simple_async_result_take_error (orig_result, error);
+
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+eject_mountable_got_proxy_cb (GVfsDBusMount *proxy,
+                              GDBusConnection *connection,
+                              GMountInfo *mount_info,
+                              const gchar *path,
+                              GSimpleAsyncResult *result,
+                              GError *error,
+                              GCancellable *cancellable,
+                              gpointer callback_data)
+{
+  AsyncMountOp *data = callback_data;
   GMountSource *mount_source;
   const char *dbus_id, *obj_path;
 
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
+  g_print ("eject_mountable_got_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
 
   dbus_id = g_mount_source_get_dbus_id (mount_source);
   obj_path = g_mount_source_get_obj_path (mount_source);
-
-  if (mount_operation)
-    g_object_ref (mount_operation);
-
-  dbus_flags = flags;
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_STOP_MOUNTABLE,
-		      cancellable,
-		      callback, user_data,
-		      stop_mountable_async_cb,
-		      mount_operation, mount_operation ? g_object_unref : NULL,
-		      DBUS_TYPE_UINT32, &dbus_flags,
-                      DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path,
-		      0);
+ 
+  gvfs_dbus_mount_call_eject_mountable (proxy,
+                                        path,
+                                        data->flags,
+                                        dbus_id,
+                                        obj_path,
+                                        cancellable,
+                                        (GAsyncReadyCallback) eject_mountable_async_cb,
+                                        data);
 
   g_object_unref (mount_source);
 }
 
-static gboolean
-g_daemon_file_stop_mountable_finish (GFile               *file,
-                                     GAsyncResult        *result,
-                                     GError             **error)
-{
-  return TRUE;
-}
-
-
-static void
-eject_mountable_async_cb (DBusMessage *reply,
-			  DBusConnection *connection,
-                          GMountInfo *mount_info,
-			  GSimpleAsyncResult *result,
-			  GCancellable *cancellable,
-			  gpointer callback_data)
-{
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
-}
-
 static void
 g_daemon_file_eject_mountable_with_operation (GFile               *file,
                                               GMountUnmountFlags   flags,
@@ -1574,30 +1697,21 @@ g_daemon_file_eject_mountable_with_operation (GFile               *file,
                                               GAsyncReadyCallback  callback,
                                               gpointer             user_data)
 {
-  guint32 dbus_flags;
-  GMountSource *mount_source;
-  const char *dbus_id, *obj_path;
-
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
-
-  dbus_id = g_mount_source_get_dbus_id (mount_source);
-  obj_path = g_mount_source_get_obj_path (mount_source);
-
-  if (mount_operation)
-    g_object_ref (mount_operation);
-
-  dbus_flags = flags;
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE,
-		      cancellable,
-		      callback, user_data,
-		      eject_mountable_async_cb,
-		      mount_operation, mount_operation ? g_object_unref : NULL,
-		      DBUS_TYPE_UINT32, &dbus_flags,
-                      DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path,
-		      0);
+  AsyncMountOp *data;
+  
+  g_print ("g_daemon_file_eject_mountable_with_operation\n");
+ 
+  data = g_new0 (AsyncMountOp, 1);
+  data->flags = flags;
+  data->mount_operation = g_object_ref (mount_operation);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  g_object_unref (mount_source);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               eject_mountable_got_proxy_cb,
+                               data, (GDestroyNotify) free_async_mount_op);
 }
 
 static gboolean
@@ -1627,50 +1741,85 @@ g_daemon_file_eject_mountable_finish (GFile               *file,
 }
 
 static void
-unmount_mountable_async_cb (DBusMessage *reply,
-			    DBusConnection *connection,
-                            GMountInfo *mount_info,
-			    GSimpleAsyncResult *result,
-			    GCancellable *cancellable,
-			    gpointer callback_data)
+unmount_mountable_async_cb (GVfsDBusMount *proxy,
+                            GAsyncResult *res,
+                            gpointer user_data)
 {
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  AsyncMountOp *data = user_data;
+  GSimpleAsyncResult *orig_result;
+  GError *error = NULL;
+
+  g_print ("unmount_mountable_async_cb\n");
+  orig_result = data->result;
+
+  if (! gvfs_dbus_mount_call_unmount_mountable_finish (proxy, res, &error))
+    g_simple_async_result_take_error (orig_result, error);
+
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
 
 static void
-g_daemon_file_unmount_mountable_with_operation (GFile               *file,
-                                                GMountUnmountFlags   flags,
-                                                GMountOperation     *mount_operation,
-                                                GCancellable        *cancellable,
-                                                GAsyncReadyCallback  callback,
-                                                gpointer             user_data)
-{
-  guint32 dbus_flags;
+unmount_mountable_got_proxy_cb (GVfsDBusMount *proxy,
+                                GDBusConnection *connection,
+                                GMountInfo *mount_info,
+                                const gchar *path,
+                                GSimpleAsyncResult *result,
+                                GError *error,
+                                GCancellable *cancellable,
+                                gpointer callback_data)
+{
+  AsyncMountOp *data = callback_data;
   GMountSource *mount_source;
   const char *dbus_id, *obj_path;
 
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
+  g_print ("unmount_mountable_got_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
 
   dbus_id = g_mount_source_get_dbus_id (mount_source);
   obj_path = g_mount_source_get_obj_path (mount_source);
-
-  if (mount_operation)
-    g_object_ref (mount_operation);
-
-  dbus_flags = flags;
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE,
-		      cancellable,
-		      callback, user_data,
-		      unmount_mountable_async_cb,
-		      mount_operation, mount_operation ? g_object_unref : NULL,
-		      DBUS_TYPE_UINT32, &dbus_flags,
-                      DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path,
-		      0);
+ 
+  gvfs_dbus_mount_call_unmount_mountable (proxy,
+                                          path,
+                                          data->flags,
+                                          dbus_id,
+                                          obj_path,
+                                          cancellable,
+                                          (GAsyncReadyCallback) unmount_mountable_async_cb,
+                                          data);
 
   g_object_unref (mount_source);
 }
 
+static void
+g_daemon_file_unmount_mountable_with_operation (GFile               *file,
+                                                GMountUnmountFlags   flags,
+                                                GMountOperation     *mount_operation,
+                                                GCancellable        *cancellable,
+                                                GAsyncReadyCallback  callback,
+                                                gpointer             user_data)
+{
+  AsyncMountOp *data;
+  
+  g_print ("g_daemon_file_unmount_mountable_with_operation\n");
+ 
+  data = g_new0 (AsyncMountOp, 1);
+  data->flags = flags;
+  data->mount_operation = g_object_ref (mount_operation);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
+
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               unmount_mountable_got_proxy_cb,
+                               data, (GDestroyNotify) free_async_mount_op);
+}
+
 static gboolean
 g_daemon_file_unmount_mountable_with_operation_finish (GFile               *file,
                                                        GAsyncResult        *result,
@@ -1680,14 +1829,46 @@ g_daemon_file_unmount_mountable_with_operation_finish (GFile               *file
 }
 
 static void
-poll_mountable_async_cb (DBusMessage *reply,
-                         DBusConnection *connection,
-                         GMountInfo *mount_info,
-                         GSimpleAsyncResult *result,
-                         GCancellable *cancellable,
-                         gpointer callback_data)
+poll_mountable_async_cb (GVfsDBusMount *proxy,
+                         GAsyncResult *res,
+                         gpointer user_data)
+{
+  AsyncMountOp *data = user_data;
+  GSimpleAsyncResult *orig_result;
+  GError *error = NULL;
+  
+  g_print ("poll_mountable_async_cb\n");
+  orig_result = data->result;
+  
+  if (! gvfs_dbus_mount_call_poll_mountable_finish (proxy, res, &error))
+    g_simple_async_result_take_error (orig_result, error);
+
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+poll_mountable_got_proxy_cb (GVfsDBusMount *proxy,
+                             GDBusConnection *connection,
+                             GMountInfo *mount_info,
+                             const gchar *path,
+                             GSimpleAsyncResult *result,
+                             GError *error,
+                             GCancellable *cancellable,
+                             gpointer callback_data)
 {
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  AsyncMountOp *data = callback_data;
+
+  g_print ("poll_mountable_got_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+  
+  gvfs_dbus_mount_call_poll_mountable (proxy,
+                                       path,
+                                       cancellable,
+                                       (GAsyncReadyCallback) poll_mountable_async_cb,
+                                       data);
 }
 
 static void
@@ -1696,14 +1877,19 @@ g_daemon_file_poll_mountable (GFile               *file,
                               GAsyncReadyCallback  callback,
                               gpointer             user_data)
 {
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_POLL_MOUNTABLE,
-		      cancellable,
-		      callback, user_data,
-		      poll_mountable_async_cb,
-		      NULL,
-		      NULL,
-                      0);
+  AsyncMountOp *data;
+  
+  g_print ("g_daemon_file_poll_mountable\n");
+ 
+  data = g_new0 (AsyncMountOp, 1);
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
+
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               poll_mountable_got_proxy_cb,
+                               data, (GDestroyNotify) free_async_mount_op);
 }
 
 static gboolean
@@ -1748,36 +1934,93 @@ static void g_daemon_file_mount_enclosing_volume (GFile *location,
 						  gpointer user_data);
 
 static void
-mount_reply (DBusMessage *reply,
-	     GError *error,
-	     gpointer user_data)
+free_mount_data (MountData *data)
+{
+  g_object_unref (data->file);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  if (data->mount_operation)
+    g_object_unref (data->mount_operation);
+  g_free (data);
+}
+
+static void
+mount_reply (GVfsDBusMountTracker *proxy,
+             GAsyncResult *res,
+             gpointer user_data)
 {
   MountData *data = user_data;
-  GSimpleAsyncResult *res;
+  GSimpleAsyncResult *ares;
+  GError *error = NULL;
+  
+  g_print ("mount_reply\n");
 
-  if (reply == NULL)
+  if (!gvfs_dbus_mount_tracker_call_mount_location_finish (proxy, res, &error))
     {
-      res = g_simple_async_result_new_from_error (G_OBJECT (data->file),
-						  data->callback,
-						  data->user_data,
-						  error);
+      ares = g_simple_async_result_new_from_error (G_OBJECT (data->file),
+						   data->callback,
+						   data->user_data,
+						   error);
+      g_error_free (error);
     }
   else
     {
-      res = g_simple_async_result_new (G_OBJECT (data->file),
+      ares = g_simple_async_result_new (G_OBJECT (data->file),
 				       data->callback,
 				       data->user_data,
 				       g_daemon_file_mount_enclosing_volume);
     }
 
-  _g_simple_async_result_complete_with_cancellable (res, data->cancellable);
+  _g_simple_async_result_complete_with_cancellable (ares, data->cancellable);
+
+  free_mount_data (data);
+}
+
+static void
+mount_enclosing_volume_proxy_cb (GObject *source_object,
+                                 GAsyncResult *res,
+                                 gpointer user_data)
+{
+  MountData *data = user_data;
+  GVfsDBusMountTracker *proxy;
+  GError *error = NULL;
+  GSimpleAsyncResult *ares;
+  GDaemonFile *daemon_file;
+  GMountSpec *spec;
+  GMountSource *mount_source;
+
+  g_print ("mount_enclosing_volume_proxy_cb\n");
+  daemon_file = G_DAEMON_FILE (data->file);
+
+  proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error);
+  if (proxy == NULL)
+    {
+      ares = g_simple_async_result_new_from_error (G_OBJECT (data->file),
+                                                   data->callback,
+                                                   data->user_data,
+                                                   error);
+      g_error_free (error);
+      _g_simple_async_result_complete_with_cancellable (ares, data->cancellable);
+      free_mount_data (data);
+      return;
+    }
   
-  g_object_unref (data->file);
-  if (data->cancellable)
-    g_object_unref (data->cancellable);
-  if (data->mount_operation)
-    g_object_unref (data->mount_operation);
-  g_free (data);
+  spec = g_mount_spec_copy (daemon_file->mount_spec);
+  g_mount_spec_set_mount_prefix (spec, daemon_file->path);
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
+
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
+
+  gvfs_dbus_mount_tracker_call_mount_location (proxy,
+                                               g_mount_spec_to_dbus (spec),
+                                               g_mount_source_to_dbus (mount_source),
+                                               data->cancellable,
+                                               (GAsyncReadyCallback) mount_reply,
+                                               data);
+
+  g_mount_spec_unref (spec);
+  g_object_unref (mount_source);
+  g_object_unref (proxy);
 }
 
 static void
@@ -1788,30 +2031,10 @@ g_daemon_file_mount_enclosing_volume (GFile *location,
 				      GAsyncReadyCallback callback,
 				      gpointer user_data)
 {
-  GDaemonFile *daemon_file;
-  DBusMessage *message;
-  GMountSpec *spec;
-  GMountSource *mount_source;
-  DBusMessageIter iter;
   MountData *data;
   
-  daemon_file = G_DAEMON_FILE (location);
+  g_print ("g_daemon_file_mount_enclosing_volume\n");
   
-  message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-					  G_VFS_DBUS_MOUNTTRACKER_PATH,
-					  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					  G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION);
-
-  spec = g_mount_spec_copy (daemon_file->mount_spec);
-  g_mount_spec_set_mount_prefix (spec, daemon_file->path);
-  dbus_message_iter_init_append (message, &iter);
-  g_mount_spec_to_dbus (&iter, spec);
-  g_mount_spec_unref (spec);
-
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
-  g_mount_source_to_dbus (mount_source, message);
-  g_object_unref (mount_source);
-
   data = g_new0 (MountData, 1);
   data->callback = callback;
   if (data->cancellable)
@@ -1821,13 +2044,13 @@ g_daemon_file_mount_enclosing_volume (GFile *location,
   if (mount_operation)
     data->mount_operation = g_object_ref (mount_operation);
 
-  /* TODO: Ignoring cancellable here */
-  _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (),
-				 message,
-				 G_VFS_DBUS_MOUNT_TIMEOUT_MSECS,
-				 mount_reply, data);
- 
-  dbus_message_unref (message);
+  gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                             G_DBUS_PROXY_FLAGS_NONE,
+                                             G_VFS_DBUS_DAEMON_NAME,
+                                             G_VFS_DBUS_MOUNTTRACKER_PATH,
+                                             NULL,
+                                             mount_enclosing_volume_proxy_cb,
+                                             data);
 }
 
 static gboolean
@@ -1845,74 +2068,127 @@ g_daemon_file_query_filesystem_info (GFile                *file,
 				     GCancellable         *cancellable,
 				     GError              **error)
 {
-  DBusMessage *reply;
-  DBusMessageIter iter;
   GFileInfo *info;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
+  GVariant *iter_info;
 
-  if (attributes == NULL)
-    attributes = "";
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO,
-			     NULL, NULL,
-			     cancellable, error,
-			     DBUS_TYPE_STRING, &attributes,
-			     0);
-  if (reply == NULL)
+  g_print ("g_daemon_file_query_filesystem_info\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return NULL;
 
-  info = NULL;
+  iter_info = NULL;
+  res = gvfs_dbus_mount_call_query_filesystem_info_sync (proxy,
+                                                         path,
+                                                         attributes ? attributes : "",
+                                                         &iter_info,
+                                                         cancellable,
+                                                         error);
   
-  if (!dbus_message_iter_init (reply, &iter) ||
-      (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "get_filesystem_info");
-      goto out;
-    }
+  g_print ("g_daemon_file_query_filesystem_info: done, res = %d\n", res);
 
-  info = _g_dbus_get_file_info (&iter, error);
+  g_free (path);
+  g_object_unref (proxy);
+
+  if (! res)
+    return NULL;
+
+  info = _g_dbus_get_file_info (iter_info, error);
+  g_variant_unref (iter_info);
 
- out:
-  dbus_message_unref (reply);
   return info;
 }
 
+
+typedef struct {
+  GFile *file;
+  char *attributes;
+  GFileQueryInfoFlags flags;
+  int io_priority;
+  GSimpleAsyncResult *result;
+  GCancellable *cancellable;
+} AsyncCallQueryFsInfo;
+
 static void
-query_fs_info_async_cb (DBusMessage *reply,
-			DBusConnection *connection,
-                        GMountInfo *mount_info,
-			GSimpleAsyncResult *result,
-			GCancellable *cancellable,
-			gpointer callback_data)
+async_call_query_fs_info_free (AsyncCallQueryFsInfo *data)
+{
+  if (data->file)
+    g_object_unref (data->file);
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  g_free (data->attributes);
+  g_free (data);
+}
+
+static void
+query_fs_info_async_cb (GVfsDBusMount *proxy,
+                        GAsyncResult *res,
+                        gpointer user_data)
 {
-  DBusMessageIter iter;
+  AsyncCallQueryFsInfo *data = user_data;
   GFileInfo *info;
-  GError *error;
+  GError *error = NULL;
+  GSimpleAsyncResult *orig_result;
+  GVariant *iter_info;
 
-  info = NULL;
+  g_print ("query_info_async_cb\n");
+  orig_result = data->result;
   
-  if (!dbus_message_iter_init (reply, &iter) ||
-      (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_STRUCT))
+  if (! gvfs_dbus_mount_call_query_filesystem_info_finish (proxy, &iter_info, res, &error))
     {
-      g_simple_async_result_set_error (result,
-				       G_IO_ERROR, G_IO_ERROR_FAILED,
-				       _("Invalid return value from %s"), "query_info");
-      _g_simple_async_result_complete_with_cancellable (result, cancellable);
-      return;
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
     }
 
-  error = NULL;
-  info = _g_dbus_get_file_info (&iter, &error);
+  info = _g_dbus_get_file_info (iter_info, &error);
+  g_variant_unref (iter_info);
+
   if (info == NULL)
     {
-      g_simple_async_result_set_from_error (result, error);
-      g_error_free (error);
-      _g_simple_async_result_complete_with_cancellable (result, cancellable);
-      return;
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
     }
 
-  g_simple_async_result_set_op_res_gpointer (result, info, g_object_unref);
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  g_simple_async_result_set_op_res_gpointer (orig_result, info, g_object_unref);
+  
+out:
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+query_info_fs_async_get_proxy_cb (GVfsDBusMount *proxy,
+                                  GDBusConnection *connection,
+                                  GMountInfo *mount_info,
+                                  const gchar *path,
+                                  GSimpleAsyncResult *result,
+                                  GError *error,
+                                  GCancellable *cancellable,
+                                  gpointer callback_data)
+{
+  AsyncCallQueryFsInfo *data = callback_data;
+  char *uri;
+
+  g_print ("query_info_fs_async_get_proxy_cb, proxy = %p\n", proxy);
+  
+  uri = g_file_get_uri (data->file);
+  
+  data->result = g_object_ref (result);
+  
+  gvfs_dbus_mount_call_query_filesystem_info (proxy,
+                                              path,
+                                              data->attributes ? data->attributes : "",
+                                              cancellable,
+                                              (GAsyncReadyCallback) query_fs_info_async_cb,
+                                              data);
+  
+  g_free (uri);
 }
 
 static void
@@ -1923,13 +2199,22 @@ g_daemon_file_query_filesystem_info_async (GFile                      *file,
 					   GAsyncReadyCallback         callback,
 					   gpointer                    user_data)
 {
-  do_async_path_call (file,
-		      G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO,
-		      cancellable,
-		      callback, user_data,
-		      query_fs_info_async_cb, NULL, NULL,
-		      DBUS_TYPE_STRING, &attributes,
-		      0);
+  AsyncCallQueryFsInfo *data;
+
+  g_print ("g_daemon_file_query_filesystem_info_async\n");
+  
+  data = g_new0 (AsyncCallQueryFsInfo, 1);
+  data->file = g_object_ref (file);
+  data->attributes = g_strdup (attributes);
+  data->io_priority = io_priority;
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
+
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               query_info_fs_async_get_proxy_cb,
+                               data, (GDestroyNotify) async_call_query_fs_info_free);
 }
 
 static GFileInfo *
@@ -1958,6 +2243,7 @@ g_daemon_file_find_enclosing_mount (GFile *file,
   
   mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
 						  daemon_file->path,
+						  cancellable,
 						  error);
   if (mount_info == NULL)
     return NULL;
@@ -1995,8 +2281,9 @@ g_daemon_file_get_child_for_display_name (GFile        *file,
   GFile *child;
 
   mount_info = _g_daemon_vfs_get_mount_info_sync (daemon_file->mount_spec,
-						daemon_file->path,
-						NULL);
+						 daemon_file->path,
+                                                 NULL,  /* TODO: cancellable */
+						 NULL);
 
 
   if (mount_info && mount_info->prefered_filename_encoding)
@@ -2031,43 +2318,39 @@ g_daemon_file_set_display_name (GFile *file,
 {
   GDaemonFile *daemon_file;
   GMountInfo  *mount_info;
-  DBusMessage *reply;
-  DBusMessageIter iter;
   char *new_path;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
 
   daemon_file = G_DAEMON_FILE (file);
-
   mount_info = NULL;
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME,
-			     &mount_info, NULL,
-			     cancellable, error,
-			     DBUS_TYPE_STRING, &display_name,
-			     0);
-  if (reply == NULL)
-    {
-      if (mount_info)
-        g_mount_info_unref (mount_info);
-      return NULL;
-    }
+  g_print ("g_daemon_file_set_display_name\n");
 
-  if (!dbus_message_iter_init (reply, &iter) ||
-      !_g_dbus_message_iter_get_args (&iter, NULL,
-				      G_DBUS_TYPE_CSTRING, &new_path,
-				      0))
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "query_filesystem_info");
-      goto out;
-    }
+  proxy = create_proxy_for_file (file, &mount_info, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return NULL;
+
+  res = gvfs_dbus_mount_call_set_display_name_sync (proxy,
+                                                    path,
+                                                    display_name,
+                                                    &new_path,
+                                                    cancellable,
+                                                    error);
+  g_print ("g_daemon_file_set_display_name: done, res = %d\n", res);
 
+  g_free (path);
+  g_object_unref (proxy);
+
+  if (! res)
+    goto out;
+  
   g_mount_info_apply_prefix (mount_info, &new_path);
   file = new_file_for_new_path (daemon_file, new_path);
   g_free (new_path);
 
  out:
   g_mount_info_unref (mount_info);
-  dbus_message_unref (reply);
   return file;
 }
 
@@ -2076,18 +2359,26 @@ g_daemon_file_delete (GFile *file,
 		      GCancellable *cancellable,
 		      GError **error)
 {
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
 
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_DELETE,
-			     NULL, NULL,
-			     cancellable, error,
-			     0);
-  if (reply == NULL)
+  g_print ("g_daemon_file_delete\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return FALSE;
 
-  dbus_message_unref (reply);
-  return TRUE;
+  res = gvfs_dbus_mount_call_delete_sync (proxy,
+                                          path,
+                                          cancellable,
+                                          error);
+  g_print ("g_daemon_file_delete: done, res = %d\n", res);
+
+  g_free (path);
+  g_object_unref (proxy);
+  
+  return res;
 }
 
 static gboolean
@@ -2095,18 +2386,26 @@ g_daemon_file_trash (GFile *file,
 		     GCancellable *cancellable,
 		     GError **error)
 {
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
 
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_TRASH,
-			     NULL, NULL,
-			     cancellable, error,
-			     0);
-  if (reply == NULL)
+  g_print ("g_daemon_file_trash\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return FALSE;
 
-  dbus_message_unref (reply);
-  return TRUE;
+  res = gvfs_dbus_mount_call_trash_sync (proxy,
+                                         path,
+                                         cancellable,
+                                         error);
+  g_print ("g_daemon_file_trash: done, res = %d\n", res);
+
+  g_free (path);
+  g_object_unref (proxy);
+  
+  return res;
 }
 
 static gboolean
@@ -2114,18 +2413,26 @@ g_daemon_file_make_directory (GFile *file,
 			      GCancellable *cancellable,
 			      GError **error)
 {
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
 
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY,
-			     NULL, NULL,
-			     cancellable, error,
-			     0);
-  if (reply == NULL)
+  g_print ("g_daemon_file_make_directory\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return FALSE;
 
-  dbus_message_unref (reply);
-  return TRUE;
+  res = gvfs_dbus_mount_call_make_directory_sync (proxy,
+                                                  path,
+                                                  cancellable,
+                                                  error);
+  g_print ("g_daemon_file_make_directory: done, res = %d\n", res);
+
+  g_free (path);
+  g_object_unref (proxy);
+  
+  return res;
 }
 
 static gboolean
@@ -2134,19 +2441,27 @@ g_daemon_file_make_symbolic_link (GFile *file,
 				  GCancellable *cancellable,
 				  GError **error)
 {
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
 
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK,
-			     NULL, NULL,
-			     cancellable, error,
-			     G_DBUS_TYPE_CSTRING, &symlink_value,
-			     0);
-  if (reply == NULL)
+  g_print ("g_daemon_file_make_symbolic_link\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
     return FALSE;
 
-  dbus_message_unref (reply);
-  return TRUE;
+  res = gvfs_dbus_mount_call_make_symbolic_link_sync (proxy,
+                                                      path,
+                                                      symlink_value,
+                                                      cancellable,
+                                                      error);
+  g_print ("g_daemon_file_make_symbolic_link: done, res = %d\n", res);
+
+  g_free (path);
+  g_object_unref (proxy);
+  
+  return res;
 }
 
 static GFileAttributeInfoList *
@@ -2154,22 +2469,34 @@ g_daemon_file_query_settable_attributes (GFile                      *file,
 					 GCancellable               *cancellable,
 					 GError                    **error)
 {
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
+  GVariant *iter_list;
   GFileAttributeInfoList *list;
-  DBusMessageIter iter;
-
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES,
-			     NULL, NULL,
-			     cancellable, error,
-			     0);
-  if (reply == NULL)
+
+  g_print ("g_daemon_file_query_settable_attributes\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return FALSE;
+
+  iter_list = NULL;
+  res = gvfs_dbus_mount_call_query_settable_attributes_sync (proxy,
+                                                             path,
+                                                             &iter_list,
+                                                             cancellable,
+                                                             error);
+  g_print ("g_daemon_file_query_settable_attributes: done, res = %d\n", res);
+
+  g_free (path);
+  g_object_unref (proxy);
+
+  if (!res)
     return NULL;
 
-  dbus_message_iter_init (reply, &iter);
-  list = _g_dbus_get_attribute_info_list (&iter, error);
-  
-  dbus_message_unref (reply);
+  list = _g_dbus_get_attribute_info_list (iter_list, error);
+  g_variant_unref (iter_list);
   
   return list;
 }
@@ -2179,20 +2506,33 @@ g_daemon_file_query_writable_namespaces (GFile                      *file,
 					 GCancellable               *cancellable,
 					 GError                    **error)
 {
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
+  GVariant *iter_list;
   GFileAttributeInfoList *list;
-  DBusMessageIter iter;
-
-  reply = do_sync_path_call (file,
-			     G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES,
-			     NULL, NULL,
-			     cancellable, error,
-			     0);
-  if (reply)
+
+  g_print ("g_daemon_file_query_writable_namespaces\n");
+
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return FALSE;
+
+  iter_list = NULL;
+  res = gvfs_dbus_mount_call_query_writable_namespaces_sync (proxy,
+                                                             path,
+                                                             &iter_list,
+                                                             cancellable,
+                                                             error);
+  g_print ("g_daemon_file_query_writable_namespaces: done, res = %d\n", res);
+
+  g_free (path);
+  g_object_unref (proxy);
+
+  if (res)
     {
-      dbus_message_iter_init (reply, &iter);
-      list = _g_dbus_get_attribute_info_list (&iter, error);
-      dbus_message_unref (reply);
+      list = _g_dbus_get_attribute_info_list (iter_list, error);
+      g_variant_unref (iter_list);
     }
   else
     {
@@ -2200,11 +2540,11 @@ g_daemon_file_query_writable_namespaces (GFile                      *file,
     }
 
   g_file_attribute_info_list_add (list,
-				  "metadata",
-				  G_FILE_ATTRIBUTE_TYPE_STRING, /* Also STRINGV, but no way express this ... */
-				  G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
-				  G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
-
+                                  "metadata",
+                                  G_FILE_ATTRIBUTE_TYPE_STRING, /* Also STRINGV, but no way express this ... */
+                                  G_FILE_ATTRIBUTE_INFO_COPY_WITH_FILE |
+                                  G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
+  
   return list;
 }
 
@@ -2282,38 +2622,34 @@ g_daemon_file_set_attribute (GFile *file,
 			     GCancellable *cancellable,
 			     GError **error)
 {
-  DBusMessage *message, *reply;
-  DBusMessageIter iter;
-  dbus_uint32_t flags_dbus;
+  GVfsDBusMount *proxy;
+  char *path;
+  gboolean res;
   GError *my_error;
 
   if (g_str_has_prefix (attribute, "metadata::"))
     return set_metadata_attribute (file, attribute, type, value_p, cancellable, error);
 
  retry:
-  
-  message = create_empty_message (file, G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE, NULL, error);
-  if (!message)
-    return FALSE;
-
-  dbus_message_iter_init_append (message, &iter);
+  g_print ("g_daemon_file_set_attribute\n");
 
-  flags_dbus = flags;
-  dbus_message_iter_append_basic (&iter,
-				  DBUS_TYPE_UINT32,
-				  &flags_dbus);
-
-  _g_dbus_append_file_attribute (&iter, attribute, 0, type, value_p);
+  proxy = create_proxy_for_file (file, NULL, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return FALSE;
 
   my_error = NULL;
-  reply = _g_vfs_daemon_call_sync (message,
-				   NULL,
-				   NULL, NULL, NULL,
-				   cancellable, &my_error);
+  res = gvfs_dbus_mount_call_set_attribute_sync (proxy,
+                                                 path,
+                                                 flags,
+                                                 _g_dbus_append_file_attribute (attribute, 0, type, value_p),
+                                                 cancellable,
+                                                 &my_error);
+  g_print ("g_daemon_file_set_attribute: done, res = %d\n", res);
 
-  dbus_message_unref (message);
+  g_free (path);
+  g_object_unref (proxy);
 
-  if (reply == NULL)
+  if (! res)
     {
       if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
 	{
@@ -2324,38 +2660,28 @@ g_daemon_file_set_attribute (GFile *file,
       return FALSE;
     }
 
-  dbus_message_unref (reply);
   return TRUE;
 }
 
-struct ProgressCallbackData {
+typedef struct {
   GFileProgressCallback progress_callback;
   gpointer progress_callback_data;
-};
+} ProgressCallbackData;
 
-static DBusHandlerResult
-progress_callback_message (DBusConnection  *connection,
-			   DBusMessage     *message,
-			   void            *user_data)
+static gboolean
+handle_progress (GVfsDBusProgress *object,
+                 GDBusMethodInvocation *invocation,
+                 guint64 arg_current,
+                 guint64 arg_total,
+                 ProgressCallbackData *data)
 {
-  struct ProgressCallbackData *data = user_data;
-  dbus_uint64_t current_dbus, total_dbus;
+  g_print ("handle_progress\n");
   
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_PROGRESS_INTERFACE,
-				   G_VFS_DBUS_PROGRESS_OP_PROGRESS))
-    {
-      if (dbus_message_get_args (message, NULL, 
-				 DBUS_TYPE_UINT64, &current_dbus,
-				 DBUS_TYPE_UINT64, &total_dbus,
-				 0))
-	data->progress_callback (current_dbus, total_dbus, data->progress_callback_data);
-    }
-  else
-    g_warning ("Unknown progress callback message type\n");
+  data->progress_callback (arg_current, arg_total, data->progress_callback_data);
   
-  /* TODO: demarshal args and call reall callback */
-  return DBUS_HANDLER_RESULT_HANDLED;
+  gvfs_dbus_progress_complete_progress (object, invocation);
+  
+  return TRUE;
 }
 
 static gboolean
@@ -2368,17 +2694,23 @@ file_transfer (GFile                  *source,
                gpointer                progress_callback_data,
                GError                **error)
 {
-  DBusMessage *reply;
-  char *obj_path, *dbus_obj_path;
-  dbus_uint32_t flags_dbus;
-  dbus_bool_t dbus_remove_source;
-  struct ProgressCallbackData data;
+  char *obj_path;
+  ProgressCallbackData data;
   char *local_path = NULL;
   gboolean source_is_daemon;
   gboolean dest_is_daemon;
   gboolean native_transfer;
   gboolean send_progress;
+  GVfsDBusMount *proxy;
+  gchar *path1, *path2;
+  GDBusConnection *connection;
+  gboolean res;
+  GVfsDBusProgress *progress_skeleton;
+  GFile *file1, *file2;
+  GError *my_error;
 
+  res = FALSE;
+  progress_skeleton = NULL;
   native_transfer  = FALSE;
   source_is_daemon = G_IS_DAEMON_FILE (source);
   dest_is_daemon   = G_IS_DAEMON_FILE (destination);
@@ -2408,76 +2740,126 @@ file_transfer (GFile                  *source,
     }
 
   if (progress_callback)
+    obj_path = g_strdup_printf ("/org/gtk/vfs/callback/%p", &obj_path);
+  else
+    obj_path = g_strdup ("/org/gtk/vfs/void");
+
+  data.progress_callback = progress_callback;
+  data.progress_callback_data = progress_callback_data;
+
+  /* need to create proxy with daemon files only */ 
+  if (native_transfer)
     {
-      obj_path = g_strdup_printf ("/org/gtk/vfs/callback/%p", &obj_path);
-      dbus_obj_path = obj_path;
+      file1 = source;
+      file2 = destination;
     }
   else
     {
-      obj_path = NULL;
-      /* Can't pass NULL obj path as arg */
-      dbus_obj_path = "/org/gtk/vfs/void";
+      if (dest_is_daemon)
+        {
+          file1 = destination;
+          file2 = NULL;
+        }
+      else
+        {
+          file1 = source;
+          file2 = NULL;
+        }
     }
+  
+retry:
+  my_error = NULL;
 
-  data.progress_callback = progress_callback;
-  data.progress_callback_data = progress_callback_data;
+  proxy = create_proxy_for_file2 (file1, file2,
+                                  NULL, NULL,
+                                  &path1, &path2,
+                                  &connection,
+                                  cancellable,
+                                  &my_error);
+  
+  if (proxy == NULL)
+    goto out;
 
-  flags_dbus = flags;
-  dbus_remove_source = remove_source;
+  /* Register progress interface skeleton */
+  progress_skeleton = gvfs_dbus_progress_skeleton_new ();
+  g_dbus_interface_skeleton_set_flags (G_DBUS_INTERFACE_SKELETON (progress_skeleton), G_DBUS_INTERFACE_SKELETON_FLAGS_HANDLE_METHOD_INVOCATIONS_IN_THREAD);
+  g_signal_connect (progress_skeleton, "handle-progress", G_CALLBACK (handle_progress), &data);
+
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (progress_skeleton),
+                                         connection,
+                                         obj_path,
+                                         &my_error))
+    goto out;
 
   if (native_transfer == TRUE)
     {
-      const char *method_string;
-
       if (remove_source == FALSE)
-        method_string = G_VFS_DBUS_MOUNT_OP_COPY;
+        {
+          res = gvfs_dbus_mount_call_copy_sync (proxy,
+                                                path1, path2,
+                                                flags,
+                                                obj_path,
+                                                cancellable,
+                                                &my_error);
+        }
       else
-        method_string = G_VFS_DBUS_MOUNT_OP_MOVE;
-
-      reply = do_sync_2_path_call (source, destination,
-                                   method_string,
-                                   obj_path, progress_callback_message, &data,
-                                   NULL, cancellable, error,
-                                   DBUS_TYPE_UINT32, &flags_dbus,
-                                   DBUS_TYPE_OBJECT_PATH, &dbus_obj_path,
-                                   0);
+        {
+          res = gvfs_dbus_mount_call_move_sync (proxy,
+                                                path1, path2,
+                                                flags,
+                                                obj_path,
+                                                cancellable,
+                                                &my_error);
+        }
     }
   else if (dest_is_daemon == TRUE)
     {
-      reply = do_sync_2_path_call (destination, NULL,
-                                   G_VFS_DBUS_MOUNT_OP_PUSH,
-                                   obj_path, progress_callback_message, &data,
-                                   NULL, cancellable, error,
-                                   G_DBUS_TYPE_CSTRING, &local_path,
-                                   DBUS_TYPE_BOOLEAN, &send_progress,
-                                   DBUS_TYPE_UINT32, &flags_dbus,
-                                   DBUS_TYPE_OBJECT_PATH, &dbus_obj_path,
-                                   DBUS_TYPE_BOOLEAN, &dbus_remove_source,
-                                   0);
+      res = gvfs_dbus_mount_call_push_sync (proxy,
+                                            path1,
+                                            local_path,
+                                            send_progress,
+                                            flags,
+                                            obj_path,
+                                            remove_source,
+                                            cancellable,
+                                            &my_error);
     }
   else
     {
-      reply = do_sync_2_path_call (source, NULL,
-                                   G_VFS_DBUS_MOUNT_OP_PULL,
-                                   obj_path, progress_callback_message, &data,
-                                   NULL, cancellable, error,
-                                   G_DBUS_TYPE_CSTRING, &local_path,
-                                   DBUS_TYPE_BOOLEAN, &send_progress,
-                                   DBUS_TYPE_UINT32, &flags_dbus,
-                                   DBUS_TYPE_OBJECT_PATH, &dbus_obj_path,
-                                   DBUS_TYPE_BOOLEAN, &dbus_remove_source,
-                                   0);
+      res = gvfs_dbus_mount_call_pull_sync (proxy,
+                                            path1,
+                                            local_path,
+                                            send_progress,
+                                            flags,
+                                            obj_path,
+                                            remove_source,
+                                            cancellable,
+                                            &my_error);
+    }
+
+ out:
+  if (progress_skeleton)
+    {
+      g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (progress_skeleton));
+      g_object_unref (progress_skeleton);
+    }
+  if (proxy)
+    g_object_unref (proxy);
 
+  if (! res)
+    {
+      if (g_error_matches (my_error, G_VFS_ERROR, G_VFS_ERROR_RETRY))
+        {
+          g_error_free (my_error);
+          goto retry;
+        }
+      g_propagate_error (error, my_error);
     }
 
   g_free (local_path);
   g_free (obj_path);
 
-  if (reply == NULL)
-    return FALSE;
-
-  dbus_message_unref (reply);
-  return TRUE;
+  return res;
 }
 
 static gboolean
@@ -2533,45 +2915,44 @@ g_daemon_file_monitor_dir (GFile* file,
 			   GError **error)
 {
   GFileMonitor *monitor;
-  char *obj_path;
-  dbus_uint32_t flags_dbus;
   GMountInfo *mount_info;
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  char *obj_path;
+  gboolean res;
 
-  flags_dbus = flags;
+  g_print ("g_daemon_file_monitor_dir\n");
 
+  monitor = NULL;
   mount_info = NULL;
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR,
-			     &mount_info, NULL,
-			     cancellable, error,
-			     DBUS_TYPE_UINT32, &flags_dbus,
-			     0);
-  
-  if (reply == NULL)
-    {
-      if (mount_info)
-	g_mount_info_unref (mount_info);
-      return NULL;
-    }
+  obj_path = NULL;
+
+  proxy = create_proxy_for_file (file, &mount_info, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return FALSE;
+
   
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_OBJECT_PATH, &obj_path,
-			      DBUS_TYPE_INVALID))
-    {
-      g_mount_info_unref (mount_info);
-      dbus_message_unref (reply);
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "monitor_dir");
-      return NULL;
-    }
+  res = gvfs_dbus_mount_call_create_directory_monitor_sync (proxy,
+                                                            path,
+                                                            flags,
+                                                            &obj_path,
+                                                            cancellable,
+                                                            error);
+  g_print ("g_daemon_file_monitor_dir: done, res = %d\n", res);
+  
+  g_free (path);
+  g_object_unref (proxy);
+
+  if (! res)
+    goto out;
   
   monitor = g_daemon_file_monitor_new (mount_info->dbus_id,
 				       obj_path);
   
+ out:
   g_mount_info_unref (mount_info);
-  dbus_message_unref (reply);
-  
+  g_free (obj_path);
+
   return monitor;
 }
 
@@ -2582,114 +2963,151 @@ g_daemon_file_monitor_file (GFile* file,
 			    GError **error)
 {
   GFileMonitor *monitor;
-  char *obj_path;
-  dbus_uint32_t flags_dbus;
   GMountInfo *mount_info;
-  DBusMessage *reply;
+  GVfsDBusMount *proxy;
+  char *path;
+  char *obj_path;
+  gboolean res;
 
-  flags_dbus = flags;
+  g_print ("g_daemon_file_monitor_file\n");
 
+  monitor = NULL;
   mount_info = NULL;
-  reply = do_sync_path_call (file, 
-			     G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR,
-			     &mount_info, NULL,
-			     cancellable, error,
-			     DBUS_TYPE_UINT32, &flags_dbus,
-			     0);
-  
-  if (reply == NULL)
-    {
-      if (mount_info)
-	g_mount_info_unref (mount_info);
-      return NULL;
-    }
+  obj_path = NULL;
+
+  proxy = create_proxy_for_file (file, &mount_info, &path, NULL, cancellable, error);
+  if (proxy == NULL)
+    return FALSE;
+
   
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_OBJECT_PATH, &obj_path,
-			      DBUS_TYPE_INVALID))
-    {
-      g_mount_info_unref (mount_info);
-      dbus_message_unref (reply);
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid return value from %s"), "monitor_file");
-      return NULL;
-    }
+  res = gvfs_dbus_mount_call_create_file_monitor_sync (proxy,
+                                                       path,
+                                                       flags,
+                                                       &obj_path,
+                                                       cancellable,
+                                                       error);
+  g_print ("g_daemon_file_monitor_file: done, res = %d\n", res);
+  
+  g_free (path);
+  g_object_unref (proxy);
+
+  if (! res)
+    goto out;
   
   monitor = g_daemon_file_monitor_new (mount_info->dbus_id,
-				       obj_path);
+                                       obj_path);
   
+ out:
   g_mount_info_unref (mount_info);
-  dbus_message_unref (reply);
-  
+  g_free (obj_path);
+
   return monitor;
 }
 
-typedef struct
-{
-  GSimpleAsyncResult *result;
-  GCancellable       *cancellable;
-  dbus_bool_t         can_seek;
-  guint64             initial_offset;
-}
-StreamOpenParams;
 
 static void
-stream_open_cb (gint fd, StreamOpenParams *params)
+file_open_write_async_cb (GVfsDBusMount *proxy,
+                          GAsyncResult *res,
+                          gpointer user_data)
 {
+  AsyncCallFileReadWrite *data = user_data;
+  GError *error = NULL;
+  GSimpleAsyncResult *orig_result;
+  gboolean can_seek;
+  GUnixFDList *fd_list;
+  int fd;
+  guint fd_id;
+  guint64 initial_offset;
   GFileOutputStream *output_stream;
 
-  if (fd == -1)
+  g_print ("file_open_write_async_cb\n");
+  orig_result = data->result;
+  
+  if (! gvfs_dbus_mount_call_open_for_write_finish (proxy, &fd_id, &can_seek, &initial_offset, &fd_list, res, &error))
     {
-      g_simple_async_result_set_error (params->result, G_IO_ERROR, G_IO_ERROR_FAILED,
-                                       "%s", _("Didn't get stream file descriptor"));
+      g_simple_async_result_take_error (orig_result, error);
       goto out;
     }
 
-  output_stream = g_daemon_file_output_stream_new (fd, params->can_seek, params->initial_offset);
-  g_simple_async_result_set_op_res_gpointer (params->result, output_stream, g_object_unref);
+  if (fd_list == NULL || g_unix_fd_list_get_length (fd_list) != 1 ||
+      (fd = g_unix_fd_list_get (fd_list, fd_id, NULL)) == -1)
+    {
+      g_simple_async_result_set_error (orig_result,
+                                       G_IO_ERROR, G_IO_ERROR_FAILED,
+                                       _("Couldn't get stream file descriptor"));
+    }
+  else
+    {
+      output_stream = g_daemon_file_output_stream_new (fd, can_seek, initial_offset);
+      g_simple_async_result_set_op_res_gpointer (orig_result, output_stream, g_object_unref);
+      g_object_unref (fd_list);
+    }
 
 out:
-  _g_simple_async_result_complete_with_cancellable (params->result, params->cancellable);
-  if (params->cancellable)
-    g_object_unref (params->cancellable);
-  g_object_unref (params->result);
-  g_slice_free (StreamOpenParams, params);
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
 }
 
 static void
-append_to_async_cb (DBusMessage *reply,
-                    DBusConnection *connection,
-                    GMountInfo *mount_info,
-                    GSimpleAsyncResult *result,
-                    GCancellable *cancellable,
-                    gpointer callback_data)
+file_open_write_async_get_proxy_cb (GVfsDBusMount *proxy,
+                                    GDBusConnection *connection,
+                                    GMountInfo *mount_info,
+                                    const gchar *path,
+                                    GSimpleAsyncResult *result,
+                                    GError *error,
+                                    GCancellable *cancellable,
+                                    gpointer callback_data)
 {
-  guint32 fd_id;
-  StreamOpenParams *open_params;
+  AsyncCallFileReadWrite *data = callback_data;
+  guint32 pid;
 
-  open_params = g_slice_new0 (StreamOpenParams);
+  g_print ("file_open_write_async_get_proxy_cb, proxy = %p\n", proxy);
 
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &open_params->can_seek,
-			      DBUS_TYPE_UINT64, &open_params->initial_offset,
-			      DBUS_TYPE_INVALID))
-    {
-      g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
-                                       _("Invalid return value from %s"), "open");
-      goto failure;
-    }
+  pid = get_pid_for_file (data->file);
+  
+  data->result = g_object_ref (result);
+  
+  gvfs_dbus_mount_call_open_for_write (proxy,
+                                       path,
+                                       data->mode,
+                                       data->etag,
+                                       data->make_backup,
+                                       data->flags,
+                                       pid,
+                                       NULL,
+                                       cancellable,
+                                       (GAsyncReadyCallback) file_open_write_async_cb,
+                                       data);
+}
 
-  open_params->result = g_object_ref (result);
+static void
+file_open_write_async (GFile                      *file,
+                       guint16                     mode,
+                       const char                 *etag,
+                       gboolean                    make_backup,
+                       GFileCreateFlags            flags,
+                       int                         io_priority,
+                       GCancellable               *cancellable,
+                       GAsyncReadyCallback         callback,
+                       gpointer                    user_data)
+{
+  AsyncCallFileReadWrite *data;
+
+  data = g_new0 (AsyncCallFileReadWrite, 1);
+  data->file = g_object_ref (file);
+  data->mode = mode;
+  data->etag = g_strdup (etag ? etag : "");
+  data->make_backup = make_backup;
+  data->io_priority = io_priority;
   if (cancellable)
-    open_params->cancellable = g_object_ref (cancellable);
-  _g_dbus_connection_get_fd_async (connection, fd_id,
-                                   (GetFdAsyncCallback) stream_open_cb, open_params);
-  return;
+    data->cancellable = g_object_ref (cancellable);
 
-failure:
-  g_slice_free (StreamOpenParams, open_params);
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               file_open_write_async_get_proxy_cb,
+                               data, (GDestroyNotify) async_call_file_read_write_free);
 }
 
 static void
@@ -2700,30 +3118,12 @@ g_daemon_file_append_to_async (GFile                      *file,
                                GAsyncReadyCallback         callback,
                                gpointer                    user_data)
 {
-  guint16 mode;
-  dbus_bool_t make_backup;
-  guint32 dbus_flags;
-  char *etag;
-  guint32 pid;
-
-  pid = get_pid_for_file (file);
-
-  mode = 1;
-  etag = "";
-  make_backup = FALSE;
-  dbus_flags = flags;
+  g_print ("g_daemon_file_append_to_async\n");
   
-  do_async_path_call (file, 
-                      G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
-                      cancellable,
-                      callback, user_data,
-                      append_to_async_cb, NULL, NULL,
-                      DBUS_TYPE_UINT16, &mode,
-                      DBUS_TYPE_STRING, &etag,
-                      DBUS_TYPE_BOOLEAN, &make_backup,
-                      DBUS_TYPE_UINT32, &dbus_flags,
-                      DBUS_TYPE_UINT32, &pid,
-                      0);
+  file_open_write_async (file,
+                         1, "", FALSE, flags, io_priority,
+                         cancellable,
+                         callback, user_data);
 }
 
 static GFileOutputStream *
@@ -2742,40 +3142,6 @@ g_daemon_file_append_to_finish (GFile                      *file,
 }
 
 static void
-create_async_cb (DBusMessage *reply,
-                 DBusConnection *connection,
-                 GMountInfo *mount_info,
-                 GSimpleAsyncResult *result,
-                 GCancellable *cancellable,
-                 gpointer callback_data)
-{
-  guint32 fd_id;
-  StreamOpenParams *open_params;
-
-  open_params = g_slice_new0 (StreamOpenParams);
-
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &open_params->can_seek,
-			      DBUS_TYPE_UINT64, &open_params->initial_offset,
-			      DBUS_TYPE_INVALID))
-    {
-      g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
-                                       _("Invalid return value from %s"), "open");
-      goto failure;
-    }
-
-  open_params->result = g_object_ref (result);
-  _g_dbus_connection_get_fd_async (connection, fd_id,
-                                   (GetFdAsyncCallback) stream_open_cb, open_params);
-  return;
-
-failure:
-  g_slice_free (StreamOpenParams, open_params);
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
-}
-
-static void
 g_daemon_file_create_async (GFile                      *file,
                             GFileCreateFlags            flags,
                             int                         io_priority,
@@ -2783,30 +3149,12 @@ g_daemon_file_create_async (GFile                      *file,
                             GAsyncReadyCallback         callback,
                             gpointer                    user_data)
 {
-  guint16 mode;
-  dbus_bool_t make_backup;
-  char *etag;
-  guint32 dbus_flags;
-  guint32 pid;
-
-  pid = get_pid_for_file (file);
-
-  mode = 0;
-  etag = "";
-  make_backup = FALSE;
-  dbus_flags = flags;
+  g_print ("g_daemon_file_create_async\n");
   
-  do_async_path_call (file, 
-                      G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
-                      cancellable,
-                      callback, user_data,
-                      create_async_cb, NULL, NULL,
-                      DBUS_TYPE_UINT16, &mode,
-                      DBUS_TYPE_STRING, &etag,
-                      DBUS_TYPE_BOOLEAN, &make_backup,
-                      DBUS_TYPE_UINT32, &dbus_flags,
-                      DBUS_TYPE_UINT32, &pid,
-                      0);
+  file_open_write_async (file,
+                         0, "", FALSE, flags, io_priority,
+                         cancellable,
+                         callback, user_data);
 }
 
 static GFileOutputStream *
@@ -2824,29 +3172,95 @@ g_daemon_file_create_finish (GFile                      *file,
   return NULL;
 }
 
+
+typedef struct {
+  GFile *file;
+  char *attributes;
+  GFileQueryInfoFlags flags;
+  int io_priority;
+  GSimpleAsyncResult *result;
+  GCancellable *cancellable;
+  GDaemonFileEnumerator *enumerator;
+} AsyncCallEnumerate;
+
 static void
-enumerate_children_async_cb (DBusMessage *reply,
-                             DBusConnection *connection,
-                             GMountInfo *mount_info,
-                             GSimpleAsyncResult *result,
-                             GCancellable *cancellable,
-                             gpointer callback_data)
+async_call_enumerate_free (AsyncCallEnumerate *data)
 {
-  GDaemonFileEnumerator *enumerator = callback_data;
+  g_print ("async_call_enumerate_free\n");
+  
+  if (data->file)
+    g_object_unref (data->file);
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  if (data->enumerator)
+    g_object_unref (data->enumerator);
+  g_free (data->attributes);
+  g_free (data);
+}
 
-  if (reply == NULL || connection == NULL)
-  {
-    g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
-                                     _("Invalid return value from %s"), "enumerate_children");
-    goto out;
-  }
+static void
+enumerate_children_async_cb (GVfsDBusMount *proxy,
+                             GAsyncResult *res,
+                             gpointer user_data)
+{
+  AsyncCallEnumerate *data = user_data;
+  GError *error = NULL;
+  GSimpleAsyncResult *orig_result;
 
-  g_object_ref (enumerator);
+  g_print ("enumerate_children_async_cb\n");
+  orig_result = data->result;
+  
+  if (! gvfs_dbus_mount_call_enumerate_finish (proxy, res, &error))
+    {
+      g_simple_async_result_take_error (orig_result, error);
+      goto out;
+    }
+  
+  g_object_ref (data->enumerator);
 
-  g_simple_async_result_set_op_res_gpointer (result, enumerator, g_object_unref);
+  g_simple_async_result_set_op_res_gpointer (orig_result, data->enumerator, g_object_unref);
 
 out:
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+  data->result = NULL;
+  g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+enumerate_children_async_get_proxy_cb (GVfsDBusMount *proxy,
+                                       GDBusConnection *connection,
+                                       GMountInfo *mount_info,
+                                       const gchar *path,
+                                       GSimpleAsyncResult *result,
+                                       GError *error,
+                                       GCancellable *cancellable,
+                                       gpointer callback_data)
+{
+  AsyncCallEnumerate *data = callback_data;
+  char *obj_path;
+  char *uri;
+
+  g_print ("enumerate_children_async_get_proxy_cb, proxy = %p\n", proxy);
+  
+  obj_path = g_daemon_file_enumerator_get_object_path (data->enumerator);
+  uri = g_file_get_uri (data->file);
+  
+  data->result = g_object_ref (result);
+  
+  gvfs_dbus_mount_call_enumerate (proxy,
+                                  path,
+                                  obj_path,
+                                  data->attributes ? data->attributes : "",
+                                  data->flags,
+                                  uri,
+                                  cancellable,
+                                  (GAsyncReadyCallback) enumerate_children_async_cb,
+                                  data);
+  
+  g_free (uri);
+  g_free (obj_path);
 }
 
 static void
@@ -2858,31 +3272,24 @@ g_daemon_file_enumerate_children_async (GFile                      *file,
                                         GAsyncReadyCallback         callback,
                                         gpointer                    user_data)
 {
-  dbus_uint32_t flags_dbus;
-  char *obj_path;
-  GDaemonFileEnumerator *enumerator;
-  char *uri;
+  AsyncCallEnumerate *data;
 
-  enumerator = g_daemon_file_enumerator_new (file, attributes);
-  obj_path = g_daemon_file_enumerator_get_object_path (enumerator);
+  g_print ("g_daemon_file_enumerate_children_async\n");
 
-  uri = g_file_get_uri (file);
+  data = g_new0 (AsyncCallEnumerate, 1);
+  data->file = g_object_ref (file);
+  data->attributes = g_strdup (attributes);
+  data->flags = flags;
+  data->io_priority = io_priority;
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
+  data->enumerator = g_daemon_file_enumerator_new (data->file, data->attributes);
 
-  if (attributes == NULL)
-    attributes = "";
-  flags_dbus = flags;
-  do_async_path_call (file, 
-                      G_VFS_DBUS_MOUNT_OP_ENUMERATE,
-                      cancellable,
-                      callback, user_data,
-                      enumerate_children_async_cb, enumerator, g_object_unref,
-                      DBUS_TYPE_STRING, &obj_path,
-                      DBUS_TYPE_STRING, &attributes,
-                      DBUS_TYPE_UINT32, &flags_dbus,
-                      DBUS_TYPE_STRING, &uri,
-                      0);
-  g_free (uri);
-  g_free (obj_path);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               enumerate_children_async_get_proxy_cb,
+                               data, (GDestroyNotify) async_call_enumerate_free);
 }
 
 static GFileEnumerator *
@@ -3007,40 +3414,6 @@ g_daemon_file_find_enclosing_mount_finish (GFile              *file,
 }
 
 static void
-replace_async_cb (DBusMessage *reply,
-                  DBusConnection *connection,
-                  GMountInfo *mount_info,
-                  GSimpleAsyncResult *result,
-                  GCancellable *cancellable,
-                  gpointer callback_data)
-{
-  guint32 fd_id;
-  StreamOpenParams *open_params;
-
-  open_params = g_slice_new0 (StreamOpenParams);
-
-  if (!dbus_message_get_args (reply, NULL,
-			      DBUS_TYPE_UINT32, &fd_id,
-			      DBUS_TYPE_BOOLEAN, &open_params->can_seek,
-			      DBUS_TYPE_UINT64, &open_params->initial_offset,
-			      DBUS_TYPE_INVALID))
-    {
-      g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
-                                       _("Invalid return value from %s"), "open");
-      goto failure;
-    }
-
-  open_params->result = g_object_ref (result);
-  _g_dbus_connection_get_fd_async (connection, fd_id,
-                                   (GetFdAsyncCallback) stream_open_cb, open_params);
-  return;
-
-failure:
-  g_slice_free (StreamOpenParams, open_params);
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
-}
-
-static void
 g_daemon_file_replace_async (GFile                      *file,
                              const char                 *etag,
                              gboolean                    make_backup,
@@ -3050,27 +3423,12 @@ g_daemon_file_replace_async (GFile                      *file,
                              GAsyncReadyCallback         callback,
                              gpointer                    user_data)
 {
-  dbus_bool_t dbus_make_backup = make_backup;
-  guint32 dbus_flags = flags;
-  guint16 mode = 2;
-  guint32 pid;
-
-  pid = get_pid_for_file (file);
+  g_print ("g_daemon_file_replace_async\n");
   
-  if (etag == NULL)
-    etag = "";
-
-  do_async_path_call (file,
-                      G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE,
-                      cancellable,
-                      callback, user_data,
-                      replace_async_cb, NULL, NULL,
-                      DBUS_TYPE_UINT16, &mode,
-                      DBUS_TYPE_STRING, &etag,
-                      DBUS_TYPE_BOOLEAN, &dbus_make_backup,
-                      DBUS_TYPE_UINT32, &dbus_flags,
-                      DBUS_TYPE_UINT32, &pid,
-                      0);
+  file_open_write_async (file,
+                         2, etag, make_backup, flags, io_priority,
+                         cancellable,
+                         callback, user_data);
 }
 
 static GFileOutputStream *
@@ -3088,38 +3446,86 @@ g_daemon_file_replace_finish (GFile                      *file,
   return NULL;
 }
 
+typedef struct {
+  GFile *file;
+  char *display_name;
+  int io_priority;
+  GMountInfo *mount_info;
+  GSimpleAsyncResult *result;
+  GCancellable *cancellable;
+} AsyncCallSetDisplayName;
+
+static void
+async_call_set_display_name_free (AsyncCallSetDisplayName *data)
+{
+  if (data->file)
+    g_object_unref (data->file);
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  if (data->mount_info)
+    g_mount_info_unref (data->mount_info);
+  g_free (data->display_name);
+  g_free (data);
+}
+
 static void
-set_display_name_async_cb (DBusMessage *reply,
-                           DBusConnection *connection,
-                           GMountInfo *mount_info,
-                           GSimpleAsyncResult *result,
-                           GCancellable *cancellable,
-                           gpointer callback_data)
+set_display_name_async_cb (GVfsDBusMount *proxy,
+                           GAsyncResult *res,
+                           gpointer user_data)
 {
-  GDaemonFile *daemon_file = callback_data;
+  AsyncCallSetDisplayName *data = user_data;
   GFile *file;
-  DBusMessageIter iter;
+  GError *error = NULL;
   gchar *new_path;
+  GSimpleAsyncResult *orig_result;
+
+  g_print ("set_display_name_async_cb\n");
+  orig_result = data->result;
 
-  if (!dbus_message_iter_init (reply, &iter) ||
-      !_g_dbus_message_iter_get_args (&iter, NULL,
-				      G_DBUS_TYPE_CSTRING, &new_path,
-				      0))
+  if (! gvfs_dbus_mount_call_set_display_name_finish (proxy, &new_path, res, &error))
     {
-      g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED,
-                                       _("Invalid return value from %s"), "set_display_name");
+      g_simple_async_result_take_error (orig_result, error);
       goto out;
     }
 
-  g_mount_info_apply_prefix (mount_info, &new_path);
-  file = new_file_for_new_path (daemon_file, new_path);
+  g_mount_info_apply_prefix (data->mount_info, &new_path);
+  file = new_file_for_new_path (G_DAEMON_FILE (data->file), new_path);
 
   g_free (new_path);
 
-  g_simple_async_result_set_op_res_gpointer (result, file, g_object_unref);
+  g_simple_async_result_set_op_res_gpointer (orig_result, file, g_object_unref);
 
-out:
-  _g_simple_async_result_complete_with_cancellable (result, cancellable);
+  out:
+    _g_simple_async_result_complete_with_cancellable (orig_result, data->cancellable);
+    data->result = NULL;
+    g_object_unref (orig_result);   /* trigger async_proxy_create_free() */
+}
+
+static void
+set_display_name_async_get_proxy_cb (GVfsDBusMount *proxy,
+                                     GDBusConnection *connection,
+                                     GMountInfo *mount_info,
+                                     const gchar *path,
+                                     GSimpleAsyncResult *result,
+                                     GError *error,
+                                     GCancellable *cancellable,
+                                     gpointer callback_data)
+{
+  AsyncCallSetDisplayName *data = callback_data;
+
+  g_print ("set_display_name_async_get_proxy_cb, proxy = %p\n", proxy);
+  
+  data->result = g_object_ref (result);
+  data->mount_info = g_mount_info_ref (mount_info);
+  
+  gvfs_dbus_mount_call_set_display_name (proxy,
+                                         path,
+                                         data->display_name,
+                                         cancellable,
+                                         (GAsyncReadyCallback) set_display_name_async_cb,
+                                         data);
 }
 
 static void
@@ -3130,15 +3536,22 @@ g_daemon_file_set_display_name_async (GFile                      *file,
                                       GAsyncReadyCallback         callback,
                                       gpointer                    user_data)
 {
-  g_object_ref (file);
+  AsyncCallSetDisplayName *data;
+
+  g_print ("g_daemon_file_set_display_name_async\n");
+  
+  data = g_new0 (AsyncCallSetDisplayName, 1);
+  data->file = g_object_ref (file);
+  data->display_name = g_strdup (display_name);
+  data->io_priority = io_priority;
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  do_async_path_call (file,
-                      G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME,
-                      cancellable,
-                      callback, user_data,
-                      set_display_name_async_cb, file, g_object_unref,
-                      DBUS_TYPE_STRING, &display_name,
-                      0);
+  create_proxy_for_file_async (file,
+                               cancellable,
+                               callback, user_data,
+                               set_display_name_async_get_proxy_cb,
+                               data, (GDestroyNotify) async_call_set_display_name_free);
 }
 
 static GFile *
diff --git a/client/gdaemonfileenumerator.c b/client/gdaemonfileenumerator.c
index 9e8722a..80502f7 100644
--- a/client/gdaemonfileenumerator.c
+++ b/client/gdaemonfileenumerator.c
@@ -32,6 +32,7 @@
 #include <gvfsdaemonprotocol.h>
 #include "gdaemonfile.h"
 #include "metatree.h"
+#include <gvfsdbus.h>
 
 #define OBJ_PATH_PREFIX "/org/gtk/vfs/client/enumerator/"
 
@@ -45,7 +46,7 @@ struct _GDaemonFileEnumerator
   GFileEnumerator parent;
 
   gint id;
-  DBusConnection *sync_connection; /* NULL if async, i.e. we're listening on main dbus connection */
+  GDBusConnection *sync_connection; /* NULL if async, i.e. we're listening on main dbus connection */
 
   /* protected by infos lock */
   GList *infos;
@@ -56,6 +57,9 @@ struct _GDaemonFileEnumerator
   gulong cancelled_tag;
   guint timeout_tag;
   GSimpleAsyncResult *async_res;
+  GMainLoop *next_files_mainloop;
+  guint next_files_sync_timeout_tag;
+  GMutex next_files_mutex;
 
   GFileAttributeMatcher *matcher;
   MetaTree *metadata_tree;
@@ -86,9 +90,8 @@ static void              g_daemon_file_enumerator_close_async (GFileEnumerator
 static gboolean          g_daemon_file_enumerator_close_finish (GFileEnumerator      *enumerator,
 							       GAsyncResult         *result,
 							       GError              **error);
-static DBusHandlerResult g_daemon_file_enumerator_dbus_filter (DBusConnection   *connection,
-							       DBusMessage      *message,
-							       void             *user_data);
+static void              trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok);
+
 
 static void
 free_info_list (GList *infos)
@@ -105,6 +108,8 @@ g_daemon_file_enumerator_finalize (GObject *object)
 
   daemon = G_DAEMON_FILE_ENUMERATOR (object);
 
+  g_print ("g_daemon_file_enumerator_finalize: daemon = %p\n", daemon);
+
   path = g_daemon_file_enumerator_get_object_path (daemon);
   _g_dbus_unregister_vfs_filter (path);
   g_free (path);
@@ -116,7 +121,9 @@ g_daemon_file_enumerator_finalize (GObject *object)
     meta_tree_unref (daemon->metadata_tree);
 
   if (daemon->sync_connection)
-    dbus_connection_unref (daemon->sync_connection);
+    g_object_unref (daemon->sync_connection);
+  
+  g_mutex_clear (&daemon->next_files_mutex);
   
   if (G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_daemon_file_enumerator_parent_class)->finalize) (object);
@@ -140,14 +147,127 @@ g_daemon_file_enumerator_class_init (GDaemonFileEnumeratorClass *klass)
 }
 
 static void
+next_files_sync_check (GDaemonFileEnumerator *enumerator)
+{
+  g_print ("next_files_sync_check: enumerator->infos = %p, enumerator->done = %d, loop = %p, daemon = %p\n", enumerator->infos, enumerator->done, enumerator->next_files_mainloop, enumerator);
+
+  g_mutex_lock (&enumerator->next_files_mutex);
+  if ((enumerator->infos || enumerator->done) && 
+      enumerator->next_files_mainloop != NULL)
+    {
+      g_print ("next_files_sync_check: calling quit\n");
+      g_main_loop_quit (enumerator->next_files_mainloop);
+    }
+  g_mutex_unlock (&enumerator->next_files_mutex);
+}
+
+static gboolean
+handle_done (GVfsDBusEnumerator *object,
+             GDBusMethodInvocation *invocation,
+             gpointer user_data)
+{
+  GDaemonFileEnumerator *enumerator = user_data;
+
+  g_print ("handle_done: daemon = %p, async_requested_files = %d\n", enumerator, enumerator->async_requested_files);
+
+  G_LOCK (infos);
+  enumerator->done = TRUE;
+  if (enumerator->async_requested_files > 0)
+    trigger_async_done (enumerator, TRUE);
+  next_files_sync_check (enumerator);
+  G_UNLOCK (infos);
+
+  gvfs_dbus_enumerator_complete_done (object, invocation);
+  
+  return TRUE;
+}
+
+static gboolean
+handle_got_info (GVfsDBusEnumerator *object,
+                 GDBusMethodInvocation *invocation,
+                 GVariant *arg_infos,
+                 gpointer user_data)
+{
+  GDaemonFileEnumerator *enumerator = user_data;
+  GList *infos;
+  GFileInfo *info;
+  GVariantIter iter;
+  GVariant *child;
+  
+  g_print ("handle_got_info: daemon = %p\n", enumerator);
+
+  infos = NULL;
+    
+  g_variant_iter_init (&iter, arg_infos);
+  while ((child = g_variant_iter_next_value (&iter)))
+    {
+      info = _g_dbus_get_file_info (child, NULL);
+      if (info)
+        g_assert (G_IS_FILE_INFO (info));
+
+      if (info)
+        infos = g_list_prepend (infos, info);
+
+      g_variant_unref (child);
+    }
+  
+  infos = g_list_reverse (infos);
+  
+  G_LOCK (infos);
+  enumerator->infos = g_list_concat (enumerator->infos, infos);
+  if (enumerator->async_requested_files > 0 &&
+      g_list_length (enumerator->infos) >= enumerator->async_requested_files)
+    trigger_async_done (enumerator, TRUE);
+  next_files_sync_check (enumerator);
+  G_UNLOCK (infos);
+
+  gvfs_dbus_enumerator_complete_got_info (object, invocation);
+  
+  return TRUE;
+}
+
+static GDBusInterfaceSkeleton *
+register_vfs_filter_cb (GDBusConnection *connection,
+                        const char *obj_path,
+                        gpointer callback_data)
+{
+  GError *error;
+  GVfsDBusEnumerator *skeleton;
+
+  skeleton = gvfs_dbus_enumerator_skeleton_new ();
+  g_signal_connect (skeleton, "handle-done", G_CALLBACK (handle_done), callback_data);
+  g_signal_connect (skeleton, "handle-got-info", G_CALLBACK (handle_got_info), callback_data);
+
+  g_print ("register_vfs_filter_cb: callback_data = %p, skeleton = %p, obj_path = '%s'\n", callback_data, skeleton, obj_path);
+
+  error = NULL;
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
+                                         connection,
+                                         obj_path,
+                                         &error))
+    {
+      g_warning ("Error registering path: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+
+  return G_DBUS_INTERFACE_SKELETON (skeleton);
+}
+
+static void
 g_daemon_file_enumerator_init (GDaemonFileEnumerator *daemon)
 {
   char *path;
   
   daemon->id = g_atomic_int_add (&path_counter, 1);
 
+  g_mutex_init (&daemon->next_files_mutex);
+  
   path = g_daemon_file_enumerator_get_object_path (daemon);
-  _g_dbus_register_vfs_filter (path, g_daemon_file_enumerator_dbus_filter,
+  g_print ("g_daemon_file_enumerator_init: daemon = %p, obj_path = '%s'\n", daemon, path);
+
+  _g_dbus_register_vfs_filter (path, 
+                               register_vfs_filter_cb,
 			       G_OBJECT (daemon));
   g_free (path);
 }
@@ -243,7 +363,7 @@ static void
 trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
 {
   GList *rest, *l;
-
+  
   if (daemon->cancelled_tag != 0)
     {
       GCancellable *cancellable = simple_async_result_get_cancellable (daemon->async_res);
@@ -309,65 +429,6 @@ trigger_async_done (GDaemonFileEnumerator *daemon, gboolean ok)
   daemon->async_res = NULL;
 }
 
-static DBusHandlerResult
-g_daemon_file_enumerator_dbus_filter (DBusConnection     *connection,
-				      DBusMessage        *message,
-				      void               *user_data)
-{
-  GDaemonFileEnumerator *enumerator = user_data;
-  const char *member;
-  DBusMessageIter iter, array_iter;
-  GList *infos;
-  GFileInfo *info;
-  
-  member = dbus_message_get_member (message);
-
-  if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_DONE) == 0)
-    {
-      G_LOCK (infos);
-      enumerator->done = TRUE;
-      if (enumerator->async_requested_files > 0)
-	trigger_async_done (enumerator, TRUE);
-      G_UNLOCK (infos);
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-  else if (strcmp (member, G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO) == 0)
-    {
-      infos = NULL;
-      
-      dbus_message_iter_init (message, &iter);
-      if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY &&
-	  dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_STRUCT)
-	{
-	  dbus_message_iter_recurse (&iter, &array_iter);
-
-	  while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
-	    {
-	      info = _g_dbus_get_file_info (&array_iter, NULL);
-	      if (info)
-		g_assert (G_IS_FILE_INFO (info));
-
-	      if (info)
-		infos = g_list_prepend (infos, info);
-
-	      dbus_message_iter_next (&iter);
-	    }
-	}
-
-      infos = g_list_reverse (infos);
-      
-      G_LOCK (infos);
-      enumerator->infos = g_list_concat (enumerator->infos, infos);
-      if (enumerator->async_requested_files > 0 &&
-	  g_list_length (enumerator->infos) >= enumerator->async_requested_files)
-	trigger_async_done (enumerator, TRUE);
-      G_UNLOCK (infos);
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
 char  *
 g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator)
 {
@@ -376,9 +437,23 @@ g_daemon_file_enumerator_get_object_path (GDaemonFileEnumerator *enumerator)
 
 void
 g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator,
-					      DBusConnection        *connection)
+					      GDBusConnection       *connection)
 {
-  enumerator->sync_connection = dbus_connection_ref (connection);
+  enumerator->sync_connection = g_object_ref (connection);
+}
+
+static gboolean
+sync_timeout (gpointer data)
+{
+  GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (data);
+
+  g_print ("sync_timeout\n");
+  
+  g_mutex_lock (&daemon->next_files_mutex);
+  g_main_loop_quit (daemon->next_files_mainloop);
+  g_mutex_unlock (&daemon->next_files_mutex);
+  
+  return FALSE;
 }
 
 static GFileInfo *
@@ -388,71 +463,61 @@ g_daemon_file_enumerator_next_file (GFileEnumerator *enumerator,
 {
   GDaemonFileEnumerator *daemon = G_DAEMON_FILE_ENUMERATOR (enumerator);
   GFileInfo *info;
-  gboolean done;
-  int count;
   
-  info = NULL;
-  done = FALSE;
-  count = 0;
-  while (count++ < G_VFS_DBUS_TIMEOUT_MSECS / 100)
+  if (daemon->sync_connection == NULL)
     {
-      G_LOCK (infos);
-      if (daemon->infos)
-	{
-	  done = TRUE;
-	  info = daemon->infos->data;
-	  if (info)
-	    {
-	      g_assert (G_IS_FILE_INFO (info));
-	      add_metadata (G_FILE_INFO (info), daemon);
-	    }
-	  daemon->infos = g_list_delete_link (daemon->infos, daemon->infos);
-	}
-      else if (daemon->done)
-	done = TRUE;
-      G_UNLOCK (infos);
+      /* The enumerator was initialized by an async call, so responses will
+         come to the async dbus connection. We can't pump that as that would
+         cause all sort of filters and stuff to run, possibly on the wrong
+         thread. If you want to do async next_files you must create the
+         enumerator asynchrounously.
+      */
+      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
+                           "Can't do synchronous next_files() on a file enumerator created asynchronously");
+      return NULL;
+    }
 
-      if (info)
-	g_assert (G_IS_FILE_INFO (info));
+  g_print ("g_daemon_file_enumerator_next_file: done = %d\n", daemon->done);
+  
+  if (! daemon->infos && ! daemon->done)
+    {
+      /* Wait for incoming data */
+      daemon->next_files_sync_timeout_tag = g_timeout_add (G_VFS_DBUS_TIMEOUT_MSECS,
+                                                           sync_timeout, daemon);
+
+      g_mutex_lock (&daemon->next_files_mutex);
+      g_print ("g_daemon_file_enumerator_next_file: starting loop, daemon = %p\n", daemon);
+      daemon->next_files_mainloop = g_main_loop_new (NULL, FALSE);
+      g_mutex_unlock (&daemon->next_files_mutex);
       
-      if (done)
-	break;
+      g_main_loop_run (daemon->next_files_mainloop);
+
+      g_mutex_lock (&daemon->next_files_mutex);
+      g_print ("g_daemon_file_enumerator_next_file: loop done.\n");
+      g_source_remove (daemon->next_files_sync_timeout_tag);
+      g_main_loop_unref (daemon->next_files_mainloop);
+      daemon->next_files_mainloop = NULL;
+      g_mutex_unlock (&daemon->next_files_mutex);
+    }
+  
+  info = NULL;
 
-      /* We sleep only 100 msecs here, not the full time because we might have
-       * raced with the filter func being called after unlocking
-       * and setting done or ->infos. So, we want to check it again reasonaby soon.
-       */
-      if (daemon->sync_connection != NULL)
-	{
-	  /* The initializing call for the enumerator was a sync one, and we
-	     have a reference to its private connection. In order to ensure we
-	     get the responses sent to that originating connection we pump it
-	     here.
-	     This should be safe as we're either on the thread that did the call
-	     so its our connection, or its the private connection for another
-	     thread. If that thread is idle the pumping won't affect anything, and
-	     if it is doing something thats ok to, because we don't use filters
-	     on the private sync connections so we won't cause any reentrancy
-	     (except the file enumerator filter, but that is safe to run in
-	     some other thread).
-	  */
-	  if (!dbus_connection_read_write_dispatch (daemon->sync_connection, 100))
-	    break;
-	}
-      else
-	{
-	  /* The enumerator was initialized by an async call, so responses will
-	     come to the async dbus connection. We can't pump that as that would
-	     cause all sort of filters and stuff to run, possibly on the wrong
-	     thread. If you want to do async next_files you must create the
-	     enumerator asynchrounously.
-	  */
-	  g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			       "Can't do synchronous next_files() on a file enumerator created asynchronously");
-	  return NULL;
-	}
+  G_LOCK (infos);
+  if (daemon->infos)
+    {
+      info = daemon->infos->data;
+      if (info)
+        {
+          g_assert (G_IS_FILE_INFO (info));
+          add_metadata (G_FILE_INFO (info), daemon);
+        }
+      daemon->infos = g_list_delete_link (daemon->infos, daemon->infos);
     }
+  G_UNLOCK (infos);
 
+  if (info)
+    g_assert (G_IS_FILE_INFO (info));
+      
   return info;
 }
 
diff --git a/client/gdaemonfileenumerator.h b/client/gdaemonfileenumerator.h
index 17e7ddb..32c6160 100644
--- a/client/gdaemonfileenumerator.h
+++ b/client/gdaemonfileenumerator.h
@@ -24,7 +24,6 @@
 #define __G_DAEMON_FILE_ENUMERATOR_H__
 
 #include <gio/gio.h>
-#include <dbus/dbus.h>
 
 G_BEGIN_DECLS
 
@@ -50,7 +49,7 @@ GDaemonFileEnumerator *g_daemon_file_enumerator_new                 (GFile *file
 								     const char *attributes);
 char  *                g_daemon_file_enumerator_get_object_path     (GDaemonFileEnumerator *enumerator);
 void                   g_daemon_file_enumerator_set_sync_connection (GDaemonFileEnumerator *enumerator,
-								     DBusConnection        *connection);
+								     GDBusConnection       *connection);
 
 
 G_END_DECLS
diff --git a/client/gdaemonmount.c b/client/gdaemonmount.c
index f1b82a7..1104f9b 100644
--- a/client/gdaemonmount.c
+++ b/client/gdaemonmount.c
@@ -31,10 +31,9 @@
 #include "gdaemonmount.h"
 #include "gvfsdaemondbus.h"
 #include "gdaemonfile.h"
-#include "gvfsdaemonprotocol.h"
-#include "gvfsdbusutils.h"
 #include "gmountsource.h"
 #include "gmountoperationdbus.h"
+#include <gvfsdbus.h>
 
 /* Protects all fields of GDaemonMount that can change
    which at this point is just foreign_volume */
@@ -173,19 +172,148 @@ g_daemon_mount_can_eject (GMount *mount)
   return FALSE;
 }
 
+
+typedef struct {
+  GMount *mount;
+  GCancellable *cancellable;
+  GSimpleAsyncResult *result;
+  GMountInfo *mount_info;
+  GMountOperation *mount_operation;
+  GMountUnmountFlags flags;
+  GDBusConnection *connection;
+  GVfsDBusMount *proxy;
+} AsyncProxyCreate;
+
+static void
+async_proxy_create_free (AsyncProxyCreate *data)
+{
+  if (data->mount)
+    g_object_unref (data->mount);
+  if (data->result)
+    g_object_unref (data->result);
+  if (data->cancellable)
+    g_object_unref (data->cancellable);
+  if (data->mount_operation)
+    g_object_unref (data->mount_operation);
+  if (data->connection)
+    g_object_unref (data->connection);
+  if (data->proxy)
+    g_object_unref (data->proxy);
+  g_free (data);
+}
+
+static void
+unmount_reply (GVfsDBusMount *proxy,
+               GAsyncResult *res,
+               gpointer user_data)
+{
+  AsyncProxyCreate *data = user_data;
+  GError *error = NULL;
+
+  g_print ("gdaemonmount.c: unmount_reply, proxy = %p\n", proxy);
+
+  if (! gvfs_dbus_mount_call_unmount_finish (proxy, res, &error))
+    {
+      g_simple_async_result_take_error (data->result, error);      
+    }
+  
+  _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
+  async_proxy_create_free (data);
+}
+
+static void
+async_proxy_new_cb (GObject *source_object,
+                    GAsyncResult *res,
+                    gpointer user_data)
+{
+  AsyncProxyCreate *data = user_data;
+  GVfsDBusMount *proxy;
+  GError *error = NULL;
+  GMountSource *mount_source;
+
+  proxy = gvfs_dbus_mount_proxy_new_finish (res, &error);
+  g_print ("gdaemonmount.c: async_proxy_new_cb, proxy = %p\n", proxy);
+  if (proxy == NULL)
+    {
+      g_simple_async_result_take_error (data->result, error);      
+      _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
+      async_proxy_create_free (data);
+      return;
+    }
+
+  data->proxy = proxy;
+  _g_dbus_connect_vfs_filters (data->connection);
+
+  mount_source = g_mount_operation_dbus_wrap (data->mount_operation, _g_daemon_vfs_get_async_bus ());
+
+  gvfs_dbus_mount_call_unmount (proxy,
+                                g_mount_source_get_dbus_id (mount_source),
+                                g_mount_source_get_obj_path (mount_source),
+                                data->flags,
+                                data->cancellable,
+                                (GAsyncReadyCallback) unmount_reply,
+                                data);
+  
+  g_object_unref (mount_source);
+}
+
+static void
+async_construct_proxy (GDBusConnection *connection,
+                       AsyncProxyCreate *data)
+{
+  data->connection = g_object_ref (connection);
+  gvfs_dbus_mount_proxy_new (connection,
+                             G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                             data->mount_info->dbus_id,
+                             data->mount_info->object_path,
+                             data->cancellable,
+                             async_proxy_new_cb,
+                             data);
+}
+
 static void
-unmount_reply (DBusMessage *reply,
-	       DBusConnection *connection,
-	       GError *io_error,
-	       gpointer _data)
+bus_get_cb (GObject *source_object,
+            GAsyncResult *res,
+            gpointer user_data)
 {
-  GSimpleAsyncResult *result = _data;
+  AsyncProxyCreate *data = user_data;
+  GDBusConnection *connection;
+  GError *error = NULL;
+  
+  connection = g_bus_get_finish (res, &error);
+  
+  if (connection == NULL)
+    {
+      g_simple_async_result_set_from_error (data->result, error);
+      _g_simple_async_result_complete_with_cancellable (data->result, data->cancellable);
+      async_proxy_create_free (data);
+      return;
+    }
+
+  async_construct_proxy (connection, data);
+}
 
-  if (io_error != NULL)
-    g_simple_async_result_set_from_error (result, io_error);
+static void
+async_got_connection_cb (GDBusConnection *connection,
+                         GError *io_error,
+                         gpointer callback_data)
+{
+  AsyncProxyCreate *data = callback_data;
+  
+  g_print ("gdaemonmount.c: async_got_connection_cb, connection = %p\n", connection);
+  
+  if (connection == NULL)
+    {
+      /* TODO: we should probably test if we really want a session bus;
+       *       for now, this code is on par with the old dbus code */ 
+      g_bus_get (G_BUS_TYPE_SESSION,
+                 data->cancellable,
+                 bus_get_cb,
+                 data);
+      return;
+    }
   
-  g_simple_async_result_complete (result);
-  g_object_unref (result);
+  async_construct_proxy (connection, data);
 }
 
 static void
@@ -197,42 +325,26 @@ g_daemon_mount_unmount_with_operation (GMount *mount,
                                        gpointer         user_data)
 {
   GDaemonMount *daemon_mount = G_DAEMON_MOUNT (mount);
-  DBusMessage *message;
-  GMountInfo *mount_info;
-  GSimpleAsyncResult *res;
-  guint32 dbus_flags;
-  GMountSource *mount_source;
-  const char *dbus_id, *obj_path;
+  AsyncProxyCreate *data;
 
-  mount_info = daemon_mount->mount_info;
+  g_print ("g_daemon_mount_unmount_with_operation\n");
 
-  message =
-    dbus_message_new_method_call (mount_info->dbus_id,
-				  mount_info->object_path,
-				  G_VFS_DBUS_MOUNT_INTERFACE,
-				  G_VFS_DBUS_MOUNT_OP_UNMOUNT);
+  data = g_new0 (AsyncProxyCreate, 1);
+  data->mount = g_object_ref (mount);
+  data->mount_info = daemon_mount->mount_info;
+  data->mount_operation = g_object_ref (mount_operation);
+  data->flags = flags;
+  if (cancellable)
+    data->cancellable = g_object_ref (cancellable);
 
-  mount_source = g_mount_operation_dbus_wrap (mount_operation, _g_daemon_vfs_get_async_bus ());
-  dbus_id = g_mount_source_get_dbus_id (mount_source);
-  obj_path = g_mount_source_get_obj_path (mount_source);
-
-  dbus_flags = flags;
-  _g_dbus_message_append_args (message,
-                               DBUS_TYPE_STRING, &dbus_id, DBUS_TYPE_OBJECT_PATH, &obj_path,
-                               DBUS_TYPE_UINT32, &dbus_flags,
-                               0);
-  
-  res = g_simple_async_result_new (G_OBJECT (mount),
-				   callback, user_data,
-				   g_daemon_mount_unmount_with_operation);
-  
-  _g_vfs_daemon_call_async (message,
-			    unmount_reply, res,
-			    cancellable);
+  data->result = g_simple_async_result_new (G_OBJECT (mount),
+                                            callback, user_data,
+                                            g_daemon_mount_unmount_with_operation);
   
-  dbus_message_unref (message);
-
-  g_object_unref (mount_source);
+  _g_dbus_connection_get_for_async (data->mount_info->dbus_id,
+                                    async_got_connection_cb,
+                                    data,
+                                    data->cancellable);
 }
 
 static gboolean
diff --git a/client/gdaemonvfs.c b/client/gdaemonvfs.c
index 6930a28..0bdee72 100644
--- a/client/gdaemonvfs.c
+++ b/client/gdaemonvfs.c
@@ -25,15 +25,12 @@
 #include <signal.h>
 #include <stdlib.h>
 #include <errno.h>
-#include <dbus/dbus.h>
 #include "gdaemonvfs.h"
 #include "gvfsuriutils.h"
 #include "gdaemonfile.h"
 #include <gio/gio.h>
 #include <gvfsdaemonprotocol.h>
 #include <gmodule.h>
-#include "gvfsdaemondbus.h"
-#include "gvfsdbusutils.h"
 #include "gmountspec.h"
 #include "gvfsurimapper.h"
 #include "gdaemonvolumemonitor.h"
@@ -41,6 +38,7 @@
 #include "gvfsiconloadable.h"
 #include <glib/gi18n-lib.h>
 #include <glib/gstdio.h>
+#include <gvfsdbus.h>
 
 typedef struct  {
   char *type;
@@ -54,7 +52,7 @@ struct _GDaemonVfs
 {
   GVfs parent;
 
-  DBusConnection *async_bus;
+  GDBusConnection *async_bus;
   
   GVfs *wrapped_vfs;
   GList *mount_cache;
@@ -101,10 +99,7 @@ g_daemon_vfs_finalize (GObject *object)
   g_strfreev (vfs->supported_uri_schemes);
 
   if (vfs->async_bus)
-    {
-      dbus_connection_close (vfs->async_bus);
-      dbus_connection_unref (vfs->async_bus);
-    }
+    g_object_unref (vfs->async_bus);
 
   if (vfs->wrapped_vfs)
     g_object_unref (vfs->wrapped_vfs);
@@ -302,9 +297,7 @@ g_daemon_vfs_init (GDaemonVfs *vfs)
   bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
 
-  dbus_threads_init_default ();
-
-  vfs->async_bus = dbus_bus_get_private (DBUS_BUS_SESSION, NULL);
+  vfs->async_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
 
   if (vfs->async_bus == NULL)
     return; /* Not supported, return here and return false in vfs_is_active() */
@@ -336,9 +329,7 @@ g_daemon_vfs_init (GDaemonVfs *vfs)
   vfs->fuse_root = g_vfs_get_file_for_path (vfs->wrapped_vfs, file);
   g_free (file);
   
-  dbus_connection_set_exit_on_disconnect (vfs->async_bus, FALSE);
-
-  _g_dbus_connection_integrate_with_main (vfs->async_bus);
+  g_dbus_connection_set_exit_on_close (vfs->async_bus, FALSE);
 
   modules = g_io_modules_load_all_in_directory (GVFS_MODULE_DIR);
 
@@ -611,107 +602,101 @@ find_string (GPtrArray *array, const char *find_me)
   return -1;
 }
 
+static GVfsDBusMountTracker *
+create_mount_tracker_proxy ()
+{
+  GVfsDBusMountTracker *proxy;
+  GError *error;
+
+  error = NULL;
+  proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                          G_DBUS_PROXY_FLAGS_NONE,
+                                                          G_VFS_DBUS_DAEMON_NAME,
+                                                          G_VFS_DBUS_MOUNTTRACKER_PATH,
+                                                          NULL,
+                                                          &error);
+  if (proxy == NULL)
+    {
+      g_printerr ("Error creating proxy: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+  
+  return proxy;
+}
 
 static void
 fill_mountable_info (GDaemonVfs *vfs)
 {
-  DBusMessage *message, *reply;
-  DBusError error;
-  DBusMessageIter iter, array_iter, struct_iter;
   MountableInfo *info;
   GPtrArray *infos, *uri_schemes;
   gint i;
-
-  message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-                                          G_VFS_DBUS_MOUNTTRACKER_PATH,
-					  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					  G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO);
-
-  if (message == NULL)
-    _g_dbus_oom ();
-  
-  dbus_message_set_auto_start (message, TRUE);
-  
-  dbus_error_init (&error);
-  reply = dbus_connection_send_with_reply_and_block (vfs->async_bus,
-                                                     message,
-						     G_VFS_DBUS_TIMEOUT_MSECS,
-						     &error);
-  dbus_message_unref (message);
+  GVfsDBusMountTracker *proxy;
+  GVariant *iter_mountables;
+  GError *error;
+  GVariantIter iter;
+  const gchar *type, *scheme, **scheme_aliases;
+  guint scheme_aliases_len;
+  gint32 default_port;
+  gboolean host_is_inet;
   
-  if (dbus_error_is_set (&error))
+  proxy = create_mount_tracker_proxy ();
+  g_return_if_fail (proxy != NULL);
+
+  error = NULL;
+  if (!gvfs_dbus_mount_tracker_call_list_mountable_info_sync (proxy, 
+                                                              &iter_mountables,
+                                                              NULL,
+                                                              &error))
     {
-      dbus_error_free (&error);
+      g_printerr ("org.gtk.vfs.MountTracker.listMountableInfo call failed: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
       return;
     }
-  
-  if (reply == NULL)
-    _g_dbus_oom ();
-
-  dbus_message_iter_init (reply, &iter);
-
-  dbus_message_iter_recurse (&iter, &array_iter);
 
   infos = g_ptr_array_new ();
   uri_schemes = g_ptr_array_new ();
   g_ptr_array_add (uri_schemes, g_strdup ("file"));
-  do
-    {
-      char *type, *scheme, **scheme_aliases;
-      int scheme_aliases_len;
-      gint32 default_port;
-      dbus_bool_t host_is_inet;
-      
-      if (dbus_message_iter_get_arg_type (&array_iter) != DBUS_TYPE_STRUCT)
-	break;
-      
-      dbus_message_iter_recurse (&array_iter, &struct_iter);
-      
-      if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
-					  DBUS_TYPE_STRING, &type,
-					  DBUS_TYPE_STRING, &scheme,
-					  DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &scheme_aliases, &scheme_aliases_len,
-					  DBUS_TYPE_INT32, &default_port,
-					  DBUS_TYPE_BOOLEAN, &host_is_inet,
-					  0))
-	break;
 
+  g_variant_iter_init (&iter, iter_mountables);
+  while (g_variant_iter_loop (&iter, "(&s&s^a&sib)", &type, &scheme, &scheme_aliases, &default_port, &host_is_inet))
+    {
       info = g_new0 (MountableInfo, 1);
       info->type = g_strdup (type);
       if (*scheme != 0)
-	{
-	  info->scheme = g_strdup (scheme);
-	  if (find_string (uri_schemes, scheme) == -1)
-	    g_ptr_array_add (uri_schemes, g_strdup (scheme));
-	}
+        {
+          info->scheme = g_strdup (scheme);
+          if (find_string (uri_schemes, scheme) == -1)
+            g_ptr_array_add (uri_schemes, g_strdup (scheme));
+        }
       
+      scheme_aliases_len = g_strv_length ((gchar **) scheme_aliases);
       if (scheme_aliases_len > 0)
-	{
-	  info->scheme_aliases = g_new (char *, scheme_aliases_len + 1);
-	  for (i = 0; i < scheme_aliases_len; i++)
-	    {
-	      info->scheme_aliases[i] = g_strdup (scheme_aliases[i]);
-	      if (find_string (uri_schemes, scheme_aliases[i]) == -1)
-		g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i]));
-	    }
-	  info->scheme_aliases[scheme_aliases_len] = NULL;
-	}
-	
+        {
+          info->scheme_aliases = g_new (char *, scheme_aliases_len + 1);
+          for (i = 0; i < scheme_aliases_len; i++)
+            {
+              info->scheme_aliases[i] = g_strdup (scheme_aliases[i]);
+              if (find_string (uri_schemes, scheme_aliases[i]) == -1)
+                g_ptr_array_add (uri_schemes, g_strdup (scheme_aliases[i]));
+            }
+          info->scheme_aliases[scheme_aliases_len] = NULL;
+        }
+        
       info->default_port = default_port;
       info->host_is_inet = host_is_inet;
       
       g_ptr_array_add (infos, info);
-
-      g_strfreev (scheme_aliases);
     }
-  while (dbus_message_iter_next (&array_iter));
-
-  dbus_message_unref (reply);
 
   g_ptr_array_add (uri_schemes, NULL);
   g_ptr_array_add (infos, NULL);
   vfs->mountable_info = (MountableInfo **)g_ptr_array_free (infos, FALSE);
   vfs->supported_uri_schemes = (char **)g_ptr_array_free (uri_schemes, FALSE);
+  
+  g_variant_unref (iter_mountables);
+  g_object_unref (proxy);
 }
 
 
@@ -814,23 +799,14 @@ _g_daemon_vfs_invalidate_dbus_id (const char *dbus_id)
 
 
 static GMountInfo *
-handler_lookup_mount_reply (DBusMessage *reply,
+handler_lookup_mount_reply (GVariant *iter,
 			    GError **error)
 {
-  DBusError derror;
   GMountInfo *info;
-  DBusMessageIter iter;
   GList *l;
   gboolean in_cache;
   
-
-  if (_g_error_from_message (reply, error))
-    return NULL;
-
-  dbus_error_init (&derror);
-  dbus_message_iter_init (reply, &iter);
-
-  info = g_mount_info_from_dbus (&iter);
+  info = g_mount_info_from_dbus (iter);
   if (info == NULL)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
@@ -869,34 +845,57 @@ typedef struct {
   GMountInfoLookupCallback callback;
   gpointer user_data;
   GMountInfo *info;
+  GMountSpec *spec;
+  char *path;
 } GetMountInfoData;
 
 static void
-async_get_mount_info_response (DBusMessage *reply,
-			       GError *io_error,
-			       void *_data)
+free_get_mount_info_data (GetMountInfoData *data)
 {
-  GetMountInfoData *data = _data;
+  if (data->info)
+    g_mount_info_unref (data->info);
+  if (data->spec)
+    g_mount_spec_unref (data->spec);
+  g_free (data->path);
+  g_free (data);
+}
+
+static void
+async_get_mount_info_response (GVfsDBusMountTracker *proxy,
+                               GAsyncResult *res,
+                               gpointer user_data)
+{
+  GetMountInfoData *data = user_data;
   GMountInfo *info;
   GError *error;
-
-  if (reply == NULL)
-    data->callback (NULL, data->user_data, io_error);
+  GVariant *iter_mount;
+  
+  error = NULL;
+  if (! gvfs_dbus_mount_tracker_call_lookup_mount_finish (proxy, 
+                                                          &iter_mount, 
+                                                          res, 
+                                                          &error))
+    {
+      g_warning ("Error from org.gtk.vfs.MountTracker.lookupMount(): %s", error->message);
+      data->callback (NULL, data->user_data, error);
+      g_error_free (error);
+    }
   else
     {
-      error = NULL;
-      info = handler_lookup_mount_reply (reply, &error);
+      info = handler_lookup_mount_reply (iter_mount, &error);
 
       data->callback (info, data->user_data, error);
 
       if (info)
-	g_mount_info_unref (info);
+        g_mount_info_unref (info);
 
+      g_variant_unref (iter_mount);
+      
       if (error)
-	g_error_free (error);
+        g_error_free (error);
     }
   
-  g_free (data);
+  free_get_mount_info_data (data);
 }
 
 static gboolean
@@ -904,11 +903,37 @@ async_get_mount_info_cache_hit (gpointer _data)
 {
   GetMountInfoData *data = _data;
   data->callback (data->info, data->user_data, NULL);
-  g_mount_info_unref (data->info);
-  g_free (data);
+  free_get_mount_info_data (data);
   return FALSE;
 }
 
+static void 
+get_mount_info_async_got_proxy_cb (GObject *source_object,
+                                   GAsyncResult *res,
+                                   gpointer user_data)
+{
+  GetMountInfoData *data = user_data;
+  GVfsDBusMountTracker *proxy;
+  GError *error = NULL;
+
+  proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error);
+  if (proxy == NULL)
+    {
+      g_warning ("Error creating MountTracker proxy: %s", error->message);
+      data->callback (NULL, data->user_data, error);
+      free_get_mount_info_data (data);
+      g_error_free (error);
+      return;
+    }
+  
+  gvfs_dbus_mount_tracker_call_lookup_mount (proxy,
+                                             g_mount_spec_to_dbus_with_path (data->spec, data->path),
+                                             NULL,
+                                             (GAsyncReadyCallback) async_get_mount_info_response,
+                                             data);
+  g_object_unref (proxy);
+}
+
 void
 _g_daemon_vfs_get_mount_info_async (GMountSpec *spec,
 				    const char *path,
@@ -917,12 +942,12 @@ _g_daemon_vfs_get_mount_info_async (GMountSpec *spec,
 {
   GMountInfo *info;
   GetMountInfoData *data;
-  DBusMessage *message;
-  DBusMessageIter iter;
 
   data = g_new0 (GetMountInfoData, 1);
   data->callback = callback;
   data->user_data = user_data;
+  data->spec = g_mount_spec_ref (spec);
+  data->path = g_strdup (path);
 
   info = lookup_mount_info_in_cache (spec, path);
 
@@ -933,70 +958,44 @@ _g_daemon_vfs_get_mount_info_async (GMountSpec *spec,
       return;
     }
 
-  message =
-    dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-				  G_VFS_DBUS_MOUNTTRACKER_PATH,
-				  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				  G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT);
-  dbus_message_set_auto_start (message, TRUE);
-  
-  dbus_message_iter_init_append (message, &iter);
-  g_mount_spec_to_dbus_with_path (&iter, spec, path);
-
-  
-  _g_dbus_connection_call_async (the_vfs->async_bus, message, G_VFS_DBUS_TIMEOUT_MSECS,
-				 async_get_mount_info_response,
-				 data);
-  
-  dbus_message_unref (message);
+  gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                             G_DBUS_PROXY_FLAGS_NONE,
+                                             G_VFS_DBUS_DAEMON_NAME,
+                                             G_VFS_DBUS_MOUNTTRACKER_PATH,
+                                             NULL,
+                                             get_mount_info_async_got_proxy_cb,
+                                             data);
 }
 
-
 GMountInfo *
 _g_daemon_vfs_get_mount_info_sync (GMountSpec *spec,
 				   const char *path,
+				   GCancellable *cancellable,
 				   GError **error)
 {
   GMountInfo *info;
-  DBusConnection *conn;
-  DBusMessage *message, *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-	
+  GVfsDBusMountTracker *proxy;
+  GVariant *iter_mount;
+  
   info = lookup_mount_info_in_cache (spec, path);
-
   if (info != NULL)
     return info;
   
-  conn = _g_dbus_connection_get_sync (NULL, error);
-  if (conn == NULL)
-    return NULL;
-
-  message =
-    dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-				  G_VFS_DBUS_MOUNTTRACKER_PATH,
-				  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				  G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT);
-  dbus_message_set_auto_start (message, TRUE);
+  proxy = create_mount_tracker_proxy ();
+  g_return_val_if_fail (proxy != NULL, NULL);
   
-  dbus_message_iter_init_append (message, &iter);
-  g_mount_spec_to_dbus_with_path (&iter, spec, path);
-
-  dbus_error_init (&derror);
-  reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
-  dbus_message_unref (message);
-
-  if (!reply)
+  if (gvfs_dbus_mount_tracker_call_lookup_mount_sync (proxy,
+                                                      g_mount_spec_to_dbus_with_path (spec, path),
+                                                      &iter_mount,
+                                                      cancellable,
+                                                      error))
     {
-      _g_error_from_dbus (&derror, error);
-      dbus_error_free (&derror);
-      return NULL;
+      info = handler_lookup_mount_reply (iter_mount, error);
+      g_variant_unref (iter_mount);
     }
-
-  info = handler_lookup_mount_reply (reply, error);
-
-  dbus_message_unref (reply);
   
+  g_object_unref (proxy);
+
   return info;
 }
 
@@ -1005,43 +1004,28 @@ _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path,
 					   char **mount_path)
 {
   GMountInfo *info;
-  DBusConnection *conn;
-  DBusMessage *message, *reply;
-  DBusMessageIter iter;
-  DBusError derror;
   int len;
   const char *mount_path_end;
-	
+  GVfsDBusMountTracker *proxy;
+  GVariant *iter_mount;
+
   info = lookup_mount_info_by_fuse_path_in_cache (fuse_path,
 						  mount_path);
   if (info != NULL)
     return info;
   
-  conn = _g_dbus_connection_get_sync (NULL, NULL);
-  if (conn == NULL)
-    return NULL;
-
-  message =
-    dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-				  G_VFS_DBUS_MOUNTTRACKER_PATH,
-				  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				  G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH);
-  dbus_message_set_auto_start (message, TRUE);
+  proxy = create_mount_tracker_proxy ();
+  g_return_val_if_fail (proxy != NULL, NULL);
   
-  dbus_message_iter_init_append (message, &iter);
-  _g_dbus_message_iter_append_cstring (&iter, fuse_path);
-
-  dbus_error_init (&derror);
-  reply = dbus_connection_send_with_reply_and_block (conn, message, -1, &derror);
-  dbus_message_unref (message);
-  if (!reply)
+  if (gvfs_dbus_mount_tracker_call_lookup_mount_by_fuse_path_sync (proxy,
+                                                                   fuse_path,
+                                                                   &iter_mount,
+                                                                   NULL,
+                                                                   NULL))
     {
-      dbus_error_free (&derror);
-      return NULL;
+      info = handler_lookup_mount_reply (iter_mount, NULL);
+      g_variant_unref (iter_mount);
     }
-
-  info = handler_lookup_mount_reply (reply, NULL);
-  dbus_message_unref (reply);
   
   if (info)
     {
@@ -1065,7 +1049,8 @@ _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path,
 	}
     }
 
-  
+  g_object_unref (proxy);
+
   return info;
 }
 
@@ -1173,44 +1158,6 @@ g_daemon_vfs_add_writable_namespaces (GVfs       *vfs,
 				  G_FILE_ATTRIBUTE_INFO_COPY_WHEN_MOVED);
 }
 
-/* Sends a message on the session bus and blocks for the reply,
-   using the thread local connection */
-gboolean
-_g_daemon_vfs_send_message_sync (DBusMessage *message,
-				 GCancellable *cancellable,
-				 GError **error)
-{
-  DBusConnection *connection;
-  DBusError derror;
-  DBusMessage *reply;
-
-  connection = _g_dbus_connection_get_sync (NULL, NULL);
-  if (connection == NULL)
-    {
-      g_set_error (error, G_IO_ERROR,
-		   G_IO_ERROR_FAILED,
-		   _("Error setting file metadata: %s"),
-		   _("Can't contact session bus"));
-      return FALSE;
-    }
-
-  dbus_error_init (&derror);
-  /* TODO: Handle cancellable */
-  reply = dbus_connection_send_with_reply_and_block (connection, message,
-						     G_VFS_DBUS_TIMEOUT_MSECS,
-						     &derror);
-  if (!reply)
-    {
-      _g_error_from_dbus (&derror, error);
-      dbus_error_free (&derror);
-      return FALSE;
-    }
-
-  dbus_message_unref (reply);
-
-  return TRUE;
-}
-
 static gboolean
 strv_equal (char **a, char **b)
 {
@@ -1529,7 +1476,7 @@ g_daemon_vfs_local_file_moved (GVfs       *vfs,
   meta_lookup_cache_free (cache);
 }
 
-DBusConnection *
+GDBusConnection *
 _g_daemon_vfs_get_async_bus (void)
 {
   return the_vfs->async_bus;
diff --git a/client/gdaemonvfs.h b/client/gdaemonvfs.h
index e656a1c..c5ecefc 100644
--- a/client/gdaemonvfs.h
+++ b/client/gdaemonvfs.h
@@ -24,7 +24,6 @@
 #define __G_DAEMON_VFS_H__
 
 #include <gio/gio.h>
-#include <dbus/dbus.h>
 #include "gmountspec.h"
 #include "gmounttracker.h"
 #include "gvfsuriutils.h"
@@ -61,6 +60,7 @@ void            _g_daemon_vfs_get_mount_info_async     (GMountSpec
 							gpointer                  user_data);
 GMountInfo *    _g_daemon_vfs_get_mount_info_sync      (GMountSpec               *spec,
 							const char               *path,
+							GCancellable             *cancellable,
 							GError                  **error);
 GMountInfo *    _g_daemon_vfs_get_mount_info_by_fuse_sync (const char *fuse_path,
 							   char **mount_path);
@@ -68,10 +68,7 @@ GMountSpec *    _g_daemon_vfs_get_mount_spec_for_path  (GMountSpec
 						        const char               *path,
 						        const char               *new_path);
 void            _g_daemon_vfs_invalidate_dbus_id       (const char               *dbus_id);
-DBusConnection *_g_daemon_vfs_get_async_bus            (void);
-gboolean        _g_daemon_vfs_send_message_sync        (DBusMessage              *message,
-							GCancellable             *cancellable,
-							GError                  **error);
+GDBusConnection *_g_daemon_vfs_get_async_bus           (void);
 int             _g_daemon_vfs_append_metadata_for_set  (GVariantBuilder *builder,
 							MetaTree *tree,
 							const char *path,
diff --git a/client/gvfsdaemondbus.c b/client/gvfsdaemondbus.c
index e8f59e2..670827a 100644
--- a/client/gvfsdaemondbus.c
+++ b/client/gvfsdaemondbus.c
@@ -38,6 +38,7 @@
 #include <gdaemonvfs.h>
 #include "gvfsdbusutils.h"
 #include "gsysutils.h"
+#include <gvfsdbus.h>
 
 /* Extra vfs-specific data for DBusConnections */
 typedef struct {
@@ -50,9 +51,6 @@ typedef struct {
   GSource *extra_fd_source;
 } VfsConnectionData;
 
-static gint32 vfs_data_slot = -1;
-static GOnce once_init_dbus = G_ONCE_INIT;
-
 typedef struct _ThreadLocalConnections ThreadLocalConnections;
 static void free_local_connections (ThreadLocalConnections *local);
 
@@ -66,10 +64,6 @@ G_LOCK_DEFINE_STATIC(async_map);
 static GHashTable *obj_path_map = NULL;
 G_LOCK_DEFINE_STATIC(obj_path_map);
 
-static void setup_async_fd_receive (VfsConnectionData *connection_data);
-static void invalidate_local_connection (const char *dbus_id,
-					 GError **error);
-  
 
 GQuark
 _g_vfs_error_quark (void)
@@ -77,42 +71,55 @@ _g_vfs_error_quark (void)
   return g_quark_from_static_string ("g-vfs-error-quark");
 }
 
-static gpointer
-vfs_dbus_init (gpointer arg)
-{
-  if (!dbus_connection_allocate_data_slot (&vfs_data_slot))
-    g_error ("Unable to allocate data slot");
-
-  return NULL;
-}
-
 /**************************************************************************
  *               message filters for vfs dbus connections                 *
  *************************************************************************/
 
 typedef struct {
-  DBusHandleMessageFunction callback;
+  GVfsRegisterVfsFilterCallback callback;
   GObject *data;
+  GHashTable *skeletons;
 } PathMapEntry;
 
+static void
+free_path_map_entry (PathMapEntry *entry)
+{
+  g_hash_table_destroy (entry->skeletons);
+  g_free (entry);
+}
+
+static void
+unref_skeleton (gpointer object)
+{
+  GDBusInterfaceSkeleton *skeleton = object;
+
+  g_print ("unref_skeleton: unreffing skeleton %p\n", skeleton);
+  g_dbus_interface_skeleton_unexport (skeleton);
+  g_object_unref (skeleton);
+}
+
+/*  Please note the obj_path has to be unique even for different interfaces  */
 void
 _g_dbus_register_vfs_filter (const char *obj_path,
-			     DBusHandleMessageFunction callback,
+                             GVfsRegisterVfsFilterCallback callback,
 			     GObject *data)
 {
-  PathMapEntry * entry;
+  PathMapEntry *entry;
   
+  g_print ("_g_dbus_register_vfs_filter: obj_path = '%s'\n", obj_path);
+
   G_LOCK (obj_path_map);
   
   if (obj_path_map == NULL)
     obj_path_map = g_hash_table_new_full (g_str_hash, g_str_equal,
-					  g_free, g_free);
+					  g_free, (GDestroyNotify)free_path_map_entry);
 
-  entry = g_new (PathMapEntry,1 );
+  entry = g_new (PathMapEntry, 1);
   entry->callback = callback;
   entry->data = data;
+  entry->skeletons = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify)unref_skeleton);
 
-  g_hash_table_insert  (obj_path_map, g_strdup (obj_path), entry);
+  g_hash_table_insert (obj_path_map, g_strdup (obj_path), entry);
   
   G_UNLOCK (obj_path_map);
 }
@@ -121,68 +128,58 @@ void
 _g_dbus_unregister_vfs_filter (const char *obj_path)
 {
   G_LOCK (obj_path_map);
-  
+
   if (obj_path_map)
       g_hash_table_remove (obj_path_map, obj_path);
   
   G_UNLOCK (obj_path_map);
 }
 
-static DBusHandlerResult
-vfs_connection_filter (DBusConnection     *connection,
-		       DBusMessage        *message,
-		       void               *user_data)
+static void
+register_skeleton (const char *obj_path,
+                   PathMapEntry *entry,
+                   GDBusConnection *dbus_conn)
 {
-  PathMapEntry *entry;
-  DBusHandlerResult res;
-  DBusHandleMessageFunction callback;
-  GObject *data;
-  VfsConnectionData *connection_data;
-  const char *path;
+  GDBusInterfaceSkeleton *skeleton;
 
-  callback = NULL;
-  data = NULL;
-
-  if (dbus_message_is_signal (message,
-			      DBUS_INTERFACE_LOCAL,
-			      "Disconnected"))
+  if (! g_hash_table_contains (entry->skeletons, dbus_conn))
     {
-      connection_data = dbus_connection_get_data (connection, vfs_data_slot);
-      if (connection_data->async_dbus_id)
-	{
-	  _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id);
-	  G_LOCK (async_map);
-	  g_hash_table_remove (async_map, connection_data->async_dbus_id);
-	  G_UNLOCK (async_map);
-	}
+      /* Note that the newly created GDBusInterfaceSkeleton instance refs the connection so it's not needed to watch for connection being destroyed */ 
+      skeleton = entry->callback (dbus_conn, obj_path, entry->data);
+      g_print ("registering interface skeleton %p for path '%s' on the %p connection\n", skeleton, obj_path, dbus_conn);
       
-      return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+      g_hash_table_insert (entry->skeletons, dbus_conn, skeleton);
     }
-  
-  path = dbus_message_get_path (message);
-  G_LOCK (obj_path_map);
-  if (obj_path_map && path)
+  else
     {
-      entry = g_hash_table_lookup (obj_path_map,
-				   path);
-      
-      if (entry)
-	{
-	  callback = entry->callback;
-	  data = g_object_ref (entry->data);
-	}
+      g_print ("interface skeleton '%s' already registered on the %p connection, skipping\n", obj_path, dbus_conn);
     }
-  G_UNLOCK (obj_path_map);
+}
 
-  res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+/*
+ *  Export registered interface skeletons on this connection. This should ideally
+ *  be called only once for every connection, but we often share/reuse existing
+ *  connections.
+ *  
+ *  Already exported interface skeletons should live as long as possible
+ *  since there might be ongoing data transfer and re-exporting (unreffing + creation)
+ *  breaks running jobs randomly.
+ *  
+ */
+void
+_g_dbus_connect_vfs_filters (GDBusConnection *connection)
+{
+  g_print ("_g_dbus_connect_vfs_filters: connection = %p\n", connection);
+  
+  G_LOCK (obj_path_map);
 
-  if (callback)
+  if (obj_path_map)
     {
-      res = callback (connection, message, data);
-      g_object_unref (data);
+      /* Export new interface skeletons */
+      g_hash_table_foreach (obj_path_map, (GHFunc) register_skeleton, connection);
     }
 
-  return res;
+  G_UNLOCK (obj_path_map);
 }
 
 static void
@@ -208,164 +205,43 @@ connection_data_free (gpointer p)
 }
 
 static void
-vfs_connection_setup (DBusConnection *connection,
-		      int extra_fd,
-		      gboolean async)
+vfs_connection_closed (GDBusConnection *connection,
+                       gboolean remote_peer_vanished,
+                       GError *error,
+                       gpointer user_data)
 {
   VfsConnectionData *connection_data;
 
-  connection_data = g_new0 (VfsConnectionData, 1);
-  connection_data->extra_fd = extra_fd;
-  connection_data->extra_fd_count = 0;
-
-  if (async)
-    setup_async_fd_receive (connection_data);
+  g_print ("gvfsdaemondbus.c: vfs_connection_closed()\n");
   
-  if (!dbus_connection_set_data (connection, vfs_data_slot, connection_data, connection_data_free))
-    _g_dbus_oom ();
+  connection_data = g_object_get_data (G_OBJECT (connection), "connection_data");
+  g_assert (connection_data != NULL);
 
-  if (!dbus_connection_add_filter (connection, vfs_connection_filter, NULL, NULL))
-    _g_dbus_oom ();
-}
+  g_print ("   async_dbus_id = '%s'\n", connection_data->async_dbus_id);
 
-/**************************************************************************
- *            Functions to get fds from vfs dbus connections              *
- *************************************************************************/
-
-typedef struct {
-  int fd;
-  GetFdAsyncCallback callback;
-  gpointer callback_data;
-} OutstandingFD;
-
-static void
-outstanding_fd_free (OutstandingFD *outstanding)
-{
-  if (outstanding->fd != -1)
-    close (outstanding->fd);
-
-  g_free (outstanding);
-}
-
-static gboolean
-async_connection_accept_new_fd (VfsConnectionData *data,
-				GIOCondition condition,
-				int fd)
-{
-  int new_fd;
-  int fd_id;
-  OutstandingFD *outstanding_fd;
-
-  if (condition & G_IO_HUP)
+  if (connection_data->async_dbus_id)
     {
-      close (data->extra_fd);
-      data->extra_fd = -1;
-      g_source_destroy (data->extra_fd_source);
-      g_source_unref (data->extra_fd_source);
-      data->extra_fd_source = NULL;
-      return FALSE;
-    }
-  
-  fd_id = data->extra_fd_count;
-  new_fd = _g_socket_receive_fd (data->extra_fd);
-  if (new_fd != -1)
-    {
-      data->extra_fd_count++;
-
-      outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id));
-      
-      if (outstanding_fd)
-	{
-	  outstanding_fd->callback (new_fd, outstanding_fd->callback_data);
-	  g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id));
-	}
-      else
-	{
-	  outstanding_fd = g_new0 (OutstandingFD, 1);
-	  outstanding_fd->fd = new_fd;
-	  outstanding_fd->callback = NULL;
-	  outstanding_fd->callback_data = NULL;
-	  g_hash_table_insert (data->outstanding_fds,
-			       GINT_TO_POINTER (fd_id),
-			       outstanding_fd);
-	}
+      _g_daemon_vfs_invalidate_dbus_id (connection_data->async_dbus_id);
+      G_LOCK (async_map);
+      g_hash_table_remove (async_map, connection_data->async_dbus_id);
+      G_UNLOCK (async_map);
     }
-
-  return TRUE;
 }
 
 static void
-setup_async_fd_receive (VfsConnectionData *connection_data)
-{
-  connection_data->outstanding_fds =
-    g_hash_table_new_full (g_direct_hash,
-			   g_direct_equal,
-			   NULL,
-			   (GDestroyNotify)outstanding_fd_free);
-  
-  
-  connection_data->extra_fd_source =
-    __g_fd_source_new (connection_data->extra_fd, G_IO_IN|G_IO_ERR, NULL);
-  g_source_set_callback (connection_data->extra_fd_source,
-			 (GSourceFunc)async_connection_accept_new_fd,
-			 connection_data, NULL);
-  g_source_attach (connection_data->extra_fd_source, NULL);
-}
-
-int
-_g_dbus_connection_get_fd_sync (DBusConnection *connection,
-				int fd_id)
+vfs_connection_setup (GDBusConnection *connection,
+		      int extra_fd,
+		      gboolean async)
 {
-  VfsConnectionData *data;
-  int fd;
-
-  data = dbus_connection_get_data (connection, vfs_data_slot);
-  g_assert (data != NULL);
-
-  /* I don't think we can get reorders here, can we?
-   * Its a sync per-thread connection after all
-   */
-  g_assert (fd_id == data->extra_fd_count);
-  
-  fd = _g_socket_receive_fd (data->extra_fd);
-  if (fd != -1)
-    data->extra_fd_count++;
-
-  return fd;
-}
+  VfsConnectionData *connection_data;
 
-void
-_g_dbus_connection_get_fd_async (DBusConnection *connection,
-				 int fd_id,
-				 GetFdAsyncCallback callback,
-				 gpointer callback_data)
-{
-  VfsConnectionData *data;
-  OutstandingFD *outstanding_fd;
-  int fd;
+  connection_data = g_new0 (VfsConnectionData, 1);
+  connection_data->extra_fd = extra_fd;
+  connection_data->extra_fd_count = 0;
   
-  data = dbus_connection_get_data (connection, vfs_data_slot);
-  g_assert (data != NULL);
-
-  outstanding_fd = g_hash_table_lookup (data->outstanding_fds, GINT_TO_POINTER (fd_id));
+  g_object_set_data_full (G_OBJECT (connection), "connection_data", connection_data, connection_data_free);
 
-  if (outstanding_fd)
-    {
-      fd = outstanding_fd->fd;
-      outstanding_fd->fd = -1;
-      g_hash_table_remove (data->outstanding_fds, GINT_TO_POINTER (fd_id));
-      callback (fd, callback_data);
-    }
-  else
-    {
-      outstanding_fd = g_new0 (OutstandingFD, 1);
-      outstanding_fd->fd = -1;
-      outstanding_fd->callback = callback;
-      outstanding_fd->callback_data = callback_data;
-      g_hash_table_insert (data->outstanding_fds,
-			   GINT_TO_POINTER (fd_id),
-			   outstanding_fd);
-    }
+  g_signal_connect (connection, "closed", G_CALLBACK (vfs_connection_closed), NULL);
 }
 
 /*******************************************************************
@@ -373,17 +249,17 @@ _g_dbus_connection_get_fd_async (DBusConnection *connection,
  *******************************************************************/
 
 
-static DBusConnection *
+static GDBusConnection *
 get_connection_for_async (const char *dbus_id)
 {
-  DBusConnection *connection;
+  GDBusConnection *connection;
 
   connection = NULL;
   G_LOCK (async_map);
   if (async_map != NULL)
     connection = g_hash_table_lookup (async_map, dbus_id);
   if (connection)
-    dbus_connection_ref (connection);
+    g_object_ref (connection);
   G_UNLOCK (async_map);
   
   return connection;
@@ -392,26 +268,31 @@ get_connection_for_async (const char *dbus_id)
 static void
 close_and_unref_connection (void *data)
 {
-  DBusConnection *connection = data;
+  GDBusConnection *connection = data;
+  
+  g_print ("close_and_unref_connection: closing connection\n");
   
-  dbus_connection_close (connection);
-  dbus_connection_unref (connection);
+  /* TODO: watch for the need to manually call g_dbus_connection_close_sync () */
+  g_object_unref (connection);
 }
 
 static void
-set_connection_for_async (DBusConnection *connection, const char *dbus_id)
+set_connection_for_async (GDBusConnection *connection, const char *dbus_id)
 {
   VfsConnectionData *data;
   
+  g_print ("set_connection_for_async: connection = %p, dbus_id = '%s'\n", connection, dbus_id);
+  
   G_LOCK (async_map);
-  data = dbus_connection_get_data (connection, vfs_data_slot);
+  data = g_object_get_data (G_OBJECT (connection), "connection_data");
+  g_assert (data != NULL);
   data->async_dbus_id = g_strdup (dbus_id);
 
   if (async_map == NULL)
     async_map = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, close_and_unref_connection);
       
   g_hash_table_insert (async_map, g_strdup (dbus_id), connection);
-  dbus_connection_ref (connection);
+  g_object_ref (connection);
   G_UNLOCK (async_map);
 }
 
@@ -422,8 +303,8 @@ set_connection_for_async (DBusConnection *connection, const char *dbus_id)
 typedef struct {
   const char *dbus_id;
 
-  DBusMessage *message;
-  DBusConnection *connection;
+  GDBusConnection *connection;
+  int extra_fd;
   GCancellable *cancellable;
 
   GVfsAsyncDBusCallback callback;
@@ -434,17 +315,15 @@ typedef struct {
 } AsyncDBusCall;
 
 static void
-async_call_finish (AsyncDBusCall *async_call,
-		   DBusMessage *reply)
+async_call_finish (AsyncDBusCall *async_call)
 {
   if (async_call->callback)
-    async_call->callback (reply, async_call->connection,
+    async_call->callback (async_call->io_error ? NULL : async_call->connection,
 			  async_call->io_error, 
 			  async_call->callback_data);
 
   if (async_call->connection)
-    dbus_connection_unref (async_call->connection);
-  dbus_message_unref (async_call->message);
+    g_object_unref (async_call->connection);
   if (async_call->cancellable)
     g_object_unref (async_call->cancellable);
   if (async_call->io_error)
@@ -453,148 +332,26 @@ async_call_finish (AsyncDBusCall *async_call,
 }
 
 static void
-async_dbus_response (DBusMessage *reply,
-		     GError *error,
-		     gpointer data)
+async_got_private_connection_cb (GObject *source_object,
+                                 GAsyncResult *res,
+                                 gpointer user_data)
 {
-  AsyncDBusCall *async_call = data;
-
-  if (async_call->cancelled_tag)
-    g_signal_handler_disconnect (async_call->cancellable,
-				 async_call->cancelled_tag);
-
-  if (reply == NULL)
-    async_call->io_error = g_error_copy (error);
+  AsyncDBusCall *async_call = user_data;
+  GDBusConnection *connection, *existing_connection;
+  GError *error = NULL;
   
-  async_call_finish (async_call, reply);
-}
-
-typedef struct {
-  DBusConnection *connection;
-  dbus_uint32_t serial;
-} AsyncCallCancelData;
-
-static void
-async_call_cancel_data_free (gpointer _data)
-{
-  AsyncCallCancelData *data = _data;
-
-  dbus_connection_unref (data->connection);
-  g_free (data);
-}
-
-/* Might be called on another thread */
-static void
-async_call_cancelled_cb (GCancellable *cancellable,
-			 gpointer _data)
-{
-  AsyncCallCancelData *data = _data;
-  DBusMessage *cancel_message;
-
-  /* Send cancellation message, this just queues it, sending
-   * will happen in mainloop */
-  cancel_message = dbus_message_new_method_call (NULL,
-						 G_VFS_DBUS_DAEMON_PATH,
-						 G_VFS_DBUS_DAEMON_INTERFACE,
-						 G_VFS_DBUS_OP_CANCEL);
-  if (cancel_message != NULL)
-    {
-      if (dbus_message_append_args (cancel_message,
-				    DBUS_TYPE_UINT32, &data->serial,
-				    DBUS_TYPE_INVALID))
-	dbus_connection_send (data->connection,
-			      cancel_message, NULL);
-      dbus_message_unref (cancel_message);
-    }
-}
-
-static void
-async_call_send (AsyncDBusCall *async_call)
-{
-  AsyncCallCancelData *cancel_data;
-
-  _g_dbus_connection_call_async (async_call->connection,
-				 async_call->message,
-				 G_VFS_DBUS_TIMEOUT_MSECS,
-				 async_dbus_response,
-				 async_call);
-
-  if (async_call->cancellable)
-    {
-      cancel_data = g_new0 (AsyncCallCancelData, 1);
-      cancel_data->connection = dbus_connection_ref (async_call->connection);
-      /* make sure we get the serial *after* the message has been sent, otherwise
-       * it will be 0
-       */
-      cancel_data->serial = dbus_message_get_serial (async_call->message);
-      async_call->cancelled_tag =
-	g_signal_connect_data (async_call->cancellable, "cancelled",
-			       (GCallback)async_call_cancelled_cb,
-			       cancel_data,
-			       (GClosureNotify)async_call_cancel_data_free,
-			       0);
-    }
-}
-
-static void
-async_get_connection_response (DBusMessage *reply,
-			       GError *error,
-			       void *data)
-{
-  AsyncDBusCall *async_call = data;
-  DBusError derror;
-  char *address1, *address2;
-  int extra_fd;
-  DBusConnection *connection, *existing_connection;
-
-  if (reply == NULL)
+  connection = g_dbus_connection_new_for_address_finish (res, &error);
+  g_print ("async_got_private_connection_cb, connection = %p\n", connection);
+  if (!connection)
     {
+      close (async_call->extra_fd);
       async_call->io_error = g_error_copy (error);
-      async_call_finish (async_call, NULL);
-      return;
-    }
-  
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (reply, &derror,
-			      DBUS_TYPE_STRING, &address1,
-			      DBUS_TYPE_STRING, &address2,
-			      DBUS_TYPE_INVALID))
-    {
-      _g_error_from_dbus (&derror, &async_call->io_error);
-      dbus_error_free (&derror);
-      async_call_finish (async_call, NULL);
-      return;
-    }
-
-  /* I don't know of any way to do an async connect */
-  error = NULL;
-  extra_fd = _g_socket_connect (address2, &error);
-  if (extra_fd == -1)
-    {
-      g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
-		   _("Error connecting to daemon: %s"), error->message);
       g_error_free (error);
-      async_call_finish (async_call, NULL);
+      async_call_finish (async_call);
       return;
     }
 
-  /* Unfortunately dbus doesn't have an async open */
-  dbus_error_init (&derror);
-  connection = dbus_connection_open_private (address1, &derror);
-  if (!connection)
-    {
-      close (extra_fd);
-      dbus_message_unref (reply);
-      
-      g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
-		   "Error while getting peer-to-peer dbus connection: %s",
-		   derror.message);
-      dbus_error_free (&derror);
-      async_call_finish (async_call, NULL);
-      return;
-    }
-
-  vfs_connection_setup (connection, extra_fd, TRUE);
+  vfs_connection_setup (connection, async_call->extra_fd, TRUE);
   
   /* Maybe we already had a connection? This happens if we requested
    * the same owner several times in parallel.
@@ -605,12 +362,11 @@ async_get_connection_response (DBusMessage *reply,
   if (existing_connection != NULL)
     {
       async_call->connection = existing_connection;
-      dbus_connection_close (connection);
-      dbus_connection_unref (connection);
+      /* TODO: watch for the need to manually call g_dbus_connection_close_sync () */
+      g_object_unref (connection);
     }
   else
     {  
-      _g_dbus_connection_integrate_with_main (connection);
       set_connection_for_async (connection, async_call->dbus_id);
       async_call->connection = connection;
     }
@@ -619,49 +375,109 @@ async_get_connection_response (DBusMessage *reply,
    * avoid doing the operation */
   if (g_cancellable_set_error_if_cancelled (async_call->cancellable, &async_call->io_error))
     {
-      async_call_finish (async_call, NULL);
+      async_call_finish (async_call);
       return;
     }
 
-  async_call_send (async_call);
+  async_call_finish (async_call);
 }
 
 static void
-open_connection_async (AsyncDBusCall *async_call)
+async_get_connection_response (GVfsDBusDaemon *proxy,
+                               GAsyncResult *res,
+                               gpointer user_data)
 {
-  DBusMessage *get_connection_message;
+  AsyncDBusCall *async_call = user_data;
+  GError *error = NULL;
+  gchar *address1, *address2;
 
-  get_connection_message = dbus_message_new_method_call (async_call->dbus_id,
-							 G_VFS_DBUS_DAEMON_PATH,
-							 G_VFS_DBUS_DAEMON_INTERFACE,
-							 G_VFS_DBUS_OP_GET_CONNECTION);
-  
-  if (get_connection_message == NULL)
-    _g_dbus_oom ();
+  g_print ("async_get_connection_response\n");
 
+  if (! gvfs_dbus_daemon_call_get_connection_finish (proxy,
+                                                     &address1, &address2,
+                                                     res,
+                                                     &error))
+    {
+      async_call->io_error = g_error_copy (error);
+      g_error_free (error);
+      async_call_finish (async_call);
+      return;
+    }
+  
+  /* I don't know of any way to do an async connect */
+  error = NULL;
+  async_call->extra_fd = _g_socket_connect (address2, &error);
+  if (async_call->extra_fd == -1)
+    {
+      g_set_error (&async_call->io_error, G_IO_ERROR, G_IO_ERROR_FAILED,
+		   _("Error connecting to daemon: %s"), error->message);
+      g_error_free (error);
+      async_call_finish (async_call);
+      return;
+    }
+  
+  g_dbus_connection_new_for_address (address1,
+                                     G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+                                     NULL, /* GDBusAuthObserver */
+                                     async_call->cancellable,
+                                     async_got_private_connection_cb,
+                                     async_call);
+}
 
-  _g_dbus_connection_call_async (_g_daemon_vfs_get_async_bus (),
-				 get_connection_message,
-				 G_VFS_DBUS_TIMEOUT_MSECS,
-				 async_get_connection_response,
-				 async_call);
+static void
+open_connection_async_cb (GObject *source_object,
+                          GAsyncResult *res,
+                          gpointer user_data)
+{
+  GVfsDBusDaemon *proxy;
+  AsyncDBusCall *async_call = user_data;
+  GError *error = NULL;
+ 
+  proxy = gvfs_dbus_daemon_proxy_new_finish (res, &error);
+  g_print ("open_connection_async_cb, proxy = %p\n", proxy);
+  
+  if (proxy == NULL)
+    {
+      async_call->io_error = g_error_copy (error);
+      g_error_free (error);
+      async_call_finish (async_call);
+      return;
+    }
+  
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), G_VFS_DBUS_TIMEOUT_MSECS);
   
-  dbus_message_unref (get_connection_message);
+  gvfs_dbus_daemon_call_get_connection (proxy,
+                                        async_call->cancellable,
+                                        (GAsyncReadyCallback) async_get_connection_response,
+                                        async_call);
+  
+  g_object_unref (proxy);
+}
+
+static void
+open_connection_async (AsyncDBusCall *async_call)
+{
+  gvfs_dbus_daemon_proxy_new (_g_daemon_vfs_get_async_bus (),
+                              G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                              async_call->dbus_id,
+                              G_VFS_DBUS_DAEMON_PATH,
+                              async_call->cancellable,
+                              open_connection_async_cb,
+                              async_call);
 }
 
 void
-_g_vfs_daemon_call_async (DBusMessage *message,
-			  GVfsAsyncDBusCallback callback,
-			  gpointer callback_data,
-			  GCancellable *cancellable)
+_g_dbus_connection_get_for_async (const char *dbus_id,
+                                  GVfsAsyncDBusCallback callback,
+                                  gpointer callback_data,
+                                  GCancellable *cancellable)
 {
   AsyncDBusCall *async_call;
 
-  g_once (&once_init_dbus, vfs_dbus_init, NULL);
-
+  g_print ("_g_dbus_connection_get_for_async\n");
+  
   async_call = g_new0 (AsyncDBusCall, 1);
-  async_call->dbus_id = dbus_message_get_destination (message);
-  async_call->message = dbus_message_ref (message);
+  async_call->dbus_id = g_strdup (dbus_id);
   if (cancellable)
     async_call->cancellable = g_object_ref (cancellable);
   async_call->callback = callback;
@@ -671,194 +487,10 @@ _g_vfs_daemon_call_async (DBusMessage *message,
   if (async_call->connection == NULL)
     open_connection_async (async_call);
   else
-    async_call_send (async_call);
-}
-
-/**************************************************************************
- *                  Synchronous daemon calls                              *
- *************************************************************************/
-
-DBusMessage *
-_g_vfs_daemon_call_sync (DBusMessage *message,
-			 DBusConnection **connection_out,
-			 const char *callback_obj_path,
-			 DBusObjectPathMessageFunction callback,
-			 gpointer callback_user_data, 
-			 GCancellable *cancellable,
-			 GError **error)
-{
-  DBusConnection *connection;
-  DBusError derror;
-  DBusMessage *reply;
-  DBusPendingCall *pending;
-  int dbus_fd;
-  int cancel_fd;
-  gboolean sent_cancel;
-  DBusMessage *cancel_message;
-  dbus_uint32_t serial;
-  gboolean handle_callbacks;
-  const char *dbus_id = dbus_message_get_destination (message);
-
-  if (g_cancellable_set_error_if_cancelled (cancellable, error))
-    return NULL;
-	    
-  connection = _g_dbus_connection_get_sync (dbus_id, error);
-  if (connection == NULL)
-    return NULL;
-
-  if (g_cancellable_set_error_if_cancelled (cancellable, error))
-    return NULL;
-
-  handle_callbacks = FALSE;
-  if (callback_obj_path != NULL && callback != NULL)
-    {
-      struct DBusObjectPathVTable vtable = { NULL, callback };
-      handle_callbacks = dbus_connection_register_object_path (connection,
-							       callback_obj_path,
-							       &vtable,
-							       callback_user_data);
-    }
-
-  reply = NULL;
-  cancel_fd = g_cancellable_get_fd (cancellable);
-  if (cancel_fd != -1 || handle_callbacks)
-    {
-      if (!dbus_connection_send_with_reply (connection, message,
-					    &pending,
-					    G_VFS_DBUS_TIMEOUT_MSECS))
-	_g_dbus_oom ();
-      
-      if (pending == NULL ||
-	  !dbus_connection_get_is_connected (connection))
-	{
-	  if (pending)
-	    dbus_pending_call_unref (pending);
-	  invalidate_local_connection (dbus_id, error);
-	  goto out;
-	}
-
-      /* Make sure the message is sent */
-      dbus_connection_flush (connection);
-
-      if (!dbus_connection_get_unix_fd (connection, &dbus_fd))
-	{
-	  dbus_pending_call_unref (pending);
-	  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-		       "Error while getting peer-to-peer dbus connection: %s",
-		       "No fd");
-	  goto out;
-	}
-
-      sent_cancel = (cancel_fd == -1);
-      while (!dbus_pending_call_get_completed (pending))
-	{
-	  GPollFD poll_fds[2];
-	  int poll_ret;
-	  
-	  do
-	    {
-	      poll_fds[0].events = G_IO_IN;
-	      poll_fds[0].fd = dbus_fd;
-	      poll_fds[1].events = G_IO_IN;
-	      poll_fds[1].fd = cancel_fd;
-	      poll_ret = g_poll (poll_fds, sent_cancel?1:2, -1);
-	    }
-	  while (poll_ret == -1 && errno == EINTR);
-
-	  if (poll_ret == -1)
-	    {
-	      dbus_pending_call_unref (pending);
-	      g_cancellable_release_fd (cancellable);
-	      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   "Error while getting peer-to-peer dbus connection: %s",
-			   "poll error");
-	      goto out;
-	    }
-
-	  if (poll_fds[0].revents & (G_IO_NVAL |  G_IO_ERR | G_IO_HUP))
-	    {
-	      dbus_pending_call_unref (pending);
-	      g_cancellable_release_fd (cancellable);
-	      invalidate_local_connection (dbus_id, error);
-	      goto out;
-	    }
-	  
-	  if (!sent_cancel && g_cancellable_is_cancelled (cancellable))
-	    {
-	      sent_cancel = TRUE;
-	      serial = dbus_message_get_serial (message);
-	      cancel_message =
-		dbus_message_new_method_call (NULL,
-					      G_VFS_DBUS_DAEMON_PATH,
-					      G_VFS_DBUS_DAEMON_INTERFACE,
-					      G_VFS_DBUS_OP_CANCEL);
-	      if (cancel_message != NULL)
-		{
-		  if (dbus_message_append_args (cancel_message,
-						DBUS_TYPE_UINT32, &serial,
-						DBUS_TYPE_INVALID))
-		    {
-		      dbus_connection_send (connection, cancel_message, NULL);
-		      dbus_connection_flush (connection);
-		    }
-			    
-		  dbus_message_unref (cancel_message);
-		}
-	    }
-
-	  if (poll_fds[0].revents != 0)
-	    {
-	      dbus_connection_read_write (connection,
-					  G_VFS_DBUS_TIMEOUT_MSECS);
-
-	      while (dbus_connection_dispatch (connection) == DBUS_DISPATCH_DATA_REMAINS)
-		;
-	    }
-	}
-
-      reply = dbus_pending_call_steal_reply (pending);
-      dbus_pending_call_unref (pending);
-      g_cancellable_release_fd (cancellable);
-    }
-  else
-    {
-      dbus_error_init (&derror);
-      reply = dbus_connection_send_with_reply_and_block (connection, message,
-							 G_VFS_DBUS_TIMEOUT_MSECS,
-							 &derror);
-      if (!reply)
-	{
-	  if (dbus_error_has_name (&derror, DBUS_ERROR_NO_REPLY) &&
-	      !dbus_connection_get_is_connected (connection))
-	    {
-	      /* The mount for this connection died, we invalidate
-	       * the caches, and then caller needs to retry.
-	       */
-
-	      invalidate_local_connection (dbus_id, error);
-	    }
-	  else
-	    _g_error_from_dbus (&derror, error);
-	  dbus_error_free (&derror);
-	  goto out;
-	}
-    }
-
-  if (connection_out)
-    *connection_out = connection;
-
- out:  
-  
-  if (handle_callbacks)
-    dbus_connection_unregister_object_path (connection, callback_obj_path);
-
-  if (reply != NULL && _g_error_from_message (reply, error))
     {
-      dbus_message_unref (reply);
-      return NULL;
+      g_print ("got connection from cache\n");
+      async_call_finish (async_call);
     }
-  
-  return reply;
 }
 
 /*************************************************************************
@@ -867,22 +499,16 @@ _g_vfs_daemon_call_sync (DBusMessage *message,
 
 struct _ThreadLocalConnections {
   GHashTable *connections;
-  DBusConnection *session_bus;
+  GDBusConnection *session_bus;
 };
 
 static void
-free_mount_connection (DBusConnection *conn)
-{
-  dbus_connection_close (conn);
-  dbus_connection_unref (conn);
-}
-
-static void
 free_local_connections (ThreadLocalConnections *local)
 {
+  g_print ("free_local_connections()\n");
   g_hash_table_destroy (local->connections);
   if (local->session_bus)
-    free_mount_connection (local->session_bus);
+    g_object_unref (local->session_bus);
   g_free (local);
 }
 
@@ -904,27 +530,29 @@ invalidate_local_connection (const char *dbus_id,
 		       "Cache invalid, retry (internally handled)");
 }
 
-DBusConnection *
+GDBusConnection *
 _g_dbus_connection_get_sync (const char *dbus_id,
+                             GCancellable *cancellable,
 			     GError **error)
 {
-  DBusConnection *bus;
+  GDBusConnection *bus;
   ThreadLocalConnections *local;
   GError *local_error;
-  DBusConnection *connection;
-  DBusMessage *message, *reply;
-  DBusError derror;
-  char *address1, *address2;
+  GDBusConnection *connection;
+  gchar *address1, *address2;
   int extra_fd;
+  GVfsDBusDaemon *daemon_proxy;
+  gboolean res;
 
-  g_once (&once_init_dbus, vfs_dbus_init, NULL);
+  if (g_cancellable_set_error_if_cancelled (cancellable, error))
+    return NULL;
 
   local = g_private_get (&local_connections);
   if (local == NULL)
     {
       local = g_new0 (ThreadLocalConnections, 1);
       local->connections = g_hash_table_new_full (g_str_hash, g_str_equal,
-						  g_free, (GDestroyNotify)free_mount_connection);
+						  g_free, (GDestroyNotify)g_object_unref);
       g_private_set (&local_connections, local);
     }
 
@@ -934,11 +562,11 @@ _g_dbus_connection_get_sync (const char *dbus_id,
       
       if (local->session_bus)
 	{
-	  if (dbus_connection_get_is_connected (local->session_bus))
+	  if (! g_dbus_connection_is_closed (local->session_bus))
 	    return local->session_bus;
 
 	  /* Session bus was disconnected, re-connect */
-	  dbus_connection_unref (local->session_bus);
+	  g_object_unref (local->session_bus);
 	  local->session_bus = NULL;
 	}
     }
@@ -949,7 +577,7 @@ _g_dbus_connection_get_sync (const char *dbus_id,
       connection = g_hash_table_lookup (local->connections, dbus_id);
       if (connection != NULL)
 	{
-	  if (!dbus_connection_get_is_connected (connection))
+	  if (g_dbus_connection_is_closed (connection))
 	    {
 	      /* The mount for this connection died, we invalidate
 	       * the caches, and then caller needs to retry.
@@ -963,50 +591,37 @@ _g_dbus_connection_get_sync (const char *dbus_id,
 	}
     }
 
-  dbus_error_init (&derror);
-
   if (local->session_bus == NULL)
     {
-      bus = dbus_bus_get_private (DBUS_BUS_SESSION, &derror);
+      bus = g_bus_get_sync (G_BUS_TYPE_SESSION, cancellable, error);
       if (bus == NULL)
-	{
-	  g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-		       "Couldn't get main dbus connection: %s",
-		       derror.message);
-	  dbus_error_free (&derror);
-	  return NULL;
-	}
+        return NULL;
       
       local->session_bus = bus;
 
       if (dbus_id == NULL)
 	return bus; /* We actually wanted the session bus, so done */
     }
-  
-  message = dbus_message_new_method_call (dbus_id,
-					  G_VFS_DBUS_DAEMON_PATH,
-					  G_VFS_DBUS_DAEMON_INTERFACE,
-					  G_VFS_DBUS_OP_GET_CONNECTION);
-  reply = dbus_connection_send_with_reply_and_block (local->session_bus, message, -1,
-						     &derror);
-  dbus_message_unref (message);
-
-  if (!reply)
-    {
-      g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-		   "Error while getting peer-to-peer dbus connection: %s",
-		   derror.message);
-      dbus_error_free (&derror);
-      return NULL;
-    }
 
-  if (_g_error_from_message (reply, error))
+  address1 = address2 = NULL;
+  daemon_proxy = gvfs_dbus_daemon_proxy_new_sync (local->session_bus,
+                                                  G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                                  dbus_id,
+                                                  G_VFS_DBUS_DAEMON_PATH,
+                                                  cancellable,
+                                                  error);
+  if (daemon_proxy == NULL)
+    return NULL;
+
+  res = gvfs_dbus_daemon_call_get_connection_sync (daemon_proxy,
+                                                   &address1,
+                                                   &address2,
+                                                   cancellable,
+                                                   error);
+  g_object_unref (daemon_proxy);
+
+  if (!res)
     return NULL;
-  
-  dbus_message_get_args (reply, NULL,
-			 DBUS_TYPE_STRING, &address1,
-			 DBUS_TYPE_STRING, &address2,
-			 DBUS_TYPE_INVALID);
 
   local_error = NULL;
   extra_fd = _g_socket_connect (address2, &local_error);
@@ -1015,23 +630,27 @@ _g_dbus_connection_get_sync (const char *dbus_id,
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 		   _("Error connecting to daemon: %s"), local_error->message);
       g_error_free (local_error);
-      dbus_message_unref (reply);
+      g_free (address1);
+      g_free (address2);
       return NULL;
     }
 
-  dbus_error_init (&derror);
-  connection = dbus_connection_open_private (address1, &derror);
+  connection = g_dbus_connection_new_for_address_sync (address1,
+                                                       G_DBUS_CONNECTION_FLAGS_AUTHENTICATION_CLIENT,
+                                                       NULL, /* GDBusAuthObserver */
+                                                       cancellable,
+                                                       &local_error);
   if (!connection)
     {
       g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 		   "Error while getting peer-to-peer dbus connection: %s",
-		   derror.message);
+		   local_error->message);
       close (extra_fd);
-      dbus_message_unref (reply);
-      dbus_error_free (&derror);
+      g_error_free (local_error);
+      g_free (address1);
+      g_free (address2);
       return NULL;
     }
-  dbus_message_unref (reply);
 
   vfs_connection_setup (connection, extra_fd, FALSE);
 
diff --git a/client/gvfsdaemondbus.h b/client/gvfsdaemondbus.h
index 3683eaf..d1cd666 100644
--- a/client/gvfsdaemondbus.h
+++ b/client/gvfsdaemondbus.h
@@ -24,7 +24,6 @@
 #define __G_VFS_DAEMON_DBUS_H__
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <gio/gio.h>
 
 G_BEGIN_DECLS
@@ -39,42 +38,28 @@ typedef enum
 } GVfsError;
 
 
-typedef void (*GVfsAsyncDBusCallback) (DBusMessage *reply,
-				       DBusConnection *connection,
+typedef void (*GVfsAsyncDBusCallback) (GDBusConnection *connection,
 				       GError *io_error,
 				       gpointer callback_data);
 typedef void (*GetFdAsyncCallback)    (int fd,
 				       gpointer callback_data);
+typedef GDBusInterfaceSkeleton *  (*GVfsRegisterVfsFilterCallback)  (GDBusConnection *connection,
+                                                                     const char      *obj_path,
+                                                                     gpointer         callback_data);
+
 
 void            _g_dbus_register_vfs_filter             (const char                     *obj_path,
-							 DBusHandleMessageFunction       callback,
+							 GVfsRegisterVfsFilterCallback   callback,
 							 GObject                        *data);
 void            _g_dbus_unregister_vfs_filter           (const char                     *obj_path);
-GList *         _g_dbus_bus_list_names_with_prefix_sync (DBusConnection                 *connection,
-							 const char                     *prefix,
-							 DBusError                      *error);
-DBusConnection *_g_dbus_connection_get_sync             (const char                     *dbus_id,
-							 GError                        **error);
-int             _g_dbus_connection_get_fd_sync          (DBusConnection                 *conn,
-							 int                             fd_id);
-void            _g_dbus_connection_get_fd_async         (DBusConnection                 *connection,
-							 int                             fd_id,
-							 GetFdAsyncCallback              callback,
-							 gpointer                        callback_data);
-void            _g_vfs_daemon_call_async                (DBusMessage                    *message,
-							 GVfsAsyncDBusCallback           callback,
-							 gpointer                        callback_data,
-							 GCancellable                   *cancellable);
-DBusMessage *   _g_vfs_daemon_call_sync                 (DBusMessage                    *message,
-							 DBusConnection                **connection_out,
-							 const char                     *callback_obj_path,
-							 DBusObjectPathMessageFunction   callback,
-							 gpointer                        callback_user_data,
-							 GCancellable                   *cancellable,
-							 GError                        **error);
-GFileInfo *     _g_dbus_get_file_info                   (DBusMessageIter                *iter,
+void            _g_dbus_connect_vfs_filters             (GDBusConnection                *connection);
+GDBusConnection *_g_dbus_connection_get_sync            (const char                     *dbus_id,
+                                                         GCancellable                   *cancellable,
 							 GError                        **error);
-
+void            _g_dbus_connection_get_for_async        (const char                     *dbus_id,
+                                                         GVfsAsyncDBusCallback           callback,
+                                                         gpointer                        callback_data,
+                                                         GCancellable                   *cancellable);
 void        _g_simple_async_result_complete_with_cancellable
                                                         (GSimpleAsyncResult             *result,
                                                          GCancellable                   *cancellable);
diff --git a/common/Makefile.am b/common/Makefile.am
index 5d5a54e..4755711 100644
--- a/common/Makefile.am
+++ b/common/Makefile.am
@@ -8,6 +8,21 @@ INCLUDES = -I$(top_srcdir) -I$(top_srcdir)/gvfs \
 	-DG_LOG_DOMAIN=\"GVFS\" \
 	-DDBUS_API_SUBJECT_TO_CHANGE
 
+dbus_built_sources = gvfsdbus.c gvfsdbus.h
+BUILT_SOURCES = $(dbus_built_sources)
+
+$(dbus_built_sources) : Makefile.am dbus-interfaces.xml
+	gdbus-codegen					\
+		--interface-prefix org.gtk.vfs.		\
+		--c-namespace GVfsDBus			\
+		--generate-c-code gvfsdbus		\
+		--annotate "org.gtk.vfs.Mount.OpenForRead()"	\
+		  org.gtk.GDBus.C.UnixFD true		\
+		--annotate "org.gtk.vfs.Mount.OpenForWrite()"	\
+		  org.gtk.GDBus.C.UnixFD true		\
+		dbus-interfaces.xml			\
+		$(NULL)
+
 libgvfscommon_la_SOURCES = 	\
 	gsysutils.c gsysutils.h \
 	gvfsdbusutils.c gvfsdbusutils.h \
@@ -19,6 +34,7 @@ libgvfscommon_la_SOURCES = 	\
 	gvfsicon.h gvfsicon.c \
 	gvfsmountinfo.h gvfsmountinfo.c \
 	gvfsfileinfo.c gvfsfileinfo.h \
+	$(dbus_built_sources) \
 	$(NULL)
 
 # needed by cygwin (see bug #564003)
@@ -46,3 +62,7 @@ libgvfscommon_dnssd_la_LIBADD =	\
 	$(GLIB_LIBS)
 endif
 
+
+EXTRA_DIST = dbus-interfaces.xml
+
+CLEANFILES = $(dbus_built_sources)
diff --git a/common/dbus-interfaces.xml b/common/dbus-interfaces.xml
new file mode 100644
index 0000000..8bd349c
--- /dev/null
+++ b/common/dbus-interfaces.xml
@@ -0,0 +1,351 @@
+<!DOCTYPE node PUBLIC
+"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN"
+"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd";>
+
+<!--
+ Copyright (C) 2011 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: Tomas Bzatek <tbzatek redhat com>
+-->
+
+<node name="/" xmlns:doc="http://www.freedesktop.org/dbus/1.0/doc.dtd";>
+  <!--
+      org.gtk.vfs.Daemon:
+
+      Each daemon (main and for mounts) implement this.
+  -->
+  <interface name='org.gtk.vfs.Daemon'>
+    <method name="GetConnection">
+      <arg type='s' name='address1' direction='out'/>
+      <arg type='s' name='address2' direction='out'/>
+    </method>
+    <method name="Cancel">
+      <arg type='u' name='serial' direction='in'/>
+    </method>
+    <method name="mount">
+      <arg type='b' name='automount' direction='in'/>
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+      <arg type='a{sv}' name='reply' direction='out'/>
+    </method>
+  </interface>
+
+  <!--
+      org.gtk.vfs.Spawner:
+
+      Implemented by the spawner of a process, the spawned process sends the
+      spawned message (with noreply) when it has spawned and gotten a dbus id.
+  -->
+  <interface name='org.gtk.vfs.Spawner'>
+    <method name="spawned">
+      <arg type='b' name='succeeded' direction='in'/>
+      <arg type='s' name='error_message' direction='in'/>
+    </method>
+  </interface>
+
+  <!--
+      org.gtk.vfs.MountTracker:
+
+      The mount tracking interface in the main daemon.
+  -->
+  <interface name='org.gtk.vfs.MountTracker'>
+    <method name="lookupMount">
+      <arg type='(aya{sv})' name='mount_spec' direction='in'/>
+      <arg type='(sosssssbay(aya{sv})ay)' name='mount' direction='out'/>
+    </method>
+    <method name="lookupMountByFusePath">
+      <arg type='ay' name='fuse_path' direction='in'/>
+      <arg type='(sosssssbay(aya{sv})ay)' name='mount' direction='out'/>
+    </method>
+    <method name="mountLocation">
+      <arg type='(aya{sv})' name='mount_spec' direction='in'/>
+      <arg type='(so)' name='mount_source' direction='in'/>
+    </method>
+    <method name="listMounts">
+      <arg type='a(sosssssbay(aya{sv})ay)' name='mounts' direction='out'/>
+    </method>
+    <method name="registerMount">
+      <arg type='o' name='obj_path' direction='in'/>
+      <arg type='s' name='display_name' direction='in'/>
+      <arg type='s' name='stable_name' direction='in'/>
+      <arg type='s' name='x_content_types' direction='in'/>
+      <arg type='s' name='icon' direction='in'/>
+      <arg type='s' name='prefered_filename_encoding' direction='in'/>
+      <arg type='b' name='user_visible' direction='in'/>
+      <arg type='(aya{sv})' name='mount_spec' direction='in'/>
+      <arg type='ay' name='default_location' direction='in'/>
+    </method>
+    <method name="unregisterMount">
+      <arg type='o' name='obj_path' direction='in'/>
+    </method>
+    <method name="listMountTypes">
+      <arg type='as' name='mount_types' direction='out'/>
+    </method>
+    <method name="listMountableInfo">
+      <arg type='a(ssasib)' name='mountables' direction='out'/>
+    </method>
+    <method name="registerFuse">
+    </method>
+    <signal name="mounted">
+      <arg type='(sosssssbay(aya{sv})ay)' name='mount'/>
+    </signal>
+    <signal name="unmounted">
+      <arg type='(sosssssbay(aya{sv})ay)' name='mount'/>
+    </signal>
+  </interface>
+
+  <!--
+      org.gtk.vfs.Mountable:
+
+      Mount daemons that support mounting more mounts implement this,
+      and set the dbus name in the mountable description file.
+  -->
+  <interface name='org.gtk.vfs.Mountable'>
+    <method name="mount">
+      <arg type='(aya{sv})' name='mount_spec' direction='in'/>
+      <arg type='b' name='automount' direction='in'/>
+      <arg type='(so)' name='mount_source' direction='in'/>
+    </method>
+  </interface>
+
+  <!--
+      org.gtk.vfs.MountOperation:
+
+      Used by the dbus-proxying implementation of GMoutOperation.
+  -->
+  <interface name='org.gtk.vfs.MountOperation'>
+    <method name="askPassword">
+      <arg type='s' name='message_string' direction='in'/>
+      <arg type='s' name='default_user' direction='in'/>
+      <arg type='s' name='default_domain' direction='in'/>
+      <arg type='u' name='flags_as_int' direction='in'/>
+      <arg type='b' name='handled' direction='out'/>
+      <arg type='b' name='aborted' direction='out'/>
+      <arg type='s' name='password' direction='out'/>
+      <arg type='s' name='username' direction='out'/>
+      <arg type='s' name='domain' direction='out'/>
+      <arg type='b' name='anonymous' direction='out'/>
+      <arg type='u' name='password_save' direction='out'/>
+    </method>
+    <method name="askQuestion">
+      <arg type='s' name='message_string' direction='in'/>
+      <arg type='as' name='choices' direction='in'/>
+      <arg type='b' name='handled' direction='out'/>
+      <arg type='b' name='aborted' direction='out'/>
+      <arg type='u' name='choice' direction='out'/>
+    </method>
+    <method name="showProcesses">
+      <arg type='s' name='message_string' direction='in'/>
+      <arg type='as' name='choices' direction='in'/>
+      <arg type='ai' name='processes' direction='in'/>
+      <arg type='b' name='handled' direction='out'/>
+      <arg type='b' name='aborted' direction='out'/>
+      <arg type='u' name='choice' direction='out'/>
+    </method>
+    <method name="ShowUnmountProgress">
+      <arg type='s' name='message_string' direction='in'/>
+      <arg type='t' name='time_left' direction='in'/>
+      <arg type='t' name='bytes_left' direction='in'/>
+    </method>
+    <method name="aborted">
+    </method>
+  </interface>
+
+  <!--
+      org.gtk.vfs.Mount:
+
+      Each mount (there might be several in a daemon) implements one of these interfaces
+      for standard i/o operations.
+  -->
+  <interface name='org.gtk.vfs.Mount'>
+    <method name="Unmount">
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+    </method>
+    <method name="OpenForRead">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='pid' direction='in'/>
+      <arg type='u' name='fd_id' direction='out'/>
+      <arg type='b' name='can_seek' direction='out'/>
+    </method>
+    <method name="OpenForWrite">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='q' name='mode' direction='in'/>
+      <arg type='s' name='etag' direction='in'/>
+      <arg type='b' name='make_backup' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='u' name='pid' direction='in'/>
+      <arg type='u' name='fd_id' direction='out'/>
+      <arg type='b' name='can_seek' direction='out'/>
+      <arg type='t' name='initial_offset' direction='out'/>
+    </method>
+    <method name="QueryInfo">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='s' name='attributes' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='uri' direction='in'/>
+      <arg type='a(suv)' name='info' direction='out'/>
+    </method>
+    <method name="QueryFilesystemInfo">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='s' name='attributes' direction='in'/>
+      <arg type='a(suv)' name='info' direction='out'/>
+    </method>
+    <method name="Enumerate">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='s' name='obj_path' direction='in'/>
+      <arg type='s' name='attributes' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='uri' direction='in'/>
+    </method>
+    <method name="CreateDirectoryMonitor">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='obj_path' direction='out'/>
+    </method>
+    <method name="CreateFileMonitor">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='obj_path' direction='out'/>
+    </method>
+    <method name="MountMountable">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+      <arg type='b' name='is_uri' direction='out'/>
+      <arg type='ay' name='path' direction='out'/>
+      <arg type='b' name='must_mount_location' direction='out'/>
+      <arg type='(aya{sv})' name='mount_spec' direction='out'/>
+    </method>
+    <method name="UnmountMountable">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+    </method>
+    <method name="EjectMountable">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+    </method>
+    <method name="StartMountable">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+    </method>
+    <method name="StopMountable">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='s' name='dbus_id' direction='in'/>
+      <arg type='o' name='obj_path' direction='in'/>
+    </method>
+    <method name="PollMountable">
+      <arg type='ay' name='path_data' direction='in'/>
+    </method>
+    <method name="SetDisplayName">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='s' name='display_name' direction='in'/>
+      <arg type='ay' name='new_path' direction='out'/>
+    </method>
+    <method name="Delete">
+      <arg type='ay' name='path_data' direction='in'/>
+    </method>
+    <method name="Trash">
+      <arg type='ay' name='path_data' direction='in'/>
+    </method>
+    <method name="MakeDirectory">
+      <arg type='ay' name='path_data' direction='in'/>
+    </method>
+    <method name="MakeSymbolicLink">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='ay' name='symlink_value' direction='in'/>
+    </method>
+    <method name="Copy">
+      <arg type='ay' name='path1_data' direction='in'/>
+      <arg type='ay' name='path2_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='o' name='progress_obj_path' direction='in'/>
+    </method>
+    <method name="Move">
+      <arg type='ay' name='path1_data' direction='in'/>
+      <arg type='ay' name='path2_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='o' name='progress_obj_path' direction='in'/>
+    </method>
+    <method name="Push">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='ay' name='local_path' direction='in'/>
+      <arg type='b' name='send_progress' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='o' name='progress_obj_path' direction='in'/>
+      <arg type='b' name='remove_source' direction='in'/>
+    </method>
+    <method name="Pull">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='ay' name='local_path' direction='in'/>
+      <arg type='b' name='send_progress' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='o' name='progress_obj_path' direction='in'/>
+      <arg type='b' name='remove_source' direction='in'/>
+    </method>
+    <method name="SetAttribute">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='u' name='flags' direction='in'/>
+      <arg type='(suv)' name='attribute' direction='in'/>
+    </method>
+    <method name="QuerySettableAttributes">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='a(suu)' name='list' direction='out'/>
+    </method>
+    <method name="QueryWritableNamespaces">
+      <arg type='ay' name='path_data' direction='in'/>
+      <arg type='a(suu)' name='list' direction='out'/>
+    </method>
+    <method name="OpenIconForRead">
+    </method>
+  </interface>
+
+  <!--
+      org.gtk.vfs.Enumerator:
+
+      Implemented by client side for a file enumerator.
+  -->
+  <interface name='org.gtk.vfs.Enumerator'>
+    <method name="Done">
+    </method>
+    <method name="GotInfo">
+      <arg type='aa(suv)' name='infos' direction='in'/>
+    </method>
+  </interface>
+
+  <!--
+      org.gtk.vfs.Progress:
+
+      Progress callback interface for copy and move.
+  -->
+  <interface name='org.gtk.vfs.Progress'>
+    <method name="Progress">
+      <arg type='t' name='current' direction='in'/>
+      <arg type='t' name='total' direction='in'/>
+    </method>
+  </interface>
+
+</node>
+
diff --git a/common/gmountoperationdbus.c b/common/gmountoperationdbus.c
index b1989c1..dc33264 100644
--- a/common/gmountoperationdbus.c
+++ b/common/gmountoperationdbus.c
@@ -24,152 +24,32 @@
 
 #include <string.h>
 
-#include <dbus/dbus.h>
-
-#define I_(string) g_intern_static_string (string)
-
 #include <gio/gio.h>
-#include "gmountoperationdbus.h"
-#include "gvfsdaemonprotocol.h"
-#include "gvfsdbusutils.h"
 #include <glib/gi18n-lib.h>
+#include "gmountoperationdbus.h"
+#include "gvfsdbus.h"
 
 typedef struct 
 {
   GMountOperation *op;
   char *obj_path;
   char *dbus_id;
-  DBusConnection *connection;
+  GDBusConnection *connection;
+  GVfsDBusMountOperation *mount_op_skeleton;
 } GMountOperationDBus;
 
-static DBusHandlerResult mount_op_message_function    (DBusConnection      *connection,
-						       DBusMessage         *message,
-						       void                *user_data);
-static void              mount_op_unregister_function (DBusConnection      *connection,
-						       void                *user_data);
-static void              mount_op_ask_password        (GMountOperationDBus *op_dbus,
-						       DBusMessage         *message);
-static void              mount_op_ask_question        (GMountOperationDBus *op_dbus,
-						       DBusMessage         *message);
-static void              mount_op_show_processes      (GMountOperationDBus *op_dbus,
-						       DBusMessage         *message);
-static void              mount_op_show_unmount_progress (GMountOperationDBus *op_dbus,
-                                                         DBusMessage         *message);
-static void              mount_op_aborted             (GMountOperationDBus *op_dbus,
-						       DBusMessage         *message);
-
-static void
-g_mount_operation_dbus_free (GMountOperationDBus *op_dbus)
-{
-  if (op_dbus->connection)
-    {
-      dbus_connection_unregister_object_path (op_dbus->connection,
-					      op_dbus->obj_path);
-      dbus_connection_unref (op_dbus->connection);
-    }
-  g_free (op_dbus->dbus_id);
-  g_free (op_dbus->obj_path);
-  g_free (op_dbus);
-}
-
-GMountSource *
-g_mount_operation_dbus_wrap (GMountOperation *op,
-			     DBusConnection *connection)
-{
-  GMountOperationDBus *op_dbus;
-  static int mount_id = 0;
-  DBusObjectPathVTable mount_vtable = {
-    mount_op_unregister_function,
-    mount_op_message_function
-  };
-
-  if (op == NULL)
-    return g_mount_source_new_dummy ();
-  
-  op_dbus = g_new0 (GMountOperationDBus, 1);
-  
-  op_dbus->op = op;
-  op_dbus->connection = dbus_connection_ref (connection);
-  op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++);
-  if (op_dbus->connection)
-    {
-      op_dbus->dbus_id = g_strdup (dbus_bus_get_unique_name (op_dbus->connection));
-      if (!dbus_connection_register_object_path (op_dbus->connection,
-						 op_dbus->obj_path,
-						 &mount_vtable,
-						 op_dbus))
-	_g_dbus_oom ();
-    }
-
-  g_object_set_data_full (G_OBJECT (op), "dbus-op",
-			  op_dbus, (GDestroyNotify)g_mount_operation_dbus_free);
-  
-  return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path);
-}
-
-/**
- * Called when a #DBusObjectPathVTable is unregistered (or its connection is freed).
- * Found in #DBusObjectPathVTable.
- */
-static void
-mount_op_unregister_function (DBusConnection  *connection,
-			      void            *user_data)
-{
-}
-
-/**
- * Called when a message is sent to a registered object path. Found in
- * #DBusObjectPathVTable which is registered with dbus_connection_register_object_path()
- * or dbus_connection_register_fallback().
- */
-static DBusHandlerResult
-mount_op_message_function (DBusConnection  *connection,
-			   DBusMessage     *message,
-			   void            *user_data)
-{
-  GMountOperationDBus *op_dbus = user_data;
-  
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-				   G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD))
-    mount_op_ask_password (op_dbus, message);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION))
-    mount_op_ask_question (op_dbus, message);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES))
-    mount_op_show_processes (op_dbus, message);
-  else if (dbus_message_is_method_call (message,
-                                        G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-                                        G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_UNMOUNT_PROGRESS))
-    mount_op_show_unmount_progress (op_dbus, message);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					G_VFS_DBUS_MOUNT_OPERATION_OP_ABORTED))
-    mount_op_aborted (op_dbus, message);
-  else
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
-  return DBUS_HANDLER_RESULT_HANDLED;
-}
-
 static void
 mount_op_send_reply (GMountOperationDBus *op_dbus,
-		     DBusMessage *reply)
+                     GDBusMethodInvocation *invocation)
 {
-  if (!dbus_connection_send (op_dbus->connection, reply, NULL))
-    _g_dbus_oom ();
-
   g_signal_handlers_disconnect_matched (op_dbus->op,
 					G_SIGNAL_MATCH_ID | G_SIGNAL_MATCH_DATA,
 					g_signal_lookup ("reply", G_TYPE_MOUNT_OPERATION),
 					0,
 					NULL,
 					NULL,
-					reply);
-  dbus_message_unref (reply);
+					invocation);
+  g_object_unref (invocation);
 }
 
 static void
@@ -177,11 +57,11 @@ ask_password_reply (GMountOperation *op,
 		    GMountOperationResult result,
 		    gpointer data)
 {
-  DBusMessage *reply = data;
+  GDBusMethodInvocation *invocation = data;
   const char *username, *password, *domain;
-  dbus_bool_t anonymous;
+  gboolean anonymous;
   guint32 password_save;
-  dbus_bool_t handled, abort_dbus;
+  gboolean handled, abort_dbus;
   GMountOperationDBus *op_dbus;
 
   op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
@@ -201,63 +81,42 @@ ask_password_reply (GMountOperation *op,
   anonymous = g_mount_operation_get_anonymous (op);
   password_save = g_mount_operation_get_password_save (op);
 
-  _g_dbus_message_append_args (reply,
-			       DBUS_TYPE_BOOLEAN, &handled,
-			       DBUS_TYPE_BOOLEAN, &abort_dbus,
-			       DBUS_TYPE_STRING, &password,
-			       DBUS_TYPE_STRING, &username,
-			       DBUS_TYPE_STRING, &domain,
-			       DBUS_TYPE_BOOLEAN, &anonymous,
-			       DBUS_TYPE_UINT32, &password_save,
-			       0);
-
-  mount_op_send_reply (op_dbus, reply);
+  gvfs_dbus_mount_operation_complete_ask_password (NULL, /* FIXME */
+                                                   invocation,
+                                                   handled,
+                                                   abort_dbus,
+                                                   password,
+                                                   username,
+                                                   domain,
+                                                   anonymous,
+                                                   password_save);
+
+  mount_op_send_reply (op_dbus, invocation);
 }
 
-static void
-mount_op_ask_password (GMountOperationDBus *op_dbus,
-		       DBusMessage *message)
+static gboolean
+handle_ask_password (GVfsDBusMountOperation *object,
+                     GDBusMethodInvocation *invocation,
+                     const gchar *arg_message_string,
+                     const gchar *arg_default_user,
+                     const gchar *arg_default_domain,
+                     guint arg_flags_as_int,
+                     gpointer data)
 {
-  const char *message_string, *default_user, *default_domain;
-  guint32 flags;
-  DBusMessageIter iter;
-  DBusMessage *reply;
-  DBusError error;
+  GMountOperationDBus *op_dbus = data;
 
-  reply = NULL;
+  g_print ("gmountoperationdbus.c: handle_ask_password()\n");
 
-  dbus_message_iter_init (message, &iter);
-  
-  dbus_error_init (&error);
-  if (!_g_dbus_message_iter_get_args (&iter,
-				      &error,
-				      DBUS_TYPE_STRING, &message_string,
-				      DBUS_TYPE_STRING, &default_user,
-				      DBUS_TYPE_STRING, &default_domain,
-				      DBUS_TYPE_UINT32, &flags,
-				      0))
-    {
-      reply = dbus_message_new_error (message, error.name, error.message);
-      if (reply == NULL)
-	_g_dbus_oom ();
-      if (!dbus_connection_send (op_dbus->connection, reply, NULL))
-	_g_dbus_oom ();
-      dbus_message_unref (reply);
-      dbus_error_free (&error);
-      return;
-    }
-  
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
-  
-  g_signal_connect (op_dbus->op, "reply", (GCallback)ask_password_reply, reply);
+  g_signal_connect (op_dbus->op, "reply", 
+                    (GCallback)ask_password_reply, 
+                    g_object_ref (invocation));
   
   g_signal_emit_by_name (op_dbus->op, "ask_password",
-			 message_string,
-			 default_user,
-			 default_domain,
-			 flags);
+                         arg_message_string,
+                         arg_default_user,
+                         arg_default_domain,
+                         arg_flags_as_int);
+  return TRUE;
 }
 
 static void
@@ -265,9 +124,9 @@ ask_question_reply (GMountOperation *op,
 		    GMountOperationResult result,
 		    gpointer data)
 {
-  DBusMessage *reply = data;
+  GDBusMethodInvocation *invocation = data;
   guint32 choice;
-  dbus_bool_t handled, abort_dbus;
+  gboolean handled, abort_dbus;
   GMountOperationDBus *op_dbus;
 
   op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
@@ -277,58 +136,35 @@ ask_question_reply (GMountOperation *op,
   
   choice = g_mount_operation_get_choice (op);
 
-  _g_dbus_message_append_args (reply,
-			       DBUS_TYPE_BOOLEAN, &handled,
-			       DBUS_TYPE_BOOLEAN, &abort_dbus,
-			       DBUS_TYPE_UINT32, &choice,
-			       0);
+  gvfs_dbus_mount_operation_complete_ask_question (NULL, /* FIXME */
+                                                   invocation,
+                                                   handled,
+                                                   abort_dbus,
+                                                   choice);
 
-  mount_op_send_reply (op_dbus, reply);
+  mount_op_send_reply (op_dbus, invocation);
 }
 
-static void
-mount_op_ask_question (GMountOperationDBus *op_dbus,
-		       DBusMessage         *message)
+static gboolean
+handle_ask_question (GVfsDBusMountOperation *object,
+                     GDBusMethodInvocation *invocation,
+                     const gchar *arg_message_string,
+                     const gchar *const *arg_choices,
+                     gpointer data)
 {
-  const char *message_string;
-  char **choices;
-  int num_choices;
-  DBusMessage *reply;
-  DBusError error;
-  DBusMessageIter iter;
-
-  reply = NULL;
-  
-  dbus_message_iter_init (message, &iter);
-  dbus_error_init (&error);
-  if (!_g_dbus_message_iter_get_args (&iter,
-				      &error,
-				      DBUS_TYPE_STRING, &message_string,
-				      DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-				      &choices, &num_choices,
-				      0))
-    {
-      reply = dbus_message_new_error (message, error.name, error.message);
-      if (reply == NULL)
-	_g_dbus_oom ();
-      if (!dbus_connection_send (op_dbus->connection, reply, NULL))
-	_g_dbus_oom ();
-      dbus_message_unref (reply);
-      dbus_error_free (&error);
-      return;
-    }
-  
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
-  
-  g_signal_connect (op_dbus->op, "reply", (GCallback)ask_question_reply, reply);
+  GMountOperationDBus *op_dbus = data;
+
+  g_print ("gmountoperationdbus.c: handle_ask_question()\n");
+
+  g_signal_connect (op_dbus->op,
+                    "reply",
+                    (GCallback)ask_question_reply,
+                    g_object_ref (invocation));
 
   g_signal_emit_by_name (op_dbus->op, "ask_question",
-			 message_string,
-			 choices);
-  
-  dbus_free_string_array (choices);
+                         arg_message_string,
+                         arg_choices);
+  return TRUE;
 }
 
 static void
@@ -336,9 +172,9 @@ show_processes_reply (GMountOperation *op,
                       GMountOperationResult result,
                       gpointer data)
 {
-  DBusMessage *reply = data;
+  GDBusMethodInvocation *invocation = data;
   guint32 choice;
-  dbus_bool_t handled, abort_dbus;
+  gboolean handled, abort_dbus;
   GMountOperationDBus *op_dbus;
 
   op_dbus = g_object_get_data (G_OBJECT (op), "dbus-op");
@@ -347,119 +183,149 @@ show_processes_reply (GMountOperation *op,
   abort_dbus = (result == G_MOUNT_OPERATION_ABORTED);
 
   choice = g_mount_operation_get_choice (op);
+  
+  gvfs_dbus_mount_operation_complete_show_processes (NULL, /* FIXME */
+                                                     invocation,
+                                                     handled,
+                                                     abort_dbus,
+                                                     choice);
 
-  _g_dbus_message_append_args (reply,
-			       DBUS_TYPE_BOOLEAN, &handled,
-			       DBUS_TYPE_BOOLEAN, &abort_dbus,
-			       DBUS_TYPE_UINT32, &choice,
-			       0);
-
-  mount_op_send_reply (op_dbus, reply);
+  mount_op_send_reply (op_dbus, invocation);
 }
 
-static void
-mount_op_show_processes (GMountOperationDBus *op_dbus,
-                         DBusMessage         *message)
+static gboolean
+handle_show_processes (GVfsDBusMountOperation *object,
+                       GDBusMethodInvocation *invocation,
+                       const gchar *arg_message_string,
+                       const gchar *const *arg_choices,
+                       GVariant *arg_processes,
+                       gpointer data)
 {
-  const char *message_string;
-  char **choices;
-  int num_choices;
-  gint32 **process_pids;
-  int num_process_pids;
-  DBusMessage *reply;
-  DBusError error;
-  DBusMessageIter iter;
+  GMountOperationDBus *op_dbus = data;
   GArray *processes;
+  GPid pid;
+  GVariantIter iter;
 
-  reply = NULL;
-
-  dbus_message_iter_init (message, &iter);
-  dbus_error_init (&error);
-  if (!_g_dbus_message_iter_get_args (&iter,
-				      &error,
-				      DBUS_TYPE_STRING, &message_string,
-				      DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-				      &choices, &num_choices,
-				      DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
-				      &process_pids, &num_process_pids,
-				      0))
-    {
-      reply = dbus_message_new_error (message, error.name, error.message);
-      if (reply == NULL)
-	_g_dbus_oom ();
-      if (!dbus_connection_send (op_dbus->connection, reply, NULL))
-	_g_dbus_oom ();
-      dbus_message_unref (reply);
-      dbus_error_free (&error);
-      return;
-    }
-
-  processes = g_array_sized_new (FALSE, FALSE, sizeof (GPid), num_process_pids);
-  g_array_append_vals (processes, process_pids, num_process_pids);
+  g_print ("gmountoperationdbus.c: handle_show_processes()\n");
 
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
+  processes = g_array_new (FALSE, FALSE, sizeof (GPid));
+  g_variant_iter_init (&iter, arg_processes);
+  while (g_variant_iter_loop (&iter, "i", &pid))
+    g_array_append_val (processes, pid);
 
-  g_signal_connect (op_dbus->op, "reply", (GCallback)show_processes_reply, reply);
+  g_signal_connect (op_dbus->op,
+                    "reply",
+                    (GCallback)show_processes_reply,
+                    g_object_ref (invocation));
 
   g_signal_emit_by_name (op_dbus->op, "show_processes",
-			 message_string,
+                         arg_message_string,
                          processes,
-			 choices);
+                         arg_choices);
 
-  dbus_free_string_array (choices);
   g_array_unref (processes);
+  
+  return TRUE;
 }
 
-static void
-mount_op_show_unmount_progress (GMountOperationDBus *op_dbus,
-                                DBusMessage *message)
+static gboolean
+handle_show_unmount_progress (GVfsDBusMountOperation *object,
+                              GDBusMethodInvocation *invocation,
+                              const gchar *arg_message_string,
+                              guint64 arg_time_left,
+                              guint64 arg_bytes_left,
+                              gpointer data)
 {
-  const gchar *message_string;
-  guint64 time_left, bytes_left;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError error;
-
-  reply = NULL;
-
-  dbus_message_iter_init (message, &iter);
-  dbus_error_init (&error);
-  if (!_g_dbus_message_iter_get_args (&iter,
-                                      &error,
-                                      DBUS_TYPE_STRING, &message_string,
-                                      DBUS_TYPE_UINT64, &time_left,
-                                      DBUS_TYPE_UINT64, &bytes_left,
-                                      0))
-    {
-      reply = dbus_message_new_error (message, error.name, error.message);
-      if (reply == NULL)
-        _g_dbus_oom ();
-      if (!dbus_connection_send (op_dbus->connection, reply, NULL))
-        _g_dbus_oom ();
-      dbus_message_unref (reply);
-      dbus_error_free (&error);
-      return;
-    }
-
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
+  GMountOperationDBus *op_dbus = data;
+ 
+  g_print ("gmountoperationdbus.c: handle_show_unmount_progress()\n");
 
   g_signal_emit_by_name (op_dbus->op, "show-unmount-progress",
-                         message_string,
-                         time_left,
-                         bytes_left);
+                         arg_message_string,
+                         arg_time_left,
+                         arg_bytes_left);
 
-  mount_op_send_reply (op_dbus, reply);
+  gvfs_dbus_mount_operation_complete_show_unmount_progress (object, invocation);
+  
+  return TRUE;
 }
 
-static void
-mount_op_aborted (GMountOperationDBus *op_dbus,
-		  DBusMessage         *message)
+static gboolean
+handle_aborted (GVfsDBusMountOperation *object,
+                GDBusMethodInvocation *invocation,
+                gpointer data)
 {
+  GMountOperationDBus *op_dbus = data;
+ 
+  g_print ("gmountoperationdbus.c: handle_aborted()\n");
+  
   /* also emit reply to make the all DBus ops return */
   g_mount_operation_reply (op_dbus->op, G_MOUNT_OPERATION_UNHANDLED);
   g_signal_emit_by_name (op_dbus->op, "aborted");
+  gvfs_dbus_mount_operation_complete_aborted (object, invocation);
+  
+  return TRUE;
+}
+
+
+static void
+g_mount_operation_dbus_free (GMountOperationDBus *op_dbus)
+{
+  if (op_dbus->connection)
+    {
+      if (op_dbus->mount_op_skeleton != NULL)
+        {
+          g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (op_dbus->mount_op_skeleton));
+          g_object_unref (op_dbus->mount_op_skeleton);
+        }
+      g_object_unref (op_dbus->connection);
+    }
+  g_free (op_dbus->dbus_id);
+  g_free (op_dbus->obj_path);
+  g_free (op_dbus);
+}
+
+GMountSource *
+g_mount_operation_dbus_wrap (GMountOperation *op,
+                             GDBusConnection *connection)
+{
+  GMountOperationDBus *op_dbus;
+  static int mount_id = 0;
+  GError *error; 
+
+  if (op == NULL)
+    return g_mount_source_new_dummy ();
+  
+  op_dbus = g_new0 (GMountOperationDBus, 1);
+  
+  op_dbus->op = op;
+  op_dbus->connection = g_object_ref (connection);
+  op_dbus->obj_path = g_strdup_printf ("/org/gtk/gvfs/mountop/%d", mount_id++);
+  if (op_dbus->connection)
+    {
+      op_dbus->dbus_id = g_strdup (g_dbus_connection_get_unique_name (op_dbus->connection));
+      op_dbus->mount_op_skeleton = gvfs_dbus_mount_operation_skeleton_new ();
+      
+      g_signal_connect (op_dbus->mount_op_skeleton, "handle-ask-password", G_CALLBACK (handle_ask_password), op_dbus);
+      g_signal_connect (op_dbus->mount_op_skeleton, "handle-ask-question", G_CALLBACK (handle_ask_question), op_dbus);
+      g_signal_connect (op_dbus->mount_op_skeleton, "handle-show-processes", G_CALLBACK (handle_show_processes), op_dbus);
+      g_signal_connect (op_dbus->mount_op_skeleton, "handle-show-unmount-progress", G_CALLBACK (handle_show_unmount_progress), op_dbus);
+      g_signal_connect (op_dbus->mount_op_skeleton, "handle-aborted", G_CALLBACK (handle_aborted), op_dbus);
+
+      error = NULL;
+      if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (op_dbus->mount_op_skeleton),
+                                             op_dbus->connection,
+                                             op_dbus->obj_path, 
+                                             &error))
+        {
+          g_warning ("Error exporting GMountOperationDBus: %s (%s, %d)\n",
+                      error->message, g_quark_to_string (error->domain), error->code);
+          g_error_free (error);
+        }
+    }
+
+  g_object_set_data_full (G_OBJECT (op), "dbus-op",
+                          op_dbus, (GDestroyNotify)g_mount_operation_dbus_free);
+  
+  return g_mount_source_new (op_dbus->dbus_id, op_dbus->obj_path);
 }
diff --git a/common/gmountoperationdbus.h b/common/gmountoperationdbus.h
index 564fc73..7d4111a 100644
--- a/common/gmountoperationdbus.h
+++ b/common/gmountoperationdbus.h
@@ -33,7 +33,7 @@
 G_BEGIN_DECLS
 
 GMountSource *g_mount_operation_dbus_wrap (GMountOperation *op,
-					   DBusConnection *connection);
+                                           GDBusConnection *connection);
 
 G_END_DECLS
 
diff --git a/common/gmountsource.c b/common/gmountsource.c
index 9520228..4aa107c 100644
--- a/common/gmountsource.c
+++ b/common/gmountsource.c
@@ -23,9 +23,8 @@
 #include <config.h>
 
 #include <gmountsource.h>
-#include <gvfsdbusutils.h>
 #include <gio/gio.h>
-#include <gvfsdaemonprotocol.h>
+#include <gvfsdbus.h>
 
 #include <string.h>
 
@@ -93,20 +92,27 @@ g_mount_source_new_dummy (void)
   return source;
 }
 
-
-void
-g_mount_source_to_dbus (GMountSource *source,
-			DBusMessage *message)
+GVariant *
+g_mount_source_to_dbus (GMountSource *source)
 {
   g_assert (source->dbus_id != NULL);
   g_assert (source->obj_path != NULL);
 
-  if (!dbus_message_append_args (message,
-				 DBUS_TYPE_STRING, &source->dbus_id,
-				 DBUS_TYPE_OBJECT_PATH, &source->obj_path,
-				 0))
-    _g_dbus_oom ();
+  return g_variant_new ("(so)",
+                        source->dbus_id,
+                        source->obj_path);
+}
+
+GMountSource *
+g_mount_source_from_dbus (GVariant *iter)
+{
+  const gchar *obj_path, *dbus_id;
+
+  g_variant_get (iter, "(&s&o)",
+                 &dbus_id,
+                 &obj_path);
   
+  return g_mount_source_new (dbus_id, obj_path);
 }
 
 const char *
@@ -156,64 +162,103 @@ ask_password_data_free (gpointer _data)
   g_free (data);
 }
 
+static GVfsDBusMountOperation *
+create_mount_operation_proxy (GMountSource        *source,
+                              GAsyncReadyCallback  callback,
+                              gpointer             user_data)
+{
+  GVfsDBusMountOperation *proxy;
+  GError *error;
+
+  /* If no dbus id specified, reply that we weren't handled */
+  if (source->dbus_id[0] == 0)
+    { 
+      if (callback != NULL)
+        g_simple_async_report_error_in_idle (G_OBJECT (source),
+                                             callback,
+                                             user_data,
+                                             G_IO_ERROR, G_IO_ERROR_FAILED, 
+                                             "Internal Error"); 
+      return NULL;
+    }
+
+  error = NULL;
+  proxy = gvfs_dbus_mount_operation_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                            G_DBUS_PROXY_FLAGS_NONE,
+                                                            source->dbus_id,
+                                                            source->obj_path,
+                                                            NULL,
+                                                            &error);
+  if (proxy == NULL)
+    if (callback != NULL)
+      g_simple_async_report_take_gerror_in_idle (G_OBJECT (source),
+                                                 callback,
+                                                 user_data,
+                                                 error);
+  
+  return proxy;
+}
+
 /* the callback from dbus -> main thread */
 static void
-ask_password_reply (DBusMessage *reply,
-		    GError      *error,
-		    gpointer     _data)
+ask_password_reply (GVfsDBusMountOperation *proxy,
+                    GAsyncResult *res,
+                    gpointer user_data)
 {
   GSimpleAsyncResult *result;
   AskPasswordData *data;
-  dbus_bool_t handled, aborted, anonymous;
+  gboolean handled, aborted, anonymous;
   guint32 password_save;
-  const char *password, *username, *domain;
-  DBusMessageIter iter;
+  gchar *password, *username, *domain;
+  GError *error;
 
-  result = G_SIMPLE_ASYNC_RESULT (_data);
+  result = G_SIMPLE_ASYNC_RESULT (user_data);
   handled = TRUE;
   
+  g_print ("gmountsource.c: ask_password_reply()\n");
+
   data = g_new0 (AskPasswordData, 1);
   g_simple_async_result_set_op_res_gpointer (result, data, ask_password_data_free);
 
-  if (reply == NULL)
+  error = NULL;
+  if (!gvfs_dbus_mount_operation_call_ask_password_finish (proxy,
+                                                           &handled,
+                                                           &aborted,
+                                                           &password,
+                                                           &username,
+                                                           &domain,
+                                                           &anonymous,
+                                                           &password_save,
+                                                           res,
+                                                           &error))
     {
       data->aborted = TRUE;
+      g_simple_async_result_take_error (result, error);
     }
   else
     {
-      dbus_message_iter_init (reply, &iter);
-      if (!_g_dbus_message_iter_get_args (&iter, NULL,
-					  DBUS_TYPE_BOOLEAN, &handled,
-					  DBUS_TYPE_BOOLEAN, &aborted,
-					  DBUS_TYPE_STRING, &password,
-					  DBUS_TYPE_STRING, &username,
-					  DBUS_TYPE_STRING, &domain,
-					  DBUS_TYPE_BOOLEAN, &anonymous,
-					  DBUS_TYPE_UINT32, &password_save,
-					  0))
-	data->aborted = TRUE;
-      else
-	{
-	  data->aborted = aborted;
-
-	  if (!anonymous)
-	    {
-	      data->password = g_strdup (password);
-	      data->username = *username == 0 ? NULL : g_strdup (username);
-	      data->domain = *domain == 0 ? NULL : g_strdup (domain);
-	    }
-	  data->password_save = (GPasswordSave)password_save;
-	  data->anonymous = anonymous;
-
-	  /* TODO: handle more args */
-	}
+      data->aborted = aborted;
+
+      if (!anonymous)
+        {
+          data->password = g_strdup (password);
+          data->username = *username == 0 ? NULL : g_strdup (username);
+          data->domain = *domain == 0 ? NULL : g_strdup (domain);
+        }
+      data->password_save = (GPasswordSave)password_save;
+      data->anonymous = anonymous;
+
+      /* TODO: handle more args */
+      g_free (password);
+      g_free (username);
+      g_free (domain);
     }
 
   if (handled == FALSE)
     {
       g_simple_async_result_set_error (result, G_IO_ERROR, G_IO_ERROR_FAILED, "Internal Error");
     }
-
+  
   g_simple_async_result_complete (result);
   g_object_unref (result);
 }
@@ -228,49 +273,27 @@ g_mount_source_ask_password_async (GMountSource              *source,
                                    gpointer                   user_data)
 {
   GSimpleAsyncResult *result;
-  DBusMessage *message;
-  guint32 flags_as_int;
- 
-
-  /* If no dbus id specified, reply that we weren't handled */
-  if (source->dbus_id[0] == 0)
-    { 
-      g_simple_async_report_error_in_idle (G_OBJECT (source),
-					   callback,
-					   user_data,
-					   G_IO_ERROR, G_IO_ERROR_FAILED, 
-					   "Internal Error"); 
-      return;
-    }
-
-  if (message_string == NULL)
-    message_string = "";
-  if (default_user == NULL)
-    default_user = "";
-  if (default_domain == NULL)
-    default_domain = "";
-
-  flags_as_int = flags;
-  
-  message = dbus_message_new_method_call (source->dbus_id,
-					  source->obj_path,
-					  G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					  G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_PASSWORD);
+  GVfsDBusMountOperation *proxy;
   
-  _g_dbus_message_append_args (message,
-			       DBUS_TYPE_STRING, &message_string,
-			       DBUS_TYPE_STRING, &default_user,
-			       DBUS_TYPE_STRING, &default_domain,
-			       DBUS_TYPE_UINT32, &flags_as_int,
-			       0);
+  proxy = create_mount_operation_proxy (source, callback, user_data);
+  if (proxy == NULL)
+    return;
 
-  result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, 
-                                      g_mount_source_ask_password_async);
   /* 30 minute timeout */
-  _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
-				 ask_password_reply, result);
-  dbus_message_unref (message);
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30);
 
+  result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, 
+                                      g_mount_source_ask_password_async);
+  
+  gvfs_dbus_mount_operation_call_ask_password (proxy,
+                                               message_string ? message_string : "",
+                                               default_user ? default_user : "",
+                                               default_domain ? default_domain : "",
+                                               flags,
+                                               NULL,
+                                               (GAsyncReadyCallback) ask_password_reply,
+                                               result);
+  g_object_unref (proxy);
 }
 
 /**
@@ -493,40 +516,39 @@ struct AskQuestionData {
 
 /* the callback from dbus -> main thread */
 static void
-ask_question_reply (DBusMessage *reply,
-		    GError      *error,
-		    gpointer     _data)
+ask_question_reply (GVfsDBusMountOperation *proxy,
+                    GAsyncResult *res,
+                    gpointer user_data)
 {
   GSimpleAsyncResult *result;
   AskQuestionData *data;
-  dbus_bool_t handled, aborted;
+  gboolean handled, aborted;
   guint32 choice;
-  DBusMessageIter iter;
-
-  result = G_SIMPLE_ASYNC_RESULT (_data);
+  GError *error;
+  
+  result = G_SIMPLE_ASYNC_RESULT (user_data);
   handled = TRUE;
   
+  g_print ("gmountsource.c: ask_question_reply()\n");
+
   data = g_new0 (AskQuestionData, 1);
   g_simple_async_result_set_op_res_gpointer (result, data, g_free);
 
-  if (reply == NULL)
+  error = NULL;
+  if (!gvfs_dbus_mount_operation_call_ask_question_finish (proxy,
+                                                           &handled,
+                                                           &aborted,
+                                                           &choice,
+                                                           res,
+                                                           &error))
     {
       data->aborted = TRUE;
+      g_simple_async_result_take_error (result, error);
     }
   else
     {
-      dbus_message_iter_init (reply, &iter);
-      if (!_g_dbus_message_iter_get_args (&iter, NULL,
-					  DBUS_TYPE_BOOLEAN, &handled,
-					  DBUS_TYPE_BOOLEAN, &aborted,
-					  DBUS_TYPE_UINT32, &choice,
-					  0))
-	data->aborted = TRUE;
-      else
-	{
-	  data->aborted = aborted;
-	  data->choice = choice;
-	}
+      data->aborted = aborted;
+      data->choice = choice;
     }
 
   if (handled == FALSE)
@@ -593,40 +615,25 @@ g_mount_source_ask_question_async (GMountSource       *source,
 				   gpointer            user_data)
 {
   GSimpleAsyncResult *result;
-  DBusMessage *message;
-
-  /* If no dbus id specified, reply that we weren't handled */
-  if (source->dbus_id[0] == 0)
-    { 
-      g_simple_async_report_error_in_idle (G_OBJECT (source),
-					   callback,
-					   user_data,
-					   G_IO_ERROR, G_IO_ERROR_FAILED, 
-					   "Internal Error"); 
-      return;
-    }
-
-  if (message_string == NULL)
-    message_string = "";
+  GVfsDBusMountOperation *proxy;
   
-  message = dbus_message_new_method_call (source->dbus_id,
-					  source->obj_path,
-					  G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					  G_VFS_DBUS_MOUNT_OPERATION_OP_ASK_QUESTION);
+  proxy = create_mount_operation_proxy (source, callback, user_data);
+  if (proxy == NULL)
+    return;
 
-  _g_dbus_message_append_args (message,
-			       DBUS_TYPE_STRING, &message_string,
-			       DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-			       &choices, n_choices,
-			       0);
+  /* 30 minute timeout */
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30);
 
   result = g_simple_async_result_new (G_OBJECT (source), callback, user_data, 
                                       g_mount_source_ask_question_async);
-  /* 30 minute timeout */
-  _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
-				 ask_question_reply, result);
-  dbus_message_unref (message);
-	
+  
+  gvfs_dbus_mount_operation_call_ask_question (proxy,
+                                               message_string ? message_string : "",
+                                               choices,   
+                                               NULL,
+                                               (GAsyncReadyCallback) ask_question_reply,
+                                               result);
+  g_object_unref (proxy);
 }
 
 gboolean
@@ -714,40 +721,40 @@ struct ShowProcessesData {
 
 /* the callback from dbus -> main thread */
 static void
-show_processes_reply (DBusMessage *reply,
-                      GError      *error,
-                      gpointer     _data)
+show_processes_reply (GVfsDBusMountOperation *proxy,
+                      GAsyncResult *res,
+                      gpointer user_data)
 {
   GSimpleAsyncResult *result;
   ShowProcessesData *data;
-  dbus_bool_t handled, aborted;
+  gboolean handled, aborted;
   guint32 choice;
-  DBusMessageIter iter;
-
-  result = G_SIMPLE_ASYNC_RESULT (_data);
+  GError *error;
+  
+  result = G_SIMPLE_ASYNC_RESULT (user_data);
   handled = TRUE;
 
+  g_print ("gmountsource.c: show_processes_reply()\n");
+
   data = g_new0 (ShowProcessesData, 1);
   g_simple_async_result_set_op_res_gpointer (result, data, g_free);
 
-  if (reply == NULL)
+  
+  error = NULL;
+  if (!gvfs_dbus_mount_operation_call_show_processes_finish (proxy,
+                                                             &handled,
+                                                             &aborted,
+                                                             &choice,
+                                                             res,
+                                                             &error))
     {
       data->aborted = TRUE;
+      g_simple_async_result_take_error (result, error);
     }
   else
     {
-      dbus_message_iter_init (reply, &iter);
-      if (!_g_dbus_message_iter_get_args (&iter, NULL,
-					  DBUS_TYPE_BOOLEAN, &handled,
-					  DBUS_TYPE_BOOLEAN, &aborted,
-					  DBUS_TYPE_UINT32, &choice,
-					  0))
-	data->aborted = TRUE;
-      else
-	{
-	  data->aborted = aborted;
-	  data->choice = choice;
-	}
+      data->aborted = aborted;
+      data->choice = choice;
     }
 
   if (handled == FALSE)
@@ -769,42 +776,33 @@ g_mount_source_show_processes_async (GMountSource        *source,
                                      gpointer             user_data)
 {
   GSimpleAsyncResult *result;
-  DBusMessage *message;
+  GVfsDBusMountOperation *proxy;
+  GVariantBuilder builder;
+  guint i;
+  
+  proxy = create_mount_operation_proxy (source, callback, user_data);
+  if (proxy == NULL)
+    return;
 
-  /* If no dbus id specified, reply that we weren't handled */
-  if (source->dbus_id[0] == 0)
-    {
-      g_simple_async_report_error_in_idle (G_OBJECT (source),
-					   callback,
-					   user_data,
-					   G_IO_ERROR, G_IO_ERROR_FAILED,
-					   "Internal Error");
-      return;
-    }
+  /* 30 minute timeout */
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30);
 
   result = g_simple_async_result_new (G_OBJECT (source), callback, user_data,
                                       g_mount_source_show_processes_async);
-
-  if (message_string == NULL)
-    message_string = "";
-
-  message = dbus_message_new_method_call (source->dbus_id,
-					  source->obj_path,
-					  G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					  G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_PROCESSES);
-
-  _g_dbus_message_append_args (message,
-			       DBUS_TYPE_STRING, &message_string,
-			       DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-			       &choices, n_choices,
-			       DBUS_TYPE_ARRAY, DBUS_TYPE_INT32,
-			       &processes->data, processes->len,
-			       0);
-
-  /* 30 minute timeout */
-  _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
-				 show_processes_reply, result);
-  dbus_message_unref (message);
+  
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("ai"));
+  for (i = 0; i < processes->len; i++)
+    g_variant_builder_add (&builder, "i", 
+                           g_array_index (processes, gint32, i));
+  
+  gvfs_dbus_mount_operation_call_show_processes (proxy,
+                                                 message_string ? message_string : "",
+                                                 choices,
+                                                 g_variant_builder_end (&builder),
+                                                 NULL,
+                                                 (GAsyncReadyCallback) show_processes_reply,
+                                                 result);
+  g_object_unref (proxy);
 }
 
 gboolean
@@ -931,23 +929,28 @@ op_show_processes (GMountOperation *op,
   return TRUE;
 }
 
-/* the callback from dbus -> main thread */
 static void
-show_unmount_progress_reply (DBusMessage *reply,
-                             GError      *error,
-                             gpointer     _data)
+show_unmount_progress_reply (GVfsDBusMountOperation *proxy,
+                             GAsyncResult *res,
+                             gpointer user_data)
 {
-  if (error != NULL)
-    g_warning ("ShowUnmountProgress request failed: %s", error->message);
+  GError *error;
+
+  error = NULL;
+  if (!gvfs_dbus_mount_operation_call_show_unmount_progress_finish (proxy, res, &error))
+    {
+      g_warning ("ShowUnmountProgress request failed: %s", error->message);
+      g_error_free (error);
+    }
 }
 
 void
-g_mount_source_show_unmount_progress (GMountSource        *source,
-                                      const char          *message_string,
-                                      guint64              time_left,
-                                      guint64              bytes_left)
+g_mount_source_show_unmount_progress (GMountSource *source,
+                                      const char   *message_string,
+                                      guint64      time_left,
+                                      guint64      bytes_left)
 {
-  DBusMessage *message;
+  GVfsDBusMountOperation *proxy;
 
   /* If no dbus id specified, warn and return */
   if (source->dbus_id[0] == 0)
@@ -956,25 +959,22 @@ g_mount_source_show_unmount_progress (GMountSource        *source,
                  "ignoring show-unmount-progress request");
       return;
     }
-
-  if (message_string == NULL)
-    message_string = "";
-
-  message = dbus_message_new_method_call (source->dbus_id,
-					  source->obj_path,
-					  G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					  G_VFS_DBUS_MOUNT_OPERATION_OP_SHOW_UNMOUNT_PROGRESS);
-
-  _g_dbus_message_append_args (message,
-			       DBUS_TYPE_STRING, &message_string,
-                               DBUS_TYPE_UINT64, &time_left,
-                               DBUS_TYPE_UINT64, &bytes_left,
-			       0);
+  
+  proxy = create_mount_operation_proxy (source, NULL, NULL);
+  if (proxy == NULL)
+    return;
 
   /* 30 minute timeout */
-  _g_dbus_connection_call_async (NULL, message, 1000 * 60 * 30,
-				 show_unmount_progress_reply, NULL);
-  dbus_message_unref (message);
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 1000 * 60 * 30);
+
+  gvfs_dbus_mount_operation_call_show_unmount_progress (proxy,
+                                                        message_string ? message_string : "",
+                                                        time_left,
+                                                        bytes_left,
+                                                        NULL,
+                                                        (GAsyncReadyCallback) show_unmount_progress_reply,
+                                                        NULL);
+  g_object_unref (proxy);
 }
 
 static void
@@ -991,38 +991,30 @@ op_show_unmount_progress (GMountOperation *op,
   g_signal_stop_emission_by_name (op, "show_unmount_progress");
 }
 
-gboolean
-g_mount_source_abort (GMountSource *source)
+static void
+abort_reply (GVfsDBusMountOperation *proxy,
+             GAsyncResult *res,
+             gpointer user_data)
 {
-  DBusMessage *message;
-  DBusConnection *connection;
-  gboolean ret;
-
-  ret = FALSE;
-
-  /* If no dbus id specified, reply that we weren't handled */
-  if (source->dbus_id[0] == 0)
-    goto out;
+  g_print ("gmountsource.c: abort_reply()\n");
 
-  connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-  if (connection == NULL)
-    goto out;
-
-  message = dbus_message_new_method_call (source->dbus_id,
-					  source->obj_path,
-					  G_VFS_DBUS_MOUNT_OPERATION_INTERFACE,
-					  G_VFS_DBUS_MOUNT_OPERATION_OP_ABORTED);
-
-  if (message)
-    {
-      dbus_connection_send (connection, message, NULL);
-      dbus_message_unref (message);
-    }
+  gvfs_dbus_mount_operation_call_aborted_finish (proxy, res, NULL);
+}
 
-  ret = TRUE;
+gboolean
+g_mount_source_abort (GMountSource *source)
+{
+  GVfsDBusMountOperation *proxy;
 
- out:
-  return ret;
+  proxy = create_mount_operation_proxy (source, NULL, NULL);
+  if (proxy == NULL)
+    return FALSE;
+  
+  gvfs_dbus_mount_operation_call_aborted (proxy, NULL, 
+                                          (GAsyncReadyCallback) abort_reply, NULL);
+  
+  g_object_unref (proxy);
+  return TRUE;
 }
 
 static void
diff --git a/common/gmountsource.h b/common/gmountsource.h
index 31b58af..ce93cb3 100644
--- a/common/gmountsource.h
+++ b/common/gmountsource.h
@@ -54,8 +54,8 @@ GType g_mount_source_get_type (void) G_GNUC_CONST;
 GMountSource *g_mount_source_new                      (const char                *dbus_id,
 						       const char                *obj_path);
 GMountSource *g_mount_source_new_dummy                (void);
-void          g_mount_source_to_dbus                  (GMountSource              *source,
-						       DBusMessage               *message);
+GVariant     *g_mount_source_to_dbus                  (GMountSource              *source);
+GMountSource *g_mount_source_from_dbus                (GVariant                  *iter);
 gboolean      g_mount_source_ask_password             (GMountSource              *mount_source,
 						       const char                *message,
 						       const char                *initial_user,
diff --git a/common/gmountspec.c b/common/gmountspec.c
index 5c42d90..968032c 100644
--- a/common/gmountspec.c
+++ b/common/gmountspec.c
@@ -27,7 +27,6 @@
 
 #include <glib/gi18n-lib.h>
 
-#include "gvfsdbusutils.h"
 #include "gmountspec.h"
 
 static GHashTable *unique_hash = NULL;
@@ -226,113 +225,64 @@ g_mount_spec_unref (GMountSpec *spec)
 }
 
 GMountSpec *
-g_mount_spec_from_dbus (DBusMessageIter *iter)
+g_mount_spec_from_dbus (GVariant *iter)
 {
   GMountSpec *spec;
-  DBusMessageIter array_iter, struct_iter, spec_iter;
-  const char *key;
-  char *value;
-  char *mount_prefix;
-
-  if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
-    return NULL;
-
-  dbus_message_iter_recurse (iter, &spec_iter);
+  const gchar *key;
+  const gchar *mount_prefix;
+  GVariantIter *iter_mount_spec_items;
+  GVariant *value;
 
   mount_prefix = NULL;
-  if (!_g_dbus_message_iter_get_args (&spec_iter, NULL,
-				      G_DBUS_TYPE_CSTRING, &mount_prefix,
-				      0))
-    return NULL;
-
+  g_variant_get (iter, "(^&aya{sv})",
+                 &mount_prefix,
+                 &iter_mount_spec_items);
+  
   spec = g_mount_spec_new (NULL);
   g_free (spec->mount_prefix);
-  spec->mount_prefix = mount_prefix;
-  
-  if (dbus_message_iter_get_arg_type (&spec_iter) != DBUS_TYPE_ARRAY ||
-      dbus_message_iter_get_element_type (&spec_iter) != DBUS_TYPE_STRUCT)
-    {
-      g_mount_spec_unref (spec);
-      return NULL;
-    }
+  spec->mount_prefix = g_strdup (mount_prefix);
 
-  dbus_message_iter_recurse (&spec_iter, &array_iter);
-  while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+  while (g_variant_iter_loop (iter_mount_spec_items, "{&sv}", &key, &value))
     {
-      dbus_message_iter_recurse (&array_iter, &struct_iter);
-      if (_g_dbus_message_iter_get_args (&struct_iter, NULL,
-					 DBUS_TYPE_STRING, &key,
-					 G_DBUS_TYPE_CSTRING, &value,
-					 0))
-	add_item (spec, key, value);
-      dbus_message_iter_next (&array_iter);
+      add_item (spec, key, g_variant_dup_bytestring (value, NULL));
     }
 
-  dbus_message_iter_next (iter);
-  
   /* Sort on key */
   g_array_sort (spec->items, item_compare);
   
   return spec;
 }
 
-void
-g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
-				GMountSpec *spec,
+GVariant *
+g_mount_spec_to_dbus_with_path (GMountSpec *spec,
 				const char *path)
 {
-  DBusMessageIter spec_iter, array_iter, item_iter;
+  GVariantBuilder builder;
+  GVariant *v;
   int i;
 
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_STRUCT,
-					 NULL,
-					 &spec_iter))
-    _g_dbus_oom ();
-
-  _g_dbus_message_iter_append_cstring (&spec_iter, path ? path : "");
-
-  if (!dbus_message_iter_open_container (&spec_iter,
-					 DBUS_TYPE_ARRAY,
- 					 G_MOUNT_SPEC_ITEM_TYPE_AS_STRING,
-					 &array_iter))
-    _g_dbus_oom ();
-
+  g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
   for (i = 0; i < spec->items->len; i++)
     {
       GMountSpecItem *item = &g_array_index (spec->items, GMountSpecItem, i);
 
-      if (!dbus_message_iter_open_container (&array_iter,
-					     DBUS_TYPE_STRUCT,
-					     NULL,
-					     &item_iter))
-	_g_dbus_oom ();
-
-      if (!dbus_message_iter_append_basic (&item_iter, DBUS_TYPE_STRING,
-					   &item->key))
-	_g_dbus_oom ();
-      _g_dbus_message_iter_append_cstring  (&item_iter, item->value);
-      
-      if (!dbus_message_iter_close_container (&array_iter, &item_iter))
-	_g_dbus_oom ();
-      
+      g_variant_builder_add_value (&builder, g_variant_new ("{sv}",
+                                                            item->key,
+                                                            g_variant_new_bytestring (item->value)));
     }
   
-  if (!dbus_message_iter_close_container (&spec_iter, &array_iter))
-    _g_dbus_oom ();
-  
+  v = g_variant_new ("(^aya{sv})",
+                      path ? path : "",
+                      &builder);
+  g_variant_builder_clear (&builder);
   
-  
-  if (!dbus_message_iter_close_container (iter, &spec_iter))
-    _g_dbus_oom ();
-    
+  return v;
 }
 
-void
-g_mount_spec_to_dbus (DBusMessageIter *iter,
-		      GMountSpec      *spec)
+GVariant *
+g_mount_spec_to_dbus (GMountSpec *spec)
 {
-  g_mount_spec_to_dbus_with_path (iter, spec, spec->mount_prefix);
+  return g_mount_spec_to_dbus_with_path (spec, spec->mount_prefix);
 }
 
 static gboolean
diff --git a/common/gmountspec.h b/common/gmountspec.h
index f7837e6..da903e1 100644
--- a/common/gmountspec.h
+++ b/common/gmountspec.h
@@ -24,28 +24,10 @@
 #define __G_MOUNT_SPEC_H__
 
 #include <glib.h>
-#include <dbus/dbus.h>
+#include <gio/gio.h>
 
 G_BEGIN_DECLS
 
-#define G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING         \
-    DBUS_TYPE_STRING_AS_STRING                         \
-    DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
-
-#define G_MOUNT_SPEC_ITEM_TYPE_AS_STRING  \
-  DBUS_STRUCT_BEGIN_CHAR_AS_STRING        \
-   G_MOUNT_SPEC_ITEM_INNER_TYPE_AS_STRING \
-  DBUS_STRUCT_END_CHAR_AS_STRING 
-
-#define G_MOUNT_SPEC_INNER_TYPE_AS_STRING                     \
-   DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING         \
-   DBUS_TYPE_ARRAY_AS_STRING G_MOUNT_SPEC_ITEM_TYPE_AS_STRING 
-
-#define G_MOUNT_SPEC_TYPE_AS_STRING  \
-  DBUS_STRUCT_BEGIN_CHAR_AS_STRING   \
-   G_MOUNT_SPEC_INNER_TYPE_AS_STRING \
-  DBUS_STRUCT_END_CHAR_AS_STRING 
-
 typedef struct {
   char *key;
   char *value;
@@ -65,11 +47,9 @@ GMountSpec *g_mount_spec_ref               (GMountSpec      *spec);
 void        g_mount_spec_unref             (GMountSpec      *spec);
 GMountSpec *g_mount_spec_get_unique_for    (GMountSpec      *spec);
 GMountSpec *g_mount_spec_copy              (GMountSpec      *spec);
-GMountSpec *g_mount_spec_from_dbus         (DBusMessageIter *iter);
-void        g_mount_spec_to_dbus           (DBusMessageIter *iter,
-					    GMountSpec      *spec);
-void        g_mount_spec_to_dbus_with_path (DBusMessageIter *iter,
-					    GMountSpec      *spec,
+GMountSpec *g_mount_spec_from_dbus         (GVariant        *iter);
+GVariant   *g_mount_spec_to_dbus           (GMountSpec      *spec);
+GVariant   *g_mount_spec_to_dbus_with_path (GMountSpec      *spec,
 					    const char      *path);
 void        g_mount_spec_set_mount_prefix  (GMountSpec      *spec,
 					    const char      *mount_prefix);
diff --git a/common/gmounttracker.c b/common/gmounttracker.c
index 00908ca..a390988 100644
--- a/common/gmounttracker.c
+++ b/common/gmounttracker.c
@@ -25,8 +25,8 @@
 #include <string.h>
 
 #include <gmounttracker.h>
-#include <gvfsdbusutils.h>
 #include <gvfsdaemonprotocol.h>
+#include <gvfsdbus.h>
 
 enum {
   MOUNTED,
@@ -51,14 +51,12 @@ struct _GMountTracker
 
   GMutex lock;
   GList *mounts;
-  DBusConnection *connection;
+  GDBusConnection *connection;
+  GVfsDBusMountTracker *proxy;
 };
 
 G_DEFINE_TYPE (GMountTracker, g_mount_tracker, G_TYPE_OBJECT)
 
-static DBusHandlerResult g_mount_tracker_filter_func  (DBusConnection        *conn,
-						       DBusMessage           *message,
-						       gpointer               data);
 static GObject*          g_mount_tracker_constructor  (GType                  type,
 						       guint                  n_construct_properties,
 						       GObjectConstructParam *construct_params);
@@ -174,53 +172,41 @@ g_mount_info_apply_prefix (GMountInfo  *info,
 }
 
 GMountInfo *
-g_mount_info_from_dbus (DBusMessageIter *iter)
+g_mount_info_from_dbus (GVariant *iter)
 {
-  DBusMessageIter struct_iter;
   GMountInfo *info;
   GMountSpec *mount_spec;
-  dbus_bool_t user_visible;
-  char *display_name;
-  char *stable_name;
-  char *x_content_types;
-  char *icon_str;
-  char *prefered_filename_encoding;
-  char *dbus_id;
-  char *obj_path;
-  char *fuse_mountpoint;
-  char *default_location;
+  gboolean user_visible;
+  const gchar *display_name;
+  const gchar *stable_name;
+  const gchar *x_content_types;
+  const gchar *icon_str;
+  const gchar *prefered_filename_encoding;
+  const gchar *dbus_id;
+  const gchar *obj_path;
+  const gchar *fuse_mountpoint;
+  const gchar *default_location;
   GIcon *icon;
+  GVariant *iter_mount_spec;
   GError *error;
 
-  if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
+  g_variant_get (iter, "(&s&o&s&s&s&s&sb^&ay@(aya{sv})^&ay)",
+                 &dbus_id,
+                 &obj_path,
+                 &display_name,
+                 &stable_name,
+                 &x_content_types,
+                 &icon_str,
+                 &prefered_filename_encoding,
+                 &user_visible,
+                 &fuse_mountpoint,
+                 &iter_mount_spec,
+                 &default_location);
+
+  mount_spec = g_mount_spec_from_dbus (iter_mount_spec);
+  g_variant_unref (iter_mount_spec);
+  if (mount_spec == NULL)
     return NULL;
-    
-  dbus_message_iter_recurse (iter, &struct_iter);
-    
-  if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
-				      DBUS_TYPE_STRING, &dbus_id,
-				      DBUS_TYPE_OBJECT_PATH, &obj_path,
-				      DBUS_TYPE_STRING, &display_name,
-				      DBUS_TYPE_STRING, &stable_name,
-                                      DBUS_TYPE_STRING, &x_content_types,
-				      DBUS_TYPE_STRING, &icon_str,
-				      DBUS_TYPE_STRING, &prefered_filename_encoding,
-				      DBUS_TYPE_BOOLEAN, &user_visible,
-				      G_DBUS_TYPE_CSTRING, &fuse_mountpoint,
-				      0))
-    return NULL;
-
-  mount_spec = g_mount_spec_from_dbus (&struct_iter);
-  if (mount_spec == NULL) {
-    g_free (fuse_mountpoint);
-    return NULL;
-  }
-
-  if (!_g_dbus_message_iter_get_args (&struct_iter, NULL,
-                                      G_DBUS_TYPE_CSTRING, &default_location,
-                                      0))
-    default_location = g_strdup ("");
-
 
   if (icon_str == NULL || strlen (icon_str) == 0)
     icon_str = "drive-removable-media";
@@ -244,13 +230,12 @@ g_mount_info_from_dbus (DBusMessageIter *iter)
   info->mount_spec = mount_spec;
   info->user_visible = user_visible;
   info->prefered_filename_encoding = g_strdup (prefered_filename_encoding);
-  info->fuse_mountpoint = fuse_mountpoint;
-  info->default_location = default_location;
+  info->fuse_mountpoint = g_strdup (fuse_mountpoint);
+  info->default_location = g_strdup (default_location);
 
   return info;
 }
 
-
 static void
 g_mount_tracker_finalize (GObject *object)
 {
@@ -264,21 +249,10 @@ g_mount_tracker_finalize (GObject *object)
 		  (GFunc)g_mount_info_unref, NULL);
   g_list_free (tracker->mounts);
 
-  dbus_connection_remove_filter (tracker->connection, g_mount_tracker_filter_func, tracker);
-
-
-  dbus_bus_remove_match (tracker->connection,
-			 "sender='"G_VFS_DBUS_DAEMON_NAME"',"
-			 "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
-			 "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
-			 NULL);
-  dbus_bus_remove_match (tracker->connection,
-			 "sender='"G_VFS_DBUS_DAEMON_NAME"',"
-			 "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
-			 "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
-			 NULL);
-  
-  dbus_connection_unref (tracker->connection);
+  if (tracker->proxy)
+    g_object_unref (tracker->proxy);
+  if (tracker->connection)
+    g_object_unref (tracker->connection);
   
   if (G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_mount_tracker_parent_class)->finalize) (object);
@@ -332,10 +306,10 @@ g_mount_tracker_set_property (GObject         *object,
     {
     case PROP_CONNECTION:
       if (tracker->connection)
-	dbus_connection_unref (tracker->connection);
+	g_object_unref (tracker->connection);
       tracker->connection = NULL;
       if (g_value_get_pointer (value))
-	tracker->connection = dbus_connection_ref (g_value_get_pointer (value));
+	tracker->connection = g_object_ref (g_value_get_pointer (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -427,115 +401,94 @@ g_mount_tracker_remove_mount (GMountTracker *tracker,
 
 static void
 list_mounts_reply (GMountTracker *tracker,
-		   DBusMessage *reply)
+                   GVariant *iter_mounts)
 {
-  DBusMessageIter iter, array_iter;
   GMountInfo *info;
-  gboolean b;
-
-  b = dbus_message_iter_init (reply, &iter);
-  if (b && dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_ARRAY)
+  GVariantIter iter;
+  GVariant *child;
+  
+  g_variant_iter_init (&iter, iter_mounts);
+  while ((child = g_variant_iter_next_value (&iter)))
     {
-      dbus_message_iter_recurse (&iter, &array_iter);
-    
-      do
+      info = g_mount_info_from_dbus (child);
+      if (info)
         {
-          info = g_mount_info_from_dbus (&array_iter);
-          if (info)
-    	{
-    	  g_mount_tracker_add_mount (tracker, info);
-    	  g_mount_info_unref (info);
-    	}
+          g_mount_tracker_add_mount (tracker, info);
+          g_mount_info_unref (info);
         }
-      while (dbus_message_iter_next (&array_iter));
-    }
-  else
-    {
-      /* list_mounts_reply problem - gvfsd not running? */
+      g_variant_unref (child);
     }
 }
 
-static DBusHandlerResult
-g_mount_tracker_filter_func (DBusConnection *conn,
-			     DBusMessage    *message,
-			     gpointer        data)
+static void
+mounted_cb (GVfsDBusMountTracker *object,
+            GVariant *arg_mount,
+            gpointer user_data)
 {
-  GMountTracker *tracker = data;
+  GMountTracker *tracker = user_data;
   GMountInfo *info;
-  DBusMessageIter iter;
-
-  if (dbus_message_is_signal (message,
-			      G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-			      G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED))
+  
+  info = g_mount_info_from_dbus (arg_mount);
+  if (info)
     {
-      dbus_message_iter_init (message, &iter);
-      info = g_mount_info_from_dbus (&iter);
-
-      if (info)
-	{
-	  g_mount_tracker_add_mount (tracker, info);
-	  g_mount_info_unref (info);
-	}
+      g_mount_tracker_add_mount (tracker, info);
+      g_mount_info_unref (info);
     }
-  else if (dbus_message_is_signal (message,
-				   G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				   G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED))
-    {
-      dbus_message_iter_init (message, &iter);
-      info = g_mount_info_from_dbus (&iter);
+}
 
-      if (info)
-	{
-	  g_mount_tracker_remove_mount (tracker, info);
-	  g_mount_info_unref (info);
-	}
+static void
+unmounted_cb (GVfsDBusMountTracker *object,
+              GVariant *arg_mount,
+              gpointer user_data)
+{
+  GMountTracker *tracker = user_data;
+  GMountInfo *info;
+  
+  info = g_mount_info_from_dbus (arg_mount);
+  if (info)
+    {
+      g_mount_tracker_remove_mount (tracker, info);
+      g_mount_info_unref (info);
     }
-    
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  
 }
 
 /* Called after construction when the construct properties (like connection) are set */
 static void
 init_connection (GMountTracker *tracker)
 {
-  DBusMessage *message, *reply;
+  GError *error;
+  GVariant *iter_mounts;
 
   if (tracker->connection == NULL)
-    tracker->connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-
-  message =
-    dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-				  G_VFS_DBUS_MOUNTTRACKER_PATH,
-				  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				  G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS);
-  if (message == NULL)
-    _g_dbus_oom ();
-  
-  dbus_message_set_auto_start (message, TRUE);
-  
-  reply = dbus_connection_send_with_reply_and_block (tracker->connection, message,
-						     G_VFS_DBUS_TIMEOUT_MSECS,
-						     NULL);
-  dbus_message_unref (message);
-  
-  if (reply != NULL)
+    tracker->connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+
+  error = NULL;
+  tracker->proxy = gvfs_dbus_mount_tracker_proxy_new_sync (tracker->connection,
+                                                           G_DBUS_PROXY_FLAGS_NONE,
+                                                           G_VFS_DBUS_DAEMON_NAME,
+                                                           G_VFS_DBUS_MOUNTTRACKER_PATH,
+                                                           NULL,
+                                                           &error);
+  if (tracker->proxy == NULL)
     {
-      list_mounts_reply (tracker, reply);
-      dbus_message_unref (reply);
+      g_printerr ("Error creating proxy: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      return;
     }
-  
-  dbus_connection_add_filter (tracker->connection, g_mount_tracker_filter_func, tracker, NULL);
-      
-  dbus_bus_add_match (tracker->connection,
-		      "sender='"G_VFS_DBUS_DAEMON_NAME"',"
-		      "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
-		      "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED"'",
-		      NULL);
-  dbus_bus_add_match (tracker->connection,
-		      "sender='"G_VFS_DBUS_DAEMON_NAME"',"
-		      "interface='"G_VFS_DBUS_MOUNTTRACKER_INTERFACE"',"
-		      "member='"G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED"'",
-		      NULL);
+
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (tracker->proxy), 
+                                    G_VFS_DBUS_TIMEOUT_MSECS);
+
+  if (gvfs_dbus_mount_tracker_call_list_mounts_sync (tracker->proxy, &iter_mounts, NULL, NULL))
+    {
+      list_mounts_reply (tracker, iter_mounts);
+      g_variant_unref (iter_mounts);
+    }
+
+  g_signal_connect (tracker->proxy, "mounted", G_CALLBACK (mounted_cb), tracker);
+  g_signal_connect (tracker->proxy, "unmounted", G_CALLBACK (unmounted_cb), tracker);
 }
 
 static void
@@ -565,7 +518,7 @@ g_mount_tracker_constructor (GType                  type,
 }
 
 GMountTracker *
-g_mount_tracker_new (DBusConnection *connection)
+g_mount_tracker_new (GDBusConnection *connection)
 {
   GMountTracker *tracker;
 
diff --git a/common/gmounttracker.h b/common/gmounttracker.h
index caaab8a..894bddb 100644
--- a/common/gmounttracker.h
+++ b/common/gmounttracker.h
@@ -76,9 +76,9 @@ const char *g_mount_info_resolve_path (GMountInfo *info,
 void        g_mount_info_apply_prefix (GMountInfo *info,
                                        char      **path);
 
-GMountInfo * g_mount_info_from_dbus (DBusMessageIter *iter);
+GMountInfo * g_mount_info_from_dbus (GVariant *iter);
 
-GMountTracker *g_mount_tracker_new                (DBusConnection *connection);
+GMountTracker *g_mount_tracker_new                (GDBusConnection *connection);
 GList *        g_mount_tracker_list_mounts        (GMountTracker *tracker);
 GMountInfo *   g_mount_tracker_find_by_mount_spec (GMountTracker *tracker,
 						   GMountSpec    *mount_spec);
diff --git a/common/gvfsdaemonprotocol.c b/common/gvfsdaemonprotocol.c
index b35efcb..c73aac7 100644
--- a/common/gvfsdaemonprotocol.c
+++ b/common/gvfsdaemonprotocol.c
@@ -23,48 +23,22 @@
 #include <config.h>
 
 #include <glib-object.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n-lib.h>
 #include <gvfsdaemonprotocol.h>
-#include <gvfsdbusutils.h>
 #include <gio/gio.h>
 
 static const char *
 get_object_signature (GObject *obj)
 {
   if (G_IS_ICON (obj))
-    {
-      return
-	DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-	 DBUS_TYPE_UINT32_AS_STRING
-	 DBUS_TYPE_STRING_AS_STRING
-	DBUS_STRUCT_END_CHAR_AS_STRING;
-    }
-  return
-    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-     DBUS_TYPE_UINT32_AS_STRING
-    DBUS_STRUCT_END_CHAR_AS_STRING;
+      return "(us)";
+  return "(u)";
 }
 
-static void
-append_strv (DBusMessageIter *iter, char **strv)
+static GVariant *
+append_object (GObject *obj)
 {
-  _g_dbus_message_iter_append_args (iter,
-				    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &strv, g_strv_length (strv),
-				    0);
-}
-
-static void
-append_object (DBusMessageIter *iter, GObject *obj)
-{
-  DBusMessageIter obj_struct_iter;
-  guint32 v_uint32;
-  
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_STRUCT,
-					 NULL,
-					 &obj_struct_iter))
-    _g_dbus_oom ();
+  GVariant *var;
 
   /* version 1 and 2 are deprecated old themed-icon and file-icon values */
   if (G_IS_ICON (obj))
@@ -72,15 +46,7 @@ append_object (DBusMessageIter *iter, GObject *obj)
       char *data;
 
       data = g_icon_to_string (G_ICON (obj));
-      v_uint32 = 3;
-      if (!dbus_message_iter_append_basic (&obj_struct_iter,
-					   DBUS_TYPE_UINT32, &v_uint32))
-	_g_dbus_oom ();
-
-      if (!dbus_message_iter_append_basic (&obj_struct_iter,
-					   DBUS_TYPE_STRING, &data))
-	_g_dbus_oom ();
-
+      var = g_variant_new ("(us)", 3, data);
       g_free (data);
     }
   else
@@ -89,14 +55,10 @@ append_object (DBusMessageIter *iter, GObject *obj)
       if (obj != NULL)
 	g_warning ("Unknown attribute object type, ignoring");
       
-      v_uint32 = 0;
-      if (!dbus_message_iter_append_basic (&obj_struct_iter,
-					   DBUS_TYPE_UINT32, &v_uint32))
-	_g_dbus_oom ();
+      var = g_variant_new ("(u)", 0);
     }
-  
-  if (!dbus_message_iter_close_container (iter, &obj_struct_iter))
-    _g_dbus_oom ();
+
+  return var;
 }
 
 void
@@ -135,42 +97,42 @@ _g_dbus_attribute_as_pointer (GFileAttributeType type,
   }
 }
 
-const char *
+static const char *
 _g_dbus_type_from_file_attribute_type (GFileAttributeType type)
 {
-  char *dbus_type;
+  const char *dbus_type;
 
   switch (type)
     {
     case G_FILE_ATTRIBUTE_TYPE_STRING:
-      dbus_type = DBUS_TYPE_STRING_AS_STRING;
+      dbus_type = "s";
       break;
     case G_FILE_ATTRIBUTE_TYPE_BYTE_STRING:
-      dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
+      dbus_type = "ay";
       break;
     case G_FILE_ATTRIBUTE_TYPE_STRINGV:
-      dbus_type = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING;
+      dbus_type = "as";
       break;
     case G_FILE_ATTRIBUTE_TYPE_BOOLEAN:
-      dbus_type = DBUS_TYPE_BOOLEAN_AS_STRING;
+      dbus_type = "b";
       break;
     case G_FILE_ATTRIBUTE_TYPE_UINT32:
-      dbus_type = DBUS_TYPE_UINT32_AS_STRING;
+      dbus_type = "u";
       break;
     case G_FILE_ATTRIBUTE_TYPE_INT32:
-      dbus_type = DBUS_TYPE_INT32_AS_STRING;
+      dbus_type = "i";
       break;
     case G_FILE_ATTRIBUTE_TYPE_UINT64:
-      dbus_type = DBUS_TYPE_UINT64_AS_STRING;
+      dbus_type = "t";
       break;
     case G_FILE_ATTRIBUTE_TYPE_INT64:
-      dbus_type = DBUS_TYPE_INT64_AS_STRING;
+      dbus_type = "x";
       break;
     case G_FILE_ATTRIBUTE_TYPE_OBJECT:
-      dbus_type = DBUS_TYPE_STRUCT_AS_STRING;
+      dbus_type = "r";
       break;
     case G_FILE_ATTRIBUTE_TYPE_INVALID:
-      dbus_type = DBUS_TYPE_BYTE_AS_STRING;
+      dbus_type = "ay";
       break;
     default:
       dbus_type = NULL;
@@ -181,114 +143,65 @@ _g_dbus_type_from_file_attribute_type (GFileAttributeType type)
   return dbus_type;
 }
 
-void
-_g_dbus_append_file_attribute (DBusMessageIter *iter,
-			       const char *attribute,
+GVariant *
+_g_dbus_append_file_attribute (const char *attribute,
 			       GFileAttributeStatus status,
 			       GFileAttributeType type,
 			       gpointer value_p)
 {
-  DBusMessageIter variant_iter, inner_struct_iter;
   const char *dbus_type;
-  guint32 dbus_status;
+  GVariant *v;
 
   dbus_type = _g_dbus_type_from_file_attribute_type (type);
 
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_STRUCT,
-					 NULL,
-					 &inner_struct_iter))
-    _g_dbus_oom ();
-
-  if (!dbus_message_iter_append_basic (&inner_struct_iter,
-				       DBUS_TYPE_STRING,
-				       &attribute))
-    _g_dbus_oom ();
-
-  dbus_status = status;
-  if (!dbus_message_iter_append_basic (&inner_struct_iter,
-				       DBUS_TYPE_UINT32,
-				       &dbus_status))
-    _g_dbus_oom ();
-
-  if (dbus_type[0] == DBUS_TYPE_STRUCT)
+  if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_TUPLE))
     dbus_type = get_object_signature ((GObject *)value_p);
-  
-  if (!dbus_message_iter_open_container (&inner_struct_iter,
-					 DBUS_TYPE_VARIANT,
-					 dbus_type,
-					 &variant_iter))
-    _g_dbus_oom ();
 
-  if (dbus_type[0] == DBUS_TYPE_STRING)
-    {
-      if (!dbus_message_iter_append_basic (&variant_iter,
-					   DBUS_TYPE_STRING, &value_p))
-	_g_dbus_oom ();
-    }
-  else if (dbus_type[0] == DBUS_TYPE_ARRAY && dbus_type[1] == DBUS_TYPE_BYTE)
-    _g_dbus_message_iter_append_cstring (&variant_iter, (char *)value_p);
-  else if (dbus_type[0] == DBUS_TYPE_ARRAY && dbus_type[1] == DBUS_TYPE_STRING)
-    append_strv (&variant_iter, (char **)value_p);
-  else if (dbus_type[0] == DBUS_TYPE_BYTE)
-    {
-      char byte = 0;
-      if (!dbus_message_iter_append_basic (&variant_iter,
-					   DBUS_TYPE_BYTE, &byte))
-	_g_dbus_oom ();
-    }
-  else if (dbus_type[0] == DBUS_STRUCT_BEGIN_CHAR)
-    append_object (&variant_iter, (GObject *)value_p);
-  else if (dbus_type[0] == DBUS_TYPE_BOOLEAN)
-    {
-      /* dbus bool is uint32, gboolean is just "int", convert */
-      dbus_bool_t bool = *(gboolean *)value_p;
-      if (!dbus_message_iter_append_basic (&variant_iter,
-					   dbus_type[0], &bool))
-	_g_dbus_oom ();
-    }
+  if (g_variant_type_is_tuple (G_VARIANT_TYPE (dbus_type)))
+    v = append_object ((GObject *)value_p);
   else
+  if (g_variant_type_is_array (G_VARIANT_TYPE (dbus_type)))
     {
-      /* All other types have the same size as dbus types */
-      if (!dbus_message_iter_append_basic (&variant_iter,
-					   dbus_type[0], value_p))
-	_g_dbus_oom ();
-    }
-
-  if (!dbus_message_iter_close_container (&inner_struct_iter, &variant_iter))
-    _g_dbus_oom ();
+      char *s;
       
-  if (!dbus_message_iter_close_container (iter, &inner_struct_iter))
-    _g_dbus_oom ();
+      s = g_strdup_printf ("^%s", dbus_type);
+      v = g_variant_new (s, value_p);
+      g_free (s);
+    }
+  else
+  if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_UINT32))
+    v = g_variant_new (dbus_type, *(guint32 *)value_p);
+  else
+  if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_INT32))
+    v = g_variant_new (dbus_type, *(gint32 *)value_p);
+  else
+  if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_UINT64))
+    v = g_variant_new (dbus_type, *(guint64 *)value_p);
+  else
+  if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_INT64))
+    v = g_variant_new (dbus_type, *(gint64 *)value_p);
+  else
+  if (g_variant_type_equal (G_VARIANT_TYPE (dbus_type), G_VARIANT_TYPE_BOOLEAN))
+    v = g_variant_new (dbus_type, *(gboolean *)value_p);
+  else
+    v = g_variant_new (dbus_type, value_p);
+  
+  return g_variant_new ("(suv)",
+                        attribute,
+                        status,
+                        v);
 }
 
-void
-_g_dbus_append_file_info (DBusMessageIter *iter,
-			  GFileInfo *info)
+GVariant *
+_g_dbus_append_file_info (GFileInfo *info)
 {
-  DBusMessageIter struct_iter, array_iter;
+  GVariantBuilder builder;
   char **attributes;
   int i;
 
-  attributes = g_file_info_list_attributes (info, NULL);
-
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_STRUCT,
-					 NULL,
-					 &struct_iter))
-    _g_dbus_oom ();
-
-
-  if (!dbus_message_iter_open_container (&struct_iter,
-					 DBUS_TYPE_ARRAY,
-					 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-					 DBUS_TYPE_STRING_AS_STRING	
-					 DBUS_TYPE_UINT32_AS_STRING
-					 DBUS_TYPE_VARIANT_AS_STRING	
-					 DBUS_STRUCT_END_CHAR_AS_STRING,
-					 &array_iter))
-    _g_dbus_oom ();
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(suv)"));
 
+  attributes = g_file_info_list_attributes (info, NULL);
   for (i = 0; attributes[i] != NULL; i++)
     {
       GFileAttributeType type;
@@ -296,323 +209,194 @@ _g_dbus_append_file_info (DBusMessageIter *iter,
       gpointer value_p;
 
       if (g_file_info_get_attribute_data (info, attributes[i], &type, &value_p, &status))
-	_g_dbus_append_file_attribute (&array_iter, attributes [i], status, type, value_p);
+        g_variant_builder_add_value (&builder, 
+            _g_dbus_append_file_attribute (attributes[i], status, type, value_p));
     }
-  
   g_strfreev (attributes);
 
-  if (!dbus_message_iter_close_container (&struct_iter, &array_iter))
-    _g_dbus_oom ();
-      
-  if (!dbus_message_iter_close_container (iter, &struct_iter))
-    _g_dbus_oom ();
+  return g_variant_builder_end (&builder);
 }
 
 gboolean
-_g_dbus_get_file_attribute (DBusMessageIter *iter,
+_g_dbus_get_file_attribute (GVariant *iter,
 			    gchar **attribute,
 			    GFileAttributeStatus *status,
 			    GFileAttributeType *type,
 			    GDbusAttributeValue *value)
 {
+  gboolean res;
   char *str;
-  char **strs;
-  int n_elements;
-  DBusMessageIter inner_struct_iter, variant_iter, cstring_iter, obj_iter;
-  const gchar *attribute_temp;
-  int element_type;
-  dbus_uint32_t obj_type, dbus_status;
-  dbus_bool_t dbus_bool;
-  guint8 byte;
+  guint32 obj_type;
   GObject *obj;
+  GVariant *v;
 
-  dbus_message_iter_recurse (iter, &inner_struct_iter);
-
-  if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_STRING)
-    goto error;
-	
-  dbus_message_iter_get_basic (&inner_struct_iter, &attribute_temp);
-  *attribute = g_strdup (attribute_temp);
-
-  dbus_message_iter_next (&inner_struct_iter);
-
-  dbus_message_iter_get_basic (&inner_struct_iter, &dbus_status);
-  if (status)
-    *status = dbus_status;
-
-  dbus_message_iter_next (&inner_struct_iter);
-
-  if (dbus_message_iter_get_arg_type (&inner_struct_iter) != DBUS_TYPE_VARIANT)
-    goto error;
-
-  dbus_message_iter_recurse (&inner_struct_iter, &variant_iter);
+  g_variant_get (iter, "(suv)",
+                 attribute,
+                 status,
+                 &v);
 
-  switch (dbus_message_iter_get_arg_type (&variant_iter))
+  res = TRUE;
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING))
     {
-    case DBUS_TYPE_STRING:
       *type = G_FILE_ATTRIBUTE_TYPE_STRING;
-      dbus_message_iter_get_basic (&variant_iter, &str);
-      value->ptr = g_strdup (str);
-      break;
-    case DBUS_TYPE_ARRAY:
-      element_type = dbus_message_iter_get_element_type (&variant_iter);
-      if (element_type == DBUS_TYPE_BYTE)
-	{
-	  *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
-
-	  dbus_message_iter_recurse (&variant_iter, &cstring_iter);
-	  dbus_message_iter_get_fixed_array (&cstring_iter,
-					     &str, &n_elements);
-	  value->ptr = g_strndup (str, n_elements);
-	}
-      else if (element_type == DBUS_TYPE_STRING)
-	{
-	  char **strv;
-	  int n_elements;
-	  if (!_g_dbus_message_iter_get_args (&variant_iter, NULL,
-					      DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &strv, &n_elements,
-					      0))
-	    goto error;
-	  *type = G_FILE_ATTRIBUTE_TYPE_STRINGV;
-	  value->ptr = strv;
-	}
-      else
-	goto error;
-
-      break;
-    case DBUS_TYPE_BYTE:
-      dbus_message_iter_get_basic (&variant_iter, &byte);
+      g_variant_get (v, "s", &value->ptr);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_BYTESTRING))
+    {
+      *type = G_FILE_ATTRIBUTE_TYPE_BYTE_STRING;
+      g_variant_get (v, "^ay", &value->ptr);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_STRING_ARRAY))
+    {
+      *type = G_FILE_ATTRIBUTE_TYPE_STRINGV;
+      g_variant_get (v, "^as", &value->ptr);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_BYTE))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_INVALID;
-      break;
-    case DBUS_TYPE_BOOLEAN:
-      dbus_message_iter_get_basic (&variant_iter, &dbus_bool);
-      value->boolean = dbus_bool;
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_BOOLEAN;
-      break;
-    case DBUS_TYPE_UINT32:
-      dbus_message_iter_get_basic (&variant_iter, value);
+      g_variant_get (v, "b", &value->boolean);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_UINT32))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_UINT32;
-      break;
-    case DBUS_TYPE_INT32:
-      dbus_message_iter_get_basic (&variant_iter, value);
+      g_variant_get (v, "u", &value->uint32);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_INT32))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_INT32;
-      break;
-    case DBUS_TYPE_UINT64:
-      dbus_message_iter_get_basic (&variant_iter, value);
+      g_variant_get (v, "i", &value->ptr);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_UINT64))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_UINT64;
-      break;
-    case DBUS_TYPE_INT64:
-      dbus_message_iter_get_basic (&variant_iter, value);
+      g_variant_get (v, "t", &value->uint64);
+    } 
+  else
+  if (g_variant_is_of_type (v, G_VARIANT_TYPE_INT64))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_INT64;
-      break;
-    case DBUS_TYPE_STRUCT:
-      dbus_message_iter_recurse (&variant_iter, &obj_iter);
-      if (dbus_message_iter_get_arg_type (&obj_iter) != DBUS_TYPE_UINT32)
-	goto error;
-      
+      g_variant_get (v, "x", &value->ptr);
+    } 
+  else
+  if (g_variant_is_container (v))
+    {
       *type = G_FILE_ATTRIBUTE_TYPE_OBJECT;
 
-      dbus_message_iter_get_basic (&obj_iter, &obj_type);
-      obj = NULL;
-      
-      dbus_message_iter_next (&obj_iter);
-      /* 0 == NULL */
-
-      if (obj_type == 1)
-	{
-	  /* Old deprecated G_THEMED_ICON */
-	  if (_g_dbus_message_iter_get_args (&obj_iter,
-					     NULL,
-					     DBUS_TYPE_ARRAY, DBUS_TYPE_STRING,
-					     &strs, &n_elements, 0))
-	    {
-	      obj = G_OBJECT (g_themed_icon_new_from_names (strs, n_elements));
-	      g_strfreev (strs);
-	    }
-	}
-      else if (obj_type == 2)
-	{
-	  /* Old deprecated G_FILE_ICON, w/ local file */
-	  if (_g_dbus_message_iter_get_args (&obj_iter,
-					     NULL,
-					     G_DBUS_TYPE_CSTRING, &str,
-					     0))
-	    {
-	      GFile *file = g_file_new_for_path (str);
-	      obj = G_OBJECT (g_file_icon_new (file));
-	      g_free (str);
-	    }
-	}
-      else if (obj_type == 3)
-	{
-	  /* serialized G_ICON */
-	  if (_g_dbus_message_iter_get_args (&obj_iter,
-					     NULL,
-					     DBUS_TYPE_STRING, &str,
-					     0))
-	    obj = (GObject *)g_icon_new_for_string (str, NULL);
-	}
+      if (g_variant_is_of_type (v, G_VARIANT_TYPE ("(u)")))
+        {
+          g_variant_get (v, "(u)", &obj_type);
+        }
       else
-	{
-	  /* NULL (or unsupported) */
-	  if (obj_type != 0)
-	    g_warning ("Unsupported object type in file attribute");
-	}
+      if (g_variant_is_of_type (v, G_VARIANT_TYPE ("(us)")))
+        {
+          g_variant_get (v, "(u&s)", &obj_type, &str);
+        }
       
-      value->ptr = obj;
-      break;
-    default:
-      goto error;
-    }
+      obj = NULL;
 
-  return TRUE;
+      /* obj_type 1 and 2 are deprecated and treated as errors */
+      if (obj_type == 3)
+        {
+          /* serialized G_ICON */
+          obj = (GObject *)g_icon_new_for_string (str, NULL);
+        }
+      else
+        {
+          /* NULL (or unsupported) */
+          if (obj_type != 0)
+            g_warning ("Unsupported object type in file attribute");
+        }
+      value->ptr = obj;
+    } 
+  else
+    res = FALSE;
 
- error:
-  return FALSE;
+  g_variant_unref (v);
+  
+  return res;
 }
 
 GFileInfo *
-_g_dbus_get_file_info (DBusMessageIter *iter,
+_g_dbus_get_file_info (GVariant *iter,
 		       GError **error)
 {
   GFileInfo *info;
-  DBusMessageIter struct_iter, array_iter;
   gchar *attribute;
   GFileAttributeType type;
   GFileAttributeStatus status;
   GDbusAttributeValue value;
+  GVariantIter i;
+  GVariant *child;
 
   info = g_file_info_new ();
 
-  if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_STRUCT)
-    goto error;
-
-  dbus_message_iter_recurse (iter, &struct_iter);
-
-  if (dbus_message_iter_get_arg_type (&struct_iter) != DBUS_TYPE_ARRAY)
-    goto error;
-  
-  dbus_message_iter_recurse (&struct_iter, &array_iter);
-
-  while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
+  g_variant_iter_init (&i, iter);
+  while ((child = g_variant_iter_next_value (&i)))
     {
-      if (!_g_dbus_get_file_attribute (&array_iter, &attribute, &status, &type, &value))
+      if (!_g_dbus_get_file_attribute (child, &attribute, &status, &type, &value))
         goto error;
 
       g_file_info_set_attribute (info, attribute, type, _g_dbus_attribute_as_pointer (type, &value));
       if (status)
-	g_file_info_set_attribute_status (info, attribute, status);
+        g_file_info_set_attribute_status (info, attribute, status);
 
       g_free (attribute);
       _g_dbus_attribute_value_destroy (type, &value);
 
-      dbus_message_iter_next (&array_iter);
+      g_variant_unref (child);
     }
 
-  dbus_message_iter_next (iter);
   return info;
 
  error:
   g_object_unref (info);
   g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
 		       _("Invalid file info format"));
-  dbus_message_iter_next (iter);
   return NULL;
 }
 
 GFileAttributeInfoList *
-_g_dbus_get_attribute_info_list (DBusMessageIter *iter,
+_g_dbus_get_attribute_info_list (GVariant *iter,
 				 GError **error)
 {
   GFileAttributeInfoList *list;
-  DBusMessageIter array_iter, struct_iter;
+  GVariantIter i;
   const char *name;
-  dbus_uint32_t type, flags;
+  guint32 type, flags;
   
-  if (dbus_message_iter_get_arg_type (iter) != DBUS_TYPE_ARRAY ||
-      dbus_message_iter_get_element_type (iter) != DBUS_TYPE_STRUCT)
-    {
-      g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			   _("Invalid attribute info list content"));
-      return NULL;
-    }
-
   list = g_file_attribute_info_list_new ();
 
-  dbus_message_iter_recurse (iter, &array_iter);
-  while (dbus_message_iter_get_arg_type (&array_iter) == DBUS_TYPE_STRUCT)
-    {
-      dbus_message_iter_recurse (&array_iter, &struct_iter);
-
-      if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_STRING)
-	{
-	  dbus_message_iter_get_basic (&struct_iter, &name);
-	  dbus_message_iter_next (&struct_iter);
-	  
-	  if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32)
-	    {
-	      dbus_message_iter_get_basic (&struct_iter, &type);
-	      dbus_message_iter_next (&struct_iter);
-	      
-	      if (dbus_message_iter_get_arg_type (&struct_iter) == DBUS_TYPE_UINT32)
-		{
-		  dbus_message_iter_get_basic (&struct_iter, &flags);
-		  
-		  g_file_attribute_info_list_add (list, name, type, flags);
-		}
-	    }
-	}
+  g_variant_iter_init (&i, iter);
+  while (g_variant_iter_next (&i, "(&suu)", &name, &type, &flags))
+    g_file_attribute_info_list_add (list, name, type, flags);
   
-      dbus_message_iter_next (&array_iter);
-    }
-
   return list;
 }
 
-void
-_g_dbus_append_attribute_info_list (DBusMessageIter         *iter,
-				    GFileAttributeInfoList  *list)
+GVariant *
+_g_dbus_append_attribute_info_list (GFileAttributeInfoList *list)
 {
-  DBusMessageIter array_iter, struct_iter;
+  GVariantBuilder builder;
   int i;
-  dbus_uint32_t dbus_type, dbus_flags;
-
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_ARRAY,
-					 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-					 DBUS_TYPE_STRING_AS_STRING	
-					 DBUS_TYPE_UINT32_AS_STRING
-					 DBUS_TYPE_UINT32_AS_STRING	
-					 DBUS_STRUCT_END_CHAR_AS_STRING,
-					 &array_iter))
-    _g_dbus_oom ();
+
+  g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(suu)"));
 
   for (i = 0; i < list->n_infos; i++)
-    {
-      if (!dbus_message_iter_open_container (&array_iter,
-					     DBUS_TYPE_STRUCT,
-					     NULL,
-					     &struct_iter))
-	_g_dbus_oom ();
-
-      if (!dbus_message_iter_append_basic (&struct_iter,
-					   DBUS_TYPE_STRING, &list->infos[i].name))
-	_g_dbus_oom ();
-      
-      dbus_type = list->infos[i].type;
-      if (!dbus_message_iter_append_basic (&struct_iter,
-					   DBUS_TYPE_UINT32, &dbus_type))
-	_g_dbus_oom ();
-      
-      dbus_flags = list->infos[i].flags;
-      if (!dbus_message_iter_append_basic (&struct_iter,
-					   DBUS_TYPE_UINT32, &dbus_flags))
-	_g_dbus_oom ();
-      
-      if (!dbus_message_iter_close_container (&array_iter, &struct_iter))
-	_g_dbus_oom ();
-    }
+    g_variant_builder_add (&builder, "(suu)", 
+                                     list->infos[i].name,
+                                     list->infos[i].type,
+                                     list->infos[i].flags);
   
-  if (!dbus_message_iter_close_container (iter, &array_iter))
-    _g_dbus_oom ();
+  return g_variant_builder_end (&builder);
 }
diff --git a/common/gvfsdaemonprotocol.h b/common/gvfsdaemonprotocol.h
index bc75486..6325e2d 100644
--- a/common/gvfsdaemonprotocol.h
+++ b/common/gvfsdaemonprotocol.h
@@ -186,26 +186,22 @@ void       _g_dbus_attribute_value_destroy       (GFileAttributeType          ty
 						  GDbusAttributeValue        *value);
 gpointer   _g_dbus_attribute_as_pointer          (GFileAttributeType          type,
 						  GDbusAttributeValue        *value);
-const char*_g_dbus_type_from_file_attribute_type (GFileAttributeType          type);
-void       _g_dbus_append_file_attribute         (DBusMessageIter            *iter,
-						  const char                 *attribute,
+GVariant * _g_dbus_append_file_attribute         (const char                 *attribute,
 						  GFileAttributeStatus        status,
 						  GFileAttributeType          type,
 						  gpointer                    value_p);
-void       _g_dbus_append_file_info              (DBusMessageIter            *iter,
-						  GFileInfo                  *file_info);
-gboolean   _g_dbus_get_file_attribute            (DBusMessageIter            *iter,
+GVariant * _g_dbus_append_file_info              (GFileInfo                  *file_info);
+gboolean   _g_dbus_get_file_attribute            (GVariant                   *iter,
 						  gchar                     **attribute,
 						  GFileAttributeStatus       *status,
 						  GFileAttributeType         *type,
 						  GDbusAttributeValue        *value);
-GFileInfo *_g_dbus_get_file_info                 (DBusMessageIter            *iter,
+GFileInfo *_g_dbus_get_file_info                 (GVariant                   *iter,
 						  GError                    **error);
 
-GFileAttributeInfoList *_g_dbus_get_attribute_info_list    (DBusMessageIter         *iter,
+GFileAttributeInfoList *_g_dbus_get_attribute_info_list    (GVariant                *iter,
 							    GError                 **error);
-void                    _g_dbus_append_attribute_info_list (DBusMessageIter         *iter,
-							    GFileAttributeInfoList  *list);
+GVariant *              _g_dbus_append_attribute_info_list (GFileAttributeInfoList  *list);
 
 G_END_DECLS
 
diff --git a/daemon/daemon-main.c b/daemon/daemon-main.c
index 39dea83..25ad3d9 100644
--- a/daemon/daemon-main.c
+++ b/daemon/daemon-main.c
@@ -28,17 +28,21 @@
 #include <locale.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include "daemon-main.h"
 #include <glib/gi18n.h>
 #include <gvfsdaemon.h>
-#include <gvfsdaemonprotocol.h>
 #include <gvfsbackend.h>
+#include <gvfsdbus.h>
 
 static char *spawner_id = NULL;
 static char *spawner_path = NULL;
 
 static gboolean print_debug = FALSE;
+static gboolean already_acquired = FALSE;
+static int process_result = 0;
+
+static GMainLoop *loop;
+
 
 static void
 log_debug (const gchar   *log_domain,
@@ -53,8 +57,8 @@ log_debug (const gchar   *log_domain,
 void
 daemon_init (void)
 {
-  DBusConnection *connection;
-  DBusError derror;
+  GDBusConnection *conn;
+  GError *error;
 
   setlocale (LC_ALL, "");
 
@@ -62,7 +66,6 @@ daemon_init (void)
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
   textdomain (GETTEXT_PACKAGE);
   
-  dbus_threads_init_default ();
   g_type_init ();
 
   g_log_set_handler (NULL, G_LOG_LEVEL_DEBUG, log_debug, NULL);
@@ -73,16 +76,17 @@ daemon_init (void)
    */
   signal (SIGPIPE, SIG_IGN);
 #endif
-  
-  dbus_error_init (&derror);
-  connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
-  if (connection == NULL)
+
+  error = NULL;
+  conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+  if (!conn)
     {
-      g_printerr (_("Error connecting to D-Bus: %s"), derror.message);
-      g_printerr ("\n");
-      dbus_error_free (&derror);
+      g_printerr ("Error connecting to D-Bus: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
       exit (1);
     }
+  g_object_unref (conn);
 }
 
 void
@@ -99,11 +103,69 @@ daemon_setup (void)
   g_free (up);
 }
 
+typedef struct {
+  GVfsDaemon *daemon;
+  GMountSpec *mount_spec;
+  int max_job_threads;
+  char *mountable_name;
+} DaemonData;
+
+typedef struct {
+  GDestroyNotify callback;
+  gpointer user_data;
+} SpawnData;
+
+static void
+spawned_failed_cb (gpointer user_data)
+{
+  process_result = 1;
+  g_main_loop_quit (loop);
+}
+
+static void
+spawned_succeeded_cb (gpointer user_data)
+{
+  DaemonData *data = user_data;
+  GMountSource *mount_source;
+  
+  if (data->mount_spec)
+    {
+      mount_source = g_mount_source_new_dummy ();
+      g_vfs_daemon_initiate_mount (data->daemon, data->mount_spec, mount_source, FALSE, NULL, NULL);
+      g_mount_spec_unref (data->mount_spec);
+      g_object_unref (mount_source);
+    }
+}
+
 static void
-send_spawned (DBusConnection *connection, gboolean succeeded, char *error_message)
+call_spawned_cb (GVfsDBusSpawner *proxy,
+                 GAsyncResult  *res,
+                 gpointer user_data)
 {
-  DBusMessage *message;
-  dbus_bool_t dbus_succeeded;
+  GError *error = NULL;
+  SpawnData *data = user_data;
+
+  if (! gvfs_dbus_spawner_call_spawned_finish (proxy, res, &error))
+    {
+      g_printerr ("call_spawned_cb: Error sending a message: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+  g_print ("call_spawned_cb\n");
+  
+  data->callback (data->user_data);
+  g_free (data);
+}
+
+static void
+send_spawned (gboolean succeeded, 
+              char *error_message,
+              GDestroyNotify callback,
+              gpointer user_data)
+{
+  GVfsDBusSpawner *proxy;
+  GError *error;
+  SpawnData *data;
 
   if (error_message == NULL)
     error_message = "";
@@ -115,26 +177,42 @@ send_spawned (DBusConnection *connection, gboolean succeeded, char *error_messag
 	  g_printerr (_("Error: %s"), error_message);
 	  g_printerr ("\n");
 	}
+      callback (user_data);
       return;
     }
+
+  g_print ("sending spawned.\n");
   
-  message = dbus_message_new_method_call (spawner_id,
-					  spawner_path,
-					  G_VFS_DBUS_SPAWNER_INTERFACE,
-					  G_VFS_DBUS_OP_SPAWNED);
-  dbus_message_set_no_reply (message, TRUE);
-
-  dbus_succeeded = succeeded;
-  if (!dbus_message_append_args (message,
-				 DBUS_TYPE_BOOLEAN, &dbus_succeeded,
-				 DBUS_TYPE_STRING, &error_message,
-				 DBUS_TYPE_INVALID))
-    _g_dbus_oom ();
-    
-  dbus_connection_send (connection, message, NULL);
-  dbus_message_unref (message);
-  /* Make sure the message is sent */
-  dbus_connection_flush (connection);
+  error = NULL;
+  g_print ("send_spawned: before proxy creation, spawner_id = '%s', spawner_path = '%s'\n", spawner_id, spawner_path);
+  proxy = gvfs_dbus_spawner_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION,
+                                                    G_DBUS_PROXY_FLAGS_NONE,
+                                                    spawner_id,
+                                                    spawner_path,
+                                                    NULL,
+                                                    &error);
+  g_print ("send_spawned: after proxy creation\n");
+  if (proxy == NULL)
+    {
+      g_printerr ("Error creating proxy: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      return;
+    }
+  
+  data = g_new0 (SpawnData, 1);
+  data->callback = callback;
+  data->user_data = user_data;
+  
+  g_print ("send_spawned: before call_spawned\n");
+  gvfs_dbus_spawner_call_spawned (proxy, 
+                                  succeeded,
+                                  error_message,
+                                  NULL,
+                                  (GAsyncReadyCallback) call_spawned_cb,
+                                  data);
+
+  g_object_unref (proxy);
 }
 
 GMountSpec *
@@ -209,6 +287,67 @@ daemon_parse_args (int argc, char *argv[], const char *default_type)
   return mount_spec;
 }
 
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  DaemonData *data = user_data;
+  gchar *s;
+  
+  if (connection == NULL)
+    {
+      g_printerr ("A connection to the bus can't be made\n");
+      process_result = 1;
+    }
+  else
+    {
+      if (already_acquired)
+        {
+          g_printerr ("Got NameLost, some other instance replaced us\n");
+        }
+      else
+        {
+          s = g_strdup_printf (_("mountpoint for %s already running"), data->mountable_name);
+          g_printerr (_("Error: %s"), s);
+          g_printerr ("\n");
+          g_free (s);
+          process_result = 1;
+        }
+    }
+  g_main_loop_quit (loop);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+  DaemonData *data = user_data;
+
+  g_warning ("daemon-main.c: Acquired the name on the session message bus\n");
+  
+  already_acquired = TRUE;
+  
+  data->daemon = g_vfs_daemon_new (FALSE, FALSE);
+  if (data->daemon == NULL)
+    {
+      send_spawned (FALSE, _("error starting mount daemon"), spawned_failed_cb, data);
+      return;
+    }
+
+  g_vfs_daemon_set_max_threads (data->daemon, data->max_job_threads);
+
+  send_spawned (TRUE, NULL, spawned_succeeded_cb, data);
+}
+
+static gboolean
+do_name_acquired (gpointer user_data)
+{
+  on_name_acquired (NULL, NULL, user_data);
+  return FALSE;
+}
+
 void
 daemon_main (int argc,
 	     char *argv[],
@@ -219,28 +358,17 @@ daemon_main (int argc,
 	     ...)
 {
   va_list var_args;
-  DBusConnection *connection;
-  GMainLoop *loop;
-  GVfsDaemon *daemon;
-  DBusError derror;
-  GMountSpec *mount_spec;
-  GMountSource *mount_source;
-  GError *error;
-  int res;
   const char *type;
+  guint name_owner_id;
+  DaemonData *data;
 
-  dbus_error_init (&derror);
-  connection = dbus_bus_get (DBUS_BUS_SESSION, &derror);
-  if (connection == NULL)
-    {
-      g_printerr (_("Error connecting to D-Bus: %s"), derror.message);
-      g_printerr ("\n");
-      dbus_error_free (&derror);
-      exit (1);
-    }
+  g_print ("daemon_main: mountable_name = '%s'\n", mountable_name);
+  
+  data = g_new0 (DaemonData, 1);
+  data->mountable_name = g_strdup (mountable_name);
+  data->max_job_threads = max_job_threads;
+  data->mount_spec = daemon_parse_args (argc, argv, default_type);
   
-  mount_spec = daemon_parse_args (argc, argv, default_type);
-
   va_start (var_args, first_type_name);
 
   type = first_type_name;
@@ -254,49 +382,38 @@ daemon_main (int argc,
       type = va_arg (var_args, char *);
     }
 
-  error = NULL;
-  if (mountable_name)
-    {
-      
-      res = dbus_bus_request_name (connection,
-				   mountable_name,
-				   0, &derror);
-
-      if (res != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
-	{
-	  if (res == -1)
-	    _g_error_from_dbus (&derror, &error);
-	  else
-	    g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			 _("mountpoint for %s already running"), mountable_name);
-
-	  send_spawned (connection, FALSE, error->message);
-	  g_error_free (error);
-	  exit (1);
-	}
-    }
+  loop = g_main_loop_new (NULL, FALSE);
   
-  daemon = g_vfs_daemon_new (FALSE, FALSE);
-  if (daemon == NULL)
+  name_owner_id = 0;
+  if (mountable_name)
     {
-      send_spawned (connection, FALSE, _("error starting mount daemon"));
-      exit (1);
+      g_print ("daemon_main: requesting name '%s'\n", mountable_name); 
+
+      name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                                      mountable_name,
+                                      G_BUS_NAME_OWNER_FLAGS_NONE,
+                                      NULL,
+                                      on_name_acquired,
+                                      on_name_lost,
+                                      data,
+                                      NULL);
     }
-
-  g_vfs_daemon_set_max_threads (daemon, max_job_threads);  
-  
-  send_spawned (connection, TRUE, NULL);
-	  
-  if (mount_spec)
+  else
     {
-      mount_source = g_mount_source_new_dummy ();
-      g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, FALSE, NULL);
-      g_mount_spec_unref (mount_spec);
-      g_object_unref (mount_source);
+      g_idle_add (do_name_acquired, data);
     }
   
-  loop = g_main_loop_new (NULL, FALSE);
-
   g_main_loop_run (loop);
+  
+  if (data->daemon != NULL)
+    g_object_unref (data->daemon);
+  g_free (data->mountable_name);
+  g_free (data);
+  if (name_owner_id != 0)
+    g_bus_unown_name (name_owner_id);
+  if (loop != NULL)
+    g_main_loop_unref (loop);
+  
+  if (process_result)
+    exit (process_result);
 }
-
diff --git a/daemon/gvfsbackend.c b/daemon/gvfsbackend.c
index 409db73..d627623 100644
--- a/daemon/gvfsbackend.c
+++ b/daemon/gvfsbackend.c
@@ -29,11 +29,9 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsbackend.h"
 #include "gvfsjobsource.h"
-#include "gvfsdaemonprotocol.h"
 #include <gvfsjobopenforread.h>
 #include <gvfsjobopeniconforread.h>
 #include <gvfsjobopenforwrite.h>
@@ -58,7 +56,7 @@
 #include <gvfsjobpull.h>
 #include <gvfsjobsetattribute.h>
 #include <gvfsjobqueryattributes.h>
-#include <gvfsdbusutils.h>
+#include <gvfsdbus.h>
 
 enum {
   PROP_0,
@@ -99,9 +97,6 @@ static void              g_vfs_backend_set_property          (GObject
 static GObject*          g_vfs_backend_constructor           (GType                  type,
 							      guint                  n_construct_properties,
 							      GObjectConstructParam *construct_params);
-static DBusHandlerResult backend_dbus_handler                (DBusConnection        *connection,
-							      DBusMessage           *message,
-							      void                  *user_data);
 
 
 G_DEFINE_TYPE_WITH_CODE (GVfsBackend, g_vfs_backend, G_TYPE_OBJECT,
@@ -254,6 +249,56 @@ g_vfs_backend_get_property (GObject    *object,
     }
 }
 
+static GDBusInterfaceSkeleton *
+register_path_cb (GDBusConnection *conn,
+                  const char *obj_path,
+                  gpointer data)
+{
+  GError *error;
+  GVfsDBusMount *skeleton;
+  
+  skeleton = gvfs_dbus_mount_skeleton_new ();
+  g_signal_connect (skeleton, "handle-enumerate", G_CALLBACK (g_vfs_job_enumerate_new_handle), data);
+  g_signal_connect (skeleton, "handle-query-info", G_CALLBACK (g_vfs_job_query_info_new_handle), data);
+  g_signal_connect (skeleton, "handle-query-filesystem-info", G_CALLBACK (g_vfs_job_query_fs_info_new_handle), data);
+  g_signal_connect (skeleton, "handle-set-display-name", G_CALLBACK (g_vfs_job_set_display_name_new_handle), data);
+  g_signal_connect (skeleton, "handle-delete", G_CALLBACK (g_vfs_job_delete_new_handle), data);
+  g_signal_connect (skeleton, "handle-trash", G_CALLBACK (g_vfs_job_trash_new_handle), data);
+  g_signal_connect (skeleton, "handle-make-directory", G_CALLBACK (g_vfs_job_make_directory_new_handle), data);
+  g_signal_connect (skeleton, "handle-make-symbolic-link", G_CALLBACK (g_vfs_job_make_symlink_new_handle), data);
+  g_signal_connect (skeleton, "handle-query-settable-attributes", G_CALLBACK (g_vfs_job_query_settable_attributes_new_handle), data);
+  g_signal_connect (skeleton, "handle-query-writable-namespaces", G_CALLBACK (g_vfs_job_query_writable_namespaces_new_handle), data);
+  g_signal_connect (skeleton, "handle-set-attribute", G_CALLBACK (g_vfs_job_set_attribute_new_handle), data);
+  g_signal_connect (skeleton, "handle-poll-mountable", G_CALLBACK (g_vfs_job_poll_mountable_new_handle), data);
+  g_signal_connect (skeleton, "handle-start-mountable", G_CALLBACK (g_vfs_job_start_mountable_new_handle), data);
+  g_signal_connect (skeleton, "handle-stop-mountable", G_CALLBACK (g_vfs_job_stop_mountable_new_handle), data);
+  g_signal_connect (skeleton, "handle-unmount-mountable", G_CALLBACK (g_vfs_job_unmount_mountable_new_handle), data);
+  g_signal_connect (skeleton, "handle-eject-mountable", G_CALLBACK (g_vfs_job_eject_mountable_new_handle), data);
+  g_signal_connect (skeleton, "handle-mount-mountable", G_CALLBACK (g_vfs_job_mount_mountable_new_handle), data);
+  g_signal_connect (skeleton, "handle-unmount", G_CALLBACK (g_vfs_job_unmount_new_handle), data);
+  g_signal_connect (skeleton, "handle-open-for-read", G_CALLBACK (g_vfs_job_open_for_read_new_handle), data);
+  g_signal_connect (skeleton, "handle-open-for-write", G_CALLBACK (g_vfs_job_open_for_write_new_handle), data);
+  g_signal_connect (skeleton, "handle_copy", G_CALLBACK (g_vfs_job_copy_new_handle), data);
+  g_signal_connect (skeleton, "handle-move", G_CALLBACK (g_vfs_job_move_new_handle), data);
+  g_signal_connect (skeleton, "handle-push", G_CALLBACK (g_vfs_job_push_new_handle), data);
+  g_signal_connect (skeleton, "handle-pull", G_CALLBACK (g_vfs_job_pull_new_handle), data);
+  g_signal_connect (skeleton, "handle-create-directory-monitor", G_CALLBACK (g_vfs_job_create_directory_monitor_new_handle), data);
+  g_signal_connect (skeleton, "handle-create-file-monitor", G_CALLBACK (g_vfs_job_create_file_monitor_new_handle), data);
+  
+  error = NULL;
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (skeleton),
+                                         conn,
+                                         obj_path,
+                                         &error))
+    {
+      g_warning ("Error registering path: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+
+  return G_DBUS_INTERFACE_SKELETON (skeleton);
+}
+  
 static GObject*
 g_vfs_backend_constructor (GType                  type,
 			   guint                  n_construct_properties,
@@ -269,7 +314,8 @@ g_vfs_backend_constructor (GType                  type,
   
   g_vfs_daemon_register_path (backend->priv->daemon,
 			      backend->priv->object_path, 
-			      backend_dbus_handler,
+			      "backend_path",
+			      register_path_cb,
 			      backend);
   
   return object;
@@ -522,167 +568,94 @@ g_vfs_backend_get_block_requests (GVfsBackend *backend)
   return backend->priv->block_requests;
 }
 
-
-static DBusHandlerResult
-backend_dbus_handler (DBusConnection  *connection,
-		      DBusMessage     *message,
-		      void            *user_data)
+gboolean
+g_vfs_backend_invocation_first_handler (GVfsDBusMount *object,
+                                        GDBusMethodInvocation *invocation,
+                                        GVfsBackend *backend)
 {
-  GVfsBackend *backend = user_data;
-  GVfsJob *job;
-
-  job = NULL;
-
   g_debug ("backend_dbus_handler %s:%s\n",
-	   dbus_message_get_interface (message),
-	   dbus_message_get_member (message));
+           g_dbus_method_invocation_get_interface_name (invocation),
+           g_dbus_method_invocation_get_method_name (invocation));
 
   if (backend->priv->block_requests)
     {
-      DBusMessage *reply;
+      g_dbus_method_invocation_return_error (invocation,
+                                             G_IO_ERROR,
+                                             G_IO_ERROR_NOT_MOUNTED,
+                                             "%s", "Backend currently unmounting");
+      return TRUE;
+    }
 
-      reply = _dbus_message_new_gerror (message,
-					G_IO_ERROR,
-					G_IO_ERROR_NOT_MOUNTED,
-					"%s", "Backend currently unmounting");
+  return FALSE;
+}
 
-      g_assert (reply != NULL);
 
-      dbus_connection_send (connection, reply, NULL);
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-  
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_MOUNT_INTERFACE,
-				   G_VFS_DBUS_MOUNT_OP_UNMOUNT))
-    job = g_vfs_job_unmount_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_MOUNT_INTERFACE,
-				   G_VFS_DBUS_MOUNT_OP_OPEN_FOR_READ))
-    job = g_vfs_job_open_for_read_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_MOUNT_INTERFACE,
-				   G_VFS_DBUS_MOUNT_OP_OPEN_ICON_FOR_READ))
-    job = g_vfs_job_open_icon_for_read_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_QUERY_INFO))
-    job = g_vfs_job_query_info_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_QUERY_FILESYSTEM_INFO))
-    job = g_vfs_job_query_fs_info_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_ENUMERATE))
-    job = g_vfs_job_enumerate_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_OPEN_FOR_WRITE))
-    job = g_vfs_job_open_for_write_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_MOUNT_MOUNTABLE))
-    job = g_vfs_job_mount_mountable_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_UNMOUNT_MOUNTABLE))
-    job = g_vfs_job_unmount_mountable_new (connection, message, backend, FALSE);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_EJECT_MOUNTABLE))
-    job = g_vfs_job_unmount_mountable_new (connection, message, backend, TRUE);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_START_MOUNTABLE))
-    job = g_vfs_job_start_mountable_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_STOP_MOUNTABLE))
-    job = g_vfs_job_stop_mountable_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_POLL_MOUNTABLE))
-    job = g_vfs_job_poll_mountable_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_SET_DISPLAY_NAME))
-    job = g_vfs_job_set_display_name_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_DELETE))
-    job = g_vfs_job_delete_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_TRASH))
-    job = g_vfs_job_trash_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_MAKE_DIRECTORY))
-    job = g_vfs_job_make_directory_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_MAKE_SYMBOLIC_LINK))
-    job = g_vfs_job_make_symlink_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_COPY))
-    job = g_vfs_job_copy_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_PUSH))
-    job = g_vfs_job_push_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_PULL))
-    job = g_vfs_job_pull_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_MOVE))
-    job = g_vfs_job_move_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_SET_ATTRIBUTE))
-    job = g_vfs_job_set_attribute_new (connection, message, backend);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_QUERY_SETTABLE_ATTRIBUTES))
-    job = g_vfs_job_query_attributes_new (connection, message, backend, FALSE);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_QUERY_WRITABLE_NAMESPACES))
-    job = g_vfs_job_query_attributes_new (connection, message, backend, TRUE);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_CREATE_DIR_MONITOR))
-    job = g_vfs_job_create_monitor_new (connection, message, backend, TRUE);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNT_INTERFACE,
-					G_VFS_DBUS_MOUNT_OP_CREATE_FILE_MONITOR))
-    job = g_vfs_job_create_monitor_new (connection, message, backend, FALSE);
-
-  if (job)
-    {
-      g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), job);
-      g_object_unref (job);
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-      
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+typedef struct {
+  GVfsBackend *backend;
+  GAsyncReadyCallback callback;
+  gpointer callback_data;
+} AsyncProxyCreate;
+
+static void
+async_proxy_create_free (AsyncProxyCreate *data)
+{
+  if (data->backend)
+    g_object_unref (data->backend);
+  g_free (data);
 }
 
-void
-g_vfs_backend_register_mount (GVfsBackend *backend,
-			      GAsyncDBusCallback callback,
-			      gpointer user_data)
+static void
+create_mount_tracker_proxy (GVfsBackend *backend,
+                            GAsyncReadyCallback op_callback,
+                            gpointer op_callback_data,
+                            GAsyncReadyCallback callback)
 {
+  AsyncProxyCreate *data;
+
+  g_print ("create_mount_tracker_proxy\n");
+  
+  data = g_new0 (AsyncProxyCreate, 1);
+  data->callback = op_callback;
+  data->callback_data = op_callback_data;
+  data->backend = g_object_ref (backend);
+
+  gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                             G_DBUS_PROXY_FLAGS_NONE,
+                                             G_VFS_DBUS_DAEMON_NAME,
+                                             G_VFS_DBUS_MOUNTTRACKER_PATH,
+                                             NULL,
+                                             callback,
+                                             data);
+}
+
+static void
+register_mount_got_proxy_cb (GObject *source_object,
+                             GAsyncResult *res,
+                             gpointer user_data)
+{
+  AsyncProxyCreate *data = user_data;
+  GVfsDBusMountTracker *proxy;
+  GError *error = NULL;
+  GSimpleAsyncResult *result;
+  GVfsBackend *backend;
   const char *stable_name;
-  DBusMessage *message;
-  DBusMessageIter iter;
-  dbus_bool_t user_visible;
   char *x_content_types_string;
   char *icon_str;
 
+  proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error);
+  g_print ("register_mount_got_proxy_cb, proxy = %p\n", proxy);
+  if (proxy == NULL)
+    {
+      result = g_simple_async_result_new_take_error (source_object,
+                                                     data->callback, data->callback_data,
+                                                     error);
+      g_simple_async_result_complete_in_idle (result);
+      g_object_unref (result);
+      async_proxy_create_free (data);
+      return;
+    }
+
+  backend = data->backend;
   backend->priv->is_mounted = TRUE;
 
   if (backend->priv->x_content_types != NULL && g_strv_length (backend->priv->x_content_types) > 0)
@@ -695,71 +668,86 @@ g_vfs_backend_register_mount (GVfsBackend *backend,
   else
     icon_str = g_strdup ("");
 
-  message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-					  G_VFS_DBUS_MOUNTTRACKER_PATH,
-					  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					  G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT);
-  if (message == NULL)
-    _g_dbus_oom ();
-
   if (backend->priv->stable_name != NULL &&
       *backend->priv->stable_name != 0)
    stable_name = backend->priv->stable_name;
   else
    stable_name = backend->priv->display_name;
 
-  user_visible = backend->priv->user_visible;
-  if (!dbus_message_append_args (message,
-				 DBUS_TYPE_OBJECT_PATH, &backend->priv->object_path,
-				 DBUS_TYPE_STRING, &backend->priv->display_name,
-				 DBUS_TYPE_STRING, &stable_name,
-				 DBUS_TYPE_STRING, &x_content_types_string,
-				 DBUS_TYPE_STRING, &icon_str,
-				 DBUS_TYPE_STRING, &backend->priv->prefered_filename_encoding,
-				 DBUS_TYPE_BOOLEAN, &user_visible,
-				 0))
-    _g_dbus_oom ();
+  g_print ("g_vfs_backend_register_mount: calling register_mount() for object_path = '%s', display_name = '%s'\n", backend->priv->object_path, backend->priv->display_name);
+  
+  gvfs_dbus_mount_tracker_call_register_mount (proxy,
+                                               backend->priv->object_path,
+                                               backend->priv->display_name,
+                                               stable_name,
+                                               x_content_types_string,
+                                               icon_str,
+                                               backend->priv->prefered_filename_encoding,
+                                               backend->priv->user_visible,
+                                               g_mount_spec_to_dbus (backend->priv->mount_spec),
+                                               backend->priv->default_location,
+                                               NULL,
+                                               data->callback, data->callback_data);
 
-  dbus_message_iter_init_append (message, &iter);
-  g_mount_spec_to_dbus (&iter, backend->priv->mount_spec);
+  g_free (x_content_types_string);
+  g_free (icon_str);
+  g_object_unref (proxy);
+  async_proxy_create_free (data);
+}
 
-  _g_dbus_message_append_args (message,
-			       G_DBUS_TYPE_CSTRING, &backend->priv->default_location,
-			       0);
+void
+g_vfs_backend_register_mount (GVfsBackend *backend,
+                              GAsyncReadyCallback callback,
+			      gpointer user_data)
+{
+  g_print ("g_vfs_backend_register_mount\n");
+  
+  create_mount_tracker_proxy (backend, callback, user_data, register_mount_got_proxy_cb);
+}
 
+static void
+unregister_mount_got_proxy_cb (GObject *source_object,
+                               GAsyncResult *res,
+                               gpointer user_data)
+{
+  AsyncProxyCreate *data = user_data;
+  GVfsDBusMountTracker *proxy;
+  GError *error = NULL;
+  GSimpleAsyncResult *result;
+  GVfsBackend *backend;
 
-  dbus_message_set_auto_start (message, TRUE);
+  proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, &error);
+  g_print ("unregister_mount_got_proxy_cb, proxy = %p\n", proxy);
+  if (proxy == NULL)
+    {
+      result = g_simple_async_result_new_take_error (source_object,
+                                                     data->callback, data->callback_data,
+                                                     error);
+      g_simple_async_result_complete_in_idle (result);
+      g_object_unref (result);
+      async_proxy_create_free (data);
+      return;
+    }
 
-  _g_dbus_connection_call_async (NULL, message, -1, 
-				 callback, user_data);
-  dbus_message_unref (message);
+  backend = data->backend;
+  
+  gvfs_dbus_mount_tracker_call_unregister_mount (proxy,
+                                                 backend->priv->object_path,
+                                                 NULL,
+                                                 data->callback, data->callback_data);
 
-  g_free (x_content_types_string);
-  g_free (icon_str);
+  g_object_unref (proxy);
+  async_proxy_create_free (data);
 }
 
 void
 g_vfs_backend_unregister_mount (GVfsBackend *backend,
-				GAsyncDBusCallback callback,
+                                GAsyncReadyCallback callback,
 				gpointer user_data)
 {
-  DBusMessage *message;
+  g_print ("g_vfs_backend_unregister_mount\n");
   
-  message = dbus_message_new_method_call (G_VFS_DBUS_DAEMON_NAME,
-					  G_VFS_DBUS_MOUNTTRACKER_PATH,
-					  G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					  G_VFS_DBUS_MOUNTTRACKER_OP_UNREGISTER_MOUNT);
-  if (message == NULL)
-    _g_dbus_oom ();
-
-  if (!dbus_message_append_args (message,
-				 DBUS_TYPE_OBJECT_PATH, &backend->priv->object_path,
-				 0))
-    _g_dbus_oom ();
-
-  _g_dbus_connection_call_async (NULL, message, -1, 
-				 callback, user_data);
-  dbus_message_unref (message);
+  create_mount_tracker_proxy (backend, callback, user_data, unregister_mount_got_proxy_cb);
 }
 
 /* ------------------------------------------------------------------------------------------------- */
diff --git a/daemon/gvfsbackend.h b/daemon/gvfsbackend.h
index cf4abb6..8ba3d03 100644
--- a/daemon/gvfsbackend.h
+++ b/daemon/gvfsbackend.h
@@ -23,12 +23,10 @@
 #ifndef __G_VFS_BACKEND_H__
 #define __G_VFS_BACKEND_H__
 
-#include <dbus/dbus.h>
 #include <gio/gio.h>
 #include <gvfsdaemon.h>
 #include <gvfsjob.h>
 #include <gmountspec.h>
-#include <gvfsdbusutils.h>
 
 G_BEGIN_DECLS
 
@@ -478,10 +476,10 @@ void        g_vfs_backend_set_default_location           (GVfsBackend        *ba
 void        g_vfs_backend_set_mount_spec                 (GVfsBackend        *backend,
 							  GMountSpec         *mount_spec);
 void        g_vfs_backend_register_mount                 (GVfsBackend        *backend,
-							  GAsyncDBusCallback  callback,
+                                                          GAsyncReadyCallback callback,
 							  gpointer            user_data);
 void        g_vfs_backend_unregister_mount               (GVfsBackend        *backend,
-							  GAsyncDBusCallback  callback,
+                                                          GAsyncReadyCallback callback,
 							  gpointer            user_data);
 const char *g_vfs_backend_get_backend_type               (GVfsBackend        *backend);
 const char *g_vfs_backend_get_display_name               (GVfsBackend        *backend);
@@ -511,6 +509,10 @@ void        g_vfs_backend_unmount_with_operation (GVfsBackend        *backend,
                                                   GAsyncReadyCallback callback,
                                                   gpointer            user_data);
 
+gboolean    g_vfs_backend_invocation_first_handler       (GVfsDBusMount *object,
+                                                          GDBusMethodInvocation *invocation,
+                                                          GVfsBackend *backend);
+
 G_END_DECLS
 
 #endif /* __G_VFS_BACKEND_H__ */
diff --git a/daemon/gvfsdaemon.c b/daemon/gvfsdaemon.c
index 0614a5c..38191b1 100644
--- a/daemon/gvfsdaemon.c
+++ b/daemon/gvfsdaemon.c
@@ -35,14 +35,12 @@
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
 #include <glib-object.h>
-#include <dbus-gmain.h>
 #include <gvfsdaemon.h>
 #include <gvfsdaemonprotocol.h>
 #include <gvfsdaemonutils.h>
 #include <gvfsjobmount.h>
 #include <gvfsjobopenforread.h>
 #include <gvfsjobopenforwrite.h>
-#include <gvfsdbusutils.h>
 
 enum {
   PROP_0
@@ -50,8 +48,10 @@ enum {
 
 typedef struct {
   char *obj_path;
-  DBusObjectPathMessageFunction callback;
+  char *name;
+  GVfsRegisterPathCallback callback;
   gpointer data;
+  GDBusInterfaceSkeleton *skeleton;
 } RegisteredPath;
 
 struct _GVfsDaemon
@@ -62,7 +62,6 @@ struct _GVfsDaemon
   gboolean main_daemon;
 
   GThreadPool *thread_pool;
-  DBusConnection *session_bus;
   GHashTable *registered_paths;
   GList *jobs;
   GList *job_sources;
@@ -70,18 +69,24 @@ struct _GVfsDaemon
   guint exit_tag;
   
   gint mount_counter;
+  
+  GDBusConnection *conn;
+  GVfsDBusDaemon *daemon_skeleton;
+  GVfsDBusMountable *mountable_skeleton;
+  guint name_watcher;
+  gboolean lost_main_daemon;
 };
 
 typedef struct {
   GVfsDaemon *daemon;
   char *socket_dir;
   guint io_watch;
-  DBusServer *server;
+  GDBusServer *server;
   
   gboolean got_dbus_connection;
   gboolean got_fd_connection;
   int fd;
-  DBusConnection *conn;
+  GDBusConnection *conn;
 } NewConnectionData;
 
 static void              g_vfs_daemon_get_property (GObject        *object,
@@ -92,12 +97,25 @@ static void              g_vfs_daemon_set_property (GObject        *object,
 						    guint           prop_id,
 						    const GValue   *value,
 						    GParamSpec     *pspec);
-static DBusHandlerResult daemon_message_func       (DBusConnection *conn,
-						    DBusMessage    *message,
-						    gpointer        data);
-static DBusHandlerResult peer_to_peer_filter_func  (DBusConnection *conn,
-						    DBusMessage    *message,
-						    gpointer        data);
+
+static gboolean          handle_get_connection     (GVfsDBusDaemon        *object,
+                                                    GDBusMethodInvocation *invocation,
+                                                    gpointer               user_data);
+static gboolean          handle_cancel             (GVfsDBusDaemon        *object,
+                                                    GDBusMethodInvocation *invocation,
+                                                    guint                  arg_serial,
+                                                    gpointer               user_data);
+static gboolean          daemon_handle_mount       (GVfsDBusMountable     *object,
+                                                    GDBusMethodInvocation *invocation,
+                                                    GVariant              *arg_mount_spec,
+                                                    gboolean               arg_automount,
+                                                    GVariant              *arg_mount_source,
+                                                    gpointer               user_data);
+static void              g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon);
+
+
+
+
 
 
 G_DEFINE_TYPE (GVfsDaemon, g_vfs_daemon, G_TYPE_OBJECT)
@@ -106,6 +124,13 @@ static void
 registered_path_free (RegisteredPath *data)
 {
   g_free (data->obj_path);
+  g_free (data->name);
+  if (data->skeleton)
+    {
+      /* Unexport the interface skeleton on session bus */
+      g_dbus_interface_skeleton_unexport (data->skeleton);
+      g_object_unref (data->skeleton);
+    }
   g_free (data);
 }
 
@@ -118,6 +143,22 @@ g_vfs_daemon_finalize (GObject *object)
 
   g_assert (daemon->jobs == NULL);
 
+  if (daemon->name_watcher)
+    g_bus_unwatch_name (daemon->name_watcher);
+  
+  if (daemon->daemon_skeleton != NULL)
+    {
+      g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon->daemon_skeleton));
+      g_object_unref (daemon->daemon_skeleton);
+    }
+  if (daemon->mountable_skeleton != NULL)
+    {
+      g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon->mountable_skeleton));
+      g_object_unref (daemon->mountable_skeleton);
+    }
+  if (daemon->conn != NULL)
+    g_object_unref (daemon->conn);
+  
   g_hash_table_destroy (daemon->registered_paths);
   g_mutex_clear (&daemon->lock);
 
@@ -145,12 +186,45 @@ job_handler_callback (gpointer       data,
 }
 
 static void
+name_appeared_handler (GDBusConnection *connection,
+                       const gchar *name,
+                       const gchar *name_owner,
+                       gpointer user_data)
+{
+  GVfsDaemon *daemon = user_data;
+
+  g_print ("gvfsdaemon: name_appeared_handler()\n");
+  
+  if (strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0 &&
+      *name_owner != 0 &&
+      daemon->lost_main_daemon)
+      {
+        /* There is a new owner. Register mounts with it */
+        g_vfs_daemon_re_register_job_sources (daemon);
+      }
+}
+
+static void 
+name_vanished_handler (GDBusConnection *connection,
+                       const gchar *name,
+                       gpointer user_data)
+{
+  GVfsDaemon *daemon = user_data;
+
+  g_print ("gvfsdaemon: name_vanished_handler()\n");
+
+  /* Ensure we react only to really lost daemon */ 
+  daemon->lost_main_daemon = TRUE;
+}
+
+static void
 g_vfs_daemon_init (GVfsDaemon *daemon)
 {
+  GError *error;
   gint max_threads = 1; /* TODO: handle max threads */
-  DBusError error;
-  
-  daemon->session_bus = dbus_bus_get (DBUS_BUS_SESSION, NULL);
+
+  g_print ("g_vfs_daemon_init\n");
+
   daemon->thread_pool = g_thread_pool_new (job_handler_callback,
 					   daemon,
 					   max_threads,
@@ -166,24 +240,40 @@ g_vfs_daemon_init (GVfsDaemon *daemon)
   daemon->registered_paths =
     g_hash_table_new_full (g_str_hash, g_str_equal,
 			   NULL, (GDestroyNotify)registered_path_free);
+  
+
+  daemon->conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL);
+  g_assert (daemon->conn != NULL);
 
-  dbus_error_init (&error);
-  dbus_bus_add_match (daemon->session_bus,
-		      "type='signal',"		      
-		      "interface='org.freedesktop.DBus',"
-		      "member='NameOwnerChanged',"
-		      "arg0='"G_VFS_DBUS_DAEMON_NAME"'",
-		      &error);
+  daemon->daemon_skeleton = gvfs_dbus_daemon_skeleton_new ();
+  g_signal_connect (daemon->daemon_skeleton, "handle-get-connection", G_CALLBACK (handle_get_connection), daemon);
+  /* TODO: this might never be called on this side */
+  g_signal_connect (daemon->daemon_skeleton, "handle-cancel", G_CALLBACK (handle_cancel), daemon);
   
-  if (dbus_error_is_set (&error))
+  error = NULL;
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon->daemon_skeleton),
+                                         daemon->conn,
+                                         G_VFS_DBUS_DAEMON_PATH,
+                                         &error))
     {
-      g_warning ("Failed to add dbus match: %s\n", error.message);
-      dbus_error_free (&error);
+      g_warning ("Error exporting daemon interface: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
     }
+
+  daemon->mountable_skeleton = gvfs_dbus_mountable_skeleton_new ();
+  g_signal_connect (daemon->mountable_skeleton, "handle-mount", G_CALLBACK (daemon_handle_mount), daemon);
   
-  if (!dbus_connection_add_filter (daemon->session_bus,
-				   daemon_message_func, daemon, NULL))
-    _g_dbus_oom ();
+  error = NULL;
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon->mountable_skeleton),
+      daemon->conn,
+                                         G_VFS_DBUS_MOUNTABLE_PATH,
+                                         &error))
+    {
+      g_warning ("Error exporting mountable interface: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
 }
 
 static void
@@ -192,11 +282,6 @@ g_vfs_daemon_set_property (GObject         *object,
 			   const GValue    *value,
 			   GParamSpec      *pspec)
 {
-#if 0
-  GVfsDaemon *daemon;
-  
-  daemon = G_VFS_DAEMON (object);
-#endif
   switch (prop_id)
     {
     default:
@@ -211,11 +296,6 @@ g_vfs_daemon_get_property (GObject    *object,
 			   GValue     *value,
 			   GParamSpec *pspec)
 {
-#if 0
-  GVfsDaemon *daemon;
-  
-  daemon = G_VFS_DAEMON (object);
-#endif
   switch (prop_id)
     {
     default:
@@ -228,58 +308,34 @@ GVfsDaemon *
 g_vfs_daemon_new (gboolean main_daemon, gboolean replace)
 {
   GVfsDaemon *daemon;
-  DBusConnection *conn;
-  DBusError error;
-  unsigned int flags;
-  int ret;
+  GDBusConnection *conn;
+  GError *error;
 
-  dbus_error_init (&error);
-  conn = dbus_bus_get (DBUS_BUS_SESSION, &error);
+  error = NULL;
+  conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
   if (!conn)
     {
-      g_printerr ("Failed to connect to the D-BUS daemon: %s\n",
-		  error.message);
-      
-      dbus_error_free (&error);
+      g_printerr ("Failed to connect to the D-BUS daemon: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
       return NULL;
     }
 
-  dbus_connection_setup_with_g_main (conn, NULL);
-  
   daemon = g_object_new (G_VFS_TYPE_DAEMON, NULL);
   daemon->main_daemon = main_daemon;
-
-  /* Request name only after we've installed the message filter */
-  if (main_daemon)
+  
+  if (! main_daemon)
     {
-      flags = DBUS_NAME_FLAG_ALLOW_REPLACEMENT | DBUS_NAME_FLAG_DO_NOT_QUEUE;
-      if (replace)
-	flags |= DBUS_NAME_FLAG_REPLACE_EXISTING;
-
-      ret = dbus_bus_request_name (conn, G_VFS_DBUS_DAEMON_NAME, flags, &error);
-      if (ret == -1)
-	{
-	  g_printerr ("Failed to acquire daemon name: %s", error.message);
-	  dbus_error_free (&error);
-	  
-	  g_object_unref (daemon);
-	  daemon = NULL;
-	}
-      else if (ret == DBUS_REQUEST_NAME_REPLY_EXISTS)
-	{
-	  g_printerr ("VFS daemon already running, exiting.\n");
-	  g_object_unref (daemon);
-	  daemon = NULL;
-	}
-      else if (ret != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER)
-	{
-	  g_printerr ("Not primary owner of the service, exiting.\n");
-	  g_object_unref (daemon);
-	  daemon = NULL;
-	}
+      daemon->name_watcher = g_bus_watch_name_on_connection (conn,
+                                                             G_VFS_DBUS_DAEMON_NAME,
+                                                             G_BUS_NAME_WATCHER_FLAGS_AUTO_START,
+                                                             name_appeared_handler,
+                                                             name_vanished_handler,
+                                                             daemon,
+                                                             NULL);
     }
 
-  dbus_connection_unref (conn);
+  g_object_unref (conn);
   
   return daemon;
 }
@@ -348,6 +404,21 @@ job_source_closed_callback (GVfsJobSource *job_source,
 }
 
 static void
+re_register_jobs_cb (GVfsDBusMountTracker *proxy,
+                     GAsyncResult *res,
+                     gpointer user_data)
+{
+  GError *error = NULL;
+
+  gvfs_dbus_mount_tracker_call_register_mount_finish (proxy,
+                                                      res,
+                                                      &error);
+  g_debug ("re_register_jobs_cb, error: %p\n", error);
+  if (error)
+    g_error_free (error);
+}
+
+static void
 g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon)
 {
   GList *l;
@@ -363,7 +434,7 @@ g_vfs_daemon_re_register_job_sources (GVfsDaemon *daemon)
 	  /* Only re-register if we registered before, not e.g
 	     if we're currently mounting. */
 	  if (g_vfs_backend_is_mounted (backend))
-	    g_vfs_backend_register_mount (backend, NULL, NULL);
+	    g_vfs_backend_register_mount (backend, (GAsyncReadyCallback) re_register_jobs_cb, NULL);
 	}
     }
   
@@ -391,22 +462,32 @@ g_vfs_daemon_add_job_source (GVfsDaemon *daemon,
   g_mutex_unlock (&daemon->lock);
 }
 
-/* This registers a dbus callback on *all* connections, client and session bus */
+/* This registers a dbus interface skeleton on *all* connections, client and session bus */
 void
 g_vfs_daemon_register_path (GVfsDaemon *daemon,
-			    const char *obj_path,
-			    DBusObjectPathMessageFunction callback,
-			    gpointer user_data)
+                            const char *obj_path,
+                            const char *name,
+                            GVfsRegisterPathCallback callback,
+                            gpointer user_data)
 {
   RegisteredPath *data;
 
+  g_print ("g_vfs_daemon_register_path: obj_path = '%s'\n", obj_path);
+
   data = g_new0 (RegisteredPath, 1);
   data->obj_path = g_strdup (obj_path);
+  data->name = g_strdup (name);
   data->callback = callback;
   data->data = user_data;
-
+  
   g_hash_table_insert (daemon->registered_paths, data->obj_path,
 		       data);
+  
+  /* Export the newly registered interface skeleton on session bus */
+  /* TODO: change the way we export skeletons on connections once 
+   *       https://bugzilla.gnome.org/show_bug.cgi?id=662718 is in place.
+   */ 
+  data->skeleton = callback (daemon->conn, data->obj_path, user_data);
 }
 
 void
@@ -484,10 +565,75 @@ new_connection_data_free (void *memory)
 }
 
 static void
+peer_unregister_skeleton (gpointer key,
+                          RegisteredPath *reg_path,
+                          GDBusConnection *dbus_conn)
+{
+  GDBusInterfaceSkeleton *skeleton;
+
+  g_print ("unregistering '%s' on the %p connection\n", reg_path->name, dbus_conn);
+  
+  skeleton = g_object_get_data (G_OBJECT (dbus_conn), reg_path->name);
+  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (skeleton));
+}
+
+static void
+peer_connection_closed (GDBusConnection *connection,
+                        gboolean         remote_peer_vanished,
+                        GError          *error,
+                        gpointer         user_data)
+{
+  GVfsDaemon *daemon = user_data;
+  GList *l;
+  GVfsDBusDaemon *daemon_skeleton;
+
+  g_print ("peer_connection_closed\n");
+  
+  g_mutex_lock (&daemon->lock);
+  for (l = daemon->jobs; l != NULL; l = l->next)
+    {
+      GVfsJob *job = l->data;
+      
+      if (G_VFS_IS_JOB_DBUS (job) &&
+          G_VFS_JOB_DBUS (job)->invocation &&
+          g_dbus_method_invocation_get_connection (G_VFS_JOB_DBUS (job)->invocation) == connection)
+        g_vfs_job_cancel (job);
+    }
+  g_mutex_unlock (&daemon->lock);
+
+
+  daemon_skeleton = g_object_get_data (G_OBJECT (connection), "daemon_skeleton");
+  /* daemon_skeleton should be always valid in this case */
+  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (daemon_skeleton));
+  
+  /* Unexport the registered interface skeletons */
+  g_hash_table_foreach (daemon->registered_paths, (GHFunc) peer_unregister_skeleton, connection);
+
+  /* The peer-to-peer connection was disconnected */
+  g_object_unref (connection);
+}
+
+static void
+peer_register_skeleton (gpointer key,
+                        RegisteredPath *reg_path,
+                        GDBusConnection *dbus_conn)
+{
+  GDBusInterfaceSkeleton *skeleton;
+
+  g_print ("registering '%s' on the %p connection\n", reg_path->name, dbus_conn);
+  
+  skeleton = reg_path->callback (dbus_conn, reg_path->obj_path, reg_path->data);
+  g_object_set_data_full (G_OBJECT (dbus_conn), reg_path->name, skeleton, (GDestroyNotify) g_object_unref);
+}
+
+static void
 daemon_peer_connection_setup (GVfsDaemon *daemon,
-			      DBusConnection *dbus_conn,
+                              GDBusConnection *dbus_conn,
 			      NewConnectionData *data)
 {
+  GVfsDBusDaemon *daemon_skeleton;
+  GError *error;
+  
   /* We wait until we have the extra fd */
   if (!data->got_fd_connection)
     return;
@@ -496,21 +642,34 @@ daemon_peer_connection_setup (GVfsDaemon *daemon,
     {
       /* The fd connection failed, abort the whole thing */
       g_warning ("Failed to accept client: %s", "accept of extra fd failed");
-      dbus_connection_unref (dbus_conn);
+      g_object_unref (data->conn);
       goto error_out;
     }
+
+  daemon_skeleton = gvfs_dbus_daemon_skeleton_new ();
+  g_signal_connect (daemon_skeleton, "handle-cancel", G_CALLBACK (handle_cancel), daemon);
   
-  dbus_connection_setup_with_g_main (dbus_conn, NULL);
-  if (!dbus_connection_add_filter (dbus_conn, peer_to_peer_filter_func, daemon, NULL) ||
-      !dbus_connection_add_filter (dbus_conn, daemon_message_func, daemon, NULL))
+  error = NULL;
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (daemon_skeleton),
+                                         dbus_conn,
+                                         G_VFS_DBUS_DAEMON_PATH,
+                                         &error))
     {
-      g_warning ("Failed to accept client: %s", "object registration failed");
-      dbus_connection_unref (dbus_conn);
+      g_warning ("Failed to accept client: %s, %s (%s, %d)", "object registration failed", 
+                 error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      g_object_unref (data->conn);
       close (data->fd);
       goto error_out;
     }
+  g_object_set_data_full (G_OBJECT (data->conn), "daemon_skeleton", daemon_skeleton, (GDestroyNotify) g_object_unref);
+  
+  /* Export registered interface skeletons on this new connection */
+  g_hash_table_foreach (daemon->registered_paths, (GHFunc) peer_register_skeleton, dbus_conn);
   
-  dbus_connection_add_fd_send_fd (dbus_conn, data->fd);
+  g_print ("daemon_peer_connection_setup: interface registration complete.\n");
+
+  g_signal_connect (data->conn, "closed", G_CALLBACK (peer_connection_closed), data->daemon);
 
  error_out:
   new_connection_data_free (data);
@@ -645,10 +804,10 @@ generate_addresses (char **address1,
 #endif
 }
 
-static void
-daemon_new_connection_func (DBusServer     *server,
-			    DBusConnection *conn,
-			    gpointer        user_data)
+static gboolean
+daemon_new_connection_func (GDBusServer *server,
+                            GDBusConnection *connection,
+                            gpointer user_data)
 {
   NewConnectionData *data;
 
@@ -656,13 +815,17 @@ daemon_new_connection_func (DBusServer     *server,
   data->got_dbus_connection = TRUE;
 
   /* Take ownership */
-  data->conn = dbus_connection_ref (conn);
+  data->conn = g_object_ref (connection);
 
-  daemon_peer_connection_setup (data->daemon, conn, data);
+  daemon_peer_connection_setup (data->daemon, data->conn, data);
 
+  g_print ("daemon_new_connection_func: closing server\n");
+  
   /* Kill the server, no more need for it */
-  dbus_server_disconnect (server);
-  dbus_server_unref (server);
+  g_dbus_server_stop (server);
+  g_object_unref (server);
+  
+  return TRUE;
 }
 
 static int
@@ -724,6 +887,8 @@ accept_new_fd_client (GIOChannel  *channel,
   struct sockaddr_un addr;
   socklen_t addrlen;
 
+  g_print ("accept_new_fd_client\n");
+  
   data->got_fd_connection = TRUE;
   
   fd = g_io_channel_unix_get_fd (channel);
@@ -743,28 +908,31 @@ accept_new_fd_client (GIOChannel  *channel,
     {
       /* Didn't accept a dbus connection, and there is no need for one now */
       g_warning ("Failed to accept client: %s", "accept of extra fd failed");
-      dbus_server_disconnect (data->server);
-      dbus_server_unref (data->server);
+      g_dbus_server_stop (data->server);
+      g_object_unref (data->server);
       new_connection_data_free (data);
     }
   
   return FALSE;
 }
 
-static void
-daemon_handle_get_connection (DBusConnection *conn,
-			      DBusMessage *message,
-			      GVfsDaemon *daemon)
+static gboolean
+handle_get_connection (GVfsDBusDaemon *object,
+                       GDBusMethodInvocation *invocation,
+                       gpointer user_data)
 {
-  DBusServer    *server;
-  DBusError      error;
-  DBusMessage   *reply;
-  gchar         *address1;
-  gchar         *address2;
+  GVfsDaemon *daemon = user_data;
+  GDBusServer *server;
+  GError *error;
+  gchar *address1;
+  gchar *address2;
   NewConnectionData *data;
   GIOChannel *channel;
   char *socket_dir;
   int fd;
+  gchar *guid;
+  
+  g_print ("called get_connection()\n");
   
   generate_addresses (&address1, &address2, &socket_dir);
 
@@ -775,60 +943,51 @@ daemon_handle_get_connection (DBusConnection *conn,
   data->got_dbus_connection = FALSE;
   data->fd = -1;
   data->conn = NULL;
-  
-  dbus_error_init (&error);
-  server = dbus_server_listen (address1, &error);
-  if (!server)
-    {
-      reply = dbus_message_new_error_printf (message,
-					     G_VFS_DBUS_ERROR_SOCKET_FAILED,
-					     "Failed to create new socket: %s", 
-					     error.message);
-      dbus_error_free (&error);
-      if (reply)
-	{
-	  dbus_connection_send (conn, reply, NULL);
-	  dbus_message_unref (reply);
-	}
-      
-      goto error_out;
-    }
-  data->server = server;
 
-  dbus_server_set_new_connection_function (server,
-					   daemon_new_connection_func,
-					   data, NULL);
-  dbus_server_setup_with_g_main (server, NULL);
-  
   fd = unix_socket_at (address2);
   if (fd == -1)
     goto error_out;
 
+  guid = g_dbus_generate_guid ();
+  error = NULL;
+  server = g_dbus_server_new_sync (address1,
+                                   G_DBUS_SERVER_FLAGS_NONE,
+                                   guid,
+                                   NULL, /* GDBusAuthObserver */
+                                   NULL, /* GCancellable */
+                                   &error);
+  g_free (guid);
+
+  if (server == NULL)
+    {
+      g_dbus_method_invocation_return_gerror (invocation, error);
+      g_printerr ("daemon: Error creating server at address %s: %s\n", address1, error->message);
+      g_error_free (error);
+      goto error_out;
+    }
+
+  g_dbus_server_start (server);
+  data->server = server;
+  
+  g_print ("Server is listening at: %s\n", g_dbus_server_get_client_address (server));
+  g_signal_connect (server, "new-connection", G_CALLBACK (daemon_new_connection_func), data);
+  
   channel = g_io_channel_unix_new (fd);
   g_io_channel_set_close_on_unref (channel, TRUE);
   data->io_watch = g_io_add_watch (channel, G_IO_IN | G_IO_HUP, accept_new_fd_client, data);
   g_io_channel_unref (channel);
-    
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
-
-  if (!dbus_message_append_args (reply,
-				 DBUS_TYPE_STRING, &address1,
-				 DBUS_TYPE_STRING, &address2,
-				 DBUS_TYPE_INVALID))
-    _g_dbus_oom ();
-  
-  dbus_connection_send (conn, reply, NULL);
-  
-  dbus_message_unref (reply);
+
+  gvfs_dbus_daemon_complete_get_connection (object,
+                                            invocation,
+                                            address1,
+                                            address2);
 
   g_free (address1);
   g_free (address2);
-
-  return;
+  return TRUE;
 
  error_out:
+  g_print ("handle_get_connection: error_out\n"); 
   g_free (data);
   g_free (address1);
   g_free (address2);
@@ -837,194 +996,78 @@ daemon_handle_get_connection (DBusConnection *conn,
       rmdir (socket_dir);
       g_free (socket_dir);
     }
+  return TRUE;
 }
 
-static void
-daemon_start_mount (GVfsDaemon *daemon,
-		    DBusConnection *connection,
-		    DBusMessage *message)
-{
-  const char *dbus_id, *obj_path;
-  DBusMessageIter iter;
-  DBusError derror;
-  DBusMessage *reply;
-  GMountSpec *mount_spec;
-  GMountSource *mount_source;
-  dbus_bool_t automount;
-
-  dbus_message_iter_init (message, &iter);
-
-  reply = NULL;
-  mount_spec = NULL;
-  dbus_error_init (&derror);
-  if ((mount_spec = g_mount_spec_from_dbus (&iter)) == NULL)
-    reply = dbus_message_new_error (message,
-				    DBUS_ERROR_INVALID_ARGS,
-				    "Error in mount spec");
-  else if (!_g_dbus_message_iter_get_args (&iter, &derror,
-					   DBUS_TYPE_BOOLEAN, &automount,
-					   DBUS_TYPE_STRING, &dbus_id,
-					   DBUS_TYPE_OBJECT_PATH, &obj_path,
-					   0))
-    {
-      reply = dbus_message_new_error (message, derror.name, derror.message);
-      dbus_error_free (&derror);
-    }
-
-  if (reply)
-    {
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
-  else
-    {
-      mount_source = g_mount_source_new (dbus_id, obj_path);
-      g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, automount, message);
-      g_object_unref (mount_source);
-      g_mount_spec_unref (mount_spec);
-    }
-}
-
-static DBusHandlerResult
-daemon_message_func (DBusConnection *conn,
-		     DBusMessage    *message,
-		     gpointer        data)
+static gboolean
+handle_cancel (GVfsDBusDaemon *object,
+               GDBusMethodInvocation *invocation,
+               guint arg_serial,
+               gpointer user_data)
 {
-  GVfsDaemon *daemon = data;
-  RegisteredPath *registered_path;
-  const char *path;
-  char *name;
-  char *old_owner, *new_owner;
+  GVfsDaemon *daemon = user_data;
+  GList *l;
+  GVfsJob *job_to_cancel = NULL;
 
-  path = dbus_message_get_path (message);
-  if (path == NULL)
-    path = "";
+  g_print ("called cancel(), should be on our private connection only\n");
   
-  if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameLost"))
-    {
-      if (dbus_message_get_args (message, NULL,
-				 DBUS_TYPE_STRING, &name,
-				 DBUS_TYPE_INVALID) &&
-	  strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0)
-	{
-	  /* Someone else got the name (i.e. someone used --replace), exit */
-	  if (daemon->main_daemon)
-	    exit (1);
-	}
-    }
-  else if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged"))
-    {
-      if (dbus_message_get_args (message, NULL,
-				 DBUS_TYPE_STRING, &name,
-				 DBUS_TYPE_STRING, &old_owner,
-				 DBUS_TYPE_STRING, &new_owner,
-				 DBUS_TYPE_INVALID) &&
-	  strcmp (name, G_VFS_DBUS_DAEMON_NAME) == 0 &&
-	  *new_owner != 0 &&
-	  !daemon->main_daemon)
-	{
-	  /* There is a new owner. Register mounts with it */
-	  g_vfs_daemon_re_register_job_sources (daemon);
-	}
-      
-    }
-
-
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_DAEMON_INTERFACE,
-				   G_VFS_DBUS_OP_GET_CONNECTION))
-    {
-      daemon_handle_get_connection (conn, message, daemon);
-      return DBUS_HANDLER_RESULT_HANDLED;
-    }
-
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_DAEMON_INTERFACE,
-				   G_VFS_DBUS_OP_CANCEL))
+  g_mutex_lock (&daemon->lock);
+  for (l = daemon->jobs; l != NULL; l = l->next)
     {
-      GList *l;
-      dbus_uint32_t serial;
-      GVfsJob *job_to_cancel = NULL;
+      GVfsJob *job = l->data;
       
-      if (dbus_message_get_args (message, NULL, 
-				 DBUS_TYPE_UINT32, &serial,
-				 DBUS_TYPE_INVALID))
-	{
-	  g_mutex_lock (&daemon->lock);
-	  for (l = daemon->jobs; l != NULL; l = l->next)
-	    {
-	      GVfsJob *job = l->data;
-	      
-	      if (G_VFS_IS_JOB_DBUS (job) &&
-		  g_vfs_job_dbus_is_serial (G_VFS_JOB_DBUS (job),
-					    conn, serial))
-		{
-		  job_to_cancel = g_object_ref (job);
-		  break;
-		}
-	    }
-	  g_mutex_unlock (&daemon->lock);
-
-
-	  if (job_to_cancel)
-	    {
-	      g_vfs_job_cancel (job_to_cancel);
-	      g_object_unref (job_to_cancel);
-	    }
-	}
-      
-      return DBUS_HANDLER_RESULT_HANDLED;
+      if (G_VFS_IS_JOB_DBUS (job) &&
+          g_vfs_job_dbus_is_serial (G_VFS_JOB_DBUS (job),
+                                    g_dbus_method_invocation_get_connection (invocation),
+                                    arg_serial))
+        {
+          job_to_cancel = g_object_ref (job);
+          break;
+        }
     }
+  g_mutex_unlock (&daemon->lock);
 
-  if (strcmp (path, G_VFS_DBUS_MOUNTABLE_PATH) == 0 &&
-      dbus_message_is_method_call (message,
-				   G_VFS_DBUS_MOUNTABLE_INTERFACE,
-				   G_VFS_DBUS_MOUNTABLE_OP_MOUNT))
+  if (job_to_cancel)
     {
-      daemon_start_mount (daemon, conn, message);
-      return DBUS_HANDLER_RESULT_HANDLED;
+      g_vfs_job_cancel (job_to_cancel);
+      g_object_unref (job_to_cancel);
     }
   
-  registered_path = g_hash_table_lookup (daemon->registered_paths, path);
-  
-  if (registered_path)
-    return registered_path->callback (conn, message, registered_path->data);
-  else
-    return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
+  gvfs_dbus_daemon_complete_cancel (object, invocation);
 
+  return TRUE;
+}
 
-/* Only called for peer-to-peer connections */
-static DBusHandlerResult
-peer_to_peer_filter_func (DBusConnection *conn,
-			  DBusMessage    *message,
-			  gpointer        data)
+static gboolean
+daemon_handle_mount (GVfsDBusMountable *object,
+                     GDBusMethodInvocation *invocation,
+                     GVariant *arg_mount_spec,
+                     gboolean arg_automount,
+                     GVariant *arg_mount_source,
+                     gpointer user_data)
 {
-  GVfsDaemon *daemon = data;
-
-  if (dbus_message_is_signal (message,
-			      DBUS_INTERFACE_LOCAL,
-			      "Disconnected"))
+  GVfsDaemon *daemon = user_data;
+  GMountSpec *mount_spec;
+  GMountSource *mount_source;
+  
+  g_print ("called daemon_handle_mount()\n");
+  
+  mount_spec = g_mount_spec_from_dbus (arg_mount_spec);
+  if (mount_spec == NULL)
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_INVALID_ARGUMENT,
+                                                   "Error in mount spec");
+  else 
     {
-      GList *l;
-
-      g_mutex_lock (&daemon->lock);
-      for (l = daemon->jobs; l != NULL; l = l->next)
-        {
-          GVfsJob *job = l->data;
-          
-          if (G_VFS_IS_JOB_DBUS (job) &&
-              G_VFS_JOB_DBUS (job)->connection == conn)
-            g_vfs_job_cancel (job);
-        }
-      g_mutex_unlock (&daemon->lock);
-
-      /* The peer-to-peer connection was disconnected */
-      dbus_connection_unref (conn);
-      return DBUS_HANDLER_RESULT_HANDLED;
+      mount_source = g_mount_source_from_dbus (arg_mount_source);
+      g_vfs_daemon_initiate_mount (daemon, mount_spec, mount_source, arg_automount,
+                                   object, invocation);
+      g_object_unref (mount_source);
+      g_mount_spec_unref (mount_spec);
     }
   
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  return TRUE;
 }
 
 void
@@ -1032,16 +1075,17 @@ g_vfs_daemon_initiate_mount (GVfsDaemon *daemon,
 			     GMountSpec *mount_spec,
 			     GMountSource *mount_source,
 			     gboolean is_automount,
-			     DBusMessage *request)
+			     GVfsDBusMountable *object,
+			     GDBusMethodInvocation *invocation)
 {
   const char *type;
   GType backend_type;
   char *obj_path;
   GVfsJob *job;
   GVfsBackend *backend;
-  DBusConnection *conn;
-  DBusMessage *reply;
 
+  g_print ("g_vfs_daemon_initiate_mount\n");
+  
   type = g_mount_spec_get_type (mount_spec);
 
   backend_type = G_TYPE_INVALID;
@@ -1050,21 +1094,11 @@ g_vfs_daemon_initiate_mount (GVfsDaemon *daemon,
 
   if (backend_type == G_TYPE_INVALID)
     {
-      if (request)
-	{
-	  reply = _dbus_message_new_gerror (request,
-					    G_IO_ERROR, G_IO_ERROR_FAILED,
-					    _("Invalid backend type"));
-	  
-	  /* Queues reply (threadsafely), actually sends it in mainloop */
-	  conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-	  if (conn)
-	    {
-	      dbus_connection_send (conn, reply, NULL);
-	      dbus_message_unref (reply);
-	      dbus_connection_unref (conn);
-	    }
-	}
+      if (invocation)
+        g_dbus_method_invocation_return_error_literal (invocation,
+                                                       G_IO_ERROR,
+                                                       G_IO_ERROR_ALREADY_MOUNTED,
+                                                       "Mountpoint Already registered");
       else
 	g_warning ("Error mounting: invalid backend type\n");
       return;
@@ -1075,12 +1109,13 @@ g_vfs_daemon_initiate_mount (GVfsDaemon *daemon,
 			  "daemon", daemon,
 			  "object-path", obj_path,
 			  NULL);
+  g_print ("g_vfs_daemon_initiate_mount: obj_path = '%s'\n", obj_path);
   g_free (obj_path);
-
+  
   g_vfs_daemon_add_job_source (daemon, G_VFS_JOB_SOURCE (backend));
   g_object_unref (backend);
 
-  job = g_vfs_job_mount_new (mount_spec, mount_source, is_automount, request, backend);
+  job = g_vfs_job_mount_new (mount_spec, mount_source, is_automount, object, invocation, backend);
   g_vfs_daemon_queue_job (daemon, job);
   g_object_unref (job);
 }
diff --git a/daemon/gvfsdaemon.h b/daemon/gvfsdaemon.h
index 00d7fe1..37ea7f0 100644
--- a/daemon/gvfsdaemon.h
+++ b/daemon/gvfsdaemon.h
@@ -26,7 +26,7 @@
 #include <glib-object.h>
 #include <gvfsjobsource.h>
 #include <gmountsource.h>
-#include <dbus/dbus.h>
+#include <gvfsdbus.h>
 
 G_BEGIN_DECLS
 
@@ -49,6 +49,10 @@ struct _GVfsDaemonClass
   
 };
 
+typedef GDBusInterfaceSkeleton *  (*GVfsRegisterPathCallback)  (GDBusConnection *conn,
+                                                                const char      *obj_path,
+                                                                gpointer         data);
+
 GType g_vfs_daemon_get_type (void) G_GNUC_CONST;
 
 GVfsDaemon *g_vfs_daemon_new             (gboolean                       main_daemon,
@@ -60,16 +64,18 @@ void        g_vfs_daemon_add_job_source  (GVfsDaemon                    *daemon,
 void        g_vfs_daemon_queue_job       (GVfsDaemon                    *daemon,
 					  GVfsJob                       *job);
 void        g_vfs_daemon_register_path   (GVfsDaemon                    *daemon,
-					  const char                    *obj_path,
-					  DBusObjectPathMessageFunction  callback,
-					  gpointer                       user_data);
+                                          const char                    *obj_path,
+                                          const char                    *name,
+                                          GVfsRegisterPathCallback       callback,
+                                          gpointer                       user_data);
 void        g_vfs_daemon_unregister_path (GVfsDaemon                    *daemon,
 					  const char                    *obj_path);
 void        g_vfs_daemon_initiate_mount  (GVfsDaemon                    *daemon,
 					  GMountSpec                    *mount_spec,
 					  GMountSource                  *mount_source,
 					  gboolean                       is_automount,
-					  DBusMessage                   *request);
+	                                  GVfsDBusMountable             *object,
+					  GDBusMethodInvocation         *invocation);
 GArray     *g_vfs_daemon_get_blocking_processes (GVfsDaemon             *daemon);
 void        g_vfs_daemon_run_job_in_thread      (GVfsDaemon             *daemon,
 						 GVfsJob                *job);
diff --git a/daemon/gvfsdaemonutils.c b/daemon/gvfsdaemonutils.c
index 1dfa4ef..7f6e99f 100644
--- a/daemon/gvfsdaemonutils.c
+++ b/daemon/gvfsdaemonutils.c
@@ -35,84 +35,9 @@
 #include <glib/gi18n.h>
 
 #include <gio/gio.h>
-#include "gvfsdbusutils.h"
-#include "gsysutils.h"
 #include "gvfsdaemonutils.h"
 #include "gvfsdaemonprotocol.h"
 
-static gint32 extra_fd_slot = -1;
-static GMutex extra_lock;
-
-typedef struct {
-  int extra_fd;
-  int fd_count;
-} ConnectionExtra;
-
-static void
-free_extra (gpointer p)
-{
-  ConnectionExtra *extra = p;
-  close (extra->extra_fd);
-  g_free (extra);
-}
-
-void
-dbus_connection_add_fd_send_fd (DBusConnection *connection,
-				int extra_fd)
-{
-  ConnectionExtra *extra;
-
-  if (extra_fd_slot == -1 && 
-      !dbus_connection_allocate_data_slot (&extra_fd_slot))
-    g_error ("Unable to allocate data slot");
-
-  extra = g_new0 (ConnectionExtra, 1);
-  extra->extra_fd = extra_fd;
-  
-  if (!dbus_connection_set_data (connection, extra_fd_slot, extra, free_extra))
-    _g_dbus_oom ();
-}
-
-gboolean 
-dbus_connection_send_fd (DBusConnection *connection,
-			 int fd, 
-			 int *fd_id,
-			 GError **error)
-{
-  ConnectionExtra *extra;
-
-  g_assert (extra_fd_slot != -1);
-  extra = dbus_connection_get_data (connection, extra_fd_slot);
-  g_assert (extra != NULL);
-
-  if (extra->extra_fd == -1)
-    {
-      g_set_error (error, G_IO_ERROR,
-		   G_IO_ERROR_FAILED,
-		   _("Internal Error (%s)"), "No fd passing socket available");
-      return FALSE;
-    }
-
-  g_mutex_lock (&extra_lock);
-
-  if (_g_socket_send_fd (extra->extra_fd, fd) == -1)
-    {
-      int errsv = errno;
-
-      g_set_error (error, G_IO_ERROR,
-		   g_io_error_from_errno (errsv),
-		   _("Error sending file descriptor: %s"),
-		   g_strerror (errsv));
-      g_mutex_unlock (&extra_lock);
-      return FALSE;
-    }
-
-  *fd_id = extra->fd_count++;
-
-  g_mutex_unlock (&extra_lock);
-
-  return TRUE;
-}
 
 char *
 g_error_to_daemon_reply (GError *error, guint32 seq_nr, gsize *len_out)
diff --git a/daemon/gvfsdaemonutils.h b/daemon/gvfsdaemonutils.h
index 9a00631..0000caa 100644
--- a/daemon/gvfsdaemonutils.h
+++ b/daemon/gvfsdaemonutils.h
@@ -24,16 +24,9 @@
 #define __G_VFS_DAEMON_UTILS_H__
 
 #include <glib-object.h>
-#include <dbus/dbus.h>
 
 G_BEGIN_DECLS
 
-void         dbus_connection_add_fd_send_fd       (DBusConnection   *connection,
-						   int               extra_fd);
-gboolean     dbus_connection_send_fd              (DBusConnection   *connection,
-						   int               fd,
-						   int              *fd_id,
-						   GError          **error);
 char *       g_error_to_daemon_reply              (GError           *error,
 						   guint32           seq_nr,
 						   gsize            *len_out);
diff --git a/daemon/gvfsjob.c b/daemon/gvfsjob.c
index d9253d1..84f2e55 100644
--- a/daemon/gvfsjob.c
+++ b/daemon/gvfsjob.c
@@ -28,7 +28,6 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include <gio/gio.h>
 #include "gvfsjob.h"
diff --git a/daemon/gvfsjobcopy.c b/daemon/gvfsjobcopy.c
index 1a48b7f..9be8472 100644
--- a/daemon/gvfsjobcopy.c
+++ b/daemon/gvfsjobcopy.c
@@ -29,19 +29,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobcopy.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
+#include <gvfsdbus.h>
 
 G_DEFINE_TYPE (GVfsJobCopy, g_vfs_job_copy, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_copy_finalize (GObject *object)
@@ -76,52 +74,90 @@ g_vfs_job_copy_init (GVfsJobCopy *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_copy_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_copy_new_handle (GVfsDBusMount *object,
+                           GDBusMethodInvocation *invocation,
+                           const gchar *arg_path1_data,
+                           const gchar *arg_path2_data,
+                           guint arg_flags,
+                           const gchar *arg_progress_obj_path,
+                           GVfsBackend *backend)
 {
   GVfsJobCopy *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path1_len, path2_len;
-  const char *path1_data, *path2_data, *callback_obj_path;
-  dbus_uint32_t flags;
   
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path1_data, &path1_len,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path2_data, &path2_len,
-                              DBUS_TYPE_UINT32, &flags,
-			      DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
+  g_print ("called Copy()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
+  job = g_object_new (G_VFS_TYPE_JOB_COPY,
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
+
+  job->source = g_strdup (arg_path1_data);
+  job->destination = g_strdup (arg_path2_data);
+  job->backend = backend;
+  job->flags = arg_flags;
+  if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0)
+    job->callback_obj_path = g_strdup (arg_progress_obj_path);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
 
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
+  return TRUE;
+}
+
+typedef struct {
+  goffset current_num_bytes;
+  goffset total_num_bytes;
+} ProgressCallbackData;
 
-      return NULL;
+static void
+progress_cb (GVfsDBusProgress *proxy,
+             GAsyncResult *res,
+             gpointer user_data)
+{
+  GError *error = NULL;
+  
+  g_print ("progress_cb\n");
+  
+  if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error))
+    {
+      g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
     }
+}
 
-  job = g_object_new (G_VFS_TYPE_JOB_COPY,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+static void
+progress_proxy_new_cb (GObject *source_object,
+                       GAsyncResult *res,
+                       gpointer user_data)
+{
+  ProgressCallbackData *data = user_data;
+  GVfsDBusProgress *proxy;
+  GError *error = NULL;
 
-  job->source = g_strndup (path1_data, path1_len);
-  job->destination = g_strndup (path2_data, path2_len);
-  job->backend = backend;
-  job->flags = flags;
-  if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
-    job->callback_obj_path = g_strdup (callback_obj_path);
+  g_print ("progress_proxy_new_cb\n");
+
+  proxy = gvfs_dbus_progress_proxy_new_finish (res, &error);
+  if (proxy == NULL)
+    {
+      g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      goto out;
+    }
+  
+  gvfs_dbus_progress_call_progress (proxy,
+                                    data->current_num_bytes,
+                                    data->total_num_bytes,
+                                    NULL,
+                                    (GAsyncReadyCallback) progress_cb,
+                                    NULL);
+  g_object_unref (proxy);
   
-  return G_VFS_JOB (job);
+ out:
+  g_free (data);
 }
 
 static void
@@ -132,31 +168,24 @@ progress_callback (goffset current_num_bytes,
   GVfsJob *job = G_VFS_JOB (user_data);
   GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
   GVfsJobCopy *op_job = G_VFS_JOB_COPY (job);
-  dbus_uint64_t current_dbus, total_dbus;
-  DBusMessage *message;
+  ProgressCallbackData *data;
 
   g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes);
 
   if (op_job->callback_obj_path == NULL)
     return;
 
-  message =
-    dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
-				  op_job->callback_obj_path,
-				  G_VFS_DBUS_PROGRESS_INTERFACE,
-				  G_VFS_DBUS_PROGRESS_OP_PROGRESS);
-  dbus_message_set_no_reply (message, TRUE);
-
-  current_dbus = current_num_bytes;
-  total_dbus = total_num_bytes;
-  dbus_message_append_args (message,
-			    DBUS_TYPE_UINT64, &current_dbus,
-			    DBUS_TYPE_UINT64, &total_dbus,
-			    0);
-
-  /* Queues reply (threadsafely), actually sends it in mainloop */
-  dbus_connection_send (dbus_job->connection, message, NULL);
-  dbus_message_unref (message);
+  data = g_new0 (ProgressCallbackData, 1);
+  data->current_num_bytes = current_num_bytes;
+  data->total_num_bytes = total_num_bytes;
+  
+  gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation),
+                                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                g_dbus_method_invocation_get_sender (dbus_job->invocation),
+                                op_job->callback_obj_path,
+                                NULL,
+                                progress_proxy_new_cb,
+                                data);
 }
 
 static void
@@ -200,14 +229,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_copy (object, invocation);
 }
diff --git a/daemon/gvfsjobcopy.h b/daemon/gvfsjobcopy.h
index ddadd50..322d2c7 100644
--- a/daemon/gvfsjobcopy.h
+++ b/daemon/gvfsjobcopy.h
@@ -58,9 +58,13 @@ struct _GVfsJobCopyClass
 
 GType g_vfs_job_copy_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_copy_new (DBusConnection *connection,
-			     DBusMessage    *message,
-			     GVfsBackend    *backend);
+gboolean g_vfs_job_copy_new_handle (GVfsDBusMount         *object,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar           *arg_path1_data,
+                                    const gchar           *arg_path2_data,
+                                    guint                  arg_flags,
+                                    const gchar           *arg_progress_obj_path,
+                                    GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobcreatemonitor.c b/daemon/gvfsjobcreatemonitor.c
index e788ee4..4e3d772 100644
--- a/daemon/gvfsjobcreatemonitor.c
+++ b/daemon/gvfsjobcreatemonitor.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobcreatemonitor.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobCreateMonitor, g_vfs_job_create_monitor, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_create_monitor_finalize (GObject *object)
@@ -75,50 +72,59 @@ g_vfs_job_create_monitor_init (GVfsJobCreateMonitor *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_create_monitor_new (DBusConnection *connection,
-			      DBusMessage *message,
-			      GVfsBackend *backend,
-			      gboolean is_directory)
+
+static gboolean
+create_monitor_new_handle (GVfsDBusMount *object,
+                           GDBusMethodInvocation *invocation,
+                           const gchar *arg_path_data,
+                           guint arg_flags,
+                           GVfsBackend *backend,
+                           gboolean is_directory)
 {
   GVfsJobCreateMonitor *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  char *path;
-  guint32 flags;
-  
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  path = NULL;
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_UINT32, &flags,
-				      0))
-    {
-      g_free (path);
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_CREATE_MONITOR,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
-
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
+  
   job->is_directory = is_directory;
-  job->filename = path;
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->flags = flags;
+  job->flags = arg_flags;
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+gboolean
+g_vfs_job_create_file_monitor_new_handle (GVfsDBusMount *object,
+                                          GDBusMethodInvocation *invocation,
+                                          const gchar *arg_path_data,
+                                          guint arg_flags,
+                                          GVfsBackend *backend)
+{
+  g_print ("called CreateFileMonitor()\n");
   
-  return G_VFS_JOB (job);
+  return create_monitor_new_handle (object, invocation, arg_path_data, arg_flags, backend, FALSE);
+}
+
+
+gboolean
+g_vfs_job_create_directory_monitor_new_handle (GVfsDBusMount *object,
+                                               GDBusMethodInvocation *invocation,
+                                               const gchar *arg_path_data,
+                                               guint arg_flags,
+                                               GVfsBackend *backend)
+{
+  g_print ("called CreateDirectoryMonitor()\n");
+  
+  return create_monitor_new_handle (object, invocation, arg_path_data, arg_flags, backend, TRUE);
 }
 
 void
@@ -217,18 +223,14 @@ unref_monitor_timeout (gpointer data)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobCreateMonitor *op_job = G_VFS_JOB_CREATE_MONITOR (job);
-  DBusMessage *reply;
-  DBusMessageIter iter;
   const char *obj_path;
 
-  reply = dbus_message_new_method_return (message);
-
   /* Keep the monitor alive for at least 5 seconds
      to allow for a subscribe call to come in and bump
      the refcount */
@@ -238,10 +240,9 @@ create_reply (GVfsJob *job,
 			 op_job->monitor);
   
   obj_path = g_vfs_monitor_get_object_path (op_job->monitor);
-  dbus_message_iter_init_append (reply, &iter);
-  _g_dbus_message_append_args (reply,
-			       DBUS_TYPE_OBJECT_PATH, &obj_path,
-			       0);
   
-  return reply;
+  if (op_job->is_directory)
+    gvfs_dbus_mount_complete_create_directory_monitor (object, invocation, obj_path);
+  else
+    gvfs_dbus_mount_complete_create_file_monitor (object, invocation, obj_path);
 }
diff --git a/daemon/gvfsjobcreatemonitor.h b/daemon/gvfsjobcreatemonitor.h
index 6c7285a..6d0f8ae 100644
--- a/daemon/gvfsjobcreatemonitor.h
+++ b/daemon/gvfsjobcreatemonitor.h
@@ -59,10 +59,17 @@ struct _GVfsJobCreateMonitorClass
 
 GType g_vfs_job_create_monitor_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_create_monitor_new         (DBusConnection       *connection,
-					       DBusMessage          *message,
-					       GVfsBackend          *backend,
-					       gboolean              is_directory);
+gboolean g_vfs_job_create_file_monitor_new_handle      (GVfsDBusMount         *object,
+                                                        GDBusMethodInvocation *invocation,
+                                                        const gchar           *arg_path_data,
+                                                        guint                  arg_flags,
+                                                        GVfsBackend           *backend);
+gboolean g_vfs_job_create_directory_monitor_new_handle (GVfsDBusMount         *object,
+                                                        GDBusMethodInvocation *invocation,
+                                                        const gchar           *arg_path_data,
+                                                        guint                  arg_flags,
+                                                        GVfsBackend           *backend);
+
 void     g_vfs_job_create_monitor_set_monitor (GVfsJobCreateMonitor *job,
 					       GVfsMonitor          *monitor);
 
diff --git a/daemon/gvfsjobdbus.c b/daemon/gvfsjobdbus.c
index 48d7f7e..a1ff65b 100644
--- a/daemon/gvfsjobdbus.c
+++ b/daemon/gvfsjobdbus.c
@@ -28,10 +28,8 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobdbus.h"
-#include "gvfsdbusutils.h"
 
 G_DEFINE_TYPE (GVfsJobDBus, g_vfs_job_dbus, G_VFS_TYPE_JOB)
 
@@ -40,8 +38,8 @@ G_DEFINE_TYPE (GVfsJobDBus, g_vfs_job_dbus, G_VFS_TYPE_JOB)
 
 enum {
   PROP_0,
-  PROP_MESSAGE,
-  PROP_CONNECTION
+  PROP_INVOCATION,
+  PROP_OBJECT
 };
 
 static void send_reply                  (GVfsJob      *job);
@@ -61,11 +59,11 @@ g_vfs_job_dbus_finalize (GObject *object)
 
   job = G_VFS_JOB_DBUS (object);
 
-  if (job->message)
-    dbus_message_unref (job->message);
-
-  if (job->connection)
-    dbus_connection_unref (job->connection);
+  if (job->invocation)
+    g_object_unref (job->invocation);
+  
+  if (job->object)
+    g_object_unref (job->object);
   
   if (G_OBJECT_CLASS (g_vfs_job_dbus_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_vfs_job_dbus_parent_class)->finalize) (object);
@@ -84,19 +82,19 @@ g_vfs_job_dbus_class_init (GVfsJobDBusClass *klass)
   job_class->send_reply = send_reply;
 
   g_object_class_install_property (gobject_class,
-				   PROP_CONNECTION,
-				   g_param_spec_pointer ("connection",
+				   PROP_INVOCATION,
+				   g_param_spec_pointer ("invocation",
 							P_("VFS Backend"),
-							P_("The implementation for this job operartion."),
+							P_("The implementation for this job operation."),
 							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
 							G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
   g_object_class_install_property (gobject_class,
-				   PROP_MESSAGE,
-				   g_param_spec_pointer ("message",
-							P_("VFS Backend"),
-							P_("The implementation for this job operartion."),
-							G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
-							G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
+                                   PROP_OBJECT,
+                                   g_param_spec_pointer ("object",
+                                                        P_("VFS Backend"),
+                                                        P_("The implementation for this job operation."),
+                                                        G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_NAME|G_PARAM_STATIC_NICK|G_PARAM_STATIC_BLURB));
 }
 
 static void
@@ -114,11 +112,11 @@ g_vfs_job_dbus_set_property (GObject         *object,
   
   switch (prop_id)
     {
-    case PROP_MESSAGE:
-      job->message = dbus_message_ref (g_value_get_pointer (value));
+    case PROP_INVOCATION:
+      job->invocation = g_object_ref (g_value_get_pointer (value));
       break;
-    case PROP_CONNECTION:
-      job->connection = dbus_connection_ref (g_value_get_pointer (value));
+    case PROP_OBJECT:
+      job->object = g_object_ref (g_value_get_pointer (value));
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -136,11 +134,11 @@ g_vfs_job_dbus_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_MESSAGE:
-      g_value_set_pointer (value, job->message);
+    case PROP_INVOCATION:
+      g_value_set_pointer (value, job->invocation);
       break;
-    case PROP_CONNECTION:
-      g_value_set_pointer (value, job->connection);
+    case PROP_OBJECT:
+      g_value_set_pointer (value, job->object);
       break;
     default:
       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -153,44 +151,29 @@ static void
 send_reply (GVfsJob *job)
 {
   GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
-  DBusMessage *reply;
   GVfsJobDBusClass *class;
 
   g_debug ("send_reply(%p), failed=%d (%s)\n", job, job->failed, job->failed?job->error->message:"");
   
   class = G_VFS_JOB_DBUS_GET_CLASS (job);
   
-  if (job->failed) 
-    reply = _dbus_message_new_from_gerror (dbus_job->message, job->error);
+  if (job->failed)
+    g_dbus_method_invocation_return_gerror (dbus_job->invocation, job->error);
   else
-    reply = class->create_reply (job, dbus_job->connection, dbus_job->message);
+    class->create_reply (job, dbus_job->object, dbus_job->invocation);
  
-  g_assert (reply != NULL);
-
-  /* Queues reply (threadsafely), actually sends it in mainloop */
-  dbus_connection_send (dbus_job->connection, reply, NULL);
-  dbus_message_unref (reply);
-
   g_vfs_job_emit_finished (job);
 }
 
-DBusConnection *
-g_vfs_job_dbus_get_connection (GVfsJobDBus *job_dbus)
-{
-  return job_dbus->connection;
-}
-
-DBusMessage *
-g_vfs_job_dbus_get_message (GVfsJobDBus *job_dbus)
-{
-  return job_dbus->message;
-}
-
 gboolean
 g_vfs_job_dbus_is_serial (GVfsJobDBus *job_dbus,
-			  DBusConnection *connection,
-			  dbus_uint32_t serial)
+                          GDBusConnection *connection,
+			  guint serial)
 {
+  return TRUE;
+  
+  /* FIXME 
   return job_dbus->connection == connection &&
     dbus_message_get_serial (job_dbus->message) == serial;
+    */
 }
diff --git a/daemon/gvfsjobdbus.h b/daemon/gvfsjobdbus.h
index 7c87634..b8ad65b 100644
--- a/daemon/gvfsjobdbus.h
+++ b/daemon/gvfsjobdbus.h
@@ -23,7 +23,6 @@
 #ifndef __G_VFS_JOB_DBUS_H__
 #define __G_VFS_JOB_DBUS_H__
 
-#include <dbus/dbus.h>
 #include <gvfsjob.h>
 #include <gvfsbackend.h>
 
@@ -43,8 +42,8 @@ struct _GVfsJobDBus
 {
   GVfsJob parent_instance;
 
-  DBusConnection *connection;
-  DBusMessage *message;
+  GVfsDBusMount *object;
+  GDBusMethodInvocation *invocation;
 };
 
 struct _GVfsJobDBusClass
@@ -52,18 +51,16 @@ struct _GVfsJobDBusClass
   GVfsJobClass parent_class;
 
   /* Might be called on an i/o thread */
-  DBusMessage * (*create_reply) (GVfsJob *job,
-				 DBusConnection *connection,
-				 DBusMessage *message);
+  void (*create_reply) (GVfsJob *job,
+                        GVfsDBusMount *object,
+                        GDBusMethodInvocation *invocation);
 };
 
 GType g_vfs_job_dbus_get_type (void) G_GNUC_CONST;
 
-gboolean        g_vfs_job_dbus_is_serial      (GVfsJobDBus    *job_dbus,
-					       DBusConnection *connection,
-					       dbus_uint32_t   serial);
-DBusConnection *g_vfs_job_dbus_get_connection (GVfsJobDBus    *job_dbus);
-DBusMessage    *g_vfs_job_dbus_get_message    (GVfsJobDBus    *job_dbus);
+gboolean g_vfs_job_dbus_is_serial (GVfsJobDBus     *job_dbus,
+                                   GDBusConnection *connection,
+                                   guint            serial);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobdelete.c b/daemon/gvfsjobdelete.c
index cc54356..51f59c3 100644
--- a/daemon/gvfsjobdelete.c
+++ b/daemon/gvfsjobdelete.c
@@ -28,19 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobdelete.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobDelete, g_vfs_job_delete, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_delete_finalize (GObject *object)
@@ -73,42 +71,31 @@ g_vfs_job_delete_init (GVfsJobDelete *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_delete_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_delete_new_handle (GVfsDBusMount *object,
+                             GDBusMethodInvocation *invocation,
+                             const gchar *arg_path_data,
+                             GVfsBackend *backend)
 {
   GVfsJobDelete *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
-  
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+
+  g_print ("called Delete()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
 
   job = g_object_new (G_VFS_TYPE_JOB_DELETE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  
-  return G_VFS_JOB (job);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -144,14 +131,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_delete (object, invocation);
 }
diff --git a/daemon/gvfsjobdelete.h b/daemon/gvfsjobdelete.h
index 91c2e8a..9dd9bef 100644
--- a/daemon/gvfsjobdelete.h
+++ b/daemon/gvfsjobdelete.h
@@ -54,10 +54,10 @@ struct _GVfsJobDeleteClass
 
 GType g_vfs_job_delete_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_delete_new (DBusConnection *connection,
-			       DBusMessage    *message,
-			       GVfsBackend    *backend);
-
+gboolean g_vfs_job_delete_new_handle (GVfsDBusMount         *object,
+                                      GDBusMethodInvocation *invocation,
+                                      const gchar           *arg_path_data,
+                                      GVfsBackend           *backend);
 G_END_DECLS
 
 #endif /* __G_VFS_JOB_DELETE_H__ */
diff --git a/daemon/gvfsjobenumerate.c b/daemon/gvfsjobenumerate.c
index 258a21f..1dd25fa 100644
--- a/daemon/gvfsjobenumerate.c
+++ b/daemon/gvfsjobenumerate.c
@@ -28,20 +28,19 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobenumerate.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
+#include <gvfsdbus.h>
 
 G_DEFINE_TYPE (GVfsJobEnumerate, g_vfs_job_enumerate, G_VFS_TYPE_JOB_DBUS)
 
 static void         run        (GVfsJob        *job);
 static gboolean     try        (GVfsJob        *job);
 static void         send_reply   (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_enumerate_finalize (GObject *object)
@@ -79,72 +78,91 @@ g_vfs_job_enumerate_init (GVfsJobEnumerate *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_enumerate_new (DBusConnection *connection,
-			 DBusMessage *message,
-			 GVfsBackend *backend)
+gboolean 
+g_vfs_job_enumerate_new_handle (GVfsDBusMount *object,
+                                GDBusMethodInvocation *invocation,
+                                const gchar *arg_path_data,
+                                const gchar *arg_obj_path,
+                                const gchar *arg_attributes,
+                                guint arg_flags,
+                                const gchar *arg_uri,
+                                GVfsBackend *backend)
 {
   GVfsJobEnumerate *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *obj_path;
-  const char *path_data;
-  char *attributes, *uri;
-  dbus_uint32_t flags;
-  DBusMessageIter iter;
-  
-  dbus_message_iter_init (message, &iter);
-  dbus_error_init (&derror);
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-				      &path_data, &path_len,
-				      DBUS_TYPE_STRING, &obj_path,
-				      DBUS_TYPE_STRING, &attributes,
-				      DBUS_TYPE_UINT32, &flags,
-				      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
-  /* Optional uri arg for thumbnail info */
-  if (!_g_dbus_message_iter_get_args (&iter, NULL,
-				      DBUS_TYPE_STRING, &uri,
-				      0))
-    uri = NULL;
+  g_print ("called Enumerate()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_ENUMERATE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
   
-  job->object_path = g_strdup (obj_path);
-  job->filename = g_strndup (path_data, path_len);
+  job->object_path = g_strdup (arg_obj_path);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->attributes = g_strdup (attributes);
-  job->attribute_matcher = g_file_attribute_matcher_new (attributes);
-  job->flags = flags;
-  job->uri = g_strdup (uri);
+  job->attributes = g_strdup (arg_attributes);
+  job->attribute_matcher = g_file_attribute_matcher_new (arg_attributes);
+  job->flags = arg_flags;
+  job->uri = g_strdup (arg_uri);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+static GVfsDBusEnumerator *
+create_enumerator_proxy (GVfsJobEnumerate *job)
+{
+  GDBusConnection *connection;
+  const gchar *sender;
+
+  connection = g_dbus_method_invocation_get_connection (G_VFS_JOB_DBUS (job)->invocation);
+  sender = g_dbus_method_invocation_get_sender (G_VFS_JOB_DBUS (job)->invocation);
+
+  g_print ("create_enumerator_proxy: sender = '%s', object_path = '%s'\n", sender, job->object_path);
   
-  return G_VFS_JOB (job);
+  return gvfs_dbus_enumerator_proxy_new_sync (connection,
+                                              G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                              sender,
+                                              job->object_path,
+                                              NULL,
+                                              NULL);
+}
+
+static void
+send_infos_cb (GVfsDBusEnumerator *proxy,
+               GAsyncResult *res,
+               gpointer user_data)
+{
+  GError *error = NULL;
+  
+  gvfs_dbus_enumerator_call_got_info_finish (proxy, res, &error);
+  if (error != NULL)
+    {
+      g_warning ("send_infos_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
 }
 
 static void
 send_infos (GVfsJobEnumerate *job)
 {
-  if (!dbus_message_iter_close_container (&job->building_iter, &job->building_array_iter))
-    _g_dbus_oom ();
+  GVfsDBusEnumerator *proxy;
+
+  proxy = create_enumerator_proxy (job);
+  g_assert (proxy != NULL);
   
-  dbus_connection_send (g_vfs_job_dbus_get_connection (G_VFS_JOB_DBUS (job)),
-			job->building_infos, NULL);
-  dbus_message_unref (job->building_infos);
+  gvfs_dbus_enumerator_call_got_info (proxy,
+                                      g_variant_builder_end (job->building_infos),
+                                      NULL,
+                                      (GAsyncReadyCallback) send_infos_cb,
+                                      NULL);
+  g_object_unref (proxy);
+
   job->building_infos = NULL;
   job->n_building_infos = 0;
 }
@@ -153,33 +171,15 @@ void
 g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job,
 			      GFileInfo *info)
 {
-  DBusMessage *message, *orig_message;
   char *uri, *escaped_name;
+  GVariant *v;
   
   if (job->building_infos == NULL)
     {
-      orig_message = g_vfs_job_dbus_get_message (G_VFS_JOB_DBUS (job));
-      
-      message = dbus_message_new_method_call (dbus_message_get_sender (orig_message),
-					      job->object_path,
-					      G_VFS_DBUS_ENUMERATOR_INTERFACE,
-					      G_VFS_DBUS_ENUMERATOR_OP_GOT_INFO);
-      dbus_message_set_no_reply (message, TRUE);
-      
-      dbus_message_iter_init_append (message, &job->building_iter);
-      
-      if (!dbus_message_iter_open_container (&job->building_iter,
-					     DBUS_TYPE_ARRAY,
-					     G_FILE_INFO_TYPE_AS_STRING, 
-					     &job->building_array_iter))
-	_g_dbus_oom ();
-
-      job->building_infos = message;
+      job->building_infos = g_variant_builder_new (G_VARIANT_TYPE ("aa(suv)"));
       job->n_building_infos = 0;
     }
 
-  
-
   uri = NULL;
   if (job->uri != NULL &&
       g_file_info_get_name (info) != NULL)
@@ -198,8 +198,9 @@ g_vfs_job_enumerate_add_info (GVfsJobEnumerate *job,
   g_free (uri);
 
   g_file_info_set_attribute_mask (info, job->attribute_matcher);
-  
-  _g_dbus_append_file_info (&job->building_array_iter, info);
+
+  v = _g_dbus_append_file_info (info);
+  g_variant_builder_add_value (job->building_infos, v);
   job->n_building_infos++;
 
   if (job->n_building_infos == 50)
@@ -220,27 +221,45 @@ g_vfs_job_enumerate_add_infos (GVfsJobEnumerate *job,
     }
 }
 
+static void
+send_done_cb (GVfsDBusEnumerator *proxy,
+               GAsyncResult *res,
+               gpointer user_data)
+{
+  GError *error = NULL;
+
+  g_print ("send_done_cb\n");
+
+  gvfs_dbus_enumerator_call_done_finish (proxy, res, &error);
+  if (error != NULL)
+    {
+      g_warning ("send_done_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+}
+
 void
 g_vfs_job_enumerate_done (GVfsJobEnumerate *job)
 {
-  DBusMessage *message, *orig_message;
+  GVfsDBusEnumerator *proxy;
   
   g_assert (!G_VFS_JOB (job)->failed);
 
+  g_print ("g_vfs_job_enumerate_done: sending...\n");
+
   if (job->building_infos != NULL)
     send_infos (job);
+
+  proxy = create_enumerator_proxy (job);
+  g_assert (proxy != NULL);
   
-  orig_message = g_vfs_job_dbus_get_message (G_VFS_JOB_DBUS (job));
-  
-  message = dbus_message_new_method_call (dbus_message_get_sender (orig_message),
-					  job->object_path,
-					  G_VFS_DBUS_ENUMERATOR_INTERFACE,
-					  G_VFS_DBUS_ENUMERATOR_OP_DONE);
-  dbus_message_set_no_reply (message, TRUE);
+  gvfs_dbus_enumerator_call_done (proxy,
+                                  NULL,
+                                  (GAsyncReadyCallback) send_done_cb,
+                                  NULL);
+  g_object_unref (proxy);
 
-  dbus_connection_send (g_vfs_job_dbus_get_connection (G_VFS_JOB_DBUS (job)),
-			message, NULL);
-  dbus_message_unref (message);
+  g_print ("g_vfs_job_enumerate_done: done.\n");
 
   g_vfs_job_emit_finished (G_VFS_JOB (job));
 }
@@ -250,7 +269,7 @@ run (GVfsJob *job)
 {
   GVfsJobEnumerate *op_job = G_VFS_JOB_ENUMERATE (job);
   GVfsBackendClass *class = G_VFS_BACKEND_GET_CLASS (op_job->backend);
-  
+
   if (class->enumerate == NULL)
     {
       g_vfs_job_failed (job, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED,
@@ -285,37 +304,26 @@ static void
 send_reply (GVfsJob *job)
 {
   GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
-  DBusMessage *reply;
   GVfsJobDBusClass *class;
 
   g_debug ("send_reply(%p), failed=%d (%s)\n", job, job->failed, job->failed?job->error->message:"");
   
   class = G_VFS_JOB_DBUS_GET_CLASS (job);
   
-  if (job->failed) 
-    reply = _dbus_message_new_from_gerror (dbus_job->message, job->error);
+  if (job->failed)
+    g_dbus_method_invocation_return_gerror (dbus_job->invocation, job->error);
   else
-    reply = class->create_reply (job, dbus_job->connection, dbus_job->message);
+    class->create_reply (job, dbus_job->object, dbus_job->invocation);
  
-  g_assert (reply != NULL);
-
-  /* Queues reply (threadsafely), actually sends it in mainloop */
-  dbus_connection_send (dbus_job->connection, reply, NULL);
-  dbus_message_unref (reply);
-  
   if (job->failed)
     g_vfs_job_emit_finished (job);
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-
-  return reply;
+  gvfs_dbus_mount_complete_enumerate (object, invocation);
 }
diff --git a/daemon/gvfsjobenumerate.h b/daemon/gvfsjobenumerate.h
index 622f49b..56b0778 100644
--- a/daemon/gvfsjobenumerate.h
+++ b/daemon/gvfsjobenumerate.h
@@ -51,9 +51,7 @@ struct _GVfsJobEnumerate
   GFileQueryInfoFlags flags;
   char *uri;
 
-  DBusMessage *building_infos;
-  DBusMessageIter building_iter;
-  DBusMessageIter building_array_iter;
+  GVariantBuilder *building_infos;
   int n_building_infos;
 };
 
@@ -64,9 +62,15 @@ struct _GVfsJobEnumerateClass
 
 GType g_vfs_job_enumerate_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_enumerate_new        (DBusConnection        *connection,
-					 DBusMessage           *message,
-					 GVfsBackend           *backend);
+gboolean g_vfs_job_enumerate_new_handle (GVfsDBusMount         *object,
+                                         GDBusMethodInvocation *invocation,
+                                         const gchar           *arg_path_data,
+                                         const gchar           *arg_obj_path,
+                                         const gchar           *arg_attributes,
+                                         guint                  arg_flags,
+                                         const gchar           *arg_uri,
+                                         GVfsBackend           *backend);
+
 void     g_vfs_job_enumerate_add_info   (GVfsJobEnumerate      *job,
 					 GFileInfo             *info);
 void     g_vfs_job_enumerate_add_infos  (GVfsJobEnumerate      *job,
diff --git a/daemon/gvfsjobmakedirectory.c b/daemon/gvfsjobmakedirectory.c
index 5422393..c26430e 100644
--- a/daemon/gvfsjobmakedirectory.c
+++ b/daemon/gvfsjobmakedirectory.c
@@ -28,19 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobmakedirectory.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobMakeDirectory, g_vfs_job_make_directory, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_make_directory_finalize (GObject *object)
@@ -73,42 +71,31 @@ g_vfs_job_make_directory_init (GVfsJobMakeDirectory *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_make_directory_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_make_directory_new_handle (GVfsDBusMount *object,
+                                     GDBusMethodInvocation *invocation,
+                                     const gchar *arg_path_data,
+                                     GVfsBackend *backend)
 {
   GVfsJobMakeDirectory *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
-  
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  g_print ("called MakeDirectory()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_MAKE_DIRECTORY,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -144,14 +131,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_make_directory (object, invocation);
 }
diff --git a/daemon/gvfsjobmakedirectory.h b/daemon/gvfsjobmakedirectory.h
index 0bb66a7..e1c5e82 100644
--- a/daemon/gvfsjobmakedirectory.h
+++ b/daemon/gvfsjobmakedirectory.h
@@ -54,10 +54,10 @@ struct _GVfsJobMakeDirectoryClass
 
 GType g_vfs_job_make_directory_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_make_directory_new (DBusConnection *connection,
-			       DBusMessage    *message,
-			       GVfsBackend    *backend);
-
+gboolean g_vfs_job_make_directory_new_handle (GVfsDBusMount         *object,
+                                              GDBusMethodInvocation *invocation,
+                                              const gchar           *arg_path_data,
+                                              GVfsBackend           *backend);
 G_END_DECLS
 
 #endif /* __G_VFS_JOB_MAKE_DIRECTORY_H__ */
diff --git a/daemon/gvfsjobmakesymlink.c b/daemon/gvfsjobmakesymlink.c
index 4f5ac43..a369c75 100644
--- a/daemon/gvfsjobmakesymlink.c
+++ b/daemon/gvfsjobmakesymlink.c
@@ -28,19 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobmakesymlink.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobMakeSymlink, g_vfs_job_make_symlink, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_make_symlink_finalize (GObject *object)
@@ -74,45 +72,33 @@ g_vfs_job_make_symlink_init (GVfsJobMakeSymlink *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_make_symlink_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_make_symlink_new_handle (GVfsDBusMount *object,
+                                   GDBusMethodInvocation *invocation,
+                                   const gchar *arg_path_data,
+                                   const gchar *arg_symlink_value,
+                                   GVfsBackend *backend)
 {
   GVfsJobMakeSymlink *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len, symlink_len;
-  const char *path_data, *symlink_data;
-  
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &symlink_data, &symlink_len,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  g_print ("called MakeSymlink()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_MAKE_SYMLINK,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
-  job->symlink_value = g_strndup (symlink_data, symlink_len);
+  job->filename = g_strdup (arg_path_data);
+  job->symlink_value = g_strdup (arg_symlink_value);
   job->backend = backend;
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -150,14 +136,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_make_symbolic_link (object, invocation);
 }
diff --git a/daemon/gvfsjobmakesymlink.h b/daemon/gvfsjobmakesymlink.h
index df82c0f..6f5d231 100644
--- a/daemon/gvfsjobmakesymlink.h
+++ b/daemon/gvfsjobmakesymlink.h
@@ -55,9 +55,11 @@ struct _GVfsJobMakeSymlinkClass
 
 GType g_vfs_job_make_symlink_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_make_symlink_new (DBusConnection *connection,
-				     DBusMessage    *message,
-				     GVfsBackend    *backend);
+gboolean g_vfs_job_make_symlink_new_handle (GVfsDBusMount         *object,
+                                            GDBusMethodInvocation *invocation,
+                                            const gchar           *arg_path_data,
+                                            const gchar           *arg_symlink_value,
+                                            GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobmount.c b/daemon/gvfsjobmount.c
index c21d828..fcca945 100644
--- a/daemon/gvfsjobmount.c
+++ b/daemon/gvfsjobmount.c
@@ -28,11 +28,8 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobmount.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobMount, g_vfs_job_mount, G_VFS_TYPE_JOB)
 
@@ -50,6 +47,10 @@ g_vfs_job_mount_finalize (GObject *object)
   g_mount_spec_unref (job->mount_spec);
   g_object_unref (job->mount_source);
   g_object_unref (job->backend);
+  if (job->object)
+    g_object_unref (job->object);
+  if (job->invocation)
+    g_object_unref (job->invocation);
   
   if (G_OBJECT_CLASS (g_vfs_job_mount_parent_class)->finalize)
     (*G_OBJECT_CLASS (g_vfs_job_mount_parent_class)->finalize) (object);
@@ -76,8 +77,9 @@ GVfsJob *
 g_vfs_job_mount_new (GMountSpec *spec,
 		     GMountSource *source,
 		     gboolean is_automount,
-		     DBusMessage *request,
-		     GVfsBackend *backend)
+		     GVfsDBusMountable *object,
+                     GDBusMethodInvocation *invocation,
+                     GVfsBackend *backend)
 {
   GVfsJobMount *job;
 
@@ -90,8 +92,11 @@ g_vfs_job_mount_new (GMountSpec *spec,
   /* Ref the backend so we're sure its alive
      during the whole job request. */
   job->backend = g_object_ref (backend);
-  if (request)
-    job->request = dbus_message_ref (request);
+  if (object != NULL && invocation != NULL)
+    {
+      job->object = g_object_ref (object);
+      job->invocation = g_object_ref (invocation);
+    }
   
   return G_VFS_JOB (job);
 }
@@ -139,23 +144,10 @@ try (GVfsJob *job)
 static void
 mount_failed (GVfsJobMount *op_job, GError *error)
 {
-  DBusConnection *conn;
-  DBusMessage *reply;
   GVfsBackend *backend;
 
-  if (op_job->request)
-    {
-      reply = _dbus_message_new_from_gerror (op_job->request, error);
-      
-      /* Queues reply (threadsafely), actually sends it in mainloop */
-      conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-      if (conn)
-	{
-	  dbus_connection_send (conn, reply, NULL);
-	  dbus_message_unref (reply);
-	  dbus_connection_unref (conn);
-	}
-    }
+  if (op_job->invocation)
+    g_dbus_method_invocation_return_gerror (op_job->invocation, error);
   else
     g_debug ("Mount failed: %s\n", error->message);
 
@@ -168,35 +160,27 @@ mount_failed (GVfsJobMount *op_job, GError *error)
 }
 
 static void
-register_mount_callback (DBusMessage *mount_reply,
-			 GError *error,
-			 gpointer user_data)
+register_mount_callback (GVfsDBusMountTracker *proxy,
+                         GAsyncResult *res,
+                         gpointer user_data)
 {
   GVfsJobMount *op_job = G_VFS_JOB_MOUNT (user_data);
-  DBusConnection *conn;
-  DBusMessage *reply;
-
-  g_debug ("register_mount_callback, mount_reply: %p, error: %p\n", mount_reply, error);
+  GError *error = NULL;
   
-  if (mount_reply == NULL)
-    mount_failed (op_job, error);
+  if (! gvfs_dbus_mount_tracker_call_register_mount_finish (proxy, res, &error))
+    {
+      mount_failed (op_job, error);
+    }
   else
     {
-      if (op_job->request)
-	{
-	  reply = dbus_message_new_method_return (op_job->request);
-	  /* Queues reply (threadsafely), actually sends it in mainloop */
-	  conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-	  if (conn)
-	    {
-	      dbus_connection_send (conn, reply, NULL);
-	      dbus_message_unref (reply);
-	      dbus_connection_unref (conn);
-	    }
-	}
+      if (op_job->invocation && op_job->object)
+        gvfs_dbus_mountable_complete_mount (op_job->object, op_job->invocation);
 
       g_vfs_job_emit_finished (G_VFS_JOB (op_job));
     }
+
+  if (error != NULL)
+    g_error_free (error);
 }
 
 /* Might be called on an i/o thread */
@@ -211,6 +195,6 @@ send_reply (GVfsJob *job)
     mount_failed (op_job, job->error);
   else
     g_vfs_backend_register_mount (op_job->backend,
-				  register_mount_callback,
+                                  (GAsyncReadyCallback) register_mount_callback,
 				  job);
 }
diff --git a/daemon/gvfsjobmount.h b/daemon/gvfsjobmount.h
index 0c3d31b..3ae89ae 100644
--- a/daemon/gvfsjobmount.h
+++ b/daemon/gvfsjobmount.h
@@ -25,8 +25,8 @@
 
 #include <gio/gio.h>
 #include <gvfsjob.h>
-#include <gvfsjobdbus.h>
 #include <gvfsbackend.h>
+#include <gvfsdbus.h>
 
 G_BEGIN_DECLS
 
@@ -47,7 +47,8 @@ struct _GVfsJobMount
   gboolean is_automount;
   GMountSpec *mount_spec;
   GMountSource *mount_source;
-  DBusMessage *request;
+  GVfsDBusMountable *object;
+  GDBusMethodInvocation *invocation;
 };
 
 struct _GVfsJobMountClass
@@ -60,7 +61,8 @@ GType g_vfs_job_mount_get_type (void) G_GNUC_CONST;
 GVfsJob *g_vfs_job_mount_new (GMountSpec  *spec,
 			      GMountSource *source,
 			      gboolean is_automount,
-			      DBusMessage *request,
+                              GVfsDBusMountable *object,
+                              GDBusMethodInvocation *invocation,
 			      GVfsBackend *backend);
 
 G_END_DECLS
diff --git a/daemon/gvfsjobmountmountable.c b/daemon/gvfsjobmountmountable.c
index 133dc94..71fe81e 100644
--- a/daemon/gvfsjobmountmountable.c
+++ b/daemon/gvfsjobmountmountable.c
@@ -28,19 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobmountmountable.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobMountMountable, g_vfs_job_mount_mountable, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_mount_mountable_finalize (GObject *object)
@@ -80,49 +78,34 @@ g_vfs_job_mount_mountable_init (GVfsJobMountMountable *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_mount_mountable_new (DBusConnection *connection,
-			       DBusMessage *message,
-			       GVfsBackend *backend)
+gboolean
+g_vfs_job_mount_mountable_new_handle (GVfsDBusMount *object,
+                                      GDBusMethodInvocation *invocation,
+                                      const gchar *arg_path_data,
+                                      const gchar *arg_dbus_id,
+                                      const gchar *arg_obj_path,
+                                      GVfsBackend *backend)
 {
   GVfsJobMountMountable *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  char *path;
-  const char *dbus_id, *obj_path;
-  
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  path = NULL;
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_STRING, &dbus_id,
-				      DBUS_TYPE_OBJECT_PATH, &obj_path,
-				      0))
-    {
-      g_free (path);
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  g_print ("called MountMountable()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_MOUNT_MOUNTABLE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = path;
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->mount_source = g_mount_source_new (dbus_id, obj_path);
-  
-  return G_VFS_JOB (job);
+  job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 void
@@ -180,38 +163,28 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobMountMountable *op_job = G_VFS_JOB_MOUNT_MOUNTABLE (job);
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  dbus_bool_t must_mount, is_uri;
-
-  reply = dbus_message_new_method_return (message);
-
+  gboolean is_uri, must_mount;
+  GMountSpec *fake_mountspec = NULL;
+  
   must_mount = op_job->must_mount_location;
   is_uri = op_job->target_uri != NULL;
-  if (is_uri)
-    {
-      _g_dbus_message_append_args (reply,
-				   DBUS_TYPE_BOOLEAN, &is_uri,
-				   G_DBUS_TYPE_CSTRING, &op_job->target_uri,
-				   DBUS_TYPE_BOOLEAN, &must_mount,
-				   0);
-    }
-  else
-    {
-      _g_dbus_message_append_args (reply,
-				   DBUS_TYPE_BOOLEAN, &is_uri,
-				   G_DBUS_TYPE_CSTRING, &op_job->target_filename,
-				   DBUS_TYPE_BOOLEAN, &must_mount,
-				   0);
-      dbus_message_iter_init_append (reply, &iter);
-      g_mount_spec_to_dbus (&iter, op_job->mount_spec);
-    }
+
+  if (! is_uri)
+    fake_mountspec = g_mount_spec_new (NULL);
+
+  gvfs_dbus_mount_complete_mount_mountable (object,
+                                            invocation,
+                                            is_uri,
+                                            is_uri ? op_job->target_uri : op_job->target_filename,
+                                            must_mount,
+                                            g_mount_spec_to_dbus (is_uri ? fake_mountspec : op_job->mount_spec));
   
-  return reply;
+  if (fake_mountspec)
+    g_mount_spec_unref (fake_mountspec);
 }
diff --git a/daemon/gvfsjobmountmountable.h b/daemon/gvfsjobmountmountable.h
index aa640da..83eb6a9 100644
--- a/daemon/gvfsjobmountmountable.h
+++ b/daemon/gvfsjobmountmountable.h
@@ -60,9 +60,13 @@ struct _GVfsJobMountMountableClass
 
 GType g_vfs_job_mount_mountable_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_mount_mountable_new        (DBusConnection        *connection,
-					       DBusMessage           *message,
-					       GVfsBackend           *backend);
+gboolean g_vfs_job_mount_mountable_new_handle (GVfsDBusMount         *object,
+                                               GDBusMethodInvocation *invocation,
+                                               const gchar           *arg_path_data,
+                                               const gchar           *arg_dbus_id,
+                                               const gchar           *arg_obj_path,
+                                               GVfsBackend           *backend);
+
 void     g_vfs_job_mount_mountable_set_target (GVfsJobMountMountable *job,
 					       GMountSpec            *mount_spec,
 					       const char            *filename,
diff --git a/daemon/gvfsjobmove.c b/daemon/gvfsjobmove.c
index da94012..bac5618 100644
--- a/daemon/gvfsjobmove.c
+++ b/daemon/gvfsjobmove.c
@@ -29,19 +29,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobmove.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
+#include "gvfsdbus.h"
 
 G_DEFINE_TYPE (GVfsJobMove, g_vfs_job_move, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_move_finalize (GObject *object)
@@ -76,85 +74,117 @@ g_vfs_job_move_init (GVfsJobMove *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_move_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_move_new_handle (GVfsDBusMount *object,
+                           GDBusMethodInvocation *invocation,
+                           const gchar *arg_path1_data,
+                           const gchar *arg_path2_data,
+                           guint arg_flags,
+                           const gchar *arg_progress_obj_path,
+                           GVfsBackend *backend)
 {
   GVfsJobMove *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path1_len, path2_len;
-  const char *path1_data, *path2_data, *callback_obj_path;
-  dbus_uint32_t flags;
   
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path1_data, &path1_len,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path2_data, &path2_len,
-                              DBUS_TYPE_UINT32, &flags,
-			      DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  g_print ("called Move()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_MOVE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->source = g_strndup (path1_data, path1_len);
-  job->destination = g_strndup (path2_data, path2_len);
+  job->source = g_strdup (arg_path1_data);
+  job->destination = g_strdup (arg_path2_data);
   job->backend = backend;
-  job->flags = flags;
-  if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
-    job->callback_obj_path = g_strdup (callback_obj_path);
+  job->flags = arg_flags;
+  if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0)
+    job->callback_obj_path = g_strdup (arg_progress_obj_path);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+typedef struct {
+  goffset current_num_bytes;
+  goffset total_num_bytes;
+} ProgressCallbackData;
+
+static void
+progress_cb (GVfsDBusProgress *proxy,
+             GAsyncResult *res,
+             gpointer user_data)
+{
+  GError *error = NULL;
+  
+  g_print ("progress_cb\n");
   
-  return G_VFS_JOB (job);
+  if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error))
+    {
+      g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
 }
 
-void
+static void
+progress_proxy_new_cb (GObject *source_object,
+                       GAsyncResult *res,
+                       gpointer user_data)
+{
+  ProgressCallbackData *data = user_data;
+  GVfsDBusProgress *proxy;
+  GError *error = NULL;
+
+  g_print ("progress_proxy_new_cb\n");
+
+  proxy = gvfs_dbus_progress_proxy_new_finish (res, &error);
+  if (proxy == NULL)
+    {
+      g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      goto out;
+    }
+  
+  gvfs_dbus_progress_call_progress (proxy,
+                                    data->current_num_bytes,
+                                    data->total_num_bytes,
+                                    NULL,
+                                    (GAsyncReadyCallback) progress_cb,
+                                    NULL);
+  g_object_unref (proxy);
+  
+ out:
+  g_free (data);
+}
+
+void 
 g_vfs_job_move_progress_callback (goffset current_num_bytes,
-				  goffset total_num_bytes,
-				  GVfsJob *job)
+                                  goffset total_num_bytes,
+                                  GVfsJob *job)
 {
   GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
   GVfsJobMove *op_job = G_VFS_JOB_MOVE (job);
-  dbus_uint64_t current_dbus, total_dbus;
-  DBusMessage *message;
+  ProgressCallbackData *data;
 
   g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes);
 
   if (op_job->callback_obj_path == NULL)
     return;
 
-  message =
-    dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
-				  op_job->callback_obj_path,
-				  G_VFS_DBUS_PROGRESS_INTERFACE,
-				  G_VFS_DBUS_PROGRESS_OP_PROGRESS);
-  dbus_message_set_no_reply (message, TRUE);
-
-  current_dbus = current_num_bytes;
-  total_dbus = total_num_bytes;
-  dbus_message_append_args (message,
-			    DBUS_TYPE_UINT64, &current_dbus,
-			    DBUS_TYPE_UINT64, &total_dbus,
-			    0);
-
-  /* Queues reply (threadsafely), actually sends it in mainloop */
-  dbus_connection_send (dbus_job->connection, message, NULL);
-  dbus_message_unref (message);
+  data = g_new0 (ProgressCallbackData, 1);
+  data->current_num_bytes = current_num_bytes;
+  data->total_num_bytes = total_num_bytes;
+  
+  gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation),
+                                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                g_dbus_method_invocation_get_sender (dbus_job->invocation),
+                                op_job->callback_obj_path,
+                                NULL,
+                                progress_proxy_new_cb,
+                                data);
 }
 
 static void
@@ -198,14 +228,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_move (object, invocation);
 }
diff --git a/daemon/gvfsjobmove.h b/daemon/gvfsjobmove.h
index f793e2d..b1eec94 100644
--- a/daemon/gvfsjobmove.h
+++ b/daemon/gvfsjobmove.h
@@ -58,9 +58,13 @@ struct _GVfsJobMoveClass
 
 GType g_vfs_job_move_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_move_new (DBusConnection *connection,
-			     DBusMessage    *message,
-			     GVfsBackend    *backend);
+gboolean g_vfs_job_move_new_handle (GVfsDBusMount         *object,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar           *arg_path1_data,
+                                    const gchar           *arg_path2_data,
+                                    guint                  arg_flags,
+                                    const gchar           *arg_progress_obj_path,
+                                    GVfsBackend           *backend);
 
 void g_vfs_job_move_progress_callback (goffset current_num_bytes,
 				       goffset total_num_bytes,
diff --git a/daemon/gvfsjobopenforread.c b/daemon/gvfsjobopenforread.c
index 1d68920..7539233 100644
--- a/daemon/gvfsjobopenforread.c
+++ b/daemon/gvfsjobopenforread.c
@@ -28,11 +28,10 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
+#include <gio/gunixfdlist.h>
 #include "gvfsreadchannel.h"
 #include "gvfsjobopenforread.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobOpenForRead, g_vfs_job_open_for_read, G_VFS_TYPE_JOB_DBUS)
@@ -40,9 +39,9 @@ G_DEFINE_TYPE (GVfsJobOpenForRead, g_vfs_job_open_for_read, G_VFS_TYPE_JOB_DBUS)
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
 static void         finished     (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_open_for_read_finalize (GObject *object)
@@ -81,45 +80,34 @@ g_vfs_job_open_for_read_init (GVfsJobOpenForRead *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_open_for_read_new (DBusConnection *connection,
-			     DBusMessage *message,
-			     GVfsBackend *backend)
+gboolean
+g_vfs_job_open_for_read_new_handle (GVfsDBusMount *object,
+                                    GDBusMethodInvocation *invocation,
+                                    GUnixFDList *fd_list,
+                                    const gchar *arg_path_data,
+                                    guint arg_pid,
+                                    GVfsBackend *backend)
 {
   GVfsJobOpenForRead *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
-  guint32 pid;
   
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-                              DBUS_TYPE_UINT32, &pid,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  g_print ("called OpenForRead()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_OPEN_FOR_READ,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
-
-  job->filename = g_strndup (path_data, path_len);
-  job->backend = backend;
-  job->pid = pid;
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
   
-  return G_VFS_JOB (job);
+  job->filename = g_strdup (arg_path_data);
+  job->backend = backend;
+  job->pid = arg_pid;
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -170,52 +158,45 @@ g_vfs_job_open_for_read_set_can_seek (GVfsJobOpenForRead *job,
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobOpenForRead *open_job = G_VFS_JOB_OPEN_FOR_READ (job);
   GVfsReadChannel *channel;
-  DBusMessage *reply;
   GError *error;
   int remote_fd;
   int fd_id;
-  dbus_bool_t can_seek;
+  GUnixFDList *fd_list;
 
   g_assert (open_job->backend_handle != NULL);
 
-  error = NULL;
   channel = g_vfs_read_channel_new (open_job->backend,
                                     open_job->pid);
 
   remote_fd = g_vfs_channel_steal_remote_fd (G_VFS_CHANNEL (channel));
-  if (!dbus_connection_send_fd (connection, 
-				remote_fd,
-				&fd_id, &error))
+  
+  fd_list = g_unix_fd_list_new ();
+  error = NULL;
+  fd_id = g_unix_fd_list_append (fd_list, remote_fd, &error);
+  if (fd_id == -1)
     {
-      close (remote_fd);
-      reply = _dbus_message_new_from_gerror (message, error);
+      g_warning ("create_reply: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
       g_error_free (error);
-      g_object_unref (channel);
-      return reply;
     }
-  close (remote_fd);
-
-  reply = dbus_message_new_method_return (message);
-  can_seek = open_job->can_seek;
-  dbus_message_append_args (reply,
-			    DBUS_TYPE_UINT32, &fd_id,
-			    DBUS_TYPE_BOOLEAN, &can_seek,
-			    DBUS_TYPE_INVALID);
 
+  gvfs_dbus_mount_complete_open_for_read (object, invocation, fd_list, fd_id, open_job->can_seek);
+  
+  /* FIXME: this could cause issues as long as fd_list closes all its fd's when it's finalized */
+  close (remote_fd);
+  g_object_unref (fd_list);
+  
   g_vfs_channel_set_backend_handle (G_VFS_CHANNEL (channel), open_job->backend_handle);
   open_job->backend_handle = NULL;
   open_job->read_channel = channel;
 
   g_signal_emit_by_name (job, "new-source", open_job->read_channel);
-  
-  return reply;
 }
 
 static void
diff --git a/daemon/gvfsjobopenforread.h b/daemon/gvfsjobopenforread.h
index 964ce1c..19f8321 100644
--- a/daemon/gvfsjobopenforread.h
+++ b/daemon/gvfsjobopenforread.h
@@ -23,7 +23,6 @@
 #ifndef __G_VFS_JOB_OPEN_FOR_READ_H__
 #define __G_VFS_JOB_OPEN_FOR_READ_H__
 
-#include <dbus/dbus.h>
 #include <gvfsjobdbus.h>
 #include <gvfsbackend.h>
 #include <gvfsreadchannel.h>
@@ -59,9 +58,12 @@ struct _GVfsJobOpenForReadClass
 
 GType g_vfs_job_open_for_read_get_type (void) G_GNUC_CONST;
 
-GVfsJob *        g_vfs_job_open_for_read_new           (DBusConnection     *connection,
-							DBusMessage        *message,
-							GVfsBackend        *backend);
+gboolean         g_vfs_job_open_for_read_new_handle    (GVfsDBusMount         *object,
+                                                        GDBusMethodInvocation *invocation,
+                                                        GUnixFDList           *fd_list,
+                                                        const gchar           *arg_path_data,
+                                                        guint                  arg_pid,
+                                                        GVfsBackend           *backend);
 void             g_vfs_job_open_for_read_set_handle    (GVfsJobOpenForRead *job,
 							GVfsBackendHandle   handle);
 void             g_vfs_job_open_for_read_set_can_seek  (GVfsJobOpenForRead *job,
diff --git a/daemon/gvfsjobopenforwrite.c b/daemon/gvfsjobopenforwrite.c
index 12ad295..8ea680f 100644
--- a/daemon/gvfsjobopenforwrite.c
+++ b/daemon/gvfsjobopenforwrite.c
@@ -28,11 +28,10 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
+#include <gio/gunixfdlist.h>
 #include "gvfswritechannel.h"
 #include "gvfsjobopenforwrite.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobOpenForWrite, g_vfs_job_open_for_write, G_VFS_TYPE_JOB_DBUS)
@@ -40,9 +39,9 @@ G_DEFINE_TYPE (GVfsJobOpenForWrite, g_vfs_job_open_for_write, G_VFS_TYPE_JOB_DBU
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
 static void         finished     (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_open_for_write_finalize (GObject *object)
@@ -82,60 +81,43 @@ g_vfs_job_open_for_write_init (GVfsJobOpenForWrite *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_open_for_write_new (DBusConnection *connection,
-			      DBusMessage *message,
-			      GVfsBackend *backend)
+gboolean
+g_vfs_job_open_for_write_new_handle (GVfsDBusMount *object,
+                                     GDBusMethodInvocation *invocation,
+                                     GUnixFDList *fd_list,
+                                     const gchar *arg_path_data,
+                                     guint16 arg_mode,
+                                     const gchar *arg_etag,
+                                     gboolean arg_make_backup,
+                                     guint arg_flags,
+                                     guint arg_pid,
+                                     GVfsBackend *backend)
 {
   GVfsJobOpenForWrite *job;
-  DBusMessageIter iter;
-  DBusMessage *reply;
-  DBusError derror;
-  char *path;
-  guint16 mode;
-  dbus_bool_t make_backup;
-  const char *etag;
-  guint32 flags;
-  guint32 pid;
-
-  path = NULL;
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_UINT16, &mode,
-				      DBUS_TYPE_STRING, &etag,
-				      DBUS_TYPE_BOOLEAN, &make_backup,
-				      DBUS_TYPE_UINT32, &flags,
-                                      DBUS_TYPE_UINT32, &pid,
-				      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      g_free (path);
-      return NULL;
-    }
+  
+  g_print ("called OpenForWrite()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
   
   job = g_object_new (G_VFS_TYPE_JOB_OPEN_FOR_WRITE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
-
-  job->filename = path;
-  job->mode = mode;
-  if (*etag != 0)
-    job->etag = g_strdup (etag);
-  job->make_backup = make_backup;
-  job->flags = flags;
-  job->backend = backend;
-  job->pid = pid;
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
   
-  return G_VFS_JOB (job);
+  job->filename = g_strdup (arg_path_data);
+  job->mode = arg_mode;
+  if (*arg_etag != 0)
+    job->etag = g_strdup (arg_etag);
+  job->make_backup = arg_make_backup;
+  job->flags = arg_flags;
+  job->backend = backend;
+  job->pid = arg_pid;
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -259,56 +241,45 @@ g_vfs_job_open_for_write_set_initial_offset (GVfsJobOpenForWrite *job,
   job->initial_offset = initial_offset;
 }
 
-/* Might be called on an i/o thwrite */
-static DBusMessage *
+/* Might be called on an i/o thread */
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobOpenForWrite *open_job = G_VFS_JOB_OPEN_FOR_WRITE (job);
   GVfsWriteChannel *channel;
-  DBusMessage *reply;
   GError *error;
   int remote_fd;
   int fd_id;
-  dbus_bool_t can_seek;
-  guint64 initial_offset;
-  
+  GUnixFDList *fd_list;
+
   g_assert (open_job->backend_handle != NULL);
 
-  error = NULL;
   channel = g_vfs_write_channel_new (open_job->backend,
                                      open_job->pid);
 
   remote_fd = g_vfs_channel_steal_remote_fd (G_VFS_CHANNEL (channel));
-  if (!dbus_connection_send_fd (connection, 
-				remote_fd,
-				&fd_id, &error))
+
+  fd_list = g_unix_fd_list_new ();
+  error = NULL;
+  fd_id = g_unix_fd_list_append (fd_list, remote_fd, &error);
+  if (fd_id == -1)
     {
-      close (remote_fd);
-      reply = _dbus_message_new_from_gerror (message, error);
+      g_warning ("create_reply: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
       g_error_free (error);
-      g_object_unref (channel);
-      return reply;
     }
-  close (remote_fd);
 
-  reply = dbus_message_new_method_return (message);
-  can_seek = open_job->can_seek;
-  initial_offset = open_job->initial_offset;
-  dbus_message_append_args (reply,
-			    DBUS_TYPE_UINT32, &fd_id,
-			    DBUS_TYPE_BOOLEAN, &can_seek,
-			    DBUS_TYPE_UINT64, &initial_offset,
-			    DBUS_TYPE_INVALID);
+  gvfs_dbus_mount_complete_open_for_write (object, invocation, fd_list, fd_id, open_job->can_seek, open_job->initial_offset);
+  
+  close (remote_fd);
+  g_object_unref (fd_list);
 
   g_vfs_channel_set_backend_handle (G_VFS_CHANNEL (channel), open_job->backend_handle);
   open_job->backend_handle = NULL;
   open_job->write_channel = channel;
 
   g_signal_emit_by_name (job, "new-source", open_job->write_channel);
-  
-  return reply;
 }
 
 static void
diff --git a/daemon/gvfsjobopenforwrite.h b/daemon/gvfsjobopenforwrite.h
index 8cab78e..79854d2 100644
--- a/daemon/gvfsjobopenforwrite.h
+++ b/daemon/gvfsjobopenforwrite.h
@@ -23,7 +23,6 @@
 #ifndef __G_VFS_JOB_OPEN_FOR_WRITE_H__
 #define __G_VFS_JOB_OPEN_FOR_WRITE_H__
 
-#include <dbus/dbus.h>
 #include <gvfsjobdbus.h>
 #include <gvfsbackend.h>
 #include <gvfswritechannel.h>
@@ -72,9 +71,16 @@ struct _GVfsJobOpenForWriteClass
 
 GType g_vfs_job_open_for_write_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_open_for_write_new                (DBusConnection      *connection,
-						      DBusMessage         *message,
-						      GVfsBackend         *backend);
+gboolean g_vfs_job_open_for_write_new_handle         (GVfsDBusMount         *object,
+                                                      GDBusMethodInvocation *invocation,
+                                                      GUnixFDList           *fd_list,
+                                                      const gchar           *arg_path_data,
+                                                      guint16                arg_mode,
+                                                      const gchar           *arg_etag,
+                                                      gboolean               arg_make_backup,
+                                                      guint                  arg_flags,
+                                                      guint                  arg_pid,
+                                                      GVfsBackend           *backend);
 void     g_vfs_job_open_for_write_set_handle         (GVfsJobOpenForWrite *job,
 						      GVfsBackendHandle    handle);
 void     g_vfs_job_open_for_write_set_can_seek       (GVfsJobOpenForWrite *job,
diff --git a/daemon/gvfsjobpollmountable.c b/daemon/gvfsjobpollmountable.c
index 1b0112a..d9bbbbc 100644
--- a/daemon/gvfsjobpollmountable.c
+++ b/daemon/gvfsjobpollmountable.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobpollmountable.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobPollMountable, g_vfs_job_poll_mountable, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_poll_mountable_finalize (GObject *object)
@@ -73,45 +70,31 @@ g_vfs_job_poll_mountable_init (GVfsJobPollMountable *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_poll_mountable_new (DBusConnection *connection,
-                              DBusMessage *message,
-                              GVfsBackend *backend)
+gboolean
+g_vfs_job_poll_mountable_new_handle (GVfsDBusMount *object,
+                                     GDBusMethodInvocation *invocation,
+                                     const gchar *arg_path_data,
+                                     GVfsBackend *backend)
 {
   GVfsJobPollMountable *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  char *path;
-
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  path = NULL;
-  if (!_g_dbus_message_iter_get_args (&iter, &derror,
-				      G_DBUS_TYPE_CSTRING, &path,
-				      0))
-    {
-      g_free (path);
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+
+  g_print ("called PollMountable()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
 
   job = g_object_new (G_VFS_TYPE_JOB_POLL_MOUNTABLE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = path;
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
 
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -147,14 +130,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_poll_mountable (object, invocation);
 }
diff --git a/daemon/gvfsjobpollmountable.h b/daemon/gvfsjobpollmountable.h
index 01f8941..6e7ccc2 100644
--- a/daemon/gvfsjobpollmountable.h
+++ b/daemon/gvfsjobpollmountable.h
@@ -54,8 +54,9 @@ struct _GVfsJobPollMountableClass
 
 GType g_vfs_job_poll_mountable_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_poll_mountable_new        (DBusConnection        *connection,
-                                              DBusMessage           *message,
+gboolean g_vfs_job_poll_mountable_new_handle (GVfsDBusMount         *object,
+                                              GDBusMethodInvocation *invocation,
+                                              const gchar           *arg_path_data,
                                               GVfsBackend           *backend);
 
 G_END_DECLS
diff --git a/daemon/gvfsjobpull.c b/daemon/gvfsjobpull.c
index 0a3347a..3dda992 100644
--- a/daemon/gvfsjobpull.c
+++ b/daemon/gvfsjobpull.c
@@ -29,19 +29,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobpull.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
+#include "gvfsdbus.h"
 
 G_DEFINE_TYPE (GVfsJobPull, g_vfs_job_pull, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_pull_finalize (GObject *object)
@@ -76,92 +74,123 @@ g_vfs_job_pull_init (GVfsJobPull *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_pull_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_pull_new_handle (GVfsDBusMount *object,
+                           GDBusMethodInvocation *invocation,
+                           const gchar *arg_path_data,
+                           const gchar *arg_local_path,
+                           gboolean arg_send_progress,
+                           guint arg_flags,
+                           const gchar *arg_progress_obj_path,
+                           gboolean arg_remove_source,
+                           GVfsBackend *backend)
 {
   GVfsJobPull *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path1_len, path2_len;
-  const char *path1_data, *path2_data, *callback_obj_path;
-  dbus_uint32_t flags;
-  dbus_bool_t remove_source, send_progress;
-
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path1_data, &path1_len,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path2_data, &path2_len,
-                              DBUS_TYPE_BOOLEAN, &send_progress,
-                              DBUS_TYPE_UINT32, &flags,
-			      DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
-                              DBUS_TYPE_BOOLEAN, &remove_source,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  
+  g_print ("called Pull()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_PULL,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->source = g_strndup (path1_data, path1_len);
-  job->local_path = g_strndup (path2_data, path2_len);
+  job->source = g_strdup (arg_path_data);
+  job->local_path = g_strdup (arg_local_path);
   job->backend = backend;
-  job->flags = flags;
-  job->send_progress = send_progress;
-  job->remove_source = remove_source;
-  g_debug ("Remove Source: %s\n", remove_source ? "true" : "false");
-  if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
-    job->callback_obj_path = g_strdup (callback_obj_path);
-
-  return G_VFS_JOB (job);
+  job->flags = arg_flags;
+  job->send_progress = arg_send_progress;
+  job->remove_source = arg_remove_source;
+  g_debug ("Remove Source: %s\n", arg_remove_source ? "true" : "false");
+  if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0)
+    job->callback_obj_path = g_strdup (arg_progress_obj_path);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+typedef struct {
+  goffset current_num_bytes;
+  goffset total_num_bytes;
+} ProgressCallbackData;
+
+static void
+progress_cb (GVfsDBusProgress *proxy,
+             GAsyncResult *res,
+             gpointer user_data)
+{
+  GError *error = NULL;
+  
+  g_print ("progress_cb\n");
+  
+  if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error))
+    {
+      g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+}
+
+static void
+progress_proxy_new_cb (GObject *source_object,
+                       GAsyncResult *res,
+                       gpointer user_data)
+{
+  ProgressCallbackData *data = user_data;
+  GVfsDBusProgress *proxy;
+  GError *error = NULL;
+
+  g_print ("progress_proxy_new_cb\n");
+
+  proxy = gvfs_dbus_progress_proxy_new_finish (res, &error);
+  if (proxy == NULL)
+    {
+      g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      goto out;
+    }
+  
+  gvfs_dbus_progress_call_progress (proxy,
+                                    data->current_num_bytes,
+                                    data->total_num_bytes,
+                                    NULL,
+                                    (GAsyncReadyCallback) progress_cb,
+                                    NULL);
+  g_object_unref (proxy);
+  
+ out:
+  g_free (data);
 }
 
 static void
 progress_callback (goffset current_num_bytes,
-		   goffset total_num_bytes,
-		   gpointer user_data)
+                   goffset total_num_bytes,
+                   gpointer user_data)
 {
   GVfsJob *job = G_VFS_JOB (user_data);
   GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
   GVfsJobPull *op_job = G_VFS_JOB_PULL (job);
-  dbus_uint64_t current_dbus, total_dbus;
-  DBusMessage *message;
+  ProgressCallbackData *data;
 
   g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes);
 
   if (op_job->callback_obj_path == NULL)
     return;
 
-  message =
-    dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
-				  op_job->callback_obj_path,
-				  G_VFS_DBUS_PROGRESS_INTERFACE,
-				  G_VFS_DBUS_PROGRESS_OP_PROGRESS);
-  dbus_message_set_no_reply (message, TRUE);
-
-  current_dbus = current_num_bytes;
-  total_dbus = total_num_bytes;
-  dbus_message_append_args (message,
-			    DBUS_TYPE_UINT64, &current_dbus,
-			    DBUS_TYPE_UINT64, &total_dbus,
-			    0);
-
-  /* Queues reply (threadsafely), actually sends it in mainloop */
-  dbus_connection_send (dbus_job->connection, message, NULL);
-  dbus_message_unref (message);
+  data = g_new0 (ProgressCallbackData, 1);
+  data->current_num_bytes = current_num_bytes;
+  data->total_num_bytes = total_num_bytes;
+  
+  gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation),
+                                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                g_dbus_method_invocation_get_sender (dbus_job->invocation),
+                                op_job->callback_obj_path,
+                                NULL,
+                                progress_proxy_new_cb,
+                                data);
 }
 
 static void
@@ -207,14 +236,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-
-  return reply;
+  gvfs_dbus_mount_complete_pull (object, invocation);
 }
diff --git a/daemon/gvfsjobpull.h b/daemon/gvfsjobpull.h
index 1b89576..eb739ea 100644
--- a/daemon/gvfsjobpull.h
+++ b/daemon/gvfsjobpull.h
@@ -59,9 +59,15 @@ struct _GVfsJobPullClass
 
 GType g_vfs_job_pull_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_pull_new (DBusConnection *connection,
-                             DBusMessage    *message,
-                             GVfsBackend    *backend);
+gboolean g_vfs_job_pull_new_handle (GVfsDBusMount         *object,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar           *arg_path_data,
+                                    const gchar           *arg_local_path,
+                                    gboolean               arg_send_progress,
+                                    guint                  arg_flags,
+                                    const gchar           *arg_progress_obj_path,
+                                    gboolean               arg_remove_source,
+                                    GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobpush.c b/daemon/gvfsjobpush.c
index 5abc7bb..824a339 100644
--- a/daemon/gvfsjobpush.c
+++ b/daemon/gvfsjobpush.c
@@ -29,19 +29,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobpush.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
+#include "gvfsdbus.h"
 
 G_DEFINE_TYPE (GVfsJobPush, g_vfs_job_push, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_push_finalize (GObject *object)
@@ -76,92 +74,123 @@ g_vfs_job_push_init (GVfsJobPush *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_push_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_push_new_handle (GVfsDBusMount *object,
+                           GDBusMethodInvocation *invocation,
+                           const gchar *arg_path_data,
+                           const gchar *arg_local_path,
+                           gboolean arg_send_progress,
+                           guint arg_flags,
+                           const gchar *arg_progress_obj_path,
+                           gboolean arg_remove_source,
+                           GVfsBackend *backend)
 {
   GVfsJobPush *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path1_len, path2_len;
-  const char *path1_data, *path2_data, *callback_obj_path;
-  dbus_uint32_t flags;
-  dbus_bool_t remove_source, send_progress;
-
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path1_data, &path1_len,
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path2_data, &path2_len,
-                              DBUS_TYPE_BOOLEAN, &send_progress,
-                              DBUS_TYPE_UINT32, &flags,
-			      DBUS_TYPE_OBJECT_PATH, &callback_obj_path,
-                              DBUS_TYPE_BOOLEAN, &remove_source,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  
+  g_print ("called Push()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_PUSH,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->destination = g_strndup (path1_data, path1_len);
-  job->local_path = g_strndup (path2_data, path2_len);
+  job->destination = g_strdup (arg_path_data);
+  job->local_path = g_strdup (arg_local_path);
   job->backend = backend;
-  job->flags = flags;
-  job->send_progress = send_progress;
-  job->remove_source = remove_source;
-  g_debug ("Remove Source: %s\n", remove_source ? "true" : "false");
-  if (strcmp (callback_obj_path, "/org/gtk/vfs/void") != 0)
-    job->callback_obj_path = g_strdup (callback_obj_path);
-
-  return G_VFS_JOB (job);
+  job->flags = arg_flags;
+  job->send_progress = arg_send_progress;
+  job->remove_source = arg_remove_source;
+  g_debug ("Remove Source: %s\n", arg_remove_source ? "true" : "false");
+  if (strcmp (arg_progress_obj_path, "/org/gtk/vfs/void") != 0)
+    job->callback_obj_path = g_strdup (arg_progress_obj_path);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+typedef struct {
+  goffset current_num_bytes;
+  goffset total_num_bytes;
+} ProgressCallbackData;
+
+static void
+progress_cb (GVfsDBusProgress *proxy,
+             GAsyncResult *res,
+             gpointer user_data)
+{
+  GError *error = NULL;
+  
+  g_print ("progress_cb\n");
+  
+  if (! gvfs_dbus_progress_call_progress_finish (proxy, res, &error))
+    {
+      g_warning ("progress_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+    }
+}
+
+static void
+progress_proxy_new_cb (GObject *source_object,
+                       GAsyncResult *res,
+                       gpointer user_data)
+{
+  ProgressCallbackData *data = user_data;
+  GVfsDBusProgress *proxy;
+  GError *error = NULL;
+
+  g_print ("progress_proxy_new_cb\n");
+
+  proxy = gvfs_dbus_progress_proxy_new_finish (res, &error);
+  if (proxy == NULL)
+    {
+      g_warning ("progress_proxy_new_cb: %s (%s, %d)\n", error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      goto out;
+    }
+  
+  gvfs_dbus_progress_call_progress (proxy,
+                                    data->current_num_bytes,
+                                    data->total_num_bytes,
+                                    NULL,
+                                    (GAsyncReadyCallback) progress_cb,
+                                    NULL);
+  g_object_unref (proxy);
+  
+ out:
+  g_free (data);
 }
 
 static void
 progress_callback (goffset current_num_bytes,
-		   goffset total_num_bytes,
-		   gpointer user_data)
+                   goffset total_num_bytes,
+                   gpointer user_data)
 {
   GVfsJob *job = G_VFS_JOB (user_data);
   GVfsJobDBus *dbus_job = G_VFS_JOB_DBUS (job);
   GVfsJobPush *op_job = G_VFS_JOB_PUSH (job);
-  dbus_uint64_t current_dbus, total_dbus;
-  DBusMessage *message;
+  ProgressCallbackData *data;
 
   g_debug ("progress_callback %" G_GOFFSET_FORMAT "/%" G_GOFFSET_FORMAT "\n", current_num_bytes, total_num_bytes);
 
   if (op_job->callback_obj_path == NULL)
     return;
 
-  message =
-    dbus_message_new_method_call (dbus_message_get_sender (dbus_job->message),
-				  op_job->callback_obj_path,
-				  G_VFS_DBUS_PROGRESS_INTERFACE,
-				  G_VFS_DBUS_PROGRESS_OP_PROGRESS);
-  dbus_message_set_no_reply (message, TRUE);
-
-  current_dbus = current_num_bytes;
-  total_dbus = total_num_bytes;
-  dbus_message_append_args (message,
-			    DBUS_TYPE_UINT64, &current_dbus,
-			    DBUS_TYPE_UINT64, &total_dbus,
-			    0);
-
-  /* Queues reply (threadsafely), actually sends it in mainloop */
-  dbus_connection_send (dbus_job->connection, message, NULL);
-  dbus_message_unref (message);
+  data = g_new0 (ProgressCallbackData, 1);
+  data->current_num_bytes = current_num_bytes;
+  data->total_num_bytes = total_num_bytes;
+  
+  gvfs_dbus_progress_proxy_new (g_dbus_method_invocation_get_connection (dbus_job->invocation),
+                                G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS,
+                                g_dbus_method_invocation_get_sender (dbus_job->invocation),
+                                op_job->callback_obj_path,
+                                NULL,
+                                progress_proxy_new_cb,
+                                data);
 }
 
 static void
@@ -207,14 +236,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-
-  return reply;
+  gvfs_dbus_mount_complete_push (object, invocation);
 }
diff --git a/daemon/gvfsjobpush.h b/daemon/gvfsjobpush.h
index 09c9aa1..ae869b0 100644
--- a/daemon/gvfsjobpush.h
+++ b/daemon/gvfsjobpush.h
@@ -59,9 +59,15 @@ struct _GVfsJobPushClass
 
 GType g_vfs_job_push_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_push_new (DBusConnection *connection,
-                             DBusMessage    *message,
-                             GVfsBackend    *backend);
+gboolean g_vfs_job_push_new_handle (GVfsDBusMount         *object,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar           *arg_path_data,
+                                    const gchar           *arg_local_path,
+                                    gboolean               arg_send_progress,
+                                    guint                  arg_flags,
+                                    const gchar           *arg_progress_obj_path,
+                                    gboolean               arg_remove_source,
+                                    GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobqueryattributes.c b/daemon/gvfsjobqueryattributes.c
index 51fbbc2..ba7d7be 100644
--- a/daemon/gvfsjobqueryattributes.c
+++ b/daemon/gvfsjobqueryattributes.c
@@ -28,10 +28,7 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
-#include "gvfsjobmove.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
 #include "gvfsjobqueryattributes.h"
 
@@ -39,9 +36,9 @@ G_DEFINE_TYPE (GVfsJobQueryAttributes, g_vfs_job_query_attributes, G_VFS_TYPE_JO
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_query_attributes_finalize (GObject *object)
@@ -76,44 +73,60 @@ g_vfs_job_query_attributes_init (GVfsJobQueryAttributes *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_query_attributes_new (DBusConnection *connection,
-				DBusMessage *message,
-				GVfsBackend *backend,
-				gboolean namespaces)
+gboolean
+g_vfs_job_query_settable_attributes_new_handle (GVfsDBusMount *object,
+                                                GDBusMethodInvocation *invocation,
+                                                const gchar *arg_path_data,
+                                                GVfsBackend *backend)
 {
   GVfsJobQueryAttributes *job;
-  DBusMessage *reply;
-  DBusError derror;
-  const gchar *path = NULL;
-  gint path_len;
-  
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path, &path_len,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  g_print ("called QuerySettableAttributes()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_QUERY_ATTRIBUTES,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
+ 
+  job->backend = backend;
+  job->filename = g_strdup (arg_path_data);
+  job->namespaces = FALSE;
 
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+gboolean
+g_vfs_job_query_writable_namespaces_new_handle (GVfsDBusMount *object,
+                                                GDBusMethodInvocation *invocation,
+                                                const gchar *arg_path_data,
+                                                GVfsBackend *backend)
+{
+  GVfsJobQueryAttributes *job;
+
+  g_print ("called QueryWritableNamespaces()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
+  job = g_object_new (G_VFS_TYPE_JOB_QUERY_ATTRIBUTES,
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
+ 
   job->backend = backend;
-  job->filename = g_strndup (path, path_len);
-  job->namespaces = namespaces;
+  job->filename = g_strdup (arg_path_data);
+  job->namespaces = TRUE;
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
 
-  return G_VFS_JOB (job);
+  return TRUE;
 }
 
 static void
@@ -172,20 +185,18 @@ g_vfs_job_query_attributes_set_list (GVfsJobQueryAttributes *job,
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobQueryAttributes *op_job = G_VFS_JOB_QUERY_ATTRIBUTES (job);
-  DBusMessage *reply;
-  DBusMessageIter iter;
-
-  reply = dbus_message_new_method_return (message);
-
-  dbus_message_iter_init_append (reply, &iter);
-  _g_dbus_append_attribute_info_list (&iter, 
-				      op_job->list);
+  GVariant *list;
   
-  return reply;
+  list = _g_dbus_append_attribute_info_list (op_job->list);
+  
+  if (! op_job->namespaces)
+    gvfs_dbus_mount_complete_query_settable_attributes (object, invocation, list);
+  else
+    gvfs_dbus_mount_complete_query_writable_namespaces (object, invocation, list);
 }
diff --git a/daemon/gvfsjobqueryattributes.h b/daemon/gvfsjobqueryattributes.h
index 31776f6..0fb35f0 100644
--- a/daemon/gvfsjobqueryattributes.h
+++ b/daemon/gvfsjobqueryattributes.h
@@ -58,10 +58,14 @@ struct _GVfsJobQueryAttributesClass
 
 GType g_vfs_job_query_attributes_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_query_attributes_new      (DBusConnection         *connection,
-					      DBusMessage            *message,
-					      GVfsBackend            *backend,
-					      gboolean                namespaces);
+gboolean g_vfs_job_query_settable_attributes_new_handle (GVfsDBusMount         *object,
+                                                         GDBusMethodInvocation *invocation,
+                                                         const gchar           *arg_path_data,
+                                                         GVfsBackend           *backend);
+gboolean g_vfs_job_query_writable_namespaces_new_handle (GVfsDBusMount         *object,
+                                                         GDBusMethodInvocation *invocation,
+                                                         const gchar           *arg_path_data,
+                                                         GVfsBackend           *backend);
 void     g_vfs_job_query_attributes_set_list (GVfsJobQueryAttributes *job,
 					      GFileAttributeInfoList *list);
 
diff --git a/daemon/gvfsjobqueryfsinfo.c b/daemon/gvfsjobqueryfsinfo.c
index 1069f00..e62769b 100644
--- a/daemon/gvfsjobqueryfsinfo.c
+++ b/daemon/gvfsjobqueryfsinfo.c
@@ -28,19 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobqueryfsinfo.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobQueryFsInfo, g_vfs_job_query_fs_info, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_query_fs_info_finalize (GObject *object)
@@ -76,48 +74,36 @@ g_vfs_job_query_fs_info_init (GVfsJobQueryFsInfo *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_query_fs_info_new (DBusConnection *connection,
-			     DBusMessage *message,
-			     GVfsBackend *backend)
+gboolean 
+g_vfs_job_query_fs_info_new_handle (GVfsDBusMount *object,
+                                    GDBusMethodInvocation  *invocation,
+                                    const gchar *arg_path_data,
+                                    const gchar *arg_attributes,
+                                    GVfsBackend *backend)
 {
   GVfsJobQueryFsInfo *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
-  char *attributes;
   
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-			      DBUS_TYPE_STRING, &attributes,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  g_print ("called QueryFsInfo()\n");
+  
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
 
   job = g_object_new (G_VFS_TYPE_JOB_QUERY_FS_INFO,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->attribute_matcher = g_file_attribute_matcher_new (attributes);
+  job->attribute_matcher = g_file_attribute_matcher_new (arg_attributes);
   
   job->file_info = g_file_info_new ();
   g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher);
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -157,20 +143,14 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobQueryFsInfo *op_job = G_VFS_JOB_QUERY_FS_INFO (job);
-  DBusMessage *reply;
-  DBusMessageIter iter;
   const char *type;
 
-  reply = dbus_message_new_method_return (message);
-
-  dbus_message_iter_init_append (reply, &iter);
-
   type = g_vfs_backend_get_backend_type (op_job->backend);
 
   if (type)
@@ -178,8 +158,6 @@ create_reply (GVfsJob *job,
 				      G_FILE_ATTRIBUTE_GVFS_BACKEND,
 				      type);
 
-  _g_dbus_append_file_info (&iter, 
-			    op_job->file_info);
-  
-  return reply;
+  gvfs_dbus_mount_complete_query_filesystem_info (object, invocation,
+      _g_dbus_append_file_info (op_job->file_info));
 }
diff --git a/daemon/gvfsjobqueryfsinfo.h b/daemon/gvfsjobqueryfsinfo.h
index 876d0eb..e1dead0 100644
--- a/daemon/gvfsjobqueryfsinfo.h
+++ b/daemon/gvfsjobqueryfsinfo.h
@@ -57,9 +57,11 @@ struct _GVfsJobQueryFsInfoClass
 
 GType g_vfs_job_query_fs_info_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_query_fs_info_new (DBusConnection   *connection,
-				      DBusMessage      *message,
-				      GVfsBackend      *backend);
+gboolean g_vfs_job_query_fs_info_new_handle (GVfsDBusMount          *object,
+                                             GDBusMethodInvocation  *invocation,
+                                             const gchar            *arg_path_data,
+                                             const gchar            *arg_attributes,
+                                             GVfsBackend            *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobqueryinfo.c b/daemon/gvfsjobqueryinfo.c
index 81b84c8..ee26dc4 100644
--- a/daemon/gvfsjobqueryinfo.c
+++ b/daemon/gvfsjobqueryinfo.c
@@ -29,19 +29,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobqueryinfo.h"
-#include "gvfsdbusutils.h"
 #include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobQueryInfo, g_vfs_job_query_info, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_query_info_finalize (GObject *object)
@@ -79,63 +77,41 @@ g_vfs_job_query_info_init (GVfsJobQueryInfo *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_query_info_new (DBusConnection *connection,
-			  DBusMessage *message,
-			  GVfsBackend *backend)
+gboolean
+g_vfs_job_query_info_new_handle (GVfsDBusMount *object,
+                                 GDBusMethodInvocation *invocation,
+                                 const gchar *arg_path_data,
+                                 const gchar *arg_attributes,
+                                 guint arg_flags,
+                                 const gchar *arg_uri,
+                                 GVfsBackend *backend)
 {
   GVfsJobQueryInfo *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
-  char *attributes;
-  char *uri;
-  dbus_uint32_t flags;
-  DBusMessageIter iter;
-
-  dbus_message_iter_init (message, &iter);
-  
-  dbus_error_init (&derror);
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-				      &path_data, &path_len,
-				      DBUS_TYPE_STRING, &attributes,
-				      DBUS_TYPE_UINT32, &flags,
-				      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
-  /* Optional uri arg for thumbnail info */
-  if (!_g_dbus_message_iter_get_args (&iter, NULL,
-				      DBUS_TYPE_STRING, &uri,
-				      0))
-    uri = NULL;
-  
+  g_print ("called QueryInfo()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+
   job = g_object_new (G_VFS_TYPE_JOB_QUERY_INFO,
-		      "message", message,
-		      "connection", connection,
+                      "object", object,
+                      "invocation", invocation,
 		      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->attributes = g_strdup (attributes);
-  job->attribute_matcher = g_file_attribute_matcher_new (attributes);
-  job->flags = flags;
-  job->uri = g_strdup (uri);
+  job->attributes = g_strdup (arg_attributes);
+  job->attribute_matcher = g_file_attribute_matcher_new (arg_attributes);
+  job->flags = arg_flags;
+  job->uri = g_strdup (arg_uri);
 
   job->file_info = g_file_info_new ();
   g_file_info_set_attribute_mask (job->file_info, job->attribute_matcher);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
   
-  return G_VFS_JOB (job);
+  return TRUE;
 }
 
 static void
@@ -177,26 +153,18 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobQueryInfo *op_job = G_VFS_JOB_QUERY_INFO (job);
-  DBusMessage *reply;
-  DBusMessageIter iter;
-
-  reply = dbus_message_new_method_return (message);
-
-  dbus_message_iter_init_append (reply, &iter);
-
-  g_vfs_backend_add_auto_info (op_job->backend,
-			       op_job->attribute_matcher,
-			       op_job->file_info,
-			       op_job->uri);
   
-  _g_dbus_append_file_info (&iter, 
-			    op_job->file_info);
-  
-  return reply;
+  g_vfs_backend_add_auto_info (op_job->backend,
+                               op_job->attribute_matcher,
+                               op_job->file_info,
+                               op_job->uri);
+
+  gvfs_dbus_mount_complete_query_info (object, invocation,
+      _g_dbus_append_file_info (op_job->file_info));
 }
diff --git a/daemon/gvfsjobqueryinfo.h b/daemon/gvfsjobqueryinfo.h
index 66faa19..f200f2a 100644
--- a/daemon/gvfsjobqueryinfo.h
+++ b/daemon/gvfsjobqueryinfo.h
@@ -60,9 +60,14 @@ struct _GVfsJobQueryInfoClass
 
 GType g_vfs_job_query_info_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_query_info_new (DBusConnection        *connection,
-				   DBusMessage           *message,
-				   GVfsBackend           *backend);
+gboolean g_vfs_job_query_info_new_handle (GVfsDBusMount *object,
+                                          GDBusMethodInvocation *invocation,
+                                          const gchar *arg_path_data,
+                                          const gchar *arg_attributes,
+                                          guint arg_flags,
+                                          const gchar *arg_uri,
+                                          GVfsBackend *backend);
+
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobsetattribute.c b/daemon/gvfsjobsetattribute.c
index d99d05f..eb45b00 100644
--- a/daemon/gvfsjobsetattribute.c
+++ b/daemon/gvfsjobsetattribute.c
@@ -28,20 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobmove.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
 #include "gvfsjobsetattribute.h"
 
 G_DEFINE_TYPE (GVfsJobSetAttribute, g_vfs_job_set_attribute, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_set_attribute_finalize (GObject *object)
@@ -78,65 +75,49 @@ g_vfs_job_set_attribute_init (GVfsJobSetAttribute *job)
   job->type = G_FILE_ATTRIBUTE_TYPE_INVALID;
 }
 
-GVfsJob *
-g_vfs_job_set_attribute_new (DBusConnection *connection,
-			     DBusMessage *message,
-			     GVfsBackend *backend)
+gboolean
+g_vfs_job_set_attribute_new_handle (GVfsDBusMount *object,
+                                    GDBusMethodInvocation *invocation,
+                                    const gchar *arg_path_data,
+                                    guint arg_flags,
+                                    GVariant *arg_attribute,
+                                    GVfsBackend *backend)
 {
   GVfsJobSetAttribute *job;
-  DBusMessage *reply;
-  DBusMessageIter iter, array_iter;
-  const gchar *filename = NULL;
-  gint filename_len;
-  GFileQueryInfoFlags flags;
   gchar *attribute;
-  dbus_uint32_t flags_u32 = 0;
   GFileAttributeType type;
   GDbusAttributeValue value;
-  
-  dbus_message_iter_init (message, &iter);
-
-  if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_ARRAY &&
-      dbus_message_iter_get_element_type (&iter) == DBUS_TYPE_BYTE)
-    {
-      dbus_message_iter_recurse (&iter, &array_iter);
-      dbus_message_iter_get_fixed_array (&array_iter, &filename, &filename_len);
-    }
-
-  dbus_message_iter_next (&iter);
-
-  if (dbus_message_iter_get_arg_type (&iter) == DBUS_TYPE_UINT32)
-    {
-      dbus_message_iter_get_basic (&iter, &flags_u32);
-      dbus_message_iter_next (&iter);
-    }
+ 
+  g_print ("called SetAttribute()\n");
 
-  flags = flags_u32;
-
-  if (!(filename && _g_dbus_get_file_attribute (&iter, &attribute, NULL, &type, &value)))
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
+  if (! _g_dbus_get_file_attribute (arg_attribute, &attribute, NULL, &type, &value))
     {
-      reply = dbus_message_new_error (message,
-				      DBUS_ERROR_FAILED,
-                                      _("Invalid dbus message"));
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
+      g_dbus_method_invocation_return_error_literal (invocation,
+                                                     G_IO_ERROR,
+                                                     G_IO_ERROR_INVALID_ARGUMENT,
+                                                     _("Invalid dbus message"));
+      return TRUE;
     }
 
   job = g_object_new (G_VFS_TYPE_JOB_SET_ATTRIBUTE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
   job->backend = backend;
-  job->filename = g_strndup (filename, filename_len);
+  job->filename = g_strdup (arg_path_data);
   job->attribute = attribute;
   job->value = value;
   job->type = type;
-  job->flags = flags;
+  job->flags = arg_flags;
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
 
-  return G_VFS_JOB (job);
+  return TRUE;
 }
 
 static void
@@ -180,14 +161,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_set_attribute (object, invocation);
 }
diff --git a/daemon/gvfsjobsetattribute.h b/daemon/gvfsjobsetattribute.h
index 4865a6a..a75c15b 100644
--- a/daemon/gvfsjobsetattribute.h
+++ b/daemon/gvfsjobsetattribute.h
@@ -60,9 +60,12 @@ struct _GVfsJobSetAttributeClass
 
 GType g_vfs_job_set_attribute_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_set_attribute_new (DBusConnection *connection,
-				      DBusMessage    *message,
-				      GVfsBackend    *backend);
+gboolean g_vfs_job_set_attribute_new_handle (GVfsDBusMount         *object,
+                                             GDBusMethodInvocation *invocation,
+                                             const gchar           *arg_path_data,
+                                             guint                  arg_flags,
+                                             GVariant              *arg_attribute,
+                                             GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobsetdisplayname.c b/daemon/gvfsjobsetdisplayname.c
index 983d6a0..148f9c7 100644
--- a/daemon/gvfsjobsetdisplayname.c
+++ b/daemon/gvfsjobsetdisplayname.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobsetdisplayname.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobSetDisplayName, g_vfs_job_set_display_name, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_set_display_name_finalize (GObject *object)
@@ -75,45 +72,33 @@ g_vfs_job_set_display_name_init (GVfsJobSetDisplayName *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_set_display_name_new (DBusConnection *connection,
-				DBusMessage *message,
-				GVfsBackend *backend)
+gboolean
+g_vfs_job_set_display_name_new_handle (GVfsDBusMount *object,
+                                       GDBusMethodInvocation *invocation,
+                                       const gchar *arg_path_data,
+                                       const gchar *arg_display_name,
+                                       GVfsBackend *backend)
 {
   GVfsJobSetDisplayName *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
-  char *display_name;
   
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-			      DBUS_TYPE_STRING, &display_name,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  g_print ("called SetDisplayName()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_SET_DISPLAY_NAME,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->display_name = g_strdup (display_name);
+  job->display_name = g_strdup (arg_display_name);
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -158,22 +143,14 @@ g_vfs_job_set_display_name_set_new_path (GVfsJobSetDisplayName *job,
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
   GVfsJobSetDisplayName *op_job = G_VFS_JOB_SET_DISPLAY_NAME (job);
-  DBusMessage *reply;
-  DBusMessageIter iter;
-
-  reply = dbus_message_new_method_return (message);
-
-  dbus_message_iter_init_append (reply, &iter);
 
   g_assert (op_job->new_path != NULL);
   
-  _g_dbus_message_iter_append_cstring (&iter, op_job->new_path);
-  
-  return reply;
+  gvfs_dbus_mount_complete_set_display_name (object, invocation, op_job->new_path);
 }
diff --git a/daemon/gvfsjobsetdisplayname.h b/daemon/gvfsjobsetdisplayname.h
index 5c9c531..8df19d8 100644
--- a/daemon/gvfsjobsetdisplayname.h
+++ b/daemon/gvfsjobsetdisplayname.h
@@ -57,9 +57,11 @@ struct _GVfsJobSetDisplayNameClass
 
 GType g_vfs_job_set_display_name_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_set_display_name_new          (DBusConnection        *connection,
-						  DBusMessage           *message,
-						  GVfsBackend           *backend);
+gboolean g_vfs_job_set_display_name_new_handle   (GVfsDBusMount         *object,
+                                                  GDBusMethodInvocation *invocation,
+                                                  const gchar           *arg_path_data,
+                                                  const gchar           *arg_display_name,
+                                                  GVfsBackend           *backend);
 void     g_vfs_job_set_display_name_set_new_path (GVfsJobSetDisplayName *job,
 						  const char            *new_path);
 
diff --git a/daemon/gvfsjobstartmountable.c b/daemon/gvfsjobstartmountable.c
index 5f68c99..9b0dce5 100644
--- a/daemon/gvfsjobstartmountable.c
+++ b/daemon/gvfsjobstartmountable.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobstartmountable.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobStartMountable, g_vfs_job_start_mountable, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_start_mountable_finalize (GObject *object)
@@ -76,49 +73,34 @@ g_vfs_job_start_mountable_init (GVfsJobStartMountable *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_start_mountable_new (DBusConnection *connection,
-			       DBusMessage *message,
-			       GVfsBackend *backend)
+gboolean
+g_vfs_job_start_mountable_new_handle (GVfsDBusMount *object,
+                                      GDBusMethodInvocation *invocation,
+                                      const gchar *arg_path_data,
+                                      const gchar *arg_dbus_id,
+                                      const gchar *arg_obj_path,
+                                      GVfsBackend *backend)
 {
   GVfsJobStartMountable *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  char *path;
-  const char *dbus_id, *obj_path;
-
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  path = NULL;
-  if (!_g_dbus_message_iter_get_args (&iter, &derror,
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_STRING, &dbus_id,
-				      DBUS_TYPE_OBJECT_PATH, &obj_path,
-				      0))
-    {
-      g_free (path);
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  g_print ("called StartMountable()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_START_MOUNTABLE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = path;
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->mount_source = g_mount_source_new (dbus_id, obj_path);
+  job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path);
+
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
 
-  return G_VFS_JOB (job);
+  return TRUE;
 }
 
 static void
@@ -156,14 +138,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-
-  return reply;
+  gvfs_dbus_mount_complete_start_mountable (object, invocation);
 }
diff --git a/daemon/gvfsjobstartmountable.h b/daemon/gvfsjobstartmountable.h
index 4593af3..0aca7e5 100644
--- a/daemon/gvfsjobstartmountable.h
+++ b/daemon/gvfsjobstartmountable.h
@@ -55,9 +55,12 @@ struct _GVfsJobStartMountableClass
 
 GType g_vfs_job_start_mountable_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_start_mountable_new        (DBusConnection        *connection,
-					       DBusMessage           *message,
-					       GVfsBackend           *backend);
+gboolean g_vfs_job_start_mountable_new_handle (GVfsDBusMount         *object,
+                                               GDBusMethodInvocation *invocation,
+                                               const gchar           *arg_path_data,
+                                               const gchar           *arg_dbus_id,
+                                               const gchar           *arg_obj_path,
+                                               GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobstopmountable.c b/daemon/gvfsjobstopmountable.c
index 96725f9..f876e7e 100644
--- a/daemon/gvfsjobstopmountable.c
+++ b/daemon/gvfsjobstopmountable.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobstopmountable.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobStopMountable, g_vfs_job_stop_mountable, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_stop_mountable_finalize (GObject *object)
@@ -76,52 +73,36 @@ g_vfs_job_stop_mountable_init (GVfsJobStopMountable *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_stop_mountable_new (DBusConnection *connection,
-                              DBusMessage *message,
-                              GVfsBackend *backend)
+gboolean
+g_vfs_job_stop_mountable_new_handle (GVfsDBusMount *object,
+                                     GDBusMethodInvocation *invocation,
+                                     const gchar *arg_path_data,
+                                     guint arg_flags,
+                                     const gchar *arg_dbus_id,
+                                     const gchar *arg_obj_path,
+                                     GVfsBackend *backend)
 {
   GVfsJobStopMountable *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  char *path;
-  const char *dbus_id, *obj_path;
-  guint32 flags;
-  
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  path = NULL;
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_UINT32, &flags,
-                                      DBUS_TYPE_STRING, &dbus_id,
-                                      DBUS_TYPE_OBJECT_PATH, &obj_path,
-				      0))
-    {
-      g_free (path);
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
-  job = g_object_new (G_VFS_TYPE_JOB_STOP_MOUNTABLE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+  g_print ("called StopMountable()\n");
 
-  job->filename = path;
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
+  job = g_object_new (G_VFS_TYPE_JOB_STOP_MOUNTABLE,
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
+  
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
-  job->mount_source = g_mount_source_new (dbus_id, obj_path);
-  job->flags = flags;
+  job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path);
+  job->flags = arg_flags;
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -161,14 +142,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_enumerate (object, invocation);
 }
diff --git a/daemon/gvfsjobstopmountable.h b/daemon/gvfsjobstopmountable.h
index 96adac2..cef6d81 100644
--- a/daemon/gvfsjobstopmountable.h
+++ b/daemon/gvfsjobstopmountable.h
@@ -56,8 +56,12 @@ struct _GVfsJobStopMountableClass
 
 GType g_vfs_job_stop_mountable_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_stop_mountable_new        (DBusConnection        *connection,
-                                              DBusMessage           *message,
+gboolean g_vfs_job_stop_mountable_new_handle (GVfsDBusMount         *object,
+                                              GDBusMethodInvocation *invocation,
+                                              const gchar           *arg_path_data,
+                                              guint                  arg_flags,
+                                              const gchar           *arg_dbus_id,
+                                              const gchar           *arg_obj_path,
                                               GVfsBackend           *backend);
 
 G_END_DECLS
diff --git a/daemon/gvfsjobtrash.c b/daemon/gvfsjobtrash.c
index 1e1b13d..5e2f8a9 100644
--- a/daemon/gvfsjobtrash.c
+++ b/daemon/gvfsjobtrash.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobtrash.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobTrash, g_vfs_job_trash, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_trash_finalize (GObject *object)
@@ -73,42 +70,31 @@ g_vfs_job_trash_init (GVfsJobTrash *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_trash_new (DBusConnection *connection,
-			DBusMessage *message,
-			GVfsBackend *backend)
+gboolean
+g_vfs_job_trash_new_handle (GVfsDBusMount *object,
+                            GDBusMethodInvocation *invocation,
+                            const gchar *arg_path_data,
+                            GVfsBackend *backend)
 {
   GVfsJobTrash *job;
-  DBusMessage *reply;
-  DBusError derror;
-  int path_len;
-  const char *path_data;
   
-  dbus_error_init (&derror);
-  if (!dbus_message_get_args (message, &derror, 
-			      DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE,
-			      &path_data, &path_len,
-			      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
+  g_print ("called Trash()\n");
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_TRASH,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = g_strndup (path_data, path_len);
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -144,14 +130,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_trash (object, invocation);
 }
diff --git a/daemon/gvfsjobtrash.h b/daemon/gvfsjobtrash.h
index ddf663c..a68ee07 100644
--- a/daemon/gvfsjobtrash.h
+++ b/daemon/gvfsjobtrash.h
@@ -54,10 +54,10 @@ struct _GVfsJobTrashClass
 
 GType g_vfs_job_trash_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_trash_new (DBusConnection *connection,
-			       DBusMessage    *message,
-			       GVfsBackend    *backend);
-
+gboolean g_vfs_job_trash_new_handle (GVfsDBusMount         *object,
+                                     GDBusMethodInvocation *invocation,
+                                     const gchar           *arg_path_data,
+                                     GVfsBackend           *backend);
 G_END_DECLS
 
 #endif /* __G_VFS_JOB_TRASH_H__ */
diff --git a/daemon/gvfsjobunmount.c b/daemon/gvfsjobunmount.c
index 75e99dd..7e79d69 100644
--- a/daemon/gvfsjobunmount.c
+++ b/daemon/gvfsjobunmount.c
@@ -28,20 +28,17 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobunmount.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonprotocol.h"
 
 G_DEFINE_TYPE (GVfsJobUnmount, g_vfs_job_unmount, G_VFS_TYPE_JOB_DBUS)
 
 static void     run        (GVfsJob *job);
 static gboolean try        (GVfsJob *job);
 static void     send_reply (GVfsJob *job);
-static DBusMessage *create_reply (GVfsJob *job,
-				  DBusConnection *connection,
-				  DBusMessage *message);
+static void     create_reply (GVfsJob               *job,
+                              GVfsDBusMount         *object,
+                              GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_unmount_finalize (GObject *object)
@@ -70,7 +67,6 @@ g_vfs_job_unmount_class_init (GVfsJobUnmountClass *klass)
   job_class->send_reply = send_reply;
 
   job_dbus_class->create_reply = create_reply;
-
 }
 
 static void
@@ -78,50 +74,36 @@ g_vfs_job_unmount_init (GVfsJobUnmount *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_unmount_new (DBusConnection *connection,
-		       DBusMessage *message,
-		       GVfsBackend *backend)
+gboolean
+g_vfs_job_unmount_new_handle (GVfsDBusMount *object,
+                              GDBusMethodInvocation *invocation,
+                              const gchar *arg_dbus_id,
+                              const gchar *arg_obj_path,
+                              guint arg_flags,
+                              GVfsBackend *backend)
 {
   GVfsJobUnmount *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  const char *dbus_id, *obj_path;
-  guint32 flags;
-  
-  
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-                                      DBUS_TYPE_STRING, &dbus_id,
-                                      DBUS_TYPE_OBJECT_PATH, &obj_path,
-                                      DBUS_TYPE_UINT32, &flags,
-				      0))
-    {
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
-  g_debug ("g_vfs_job_unmount_new request: %p\n", message);
-  
+  g_print ("called Unmount()\n");
+
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+
+  g_debug ("g_vfs_job_unmount_new request: %p\n", invocation);
+
   job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
   job->backend = backend;
-  job->flags = flags;
-  job->mount_source = g_mount_source_new (dbus_id, obj_path);
+  job->flags = arg_flags;
+  job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path);
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
 }
 
 static void
@@ -289,16 +271,29 @@ try (GVfsJob *job)
 }
 
 static void
-unregister_mount_callback (DBusMessage *unmount_reply,
-			   GError *error,
-			   gpointer user_data)
+unregister_mount_callback (GVfsDBusMountTracker *proxy,
+                           GAsyncResult *res,
+                           gpointer user_data)
 {
   GVfsBackend *backend;
   GVfsDaemon *daemon;
+  GVfsJob *job = G_VFS_JOB (user_data);
   GVfsJobUnmount *op_job = G_VFS_JOB_UNMOUNT (user_data);
+  GError *error = NULL;
 
-  g_debug ("unregister_mount_callback, unmount_reply: %p, error: %p\n", unmount_reply, error);
-
+  gvfs_dbus_mount_tracker_call_unregister_mount_finish (proxy,
+                                                        res,
+                                                        &error);
+  g_debug ("unregister_mount_callback, error: %p\n", error);
+  
+  if (error != NULL)
+    {
+      /* If we failed before, don't overwrite the error as this one is not that important */ 
+      if (! job->failed)
+        g_vfs_job_failed_from_error (job, error);
+      g_error_free (error);
+    }
+  
   backend = op_job->backend;
   (*G_VFS_JOB_CLASS (g_vfs_job_unmount_parent_class)->send_reply) (G_VFS_JOB (op_job));
 
@@ -327,20 +322,16 @@ send_reply (GVfsJob *job)
          set active GVfsChannels to block requets  */
       g_vfs_backend_set_block_requests (backend);
       g_vfs_backend_unregister_mount (backend,
-				      unregister_mount_callback,
+				      (GAsyncReadyCallback) unregister_mount_callback,
 				      job);
     }
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-
-  return reply;
+  gvfs_dbus_mount_complete_unmount (object, invocation);
 }
diff --git a/daemon/gvfsjobunmount.h b/daemon/gvfsjobunmount.h
index c5266cd..991db45 100644
--- a/daemon/gvfsjobunmount.h
+++ b/daemon/gvfsjobunmount.h
@@ -58,9 +58,12 @@ struct _GVfsJobUnmountClass
 
 GType g_vfs_job_unmount_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_unmount_new (DBusConnection *connection,
-				DBusMessage *request,
-				GVfsBackend *backend);
+gboolean g_vfs_job_unmount_new_handle (GVfsDBusMount         *object,
+                                       GDBusMethodInvocation *invocation,
+                                       const gchar           *arg_dbus_id,
+                                       const gchar           *arg_obj_path,
+                                       guint                  arg_flags,
+                                       GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/gvfsjobunmountmountable.c b/daemon/gvfsjobunmountmountable.c
index 3c99284..a87de3b 100644
--- a/daemon/gvfsjobunmountmountable.c
+++ b/daemon/gvfsjobunmountmountable.c
@@ -28,19 +28,16 @@
 #include <sys/un.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
 #include "gvfsjobunmountmountable.h"
-#include "gvfsdbusutils.h"
-#include "gvfsdaemonutils.h"
 
 G_DEFINE_TYPE (GVfsJobUnmountMountable, g_vfs_job_unmount_mountable, G_VFS_TYPE_JOB_DBUS)
 
 static void         run          (GVfsJob        *job);
 static gboolean     try          (GVfsJob        *job);
-static DBusMessage *create_reply (GVfsJob        *job,
-				  DBusConnection *connection,
-				  DBusMessage    *message);
+static void         create_reply (GVfsJob               *job,
+                                  GVfsDBusMount         *object,
+                                  GDBusMethodInvocation *invocation);
 
 static void
 g_vfs_job_unmount_mountable_finalize (GObject *object)
@@ -76,54 +73,78 @@ g_vfs_job_unmount_mountable_init (GVfsJobUnmountMountable *job)
 {
 }
 
-GVfsJob *
-g_vfs_job_unmount_mountable_new (DBusConnection *connection,
-				 DBusMessage *message,
-				 GVfsBackend *backend,
-				 gboolean eject)
+static gboolean
+do_g_vfs_job_unmount_mountable_new_handle (GVfsDBusMount *object,
+                                           GDBusMethodInvocation *invocation,
+                                           const gchar *arg_path_data,
+                                           guint arg_flags,
+                                           const gchar *arg_dbus_id,
+                                           const gchar *arg_obj_path,
+                                           GVfsBackend *backend,
+                                           gboolean eject)
 {
   GVfsJobUnmountMountable *job;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  DBusError derror;
-  char *path;
-  guint32 flags;
-  const char *dbus_id, *obj_path;
-  
-  dbus_error_init (&derror);
-  dbus_message_iter_init (message, &iter);
-
-  path = NULL;
-  if (!_g_dbus_message_iter_get_args (&iter, &derror, 
-				      G_DBUS_TYPE_CSTRING, &path,
-				      DBUS_TYPE_UINT32, &flags,
-                                      DBUS_TYPE_STRING, &dbus_id,
-                                      DBUS_TYPE_OBJECT_PATH, &obj_path,
-				      0))
-    {
-      g_free (path);
-      reply = dbus_message_new_error (message,
-				      derror.name,
-                                      derror.message);
-      dbus_error_free (&derror);
-
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-      return NULL;
-    }
 
+  if (g_vfs_backend_invocation_first_handler (object, invocation, backend))
+    return TRUE;
+  
   job = g_object_new (G_VFS_TYPE_JOB_UNMOUNT_MOUNTABLE,
-		      "message", message,
-		      "connection", connection,
-		      NULL);
+                      "object", object,
+                      "invocation", invocation,
+                      NULL);
 
-  job->filename = path;
+  job->filename = g_strdup (arg_path_data);
   job->backend = backend;
   job->eject = eject;
-  job->flags = flags;
-  job->mount_source = g_mount_source_new (dbus_id, obj_path);
+  job->flags = arg_flags;
+  job->mount_source = g_mount_source_new (arg_dbus_id, arg_obj_path);
   
-  return G_VFS_JOB (job);
+  g_vfs_job_source_new_job (G_VFS_JOB_SOURCE (backend), G_VFS_JOB (job));
+  g_object_unref (job);
+
+  return TRUE;
+}
+
+gboolean
+g_vfs_job_unmount_mountable_new_handle (GVfsDBusMount *object,
+                                        GDBusMethodInvocation *invocation,
+                                        const gchar *arg_path_data,
+                                        guint arg_flags,
+                                        const gchar *arg_dbus_id,
+                                        const gchar *arg_obj_path,
+                                        GVfsBackend *backend)
+{
+  g_print ("called UnmountMountable()\n");
+
+  return do_g_vfs_job_unmount_mountable_new_handle (object,
+                                                    invocation,
+                                                    arg_path_data,
+                                                    arg_flags,
+                                                    arg_dbus_id,
+                                                    arg_obj_path,
+                                                    backend,
+                                                    FALSE);
+}
+
+gboolean
+g_vfs_job_eject_mountable_new_handle (GVfsDBusMount *object,
+                                      GDBusMethodInvocation *invocation,
+                                      const gchar *arg_path_data,
+                                      guint arg_flags,
+                                      const gchar *arg_dbus_id,
+                                      const gchar *arg_obj_path,
+                                      GVfsBackend *backend)
+{
+  g_print ("called EjectMountable()\n");
+
+  return do_g_vfs_job_unmount_mountable_new_handle (object,
+                                                    invocation,
+                                                    arg_path_data,
+                                                    arg_flags,
+                                                    arg_dbus_id,
+                                                    arg_obj_path,
+                                                    backend,
+                                                    TRUE);
 }
 
 static void
@@ -195,14 +216,10 @@ try (GVfsJob *job)
 }
 
 /* Might be called on an i/o thread */
-static DBusMessage *
+static void
 create_reply (GVfsJob *job,
-	      DBusConnection *connection,
-	      DBusMessage *message)
+              GVfsDBusMount *object,
+              GDBusMethodInvocation *invocation)
 {
-  DBusMessage *reply;
-
-  reply = dbus_message_new_method_return (message);
-  
-  return reply;
+  gvfs_dbus_mount_complete_enumerate (object, invocation);
 }
diff --git a/daemon/gvfsjobunmountmountable.h b/daemon/gvfsjobunmountmountable.h
index d90da8e..988514e 100644
--- a/daemon/gvfsjobunmountmountable.h
+++ b/daemon/gvfsjobunmountmountable.h
@@ -57,10 +57,21 @@ struct _GVfsJobUnmountMountableClass
 
 GType g_vfs_job_unmount_mountable_get_type (void) G_GNUC_CONST;
 
-GVfsJob *g_vfs_job_unmount_mountable_new        (DBusConnection        *connection,
-						 DBusMessage           *message,
-						 GVfsBackend           *backend,
-						 gboolean               eject);
+gboolean g_vfs_job_unmount_mountable_new_handle (GVfsDBusMount         *object,
+                                                 GDBusMethodInvocation *invocation,
+                                                 const gchar           *arg_path_data,
+                                                 guint                  arg_flags,
+                                                 const gchar           *arg_dbus_id,
+                                                 const gchar           *arg_obj_path,
+                                                 GVfsBackend           *backend);
+
+gboolean g_vfs_job_eject_mountable_new_handle   (GVfsDBusMount         *object,
+                                                 GDBusMethodInvocation *invocation,
+                                                 const gchar           *arg_path_data,
+                                                 guint                  arg_flags,
+                                                 const gchar           *arg_dbus_id,
+                                                 const gchar           *arg_obj_path,
+                                                 GVfsBackend           *backend);
 
 G_END_DECLS
 
diff --git a/daemon/main.c b/daemon/main.c
index 1ec1eb4..2a247bd 100644
--- a/daemon/main.c
+++ b/daemon/main.c
@@ -25,21 +25,104 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib/gstdio.h>
-#include <dbus/dbus.h>
 #include "gvfsdaemon.h"
 #include "gvfsbackendtest.h"
 #include <gvfsdaemonprotocol.h>
 #include "mount.h"
 #include <locale.h>
 
+
+
+static GMainLoop *loop;
+static gboolean already_acquired = FALSE;
+static int process_result = 0;
+
+static void
+on_name_lost (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  if (connection == NULL)
+    {
+      g_printerr ("A connection to the bus can't be made\n");
+      process_result = 1;
+    }
+  else
+    {
+      if (already_acquired)
+        {
+          g_printerr ("Got NameLost, some other instance replaced us\n");
+        }
+      else
+        {
+          g_printerr ("Failed to acquire daemon name, perhaps the VFS daemon is already running?\n");
+          process_result = 1;
+        }
+    }
+  g_main_loop_quit (loop);
+}
+
+static void
+on_name_acquired (GDBusConnection *connection,
+                  const gchar     *name,
+                  gpointer         user_data)
+{
+  gboolean no_fuse = GPOINTER_TO_UINT (user_data);
+
+  g_warning ("main.c: Acquired the name %s on the session message bus\n", name);
+  already_acquired = TRUE;
+
+  mount_init ();
+  
+#ifdef HAVE_FUSE
+  if (!no_fuse)
+    {
+      char *fuse_path;
+      char *argv2[4];
+      
+      /* Use the old .gvfs location as fallback, not .cache/gvfs */
+      if (g_get_user_runtime_dir() == g_get_user_cache_dir ())
+        fuse_path = g_build_filename (g_get_home_dir(), ".gvfs", NULL);
+      else
+        fuse_path = g_build_filename (g_get_user_runtime_dir (), "gvfs", NULL);
+      
+      if (!g_file_test (fuse_path, G_FILE_TEST_EXISTS))
+        g_mkdir (fuse_path, 0700);
+      
+      /* The -f (foreground) option prevent libfuse to call daemon(). */
+      /* First, this is not required as g_spawn_async() already       */
+      /* detach the process. Secondly, calling daemon() and then      */
+      /* pthread_create() produce an undefined result accoring to     */
+      /* Opengroup. On system with the uClibc library this will badly */
+      /* hang the process.                                            */
+      argv2[0] = LIBEXEC_DIR "/gvfsd-fuse";
+      argv2[1] = "-f";
+      argv2[2] = fuse_path;
+      argv2[3] = NULL;
+      
+      g_spawn_async (NULL,
+                     argv2,
+                     NULL,
+                     G_SPAWN_STDOUT_TO_DEV_NULL |
+                     G_SPAWN_STDERR_TO_DEV_NULL, 
+                     NULL, NULL,
+                     NULL, NULL);
+      
+      g_free (fuse_path);
+    }
+#endif
+}
+
+
 int
 main (int argc, char *argv[])
 {
-  GMainLoop *loop;
   GVfsDaemon *daemon;
   gboolean replace;
   gboolean no_fuse;
   GError *error;
+  guint name_owner_id;
+  GBusNameOwnerFlags flags;
   GOptionContext *context;
   const GOptionEntry options[] = {
     { "replace", 'r', 0, G_OPTION_ARG_NONE, &replace,  N_("Replace old daemon."), NULL },
@@ -87,58 +170,39 @@ main (int argc, char *argv[])
 
   g_option_context_free (context);
 
-  dbus_threads_init_default ();
-  
   g_type_init ();
+  loop = g_main_loop_new (NULL, FALSE);
 
   daemon = g_vfs_daemon_new (TRUE, replace);
   if (daemon == NULL)
     return 1;
 
-  mount_init ();
-  
-  loop = g_main_loop_new (NULL, FALSE);
+  /* FIXME: a message filter??! */
+  /* Request name only after we've installed the message filter */
+  flags = G_BUS_NAME_OWNER_FLAGS_ALLOW_REPLACEMENT;
+  if (replace)
+    flags |= G_BUS_NAME_OWNER_FLAGS_REPLACE;
 
+  name_owner_id = g_bus_own_name (G_BUS_TYPE_SESSION,
+                                  G_VFS_DBUS_DAEMON_NAME,
+                                  flags,
+                                  NULL,
+                                  on_name_acquired,
+                                  on_name_lost,
+                                  GUINT_TO_POINTER (no_fuse),
+                                  NULL);
 
-#ifdef HAVE_FUSE
-  if (!no_fuse)
-    {
-      char *fuse_path;
-      char *argv2[4];
-      
-      /* Use the old .gvfs location as fallback, not .cache/gvfs */
-      if (g_get_user_runtime_dir() == g_get_user_cache_dir ())
-	fuse_path = g_build_filename (g_get_home_dir(), ".gvfs", NULL);
-      else
-	fuse_path = g_build_filename (g_get_user_runtime_dir (), "gvfs", NULL);
-      
-      if (!g_file_test (fuse_path, G_FILE_TEST_EXISTS))
-	g_mkdir (fuse_path, 0700);
-      
-      /* The -f (foreground) option prevent libfuse to call daemon(). */
-      /* First, this is not required as g_spawn_async() already       */
-      /* detach the process. Secondly, calling daemon() and then      */
-      /* pthread_create() produce an undefined result accoring to     */
-      /* Opengroup. On system with the uClibc library this will badly */
-      /* hang the process.                                            */
-      argv2[0] = LIBEXEC_DIR "/gvfsd-fuse";
-      argv2[1] = "-f";
-      argv2[2] = fuse_path;
-      argv2[3] = NULL;
-      
-      g_spawn_async (NULL,
-		     argv2,
-		     NULL,
-		     G_SPAWN_STDOUT_TO_DEV_NULL |
-		     G_SPAWN_STDERR_TO_DEV_NULL, 
-		     NULL, NULL,
-		     NULL, NULL);
-      
-      g_free (fuse_path);
-    }
-#endif
-  
   g_main_loop_run (loop);
+
+#if 0
+  /* FIXME: crashing */
+  if (daemon != NULL)
+    g_object_unref (daemon);
+#endif
+  if (name_owner_id != 0)
+    g_bus_unown_name (name_owner_id);
+  if (loop != NULL)
+    g_main_loop_unref (loop);
   
-  return 0;
+  return process_result;
 }
diff --git a/daemon/mount.c b/daemon/mount.c
index b690946..97a0109 100644
--- a/daemon/mount.c
+++ b/daemon/mount.c
@@ -27,13 +27,12 @@
 #include <signal.h>
 
 #include <glib.h>
-#include <dbus/dbus.h>
 #include <glib/gi18n.h>
+#include <gio/gio.h>
 #include "mount.h"
 #include "gmountoperationdbus.h"
 #include "gvfsdaemonprotocol.h"
-#include "gvfsdbusutils.h"
-#include <gio/gio.h>
+#include <gvfsdbus.h>
 
 typedef struct {
   char *display_name;
@@ -43,11 +42,12 @@ typedef struct {
   char *prefered_filename_encoding;
   gboolean user_visible;
   char *default_location;
-  char *fuse_mountpoint; /* Always set, even if fuse not availible */
+  char *fuse_mountpoint; /* Always set, even if fuse not available */
   
   /* Daemon object ref */
   char *dbus_id;
   char *object_path;
+  guint name_watcher_id;
 
   /* Mount details */
   GMountSpec *mount_spec;
@@ -73,15 +73,10 @@ static GList *mounts = NULL;
 
 static gboolean fuse_available;
 
-static void lookup_mount (DBusConnection *connection,
-			  DBusMessage *message,
-			  gboolean do_automount);
-static void mountable_mount (VfsMountable *mountable,
-			     GMountSpec *mount_spec,
-			     GMountSource *source,
-			     gboolean automount,
-			     MountCallback callback,
-			     gpointer user_data);
+static void lookup_mount (GVfsDBusMountTracker *object,
+                          GDBusMethodInvocation *invocation,
+                          GMountSpec *spec,
+                          gboolean do_automount);
 
 static VfsMount *
 find_vfs_mount (const char *dbus_id,
@@ -125,7 +120,6 @@ find_vfs_mount_by_fuse_path (const char *fuse_path)
   return NULL;
 }
 
-
 static VfsMount *
 match_vfs_mount (GMountSpec *match)
 {
@@ -183,6 +177,9 @@ vfs_mountable_free (VfsMountable *mountable)
 static void
 vfs_mount_free (VfsMount *mount)
 {
+  if (mount->name_watcher_id != 0)
+    g_bus_unwatch_name (mount->name_watcher_id);
+
   g_free (mount->display_name);
   g_free (mount->stable_name);
   g_free (mount->x_content_types);
@@ -193,129 +190,43 @@ vfs_mount_free (VfsMount *mount)
   g_free (mount->dbus_id);
   g_free (mount->object_path);
   g_mount_spec_unref (mount->mount_spec);
-  
+
   g_free (mount);
 }
 
-static void
-vfs_mount_to_dbus (VfsMount *mount,
-		   DBusMessageIter *iter)
+
+/* Keep in sync with dbus-interfaces.xml */
+#define VFS_MOUNT_ARRAY_DBUS_STRUCT_TYPE "a(sosssssbay(aya{sv})ay)"
+#define VFS_MOUNTABLE_ARRAY_DBUS_STRUCT_TYPE "a(ssasib)"
+
+static GVariant *
+vfs_mount_to_dbus (VfsMount *mount)
 {
-  DBusMessageIter struct_iter;
-  dbus_bool_t user_visible;
-  char *fuse_mountpoint;
-  
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_STRUCT,
-					 NULL,
-					 &struct_iter))
-    _g_dbus_oom ();
-  
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mount->dbus_id))
-    _g_dbus_oom ();
-  
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_OBJECT_PATH,
-				       &mount->object_path))
-    _g_dbus_oom ();
-  
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mount->display_name))
-    _g_dbus_oom ();
-
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mount->stable_name))
-    _g_dbus_oom ();
-
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mount->x_content_types))
-    _g_dbus_oom ();
-  
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mount->icon))
-    _g_dbus_oom ();
-	      
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mount->prefered_filename_encoding))
-    _g_dbus_oom ();
-
-  user_visible = mount->user_visible;
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_BOOLEAN,
-				       &user_visible))
-    _g_dbus_oom ();
-
-  fuse_mountpoint = "";
-  if (fuse_available && mount->fuse_mountpoint)
-    fuse_mountpoint = mount->fuse_mountpoint;
-  _g_dbus_message_iter_append_cstring (&struct_iter, fuse_mountpoint);
-
-  g_mount_spec_to_dbus (&struct_iter, mount->mount_spec);
-
-  _g_dbus_message_iter_append_cstring (&struct_iter, mount->default_location);
-
-  if (!dbus_message_iter_close_container (iter, &struct_iter))
-    _g_dbus_oom ();
+  return g_variant_new ("(sosssssb^ay@(aya{sv})^ay)",
+                        mount->dbus_id,
+                        mount->object_path,
+                        mount->display_name,
+                        mount->stable_name,
+                        mount->x_content_types,
+                        mount->icon,
+                        mount->prefered_filename_encoding,
+                        mount->user_visible,
+                        (fuse_available && mount->fuse_mountpoint) ? mount->fuse_mountpoint : "",
+                        g_mount_spec_to_dbus (mount->mount_spec),
+                        mount->default_location);
 }
 
-static void
-vfs_mountable_to_dbus (VfsMountable *mountable,
-		       DBusMessageIter *iter)
+static GVariant *
+vfs_mountable_to_dbus (VfsMountable *mountable)
 {
-  DBusMessageIter struct_iter;
-  dbus_bool_t bool;
-  guint32 int32;
-  char *s;
-  char **a;
   char *empty[] = {NULL};
   
-  if (!dbus_message_iter_open_container (iter,
-					 DBUS_TYPE_STRUCT,
-					 NULL,
-					 &struct_iter))
-    _g_dbus_oom ();
-
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &mountable->type))
-    _g_dbus_oom ();
-  
-  s = mountable->scheme;
-  if (s == NULL)
-    s = "";
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_STRING,
-				       &s))
-    _g_dbus_oom ();
-
-  a = mountable->scheme_aliases;
-  if (a == NULL)
-    a = empty;
-  _g_dbus_message_iter_append_args (&struct_iter,
-				    DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &a, (int)g_strv_length (a),
-				    0);
-  
-  int32 = mountable->default_port;
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_INT32,
-				       &int32))
-    _g_dbus_oom ();
-  
-  bool = mountable->hostname_is_inet;
-  if (!dbus_message_iter_append_basic (&struct_iter,
-				       DBUS_TYPE_BOOLEAN,
-				       &bool))
-    _g_dbus_oom ();
-
-  if (!dbus_message_iter_close_container (iter, &struct_iter))
-    _g_dbus_oom ();
+  return g_variant_new ("(ss^asib)",
+                        mountable->type,
+                        mountable->scheme ? mountable->scheme : "",
+                        mountable->scheme_aliases ? mountable->scheme_aliases : empty,
+                        mountable->default_port,
+                        mountable->hostname_is_inet);
 }
 
 
@@ -326,13 +237,14 @@ vfs_mountable_to_dbus (VfsMountable *mountable,
 
 typedef struct {
   VfsMountable *mountable;
-  dbus_bool_t automount;
+  gboolean automount;
   GMountSource *source;
   GMountSpec *mount_spec;
   MountCallback callback;
   gpointer user_data;
   char *obj_path;
   gboolean spawned;
+  GVfsDBusSpawner *spawner;
 } MountData;
 
 static void spawn_mount (MountData *data);
@@ -343,7 +255,11 @@ mount_data_free (MountData *data)
   g_object_unref (data->source);
   g_mount_spec_unref (data->mount_spec);
   g_free (data->obj_path);
-  
+  if (data->spawner)
+    g_object_unref (data->spawner);
+
+  g_print ("mount_data_free\n");
+
   g_free (data);
 }
 
@@ -355,123 +271,116 @@ mount_finish (MountData *data, GError *error)
 }
 
 static void
-dbus_mount_reply (DBusPendingCall *pending,
-		  void            *_data)
+dbus_mount_reply (GVfsDBusMountable *proxy,
+                  GAsyncResult  *res,
+                  gpointer user_data)
 {
-  DBusMessage *reply;
-  GError *error;
-  MountData *data = _data;
-
-  reply = dbus_pending_call_steal_reply (pending);
-  dbus_pending_call_unref (pending);
+  GError *error = NULL;
+  MountData *data = user_data;
 
-  if ((dbus_message_is_error (reply, DBUS_ERROR_NAME_HAS_NO_OWNER) ||
-       dbus_message_is_error (reply, DBUS_ERROR_SERVICE_UNKNOWN)) &&
-      !data->spawned)
-    spawn_mount (data);
+  if (!gvfs_dbus_mountable_call_mount_finish (proxy,
+                                              res,
+                                              &error))
+    {
+      g_warning ("dbus_mount_reply: Error from org.gtk.vfs.Mountable.mount(): %s", error->message);
+      g_warning ("dbus_mount_reply: TODO handle not spawned");
+
+      /* FIXME: handle NOT_SPAWNED */
+#if 0
+      if ((dbus_message_is_error (reply, DBUS_ERROR_NAME_HAS_NO_OWNER) ||
+           dbus_message_is_error (reply, DBUS_ERROR_SERVICE_UNKNOWN)) &&
+          !data->spawned)
+        spawn_mount (data);
+#endif
+      
+      mount_finish (data, error);
+      g_error_free (error);
+    }
   else
     {
-      error = NULL;
-      if (_g_error_from_message (reply, &error))
-	{
-	  mount_finish (data, error);
-	  g_error_free (error);
-	}
-      else
-	mount_finish (data, NULL);
+      mount_finish (data, NULL);
     }
-  
-  dbus_message_unref (reply);
 }
 
 static void
-mountable_mount_with_name (MountData *data,
-			   const char *dbus_name)
+mountable_mount_proxy_cb (GObject *source_object,
+                          GAsyncResult *res,
+                          gpointer user_data)
 {
-  DBusConnection *conn;
-  DBusMessage *message;
-  DBusPendingCall *pending;
+  GVfsDBusMountable *proxy;
   GError *error = NULL;
-  DBusMessageIter iter;
-
-  conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-  message = dbus_message_new_method_call (dbus_name,
-					  G_VFS_DBUS_MOUNTABLE_PATH,
-					  G_VFS_DBUS_MOUNTABLE_INTERFACE,
-					  G_VFS_DBUS_MOUNTABLE_OP_MOUNT);
-
-  dbus_message_iter_init_append (message, &iter);
-  g_mount_spec_to_dbus (&iter, data->mount_spec);
-
-  _g_dbus_message_append_args (message,
-			       DBUS_TYPE_BOOLEAN, &data->automount,
-			       0);
-  
-  g_mount_source_to_dbus (data->source, message);
-  
-  if (!dbus_connection_send_with_reply (conn, message,
-					&pending,
-					G_VFS_DBUS_MOUNT_TIMEOUT_MSECS))
-    _g_dbus_oom ();
-  
-  dbus_message_unref (message);
-  dbus_connection_unref (conn);
+  MountData *data = user_data;
   
-  if (pending == NULL)
+  proxy = gvfs_dbus_mountable_proxy_new_for_bus_finish (res, &error);
+  g_print ("mountable_mount_proxy_cb: proxy = %p, error = %p\n", proxy, error);
+
+  if (proxy == NULL)
     {
-      g_set_error (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
-		   "Error while getting peer-to-peer dbus connection: %s",
-		   "Connection is closed");
+      g_printerr ("mountable_mount_proxy_cb: Error creating proxy: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
       mount_finish (data, error);
       g_error_free (error);
       return;
     }
+
+  g_dbus_proxy_set_default_timeout (G_DBUS_PROXY (proxy), 
+                                    G_VFS_DBUS_MOUNT_TIMEOUT_MSECS);
   
-  if (!dbus_pending_call_set_notify (pending,
-				     dbus_mount_reply,
-				     data, NULL))
-    _g_dbus_oom ();
+  g_print ("mountable_mount_with_name: before call_mount\n");
+  gvfs_dbus_mountable_call_mount (proxy,
+                                  g_mount_spec_to_dbus (data->mount_spec),
+                                  data->automount,
+                                  g_mount_source_to_dbus (data->source),
+                                  NULL,
+                                  (GAsyncReadyCallback) dbus_mount_reply, data);
+  g_print ("mountable_mount_with_name: after call_mount\n");
+
+  g_object_unref (proxy);
 }
 
-static DBusHandlerResult
-spawn_mount_message_function (DBusConnection  *connection,
-			      DBusMessage     *message,
-			      void            *user_data)
+static void
+mountable_mount_with_name (MountData *data,
+			   const char *dbus_name)
+{
+  g_print ("mountable_mount_with_name: dbus_name = '%s'\n", dbus_name);
+  
+  gvfs_dbus_mountable_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                         G_DBUS_PROXY_FLAGS_NONE,
+                                         dbus_name,
+                                         G_VFS_DBUS_MOUNTABLE_PATH,
+                                         NULL,
+                                         mountable_mount_proxy_cb,
+                                         data);
+}
+
+static gboolean
+spawn_mount_handle_spawned (GVfsDBusSpawner *object,
+                            GDBusMethodInvocation *invocation,
+                            gboolean arg_succeeded,
+                            const gchar *arg_error_message,
+                            gpointer user_data)
 {
   MountData *data = user_data;
-  GError *error = NULL;
-  dbus_bool_t succeeded;
-  char *error_message;
+  GError *error;
 
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_SPAWNER_INTERFACE,
-				   G_VFS_DBUS_OP_SPAWNED))
+  g_print ("called org.gtk.vfs.Spawner.spawned(), sender = '%s', succeeded = %d\n", g_dbus_method_invocation_get_sender (invocation), arg_succeeded);
+  
+  g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (data->spawner));
+  
+  if (!arg_succeeded)
     {
-      dbus_connection_unregister_object_path (connection, data->obj_path);
-
-      if (!dbus_message_get_args (message, NULL,
-				  DBUS_TYPE_BOOLEAN, &succeeded,
-				  DBUS_TYPE_STRING, &error_message,
-				  DBUS_TYPE_INVALID))
-	{
-	  g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED,
-			       _("Invalid arguments from spawned child"));
-	  mount_finish (data, error);
-	  g_error_free (error);
-	}
-      else if (!succeeded)
-	{
-	  g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, error_message);
-	  mount_finish (data, error);
-	  g_error_free (error);
-	}
-      else
-	mountable_mount_with_name (data, dbus_message_get_sender (message));
-      
-      return DBUS_HANDLER_RESULT_HANDLED;
+      g_set_error_literal (&error, G_IO_ERROR, G_IO_ERROR_FAILED, arg_error_message);
+      mount_finish (data, error);
+      g_error_free (error);
     }
-
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  else
+    {
+      mountable_mount_with_name (data, g_dbus_method_invocation_get_sender (invocation));
+    }
+  
+  gvfs_dbus_spawner_complete_spawned (object, invocation);
+  
+  return TRUE;
 }
 
 static void
@@ -479,12 +388,8 @@ spawn_mount (MountData *data)
 {
   char *exec;
   GError *error;
-  DBusConnection *connection;
+  GDBusConnection *connection;
   static int mount_id = 0;
-  DBusObjectPathVTable spawn_vtable = {
-    NULL,
-    spawn_mount_message_function
-  };
 
   data->spawned = TRUE;
   
@@ -500,25 +405,41 @@ spawn_mount (MountData *data)
     {
       data->obj_path = g_strdup_printf ("/org/gtk/gvfs/exec_spaw/%d", mount_id++);
 
-      connection = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-      if (!dbus_connection_register_object_path (connection,
-						 data->obj_path,
-						 &spawn_vtable,
-						 data))
-	_g_dbus_oom ();
+      connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+      if (! connection)
+        {
+          mount_finish (data, error);
+          g_error_free (error);
+          return;
+        }
       
-      exec = g_strconcat (data->mountable->exec, " --spawner ", dbus_bus_get_unique_name (connection), " ", data->obj_path, NULL);
-
+      data->spawner = gvfs_dbus_spawner_skeleton_new ();
+      g_signal_connect (data->spawner, "handle-spawned", G_CALLBACK (spawn_mount_handle_spawned), data);
+      
+      if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (data->spawner),
+                                             connection,
+                                             data->obj_path, 
+                                             &error))
+        {
+          mount_finish (data, error);
+          g_error_free (error);
+          g_object_unref (connection);
+          return;
+        }
+
+      exec = g_strconcat (data->mountable->exec, " --spawner ", g_dbus_connection_get_unique_name (connection), " ", data->obj_path, NULL);
       if (!g_spawn_command_line_async (exec, &error))
 	{
-	  dbus_connection_unregister_object_path (connection, data->obj_path);
+          g_print ("spawning failed.\n");
+          g_dbus_interface_skeleton_unexport (G_DBUS_INTERFACE_SKELETON (data->spawner));
 	  mount_finish (data, error);
 	  g_error_free (error);
 	}
+      g_print ("spawn okay.\n");
       
       /* TODO: Add a timeout here to detect spawned app crashing */
       
-      dbus_connection_unref (connection);
+      g_object_unref (connection);
       g_free (exec);
     }
 }
@@ -618,31 +539,52 @@ re_read_mountable_config (void)
  * Support for keeping track of active mounts                           *
  ************************************************************************/
 
+typedef struct
+{
+  GVariant *mount;
+  gboolean mounted;
+} SignalMountedData;
+
+static void
+mount_tracker_proxy_cb (GObject *source_object,
+                        GAsyncResult *res,
+                        gpointer user_data)
+{
+  GVfsDBusMountTracker *proxy;
+  SignalMountedData *data = user_data;
+  
+  proxy = gvfs_dbus_mount_tracker_proxy_new_for_bus_finish (res, NULL);
+  g_print ("mount_tracker_proxy_cb: signalling %s, proxy = %p\n", data->mounted ? "mount" : "umount", proxy);
+
+  if (proxy != NULL)
+    {
+      if (data->mounted)
+        gvfs_dbus_mount_tracker_emit_mounted (proxy, data->mount);
+      else
+        gvfs_dbus_mount_tracker_emit_unmounted (proxy, data->mount);
+      
+      g_object_unref (proxy);
+      g_free (data);
+    }
+}
+
 static void
 signal_mounted_unmounted (VfsMount *mount,
 			  gboolean mounted)
 {
-  DBusMessage *message;
-  DBusMessageIter iter;
-  DBusConnection *conn;
-
-  message = dbus_message_new_signal (G_VFS_DBUS_MOUNTTRACKER_PATH,
-				     G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				     mounted ?
-				     G_VFS_DBUS_MOUNTTRACKER_SIGNAL_MOUNTED :
-				     G_VFS_DBUS_MOUNTTRACKER_SIGNAL_UNMOUNTED
-				     );
-  if (message == NULL)
-    _g_dbus_oom ();
-
-  dbus_message_iter_init_append (message, &iter);
-  vfs_mount_to_dbus (mount, &iter);
-
-  conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-  dbus_connection_send (conn, message, NULL);
-  dbus_connection_unref (conn);
+  SignalMountedData *data;
+
+  data = g_new0 (SignalMountedData, 1);
+  data->mount = vfs_mount_to_dbus (mount);
+  data->mounted = mounted;
   
-  dbus_message_unref (message);
+  gvfs_dbus_mount_tracker_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                             G_DBUS_PROXY_FLAGS_NONE,
+                                             G_VFS_DBUS_DAEMON_NAME,
+                                             G_VFS_DBUS_MOUNTTRACKER_PATH,
+                                             NULL,
+                                             mount_tracker_proxy_cb,
+                                             data);
 }
 
 static void
@@ -667,100 +609,107 @@ dbus_client_disconnected (const char *dbus_id)
 }
 
 static void
-register_mount (DBusConnection *connection,
-		DBusMessage *message)
+name_vanished_cb (GDBusConnection *connection,
+                  const gchar *name,
+                  gpointer user_data)
+{
+  g_print ("name_vanished_cb: name = '%s'\n", name);
+  
+  dbus_client_disconnected (name);
+}
+
+static gboolean
+handle_register_mount (GVfsDBusMountTracker *object,
+                       GDBusMethodInvocation *invocation,
+                       const gchar *arg_obj_path,
+                       const gchar *arg_display_name,
+                       const gchar *arg_stable_name,
+                       const gchar *arg_x_content_types,
+                       const gchar *arg_icon,
+                       const gchar *arg_prefered_filename_encoding,
+                       gboolean arg_user_visible,
+                       GVariant *arg_mount_spec,
+                       const gchar *arg_default_location,
+                       gpointer user_data)
 {
   VfsMount *mount;
-  DBusMessage *reply;
-  DBusError error;
-  const char *display_name, *stable_name, *x_content_types, *icon, *obj_path;
-  const char *id, *prefered_filename_encoding;
-  char *default_location;
-  dbus_bool_t user_visible;
-  DBusMessageIter iter;
+  const char *id;
   GMountSpec *mount_spec;
 
-  id = dbus_message_get_sender (message);
-
-  dbus_message_iter_init (message, &iter);
-
-  dbus_error_init (&error);
-  if (_g_dbus_message_iter_get_args (&iter,
-				     &error,
-				     DBUS_TYPE_OBJECT_PATH, &obj_path,
-				     DBUS_TYPE_STRING, &display_name,
-                                     DBUS_TYPE_STRING, &stable_name,
-                                     DBUS_TYPE_STRING, &x_content_types,
-				     DBUS_TYPE_STRING, &icon,
-				     DBUS_TYPE_STRING, &prefered_filename_encoding,
-				     DBUS_TYPE_BOOLEAN, &user_visible,
-				     0))
+  g_print ("called handle_register_mount()\n");
+
+  id = g_dbus_method_invocation_get_sender (invocation);
+
+  if (find_vfs_mount (id, arg_obj_path) != NULL) {
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_ALREADY_MOUNTED,
+                                                   "Mountpoint Already registered");
+  }
+  else if ((mount_spec = g_mount_spec_from_dbus (arg_mount_spec)) == NULL) {
+    g_dbus_method_invocation_return_error_literal (invocation, 
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_INVALID_ARGUMENT,
+                                                   "Error in mount spec");
+  }
+  else if (match_vfs_mount (mount_spec) != NULL) {
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_ALREADY_MOUNTED,
+                                                   "Mountpoint Already registered");
+  }
+  else
     {
-      if (find_vfs_mount (id, obj_path) != NULL)
-	reply = dbus_message_new_error (message,
-					DBUS_ERROR_INVALID_ARGS,
-					"Mountpoint Already registered");
-      else if ((mount_spec = g_mount_spec_from_dbus (&iter)) == NULL)
-	reply = dbus_message_new_error (message,
-					DBUS_ERROR_INVALID_ARGS,
-                                        "Error in mount spec");
-      else if (match_vfs_mount (mount_spec) != NULL)
-	reply = dbus_message_new_error (message,
-					DBUS_ERROR_INVALID_ARGS,
-					"Mountpoint Already registered");
+      mount = g_new0 (VfsMount, 1);
+      mount->display_name = g_strdup (arg_display_name);
+      mount->stable_name = g_strdup (arg_stable_name);
+      mount->x_content_types = g_strdup (arg_x_content_types);
+      mount->icon = g_strdup (arg_icon);
+      mount->prefered_filename_encoding = g_strdup (arg_prefered_filename_encoding);
+      mount->user_visible = arg_user_visible;
+      mount->dbus_id = g_strdup (id);
+      mount->object_path = g_strdup (arg_obj_path);
+      mount->mount_spec = mount_spec;
+
+      if (arg_default_location)  
+        mount->default_location = g_strdup (arg_default_location);
       else
-	{
-	  mount = g_new0 (VfsMount, 1);
-	  mount->display_name = g_strdup (display_name);
-          mount->stable_name = g_strdup (stable_name);
-          mount->x_content_types = g_strdup (x_content_types);
-	  mount->icon = g_strdup (icon);
-	  mount->prefered_filename_encoding = g_strdup (prefered_filename_encoding);
-	  mount->user_visible = user_visible;
-	  mount->dbus_id = g_strdup (id);
-	  mount->object_path = g_strdup (obj_path);
-	  mount->mount_spec = mount_spec;
-
-	  if (_g_dbus_message_iter_get_args (&iter, NULL,
-					     G_DBUS_TYPE_CSTRING, &default_location,
-					     0))
-	    mount->default_location = default_location;
-	  else
-	    mount->default_location = g_strdup ("");
-
-	  if (user_visible)
-	    {
-	      char *fs_name;
-	      
-	      /* Keep in sync with fuse daemon */
-	      fs_name = g_uri_escape_string (mount->stable_name, "+ #$ , ", TRUE);
-	      
-	      /* Use the old .gvfs location as fallback, not .cache/gvfs */
-	      if (g_get_user_runtime_dir() == g_get_user_cache_dir ())
-		mount->fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL);
-	      else
-		mount->fuse_mountpoint = g_build_filename (g_get_user_runtime_dir(), "gvfs", fs_name, NULL);
-	    }
-	  
-	  mounts = g_list_prepend (mounts, mount);
-
-	  signal_mounted_unmounted (mount, TRUE);
+        mount->default_location = g_strdup ("");
+
+      if (arg_user_visible)
+        {
+          char *fs_name;
+          
+          /* Keep in sync with fuse daemon */
+          fs_name = g_uri_escape_string (mount->stable_name, "+ #$ , ", TRUE);
+          
+          /* Use the old .gvfs location as fallback, not .cache/gvfs */
+          if (g_get_user_runtime_dir() == g_get_user_cache_dir ())
+            mount->fuse_mountpoint = g_build_filename (g_get_home_dir(), ".gvfs", fs_name, NULL);
+          else
+            mount->fuse_mountpoint = g_build_filename (g_get_user_runtime_dir(), "gvfs", fs_name, NULL);
+        }
+      
+      mounts = g_list_prepend (mounts, mount);
 
-	  reply = dbus_message_new_method_return (message);
-	}
-    }
-  else
-    {
-      reply = dbus_message_new_error (message,
-				      error.name, error.message);
-      dbus_error_free (&error);
+      g_print ("handle_register_mount: dbus_id = '%s'\n", id);
+      
+      /* watch the mount for being disconnected */
+      mount->name_watcher_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                                 id,
+                                                 G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                                 NULL,
+                                                 name_vanished_cb,
+                                                 NULL,
+                                                 NULL); 
+
+      signal_mounted_unmounted (mount, TRUE);
+
+      g_print ("handle_register_mount: calling complete\n");
+      gvfs_dbus_mount_tracker_complete_register_mount (object, invocation);
     }
   
-  if (reply == NULL)
-    _g_dbus_oom ();
-  
-  dbus_connection_send (connection, reply, NULL);
-  dbus_message_unref (reply);
+  return TRUE;
 }
 
 typedef struct {
@@ -773,39 +722,34 @@ automount_done (VfsMountable *mountable,
 		GError *error,
 		gpointer _data)
 {
-  DBusMessage *reply;
   AutoMountData *data = _data;
   
   if (error)
-    {
-      reply = _dbus_message_new_gerror (data->message,
-					G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
-					_("Automount failed: %s"), error->message);
-      dbus_connection_send (data->connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
+    g_dbus_method_invocation_return_error (data->invocation,
+                                           G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
+                                           _("Automount failed: %s"), error->message);
   else
-    lookup_mount (data->connection,
-		  data->message,
-		  FALSE);
-
-  dbus_connection_unref (data->connection);
-  dbus_message_unref (data->message);
+    lookup_mount (data->object,
+                  data->invocation,
+                  data->spec,
+                  FALSE);
+
+  g_object_unref (data->object);
+  g_object_unref (data->invocation);
+  g_mount_spec_unref (data->spec);
   g_free (data);
 }
 
-static DBusMessage *
+static void
 maybe_automount (GMountSpec *spec,
-		 DBusMessage *message,
-		 DBusConnection *connection,
-		 gboolean do_automount)
+                 GVfsDBusMountTracker *object,
+                 GDBusMethodInvocation *invocation,
+                 gboolean do_automount)
 {
   VfsMountable *mountable;
-  DBusMessage *reply;
 
   mountable = lookup_mountable (spec);
 
-  reply = NULL;
   if (mountable != NULL && do_automount && mountable->automount)
     {
       AutoMountData *data;
@@ -816,163 +760,109 @@ maybe_automount (GMountSpec *spec,
       mount_source = g_mount_source_new_dummy ();
 
       data = g_new0 (AutoMountData, 1);
-      data->message = dbus_message_ref (message);
-      data->connection = dbus_connection_ref (connection);
+      data->object = g_object_ref (object);
+      data->invocation = g_object_ref (invocation);
+      data->spec = g_mount_spec_ref (spec);
       
       mountable_mount (mountable, spec, mount_source, TRUE, automount_done, data);
       g_object_unref (mount_source);
     }
   else if (mountable != NULL)
-    reply = _dbus_message_new_gerror (message,
-				      G_IO_ERROR,
-				      G_IO_ERROR_NOT_MOUNTED,
-				      _("The specified location is not mounted"));
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_NOT_MOUNTED,
+                                                   _("The specified location is not mounted"));
   else
-    reply = _dbus_message_new_gerror (message,
-				      G_IO_ERROR,
-				      G_IO_ERROR_NOT_SUPPORTED,
-				      _("The specified location is not supported"));
-  
-  return reply;
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_NOT_SUPPORTED,
+                                                   _("The specified location is not supported"));
 }
 
 static void
-lookup_mount (DBusConnection *connection,
-	      DBusMessage *message,
-	      gboolean do_automount)
+lookup_mount (GVfsDBusMountTracker *object,
+              GDBusMethodInvocation *invocation,
+              GMountSpec *spec,
+              gboolean do_automount)
 {
   VfsMount *mount;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  GMountSpec *spec;
 
-  dbus_message_iter_init (message, &iter);
-  spec = g_mount_spec_from_dbus (&iter);
+  mount = match_vfs_mount (spec);
+  if (mount == NULL)
+    maybe_automount (spec, object, invocation, do_automount);
+  else
+    gvfs_dbus_mount_tracker_complete_lookup_mount (object, invocation,
+                                                   vfs_mount_to_dbus (mount)); 
+}
 
-  reply = NULL;
-  if (spec != NULL)
-    {
-      mount = match_vfs_mount (spec);
+static gboolean 
+handle_lookup_mount (GVfsDBusMountTracker *object,
+                     GDBusMethodInvocation *invocation,
+                     GVariant *arg_mount_spec,
+                     gpointer user_data)
+{
+  GMountSpec *spec;
 
-      if (mount == NULL)
-	reply = maybe_automount (spec, message, connection, do_automount);
-      else
-	{
-	  reply = dbus_message_new_method_return (message);
+  g_print ("called lookup_mount(), sender = '%s', obj_path = '%s'\n", g_dbus_method_invocation_get_sender (invocation), g_dbus_method_invocation_get_object_path (invocation));
 
-	  if (reply)
-	    {
-	      dbus_message_iter_init_append (reply, &iter);
-
-	      vfs_mount_to_dbus (mount, &iter);
-	    }
-	}
+  spec = g_mount_spec_from_dbus (arg_mount_spec);
 
+  if (spec != NULL)
+    {
+      lookup_mount (object, invocation, spec, TRUE);
       g_mount_spec_unref (spec);
     }
   else
-    reply = dbus_message_new_error (message,
-				    DBUS_ERROR_INVALID_ARGS,
-				    "Invalid arguments");
-  
-  if (reply != NULL)
-    {
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_INVALID_ARGUMENT,
+                                                   "Invalid arguments");
+  return TRUE;
 }
 
-static void
-lookup_mount_by_fuse_path (DBusConnection *connection,
-			   DBusMessage *message)
+static gboolean
+handle_lookup_mount_by_fuse_path (GVfsDBusMountTracker *object,
+                                  GDBusMethodInvocation *invocation,
+                                  const gchar *arg_fuse_path,
+                                  gpointer user_data)
 {
   VfsMount *mount;
-  DBusMessage *reply;
-  DBusMessageIter iter;
-  char *fuse_path;
 
-  dbus_message_iter_init (message, &iter);
+  g_print ("called lookup_mount_by_fuse_path()\n");
 
-  reply = NULL;
-  if (_g_dbus_message_iter_get_args (&iter, NULL, 
-				     G_DBUS_TYPE_CSTRING, &fuse_path,
-				     0))
-    {
-      mount = find_vfs_mount_by_fuse_path (fuse_path);
+  mount = find_vfs_mount_by_fuse_path (arg_fuse_path);
 
-      if (mount == NULL)
-	reply = _dbus_message_new_gerror (message,
-					  G_IO_ERROR,
-					  G_IO_ERROR_NOT_MOUNTED,
-					  _("The specified location is not mounted"));
-      else
-	{
-	  reply = dbus_message_new_method_return (message);
-	  if (reply)
-	    {
-	      dbus_message_iter_init_append (reply, &iter);
-	      vfs_mount_to_dbus (mount, &iter);
-	    }
-	}
-    }
+  if (mount == NULL)
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_NOT_MOUNTED,
+                                                   _("The specified location is not mounted"));
   else
-    reply = dbus_message_new_error (message,
-				    DBUS_ERROR_INVALID_ARGS,
-				    "Invalid arguments");
-
-  if (reply != NULL)
-    {
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
+    gvfs_dbus_mount_tracker_complete_lookup_mount_by_fuse_path (object,
+                                                                invocation,
+                                                                vfs_mount_to_dbus (mount));
+  
+  return TRUE;
 }
 
-static void
-list_mounts (DBusConnection *connection,
-	     DBusMessage *message)
+static gboolean
+handle_list_mounts (GVfsDBusMountTracker *object,
+                    GDBusMethodInvocation *invocation,
+                    gpointer user_data)
 {
-  VfsMount *mount;
-  DBusMessage *reply;
-  DBusMessageIter iter, array_iter;
   GList *l;
+  GVariantBuilder mounts_array;
 
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
-
-  dbus_message_iter_init_append (reply, &iter);
-
-
-  if (!dbus_message_iter_open_container (&iter,
-					 DBUS_TYPE_ARRAY,
-					 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING
-					   DBUS_TYPE_OBJECT_PATH_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING
-					   DBUS_TYPE_BOOLEAN_AS_STRING
-					   DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
- 					   G_MOUNT_SPEC_TYPE_AS_STRING
-					   DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING
-					 DBUS_STRUCT_END_CHAR_AS_STRING,
-					 &array_iter))
-    _g_dbus_oom ();
+  g_print ("called list_mounts()\n");
 
+  g_variant_builder_init (&mounts_array, G_VARIANT_TYPE (VFS_MOUNT_ARRAY_DBUS_STRUCT_TYPE));
   for (l = mounts; l != NULL; l = l->next)
-    {
-      mount = l->data;
-
-      vfs_mount_to_dbus (mount, &array_iter);
-    }
-
-  if (!dbus_message_iter_close_container (&iter, &array_iter))
-    _g_dbus_oom ();
-
-  dbus_connection_send (connection, reply, NULL);
-  dbus_message_unref (reply);
+    g_variant_builder_add_value (&mounts_array, vfs_mount_to_dbus (l->data));
+  
+  gvfs_dbus_mount_tracker_complete_list_mounts (object, invocation,
+                                                g_variant_builder_end (&mounts_array));
+  
+  return TRUE;
 }
 
 static void
@@ -980,263 +870,133 @@ mount_location_done  (VfsMountable *mountable,
 		      GError *error,
 		      gpointer user_data)
 {
-  DBusMessage *message, *reply;
-  DBusConnection *conn;
-
-  message = user_data;
+  GDBusMethodInvocation *invocation = user_data;
   
   if (error)
-    reply = _dbus_message_new_from_gerror (message, error);
+    g_dbus_method_invocation_return_gerror (invocation, error);
   else
-    reply = dbus_message_new_method_return (message);
-
-  dbus_message_unref (message);
+    /* alas gvfs_dbus_mount_tracker_complete_mount_location() */
+    g_dbus_method_invocation_return_value (invocation, g_variant_new ("()"));
 
-  if (reply == NULL)
-    _g_dbus_oom ();
-    
-  conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-  if (conn)
-    {
-      dbus_connection_send (conn, reply, NULL);
-      dbus_connection_unref (conn);
-    }
-  
-  dbus_message_unref (reply);
+  g_object_unref (invocation);
 }
 
-static void
-mount_location (DBusConnection *connection,
-		DBusMessage *message)
+static gboolean 
+handle_mount_location (GVfsDBusMountTracker *object,
+                       GDBusMethodInvocation *invocation,
+                       GVariant *arg_mount_spec,
+                       GVariant *arg_mount_source,
+                       gpointer user_data)
 {
-  DBusMessageIter iter;
-  DBusMessage *reply;
-  DBusError derror;
   GMountSpec *spec;
-  const char *obj_path, *dbus_id;
   VfsMountable *mountable;
-  
-  dbus_message_iter_init (message, &iter);
 
-  mountable = NULL;
-  spec = NULL;
-  reply = NULL;
+  g_print ("called mount_location()\n");
 
-  spec = g_mount_spec_from_dbus (&iter);
+  spec = g_mount_spec_from_dbus (arg_mount_spec);
   if (spec == NULL)
-    reply = dbus_message_new_error (message, DBUS_ERROR_INVALID_ARGS,
-				    "Invalid arguments");
+    g_dbus_method_invocation_return_error_literal (invocation,
+                                                   G_IO_ERROR,
+                                                   G_IO_ERROR_INVALID_ARGUMENT,
+                                                   "Invalid arguments");
   else
     {
-      dbus_error_init (&derror);
-      if (!_g_dbus_message_iter_get_args (&iter,
-					  &derror,
-					  DBUS_TYPE_STRING, &dbus_id,
-					  DBUS_TYPE_OBJECT_PATH, &obj_path,
-					  0))
-	{
-	  reply = dbus_message_new_error (message, derror.name, derror.message);
-	  dbus_error_free (&derror);
-	}
+      VfsMount *mount;
+      mount = match_vfs_mount (spec);
+      
+      if (mount != NULL)
+        g_dbus_method_invocation_return_error_literal (invocation,
+                                                       G_IO_ERROR,
+                                                       G_IO_ERROR_ALREADY_MOUNTED,
+                                                       _("Location is already mounted"));
       else
-	{
-	  VfsMount *mount;
-	  mount = match_vfs_mount (spec);
-	  
-	  if (mount != NULL)
-	    reply = _dbus_message_new_gerror (message,
-					      G_IO_ERROR, G_IO_ERROR_ALREADY_MOUNTED,
-					      _("Location is already mounted"));
-	  else
-	    {
-	      mountable = lookup_mountable (spec);
-	      
-	      if (mountable == NULL)
-		reply = _dbus_message_new_gerror (message,
-						  G_IO_ERROR, G_IO_ERROR_NOT_MOUNTED,
-						  _("Location is not mountable"));
-	    }
-	}
+        {
+          mountable = lookup_mountable (spec);
+          
+          if (mountable == NULL)
+            g_dbus_method_invocation_return_error_literal (invocation,
+                                                           G_IO_ERROR,
+                                                           G_IO_ERROR_NOT_MOUNTED,
+                                                           _("Location is not mountable"));
+          else
+            {
+              GMountSource *source;
+
+              source = g_mount_source_from_dbus (arg_mount_source);
+              mountable_mount (mountable,
+                               spec,
+                               source,
+                               FALSE,
+                               mount_location_done, g_object_ref (invocation));
+              g_object_unref (source);
+            }
+        }
     }
   
-  if (reply)
-    {
-      dbus_connection_send (connection, reply, NULL);
-      dbus_message_unref (reply);
-    }
-  else
-    {
-      GMountSource *source;
-
-      source = g_mount_source_new (dbus_id, obj_path);
-      mountable_mount (mountable,
-		       spec,
-		       source,
-		       FALSE,
-		       mount_location_done, dbus_message_ref (message));
-      g_object_unref (source);
-    }
-
   if (spec)
     g_mount_spec_unref (spec);
-  
+
+  return TRUE;
 }
 
-static void
-list_mount_types (DBusConnection *connection,
-		  DBusMessage *message)
+static gboolean
+handle_list_mount_types (GVfsDBusMountTracker *object,
+                         GDBusMethodInvocation *invocation,
+                         gpointer user_data)
 {
   VfsMountable *mountable;
-  DBusMessage *reply;
-  DBusMessageIter iter, array_iter;
+  GPtrArray *types;
   GList *l;
 
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
-
-  dbus_message_iter_init_append (reply, &iter);
-
-  
-  if (!dbus_message_iter_open_container (&iter,
-					 DBUS_TYPE_ARRAY,
-					 DBUS_TYPE_STRING_AS_STRING,
-					 &array_iter))
-    _g_dbus_oom ();
+  g_print ("called list_mount_types()\n");
 
+  types = g_ptr_array_new ();
   for (l = mountables; l != NULL; l = l->next)
     {
       mountable = l->data;
-      if (!dbus_message_iter_append_basic (&array_iter,
-            DBUS_TYPE_STRING,
-	    &mountable->type))
-        _g_dbus_oom ();
+      g_ptr_array_add (types, (gpointer) mountable->type);
     }
+  g_ptr_array_add (types, NULL);
 
-  if (!dbus_message_iter_close_container (&iter, &array_iter))
-    _g_dbus_oom ();
+  gvfs_dbus_mount_tracker_complete_list_mount_types (object, invocation,
+                                                     (const gchar *const *) types->pdata);
 
-  dbus_connection_send (connection, reply, NULL);
-  dbus_message_unref (reply);
+  g_ptr_array_free (types, TRUE);
+  return TRUE;
 }
 
-static void
-list_mountable_info (DBusConnection *connection,
-		     DBusMessage *message)
+static gboolean
+handle_list_mountable_info (GVfsDBusMountTracker *object,
+                            GDBusMethodInvocation *invocation,
+                            gpointer user_data)
 {
-  VfsMountable *mountable;
-  DBusMessage *reply;
-  DBusMessageIter iter, array_iter;
   GList *l;
-
-  reply = dbus_message_new_method_return (message);
-  if (reply == NULL)
-    _g_dbus_oom ();
-
-  dbus_message_iter_init_append (reply, &iter);
-
+  GVariantBuilder mountables_array;
   
-  if (!dbus_message_iter_open_container (&iter,
-					 DBUS_TYPE_ARRAY,
-					 DBUS_STRUCT_BEGIN_CHAR_AS_STRING
-					   DBUS_TYPE_STRING_AS_STRING /* type */
-					   DBUS_TYPE_STRING_AS_STRING /* scheme */
-					   DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING /* scheme aliases */
-					   DBUS_TYPE_INT32_AS_STRING /* default port */
-					   DBUS_TYPE_BOOLEAN_AS_STRING /* host is inet */
-					 DBUS_STRUCT_END_CHAR_AS_STRING,
-					 &array_iter))
-    _g_dbus_oom ();
-
-  for (l = mountables; l != NULL; l = l->next)
-    {
-      mountable = l->data;
-      
-      vfs_mountable_to_dbus (mountable, &array_iter);
-    }
-
-  if (!dbus_message_iter_close_container (&iter, &array_iter))
-    _g_dbus_oom ();
-
-  dbus_connection_send (connection, reply, NULL);
-  dbus_message_unref (reply);
-}
-
-static DBusHandlerResult
-dbus_message_function (DBusConnection  *connection,
-		       DBusMessage     *message,
-		       void            *user_data)
-{
-  DBusHandlerResult res;
+  g_print ("called list_mountable_info()\n");
   
-  res = DBUS_HANDLER_RESULT_HANDLED;
-  if (dbus_message_is_method_call (message,
-				   G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-				   G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_FUSE))
-    fuse_available = TRUE;
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_REGISTER_MOUNT))
-    register_mount (connection, message);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT))
-    lookup_mount (connection, message, TRUE);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_LOOKUP_MOUNT_BY_FUSE_PATH))
-    lookup_mount_by_fuse_path (connection, message);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTS))
-    list_mounts (connection, message);
-  else if (dbus_message_is_method_call (message,
-					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_MOUNT_LOCATION))
-    mount_location (connection, message);
-  else if (dbus_message_is_method_call (message,
-  					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNT_TYPES))
-    list_mount_types (connection, message);
-  else if (dbus_message_is_method_call (message,
-  					G_VFS_DBUS_MOUNTTRACKER_INTERFACE,
-					G_VFS_DBUS_MOUNTTRACKER_OP_LIST_MOUNTABLE_INFO))
-    list_mountable_info (connection, message);
-  else
-    res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  g_variant_builder_init (&mountables_array, G_VARIANT_TYPE (VFS_MOUNTABLE_ARRAY_DBUS_STRUCT_TYPE));
+  for (l = mountables; l != NULL; l = l->next) {
+    g_variant_builder_add_value (&mountables_array, vfs_mountable_to_dbus (l->data));
+  }
   
-  return res;
+  gvfs_dbus_mount_tracker_complete_list_mountable_info (object, invocation,
+                                                        g_variant_builder_end (&mountables_array));
+  
+  return TRUE;
 }
 
-static struct DBusObjectPathVTable tracker_dbus_vtable = {
-  NULL,
-  dbus_message_function
-};
-
-
-static DBusHandlerResult
-mount_tracker_filter_func (DBusConnection *conn,
-			   DBusMessage    *message,
-			   gpointer        data)
+static gboolean 
+handle_register_fuse (GVfsDBusMountTracker *object,
+                      GDBusMethodInvocation *invocation,
+                      gpointer user_data)
 {
-  const char *name, *from, *to;
-
-  if (dbus_message_is_signal (message,
-			      DBUS_INTERFACE_DBUS,
-			      "NameOwnerChanged"))
-    {
-      if (dbus_message_get_args (message, NULL,
-				 DBUS_TYPE_STRING, &name,
-				 DBUS_TYPE_STRING, &from,
-				 DBUS_TYPE_STRING, &to,
-				 DBUS_TYPE_INVALID))
-	{
-	  if (*name == ':' &&  *to == 0)
-	    dbus_client_disconnected (name);
-	}
-      
-    }
-  return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+  g_print ("called register_fuse()\n");
+  
+  fuse_available = TRUE;
+  gvfs_dbus_mount_tracker_complete_register_fuse (object, invocation);
+  
+  return TRUE;
 }
 
 
@@ -1267,10 +1027,11 @@ reload_pipes_cb (GIOChannel *io,
 void
 mount_init (void)
 {
-  DBusConnection *conn;
-  DBusError error;
+  GDBusConnection *conn;
   struct sigaction sa;
   GIOChannel *io;
+  GVfsDBusMountTracker *mount_tracker;
+  GError *error;
   
   read_mountable_config ();
 
@@ -1285,27 +1046,39 @@ mount_init (void)
       sigaction (SIGUSR1, &sa, NULL);
     }
   
-  conn = dbus_bus_get (DBUS_BUS_SESSION, NULL);
-
-  if (!dbus_connection_register_object_path (conn, G_VFS_DBUS_MOUNTTRACKER_PATH,
-					     &tracker_dbus_vtable, NULL))
-    _g_dbus_oom ();
-
-  if (!dbus_connection_add_filter (conn,
-				   mount_tracker_filter_func, NULL, NULL))
-    _g_dbus_oom ();
   
+  error = NULL;
+  conn = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
+  if (! conn)
+    {
+      g_warning ("Error connecting to session bus: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      return;  /* FIXME: gracefully return */
+    }
+  
+  mount_tracker = gvfs_dbus_mount_tracker_skeleton_new ();
+
+  g_signal_connect (mount_tracker, "handle-register-fuse", G_CALLBACK (handle_register_fuse), NULL);
+  g_signal_connect (mount_tracker, "handle-register-mount", G_CALLBACK (handle_register_mount), NULL);
+  g_signal_connect (mount_tracker, "handle-mount-location", G_CALLBACK (handle_mount_location), NULL);
+  g_signal_connect (mount_tracker, "handle-lookup-mount", G_CALLBACK (handle_lookup_mount), NULL);
+  g_signal_connect (mount_tracker, "handle-lookup-mount-by-fuse-path", G_CALLBACK (handle_lookup_mount_by_fuse_path), NULL);
+  g_signal_connect (mount_tracker, "handle-list-mounts", G_CALLBACK (handle_list_mounts), NULL);
+  g_signal_connect (mount_tracker, "handle-list-mountable-info", G_CALLBACK (handle_list_mountable_info), NULL);
+  g_signal_connect (mount_tracker, "handle-list-mount-types", G_CALLBACK (handle_list_mount_types), NULL);
   
-  dbus_error_init (&error);
-  dbus_bus_add_match (conn,
-		      "sender='org.freedesktop.DBus',"
-		      "interface='org.freedesktop.DBus',"
-		      "member='NameOwnerChanged'",
-		      &error);
-  if (dbus_error_is_set (&error))
+  error = NULL;
+  if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (mount_tracker), conn,
+                                         G_VFS_DBUS_MOUNTTRACKER_PATH, &error))
     {
-      g_warning ("Failed to add dbus match: %s\n", error.message);
-      dbus_error_free (&error);
+      g_warning ("Error exporting mount tracker: %s (%s, %d)\n",
+                  error->message, g_quark_to_string (error->domain), error->code);
+      g_error_free (error);
+      g_object_unref (mount_tracker);
     }
+  g_object_unref (conn);
+  
+  /* TODO: keep reference for 'mount_tracker' */
 }
 



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