[gvfs/wip/goa: 4/4] Add GVfsGoaVolumeMonitor



commit e1ce5bf5a564f86ec87ec1ae1c0294a6cb509e27
Author: Debarshi Ray <debarshir gnome org>
Date:   Tue Oct 23 21:46:33 2012 +0200

    Add GVfsGoaVolumeMonitor
    
    https://bugzilla.gnome.org/show_bug.cgi?id=686526

 configure.ac                                       |   24 +
 monitor/Makefile.am                                |    6 +-
 monitor/goa/Makefile.am                            |   46 ++
 monitor/goa/goa.monitor                            |    4 +
 monitor/goa/goavolume.c                            |  556 ++++++++++++++++++++
 monitor/goa/goavolume.h                            |   66 +++
 monitor/goa/goavolumemonitor.c                     |  460 ++++++++++++++++
 monitor/goa/goavolumemonitor.h                     |   63 +++
 monitor/goa/goavolumemonitordaemon.c               |   49 ++
 .../org.gtk.Private.GoaVolumeMonitor.service.in    |    3 +
 10 files changed, 1276 insertions(+), 1 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 98f2ebc..612bfad 100644
--- a/configure.ac
+++ b/configure.ac
@@ -378,6 +378,28 @@ AC_SUBST(AFC_CFLAGS)
 
 AM_CONDITIONAL(USE_AFC, [test "$msg_afc" = "yes"])
 
+dnl *************************************************
+dnl *** Check if we should build with GOA backend ***
+dnl *************************************************
+AC_ARG_ENABLE(goa, AS_HELP_STRING([--disable-goa],[build without GOA backend]))
+msg_goa=no
+GOA_LIBS=
+GOA_CFLAGS=
+
+if test "x$enable_goa" != "xno" ; then
+  PKG_CHECK_EXISTS(goa-1.0 >= 3.7.1, msg_goa=yes)
+
+  if test "x$msg_goa" = "xyes"; then
+    PKG_CHECK_MODULES(GOA, goa-1.0)
+    AC_DEFINE(HAVE_GOA, 1, [Define to 1 if GOA is going to be built])
+  fi
+fi
+
+AC_SUBST(GOA_LIBS)
+AC_SUBST(GOA_CFLAGS)
+
+AM_CONDITIONAL(USE_GOA, [test "$msg_goa" = "yes"])
+
 dnl *****************************************************
 dnl *** Check if we should build with obexftp backend ***
 dnl *****************************************************
@@ -869,6 +891,7 @@ monitor/udisks2/Makefile
 monitor/gphoto2/Makefile
 monitor/afc/Makefile
 monitor/mtp/Makefile
+monitor/goa/Makefile
 programs/Makefile
 man/Makefile
 test/Makefile
@@ -898,6 +921,7 @@ echo "
 	Build HAL volume monitor:     $msg_hal (with fast init path: $have_hal_fast_init)
 	Build GDU volume monitor:     $msg_gdu
 	Build udisks2 volume monitor: $msg_udisks2
+	Build GOA volume monitor:     $msg_goa
         Use libsystemd-login:         $msg_libsystemd_login
 	GNOME Keyring support:        $msg_keyring
 	GTK+ support:                 $msg_gtk
diff --git a/monitor/Makefile.am b/monitor/Makefile.am
index 7a4e87f..f7cf7a2 100644
--- a/monitor/Makefile.am
+++ b/monitor/Makefile.am
@@ -1,4 +1,4 @@
-DIST_SUBDIRS = proxy hal gdu gphoto2 afc udisks2 mtp
+DIST_SUBDIRS = proxy hal gdu gphoto2 afc udisks2 mtp goa
 SUBDIRS = proxy
 
 if USE_HAL
@@ -24,3 +24,7 @@ endif
 if USE_LIBMTP
 SUBDIRS += mtp
 endif
+
+if USE_GOA
+SUBDIRS += goa
+endif
diff --git a/monitor/goa/Makefile.am b/monitor/goa/Makefile.am
new file mode 100644
index 0000000..e8ef564
--- /dev/null
+++ b/monitor/goa/Makefile.am
@@ -0,0 +1,46 @@
+NULL =
+
+gvfs_src_dir = $(top_srcdir)/@with_gvfs_source@
+
+libexec_PROGRAMS = gvfs-goa-volume-monitor
+
+gvfs_goa_volume_monitor_SOURCES = \
+	goavolume.c 		goavolume.h \
+	goavolumemonitor.c 	goavolumemonitor.h \
+	goavolumemonitordaemon.c \
+	$(NULL)
+
+gvfs_goa_volume_monitor_CFLAGS = \
+	-DG_LOG_DOMAIN=\"GVFS-GOA\" \
+	-I$(top_srcdir)/common \
+	-I$(top_srcdir)/monitor/proxy \
+	$(GLIB_CFLAGS) \
+	$(GOA_CFLAGS) \
+	$(WARN_CFLAGS) \
+	-DGIO_MODULE_DIR=\"$(GIO_MODULE_DIR)\" \
+	-DGVFS_LOCALEDIR=\"$(localedir)\" \
+	$(NULL)
+
+gvfs_goa_volume_monitor_LDADD = \
+	$(GLIB_LIBS) \
+	$(GOA_LIBS) \
+	$(top_builddir)/common/libgvfscommon.la \
+	$(top_builddir)/monitor/proxy/libgvfsproxyvolumemonitordaemon-noin.la \
+	$(NULL)
+
+remote_volume_monitorsdir = $(datadir)/gvfs/remote-volume-monitors
+remote_volume_monitors_DATA = goa.monitor
+
+servicedir = $(datadir)/dbus-1/services
+service_in_files = org.gtk.Private.GoaVolumeMonitor.service.in
+service_DATA = $(service_in_files:.service.in=.service)
+
+$(service_DATA): $(service_in_files) Makefile
+	$(AM_V_GEN) $(SED) -e "s|\ libexecdir\@|$(libexecdir)|" $< > $@
+
+clean-local:
+	rm -f *~ *.loT $(BUILT_SOURCES) $(service_DATA)
+
+DISTCLEANFILES = $(service_DATA)
+
+EXTRA_DIST = $(service_in_files) goa.monitor
diff --git a/monitor/goa/goa.monitor b/monitor/goa/goa.monitor
new file mode 100644
index 0000000..a763c6b
--- /dev/null
+++ b/monitor/goa/goa.monitor
@@ -0,0 +1,4 @@
+[RemoteVolumeMonitor]
+Name=GProxyVolumeMonitorGoa
+DBusName=org.gtk.Private.GoaVolumeMonitor
+IsNative=false
diff --git a/monitor/goa/goavolume.c b/monitor/goa/goavolume.c
new file mode 100644
index 0000000..c9bfb2d
--- /dev/null
+++ b/monitor/goa/goavolume.c
@@ -0,0 +1,556 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ */
+
+#include <config.h>
+#include <string.h>
+#include <glib.h>
+#include <gio/gio.h>
+#include <glib/gi18n.h>
+
+#include "goavolume.h"
+
+struct _GVfsGoaVolume
+{
+  GObject parent;
+  GFile *root;
+  GMount *mount;
+  GoaObject *object;
+  gboolean auth_failed;
+  gchar *uuid;
+  gchar *icon;
+  gchar *symbolic_icon;
+};
+
+struct _GVfsGoaVolumeClass
+{
+  GObjectClass parent_class;
+};
+
+enum
+{
+  PROP_0,
+  PROP_ACCOUNT,
+  PROP_UUID
+};
+
+static void g_vfs_goa_volume_iface_init (GVolumeIface *iface);
+
+G_DEFINE_TYPE_EXTENDED (GVfsGoaVolume, g_vfs_goa_volume, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (G_TYPE_VOLUME,
+                                               g_vfs_goa_volume_iface_init))
+
+typedef struct
+{
+  GAsyncReadyCallback callback;
+  GCancellable *cancellable;
+  GMountOperation *mount_operation;
+  GSimpleAsyncResult *simple;
+  gchar *passwd;
+  gpointer user_data;
+} MountOp;
+
+static void
+mount_op_free (MountOp *data)
+{
+  g_clear_object (&data->cancellable);
+  g_clear_object (&data->mount_operation);
+  g_object_unref (data->simple);
+  g_free (data->passwd);
+  g_slice_free (MountOp, data);
+}
+
+static void
+mount_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  MountOp *data = user_data;
+
+  if (data->callback != NULL)
+    data->callback (source_object, res, data->user_data);
+
+  mount_op_free (data);
+}
+
+static void
+account_attention_needed_cb (GObject *_object, GParamSpec *pspec, gpointer user_data)
+{
+  GoaAccount *account = GOA_ACCOUNT (_object);
+  GVfsGoaVolume *self = user_data;
+  gboolean attention_needed;
+
+  attention_needed = goa_account_get_attention_needed (account);
+  if (self->auth_failed && !attention_needed)
+    g_volume_mount (G_VOLUME (self), G_MOUNT_MOUNT_NONE, NULL, NULL, NULL, NULL);
+}
+
+static void
+mount_operation_ask_password_cb (GMountOperation   *op,
+                                 gchar             *message,
+                                 gchar             *default_user,
+                                 gchar             *default_domain,
+                                 GAskPasswordFlags  flags,
+                                 gpointer           user_data)
+{
+  MountOp *data = user_data;
+
+  g_mount_operation_set_password (data->mount_operation, data->passwd);
+  g_mount_operation_reply (data->mount_operation, G_MOUNT_OPERATION_HANDLED);
+}
+
+static void
+find_enclosing_mount_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GFile *root = G_FILE (source_object);
+  GSimpleAsyncResult *simple = user_data;
+  GVfsGoaVolume *self;
+  GError *error;
+  MountOp *data;
+
+  self = G_VFS_GOA_VOLUME (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+  data = g_async_result_get_user_data (G_ASYNC_RESULT (simple));
+
+  error = NULL;
+  g_clear_object (&self->mount);
+  self->mount = g_file_find_enclosing_mount_finish (root, res, &error);
+  if (error != NULL)
+    g_simple_async_result_take_error (simple, error);
+  else
+    self->auth_failed = FALSE;
+
+  g_simple_async_result_complete_in_idle (simple);
+}
+
+static void
+mount_enclosing_volume_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GFile *root = G_FILE (source_object);
+  GSimpleAsyncResult *simple = user_data;
+  GVfsGoaVolume *self;
+  GError *error;
+  MountOp *data;
+
+  self = G_VFS_GOA_VOLUME (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+  data = g_async_result_get_user_data (G_ASYNC_RESULT (simple));
+
+  error = NULL;
+  if (!g_file_mount_enclosing_volume_finish (root, res, &error))
+    {
+      if (error->code == G_IO_ERROR_CANCELLED)
+        {
+          g_simple_async_result_take_error (simple, error);
+          g_simple_async_result_complete (simple);
+          return;
+        }
+      else
+        {
+          g_warning ("Failed to mount %s: %s", g_file_get_uri (root), error->message);
+          g_error_free (error);
+          /* We carry on because the failure could have been caused
+           * by a volume that was already mounted.
+           */
+        }
+    }
+
+  g_file_find_enclosing_mount_async (root, G_PRIORITY_DEFAULT, NULL, find_enclosing_mount_cb, simple);
+}
+
+static void
+get_password_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GoaPasswordBased *passwd_based = GOA_PASSWORD_BASED (source_object);
+  GSimpleAsyncResult *simple = user_data;
+  GVfsGoaVolume *self;
+  GError *error;
+  GoaAccount *account;
+  GoaFiles *files;
+  MountOp *data;
+
+  self = G_VFS_GOA_VOLUME (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+  data = g_async_result_get_user_data (G_ASYNC_RESULT (simple));
+
+  error = NULL;
+  if (!goa_password_based_call_get_password_finish (passwd_based, &data->passwd, res, &error))
+    {
+      self->auth_failed = TRUE;
+      g_simple_async_result_take_error (simple, error);
+      g_simple_async_result_complete (simple);
+      return;
+    }
+
+  account = goa_object_peek_account (self->object);
+  files = goa_object_peek_files (self->object);
+  if (files == NULL)
+    {
+      g_simple_async_result_set_error (simple,
+                                       G_IO_ERROR,
+                                       G_IO_ERROR_FAILED,
+                                       "Failed to get org.gnome.OnlineAccounts.Files for %s",
+                                       goa_account_get_id (account));
+      g_simple_async_result_complete (simple);
+      return;
+    }
+
+  g_mount_operation_set_username (data->mount_operation, goa_account_get_identity (account));
+  g_file_mount_enclosing_volume (self->root,
+                                 G_MOUNT_MOUNT_NONE,
+                                 data->mount_operation,
+                                 data->cancellable,
+                                 mount_enclosing_volume_cb,
+                                 simple);
+}
+
+static void
+ensure_credentials_cb (GObject *source_object, GAsyncResult *res, gpointer user_data)
+{
+  GoaAccount *account = GOA_ACCOUNT (source_object);
+  GSimpleAsyncResult *simple = user_data;
+  GVfsGoaVolume *self;
+  GError *error;
+  GoaPasswordBased *passwd_based;
+  MountOp *data;
+
+  self = G_VFS_GOA_VOLUME (g_async_result_get_source_object (G_ASYNC_RESULT (simple)));
+  data = g_async_result_get_user_data (G_ASYNC_RESULT (simple));
+
+  error = NULL;
+  if (!goa_account_call_ensure_credentials_finish (account, NULL, res, &error))
+    {
+      if (error->domain == GOA_ERROR && error->code == GOA_ERROR_NOT_AUTHORIZED)
+        {
+          g_simple_async_result_set_error (simple,
+                                           G_IO_ERROR,
+                                           G_IO_ERROR_FAILED,
+                                           "Invalid password for %s",
+                                           goa_account_get_presentation_identity (account));
+          g_error_free (error);
+        }
+      else
+        g_simple_async_result_take_error (simple, error);
+
+      self->auth_failed = TRUE;
+      g_simple_async_result_complete (simple);
+      return;
+    }
+
+  passwd_based = goa_object_peek_password_based (self->object);
+  if (passwd_based != NULL)
+    {
+      const gchar *id;
+
+      id = goa_account_get_id (account);
+      goa_password_based_call_get_password (passwd_based, id, data->cancellable, get_password_cb, simple);
+    }
+}
+
+static gboolean
+g_vfs_goa_volume_can_eject (GVolume *_self)
+{
+  return FALSE;
+}
+
+static gboolean
+g_vfs_goa_volume_can_mount (GVolume *_self)
+{
+  return TRUE;
+}
+
+static char **
+g_vfs_goa_volume_enumerate_identifiers (GVolume *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  GPtrArray *res;
+
+  res = g_ptr_array_new ();
+  g_ptr_array_add (res, g_strdup (G_VOLUME_IDENTIFIER_KIND_CLASS));
+  g_ptr_array_add (res, g_strdup (G_VOLUME_IDENTIFIER_KIND_UUID));
+  g_ptr_array_add (res, NULL);
+
+  return (gchar **) g_ptr_array_free (res, FALSE);
+}
+
+static GFile *
+g_vfs_goa_volume_get_activation_root (GVolume *_self)
+{
+  /* Even though we know the activation root before mounting the
+   * volume we can not reveal it, because we do not want it to be
+   * handled as a GProxyVolume.
+   */
+  return NULL;
+}
+
+static GDrive *
+g_vfs_goa_volume_get_drive (GVolume *_self)
+{
+  return NULL;
+}
+
+static GIcon *
+g_vfs_goa_volume_get_icon (GVolume *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  return g_themed_icon_new_with_default_fallbacks (self->icon);
+}
+
+static char *
+g_vfs_goa_volume_get_identifier (GVolume *_self, const gchar *kind)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+
+  if (g_strcmp0 (kind, G_VOLUME_IDENTIFIER_KIND_CLASS) == 0)
+    return g_strdup ("network");
+  else if (g_strcmp0 (kind, G_VOLUME_IDENTIFIER_KIND_UUID) == 0)
+    return g_strdup (self->uuid);
+
+  return NULL;
+}
+
+static GMount *
+g_vfs_goa_volume_get_mount (GVolume *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  GMount *mount;
+
+  mount = NULL;
+
+  if (self->mount != NULL)
+    mount = g_object_ref (self->mount);
+
+  return mount;
+}
+
+static char *
+g_vfs_goa_volume_get_name (GVolume *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  GoaAccount *account;
+
+  account = goa_object_peek_account (self->object);
+  return goa_account_dup_presentation_identity (account);
+}
+
+static GIcon *
+g_vfs_goa_volume_get_symbolic_icon (GVolume *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  return g_themed_icon_new_with_default_fallbacks (self->symbolic_icon);
+}
+
+static char *
+g_vfs_goa_volume_get_uuid (GVolume *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  return g_strdup (self->uuid);
+}
+
+static void
+g_vfs_goa_volume_mount (GVolume             *_self,
+                        GMountMountFlags     flags,
+                        GMountOperation     *mount_operation,
+                        GCancellable        *cancellable,
+                        GAsyncReadyCallback  callback,
+                        gpointer             user_data)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  MountOp *data;
+  GSimpleAsyncResult *simple;
+  GoaAccount *account;
+
+  data = g_slice_new0 (MountOp);
+  simple = g_simple_async_result_new (G_OBJECT (self), mount_cb, data, g_vfs_goa_volume_mount);
+
+  data->simple = simple;
+  data->callback = callback;
+  data->user_data = user_data;
+
+  if (cancellable != NULL)
+    {
+      data->cancellable = g_object_ref (cancellable);
+      g_simple_async_result_set_check_cancellable (simple, cancellable);
+    }
+
+  /* We ignore the GMountOperation handed to us by the proxy volume
+   * monitor because it is set up to emit MountOpAskPassword on
+   * ask-password.
+   */
+  data->mount_operation = g_mount_operation_new ();
+  g_signal_connect (data->mount_operation, "ask-password", G_CALLBACK (mount_operation_ask_password_cb), data);
+
+  account = goa_object_peek_account (self->object);
+  goa_account_call_ensure_credentials (account, data->cancellable, ensure_credentials_cb, simple);
+}
+
+static gboolean
+g_vfs_goa_volume_mount_finish (GVolume *_self, GAsyncResult *res, GError **error)
+{
+  GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res);;
+
+  g_return_val_if_fail (g_simple_async_result_is_valid (res, G_OBJECT (_self), g_vfs_goa_volume_mount), FALSE);
+
+  if (g_simple_async_result_propagate_error (simple, error))
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+g_vfs_goa_volume_removed (GVolume *volume)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (volume);
+
+  if (self->mount == NULL)
+    return;
+
+  g_mount_unmount_with_operation (self->mount, G_MOUNT_UNMOUNT_NONE, NULL, NULL, NULL, NULL);
+}
+
+static gboolean
+g_vfs_goa_volume_should_automount (GVolume *volume)
+{
+  return FALSE;
+}
+
+static void
+g_vfs_goa_volume_constructed (GObject *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+  GoaAccount *account;
+
+  G_OBJECT_CLASS (g_vfs_goa_volume_parent_class)->constructed (_self);
+
+  self->root = g_file_new_for_uri (self->uuid);
+
+  account = goa_object_peek_account (self->object);
+  g_signal_connect (account, "notify::attention-needed", G_CALLBACK (account_attention_needed_cb), self);
+}
+
+static void
+g_vfs_goa_volume_dispose (GObject *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+
+  g_clear_object (&self->root);
+  g_clear_object (&self->mount);
+  g_clear_object (&self->object);
+
+  G_OBJECT_CLASS (g_vfs_goa_volume_parent_class)->dispose (_self);
+}
+
+static void
+g_vfs_goa_volume_finalize (GObject *_self)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+
+  g_free (self->uuid);
+  g_free (self->icon);
+  g_free (self->symbolic_icon);
+
+  G_OBJECT_CLASS (g_vfs_goa_volume_parent_class)->finalize (_self);
+}
+
+static void
+g_vfs_goa_volume_set_property (GObject *_self, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+  GVfsGoaVolume *self = G_VFS_GOA_VOLUME (_self);
+
+  switch (prop_id)
+    {
+    case PROP_ACCOUNT:
+      self->object = g_value_dup_object (value);
+      break;
+
+    case PROP_UUID:
+      self->uuid = g_value_dup_string (value);
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (_self, prop_id, pspec);
+      break;
+    }
+}
+
+static void
+g_vfs_goa_volume_class_init (GVfsGoaVolumeClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+  gobject_class->constructed = g_vfs_goa_volume_constructed;
+  gobject_class->dispose = g_vfs_goa_volume_dispose;
+  gobject_class->finalize = g_vfs_goa_volume_finalize;
+  gobject_class->set_property = g_vfs_goa_volume_set_property;
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_ACCOUNT,
+                                   g_param_spec_object ("account",
+                                                        "GoaObject object",
+                                                        "The GOA account represented by the volume",
+                                                        GOA_TYPE_OBJECT,
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_STRINGS |
+                                                        G_PARAM_WRITABLE));
+
+  g_object_class_install_property (gobject_class,
+                                   PROP_UUID,
+                                   g_param_spec_string ("uuid",
+                                                        "UUID",
+                                                        "The UUID of the volume",
+                                                        NULL,
+                                                        G_PARAM_CONSTRUCT_ONLY |
+                                                        G_PARAM_STATIC_STRINGS |
+                                                        G_PARAM_WRITABLE));
+}
+
+static void
+g_vfs_goa_volume_init (GVfsGoaVolume *self)
+{
+  self->icon = g_strdup ("network-server");
+  self->symbolic_icon = g_strdup ("network-server-symbolic");
+}
+
+static void
+g_vfs_goa_volume_iface_init (GVolumeIface *iface)
+{
+  iface->removed = g_vfs_goa_volume_removed;
+
+  iface->can_eject = g_vfs_goa_volume_can_eject;
+  iface->can_mount = g_vfs_goa_volume_can_mount;
+  iface->enumerate_identifiers = g_vfs_goa_volume_enumerate_identifiers;
+  iface->get_activation_root = g_vfs_goa_volume_get_activation_root;
+  iface->get_drive = g_vfs_goa_volume_get_drive;
+  iface->get_icon = g_vfs_goa_volume_get_icon;
+  iface->get_identifier = g_vfs_goa_volume_get_identifier;
+  iface->get_mount = g_vfs_goa_volume_get_mount;
+  iface->get_name = g_vfs_goa_volume_get_name;
+  iface->get_symbolic_icon = g_vfs_goa_volume_get_symbolic_icon;
+  iface->get_uuid = g_vfs_goa_volume_get_uuid;
+  iface->mount_fn = g_vfs_goa_volume_mount;
+  iface->mount_finish = g_vfs_goa_volume_mount_finish;
+  iface->should_automount = g_vfs_goa_volume_should_automount;
+}
+
+GVolume *
+g_vfs_goa_volume_new (GoaObject *object, const gchar *uuid)
+{
+  return g_object_new (G_VFS_TYPE_GOA_VOLUME,
+                       "account", object,
+                       "uuid", uuid,
+                       NULL);
+}
diff --git a/monitor/goa/goavolume.h b/monitor/goa/goavolume.h
new file mode 100644
index 0000000..2d01383
--- /dev/null
+++ b/monitor/goa/goavolume.h
@@ -0,0 +1,66 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ */
+
+#ifndef __GOA_VOLUME_H__
+#define __GOA_VOLUME_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_GOA_VOLUME (g_vfs_goa_volume_get_type())
+
+#define G_VFS_GOA_VOLUME(o) \
+  (G_TYPE_CHECK_INSTANCE_CAST((o), \
+   G_VFS_TYPE_GOA_VOLUME, GVfsGoaVolume))
+
+#define G_VFS_GOA_VOLUME_CLASS(k) \
+  (G_TYPE_CHECK_CLASS_CAST((k), \
+   G_VFS_TYPE_GOA_VOLUME, GVfsGoaVolumeClass))
+
+#define G_VFS_IS_GOA_VOLUME(o) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((o), \
+   G_VFS_TYPE_GOA_VOLUME))
+
+#define G_VFS_IS_GOA_VOLUME_CLASS(k) \
+  (G_TYPE_CHECK_CLASS_TYPE((k), \
+   G_VFS_TYPE_GOA_VOLUME))
+
+#define G_VFS_GOA_VOLUME_GET_CLASS(o) \
+  (G_TYPE_INSTANCE_GET_CLASS((o), \
+   G_VFS_TYPE_GOA_VOLUME, GVfsGoaVolumeClass))
+
+typedef struct _GVfsGoaVolume GVfsGoaVolume;
+typedef struct _GVfsGoaVolumeClass GVfsGoaVolumeClass;
+
+GType g_vfs_goa_volume_get_type (void) G_GNUC_CONST;
+
+GVolume *g_vfs_goa_volume_new (GoaObject *object, const gchar *uuid);
+
+G_END_DECLS
+
+#endif /* __GOA_VOLUME_H__ */
diff --git a/monitor/goa/goavolumemonitor.c b/monitor/goa/goavolumemonitor.c
new file mode 100644
index 0000000..ae9c103
--- /dev/null
+++ b/monitor/goa/goavolumemonitor.c
@@ -0,0 +1,460 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ */
+
+#include <config.h>
+
+#include <stdio.h>
+
+#include <glib.h>
+#include <gio/gio.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+#include <gvfsproxyvolumemonitordaemon.h>
+#include "goavolume.h"
+#include "goavolumemonitor.h"
+
+struct _GVfsGoaVolumeMonitor
+{
+  GNativeVolumeMonitor parent;
+  GList *accounts;
+  GList *volumes;
+  GoaClient *client;
+};
+
+struct _GVfsGoaVolumeMonitorClass
+{
+  GVolumeMonitorClass parent_class;
+};
+
+G_DEFINE_TYPE(GVfsGoaVolumeMonitor, g_vfs_goa_volume_monitor, G_TYPE_VOLUME_MONITOR)
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+diff_sorted_lists (GList         *list1,
+                   GList         *list2,
+                   GCompareFunc   compare,
+                   GList        **added,
+                   GList        **removed,
+                   GList        **unchanged)
+{
+  int order;
+
+  *added = *removed = NULL;
+  if (unchanged != NULL)
+    *unchanged = NULL;
+
+  while (list1 != NULL &&
+         list2 != NULL)
+    {
+      order = (*compare) (list1->data, list2->data);
+      if (order < 0)
+        {
+          *removed = g_list_prepend (*removed, list1->data);
+          list1 = list1->next;
+        }
+      else if (order > 0)
+        {
+          *added = g_list_prepend (*added, list2->data);
+          list2 = list2->next;
+        }
+      else
+        { /* same item */
+          if (unchanged != NULL)
+            *unchanged = g_list_prepend (*unchanged, list1->data);
+          list1 = list1->next;
+          list2 = list2->next;
+        }
+    }
+
+  while (list1 != NULL)
+    {
+      *removed = g_list_prepend (*removed, list1->data);
+      list1 = list1->next;
+    }
+  while (list2 != NULL)
+    {
+      *added = g_list_prepend (*added, list2->data);
+      list2 = list2->next;
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+account_compare (GoaObject *a, GoaObject *b)
+{
+  GoaAccount *account_a;
+  GoaAccount *account_b;
+
+  account_a = goa_object_peek_account (a);
+  account_b = goa_object_peek_account (b);
+
+  return g_strcmp0 (goa_account_get_id (account_a), goa_account_get_id (account_b));
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+uuid_compare (GVolume *volume_a, const gchar *uuid_b)
+{
+  gchar *uuid_a;
+  gint ret_val;
+
+  uuid_a = g_volume_get_uuid (volume_a);
+  ret_val = g_strcmp0 (uuid_a, uuid_b);
+  g_free (uuid_a);
+
+  return ret_val;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static gint
+volume_compare (GVolume *a, GVolume *b)
+{
+  gchar *uuid_a;
+  gchar *uuid_b;
+  gint ret_val;
+
+  uuid_a = g_volume_get_uuid (a);
+  uuid_b = g_volume_get_uuid (b);
+
+  ret_val = g_strcmp0 (uuid_a, uuid_b);
+
+  g_free (uuid_a);
+  g_free (uuid_b);
+
+  return ret_val;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+object_list_emit (GVfsGoaVolumeMonitor *monitor,
+                  const gchar          *monitor_signal,
+                  const gchar          *object_signal,
+                  GList                *objects)
+{
+  GList *l;
+
+  for (l = objects; l != NULL; l = l->next)
+    {
+      g_signal_emit_by_name (monitor, monitor_signal, l->data);
+      if (object_signal)
+        g_signal_emit_by_name (l->data, object_signal);
+    }
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_accounts (GVfsGoaVolumeMonitor *self, GList **added_accounts, GList **removed_accounts)
+{
+  GList *added;
+  GList *l;
+  GList *new_accounts;
+  GList *new_files_accounts = NULL;
+  GList *removed;
+
+  new_accounts = goa_client_get_accounts (self->client);
+  for (l = new_accounts; l != NULL; l = l->next)
+    {
+      GoaObject *object = GOA_OBJECT (l->data);
+
+      if (goa_object_peek_files (object) != NULL)
+        new_files_accounts = g_list_prepend (new_files_accounts, object);
+    }
+
+  new_files_accounts = g_list_sort (new_files_accounts, (GCompareFunc) account_compare);
+  diff_sorted_lists (self->accounts,
+                     new_files_accounts,
+                     (GCompareFunc) account_compare,
+                     &added,
+                     &removed,
+                     NULL);
+
+  if (added_accounts != NULL)
+    *added_accounts = g_list_copy_deep (added, (GCopyFunc) g_object_ref, NULL);
+
+  if (removed_accounts != NULL)
+    *removed_accounts = g_list_copy_deep (removed, (GCopyFunc) g_object_ref, NULL);
+
+  for (l = removed; l != NULL; l = l->next)
+    {
+      GList *llink;
+
+      llink = g_list_find_custom (self->accounts, l->data, (GCompareFunc) account_compare);
+      self->accounts = g_list_remove_link (self->accounts, llink);
+      g_list_free_full (llink, g_object_unref);
+    }
+
+  g_list_foreach (added, (GFunc) g_object_ref, NULL);
+  self->accounts = g_list_concat (self->accounts, added);
+  self->accounts = g_list_sort (self->accounts, (GCompareFunc) account_compare);
+
+  g_list_free (removed);
+  g_list_free (new_files_accounts);
+  g_list_free_full (new_accounts, g_object_unref);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_volumes (GVfsGoaVolumeMonitor *self, GList **added_volumes, GList **removed_volumes)
+{
+  GList *added;
+  GList *l;
+  GList *new_volumes = NULL;
+  GList *removed;
+
+  if (added_volumes != NULL)
+    *added_volumes = NULL;
+
+  if (removed_volumes != NULL)
+    *removed_volumes = NULL;
+
+  for (l = self->accounts; l != NULL; l = l->next)
+    {
+      GVolume *volume;
+      GoaFiles *files;
+      GoaObject *object = GOA_OBJECT (l->data);
+      const gchar *uri;
+
+      files = goa_object_peek_files (object);
+      uri = goa_files_get_uri (files);
+
+      volume = g_vfs_goa_volume_new (object, uri);
+      new_volumes = g_list_prepend (new_volumes, volume);
+    }
+
+  new_volumes = g_list_sort (new_volumes, (GCompareFunc) volume_compare);
+  diff_sorted_lists (self->volumes,
+                     new_volumes,
+                     (GCompareFunc) account_compare,
+                     &added,
+                     &removed,
+                     NULL);
+
+  for (l = removed; l != NULL; l = l->next)
+    {
+      GList *llink;
+      GVolume *volume = G_VOLUME (l->data);
+
+      if (removed_volumes != NULL)
+        *removed_volumes = g_list_prepend (*removed_volumes, g_object_ref (volume));
+
+      llink = g_list_find_custom (self->volumes, volume, (GCompareFunc) volume_compare);
+      self->volumes = g_list_remove_link (self->volumes, llink);
+      g_list_free_full (llink, g_object_unref);
+    }
+
+  for (l = added; l != NULL; l = l->next)
+    {
+      GVolume *volume = G_VOLUME (l->data);
+
+      self->volumes = g_list_prepend (self->volumes, g_object_ref (volume));
+
+      if (added_volumes != NULL)
+        *added_volumes = g_list_prepend (*added_volumes, g_object_ref (volume));
+    }
+
+  self->volumes = g_list_sort (self->volumes, (GCompareFunc) volume_compare);
+
+  g_list_free (added);
+  g_list_free (removed);
+  g_list_free_full (new_volumes, g_object_unref);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_all (GVfsGoaVolumeMonitor *self)
+{
+  GList *added_volumes;
+  GList *removed_volumes;
+
+  update_accounts (self, NULL, NULL);
+  update_volumes (self, &added_volumes, &removed_volumes);
+
+  object_list_emit (self, "volume-removed", "removed", removed_volumes);
+  object_list_emit (self, "volume-added", NULL, added_volumes);
+
+  g_list_free_full (added_volumes, g_object_unref);
+  g_list_free_full (removed_volumes, g_object_unref);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static GoaClient *
+get_goa_client_sync (GError **error)
+{
+  static GoaClient *client = NULL;
+  static GError *_error = NULL;
+  static volatile gsize initialized = 0;
+
+  if (g_once_init_enter (&initialized))
+    {
+      client = goa_client_new_sync (NULL, &_error);
+      g_once_init_leave (&initialized, 1);
+    }
+
+  if (_error != NULL && error != NULL)
+    *error = g_error_copy (_error);
+
+  return client;
+}
+
+static GList *
+g_vfs_goa_volume_monitor_get_connected_drives (GVolumeMonitor *_self)
+{
+  return NULL;
+}
+
+static GMount *
+g_vfs_goa_volume_monitor_get_mount_for_uuid (GVolumeMonitor *_self, const gchar *uuid)
+{
+  GVfsGoaVolumeMonitor *self = G_VFS_GOA_VOLUME_MONITOR (_self);
+  GMount *mount;
+  GVolume *volume;
+
+  mount = NULL;
+
+  volume = g_volume_monitor_get_volume_for_uuid (_self, uuid);
+  if (volume != NULL)
+    mount = g_volume_get_mount (G_VOLUME (volume));
+
+  return mount;
+}
+
+static GList *
+g_vfs_goa_volume_monitor_get_mounts (GVolumeMonitor *_self)
+{
+  GVfsGoaVolumeMonitor *self = G_VFS_GOA_VOLUME_MONITOR (_self);
+  GList *l;
+  GList *mounts = NULL;
+
+  for (l = self->volumes; l != NULL; l = l->next)
+    {
+      GMount *mount;
+      GVolume *volume = G_VOLUME (l->data);
+
+      mount = g_volume_get_mount (volume);
+      if (mount != NULL)
+        mounts = g_list_prepend (mounts, mount);
+    }
+
+  return mounts;
+}
+
+static GVolume *
+g_vfs_goa_volume_monitor_get_volume_for_uuid (GVolumeMonitor *_self, const gchar *uuid)
+{
+  GVfsGoaVolumeMonitor *self = G_VFS_GOA_VOLUME_MONITOR (_self);
+  GList *llink;
+  GVolume *volume = NULL;
+  gpointer value;
+
+  llink = g_list_find_custom (self->volumes, uuid, (GCompareFunc) uuid_compare);
+  if (llink != NULL)
+    volume = G_VOLUME (g_object_ref (llink->data));
+
+  return volume;
+}
+
+static GList *
+g_vfs_goa_volume_monitor_get_volumes (GVolumeMonitor *_self)
+{
+  GVfsGoaVolumeMonitor *self = G_VFS_GOA_VOLUME_MONITOR (_self);
+
+  return g_list_copy_deep (self->volumes, (GCopyFunc) g_object_ref, NULL);
+}
+
+static gboolean
+g_vfs_goa_volume_monitor_is_supported (void)
+{
+  if (get_goa_client_sync (NULL) != NULL)
+    return TRUE;
+  return FALSE;
+}
+
+static void
+g_vfs_goa_volume_monitor_dispose (GObject *_self)
+{
+  GVfsGoaVolumeMonitor *self = G_VFS_GOA_VOLUME_MONITOR (_self);
+
+  g_list_free_full (self->accounts, g_object_unref);
+  self->accounts = NULL;
+
+  g_list_free_full (self->volumes, g_object_unref);
+  self->volumes = NULL;
+
+  g_clear_object (&self->client);
+
+  G_OBJECT_CLASS (g_vfs_goa_volume_monitor_parent_class)->dispose (_self);
+}
+
+static void
+g_vfs_goa_volume_monitor_class_init (GVfsGoaVolumeMonitorClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GVolumeMonitorClass *monitor_class = G_VOLUME_MONITOR_CLASS (klass);
+
+  gobject_class->dispose = g_vfs_goa_volume_monitor_dispose;
+
+  monitor_class->get_connected_drives = g_vfs_goa_volume_monitor_get_connected_drives;
+  monitor_class->get_mount_for_uuid = g_vfs_goa_volume_monitor_get_mount_for_uuid;
+  monitor_class->get_mounts = g_vfs_goa_volume_monitor_get_mounts;
+  monitor_class->get_volume_for_uuid = g_vfs_goa_volume_monitor_get_volume_for_uuid;
+  monitor_class->get_volumes = g_vfs_goa_volume_monitor_get_volumes;
+  monitor_class->is_supported = g_vfs_goa_volume_monitor_is_supported;
+}
+
+static void
+g_vfs_goa_volume_monitor_init (GVfsGoaVolumeMonitor *self)
+{
+  GError *error;
+
+  error = NULL;
+  self->client = get_goa_client_sync (&error);
+  if (error != NULL)
+    {
+      g_warning ("Failed to connect to GOA: %s", error->message);
+      g_error_free (error);
+      return;
+    }
+
+  update_all (self);
+
+  g_signal_connect_swapped (self->client, "account-added", G_CALLBACK (update_all), self);
+  g_signal_connect_swapped (self->client, "account-changed", G_CALLBACK (update_all), self);
+  g_signal_connect_swapped (self->client, "account-removed", G_CALLBACK (update_all), self);
+}
+
+GVolumeMonitor *
+g_vfs_goa_volume_monitor_new (void)
+{
+  return g_object_new (G_VFS_TYPE_GOA_VOLUME_MONITOR, NULL);
+}
diff --git a/monitor/goa/goavolumemonitor.h b/monitor/goa/goavolumemonitor.h
new file mode 100644
index 0000000..149f86e
--- /dev/null
+++ b/monitor/goa/goavolumemonitor.h
@@ -0,0 +1,63 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ */
+
+#ifndef __GOA_VOLUME_MONITOR_H__
+#define __GOA_VOLUME_MONITOR_H__
+
+#include <glib-object.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_GOA_VOLUME_MONITOR (g_vfs_goa_volume_monitor_get_type())
+
+#define G_VFS_GOA_VOLUME_MONITOR(o) \
+  (G_TYPE_CHECK_INSTANCE_CAST((o), \
+   G_VFS_TYPE_GOA_VOLUME_MONITOR, GVfsGoaVolumeMonitor))
+
+#define G_VFS_GOA_VOLUME_MONITOR_CLASS(k) \
+  (G_TYPE_CHECK_CLASS_CAST((k), \
+   G_VFS_TYPE_GOA_VOLUME_MONITOR, GVfsGoaVolumeMonitorClass))
+
+#define G_VFS_IS_GOA_VOLUME_MONITOR(o) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((o), \
+   G_VFS_TYPE_GOA_VOLUME_MONITOR))
+
+#define G_VFS_IS_GOA_VOLUME_MONITOR_CLASS(k) \
+  (G_TYPE_CHECK_CLASS_TYPE((k), \
+   G_VFS_TYPE_GOA_VOLUME_MONITOR))
+
+#define G_VFS_GOA_VOLUME_MONITOR_GET_CLASS(o) \
+  (G_TYPE_INSTANCE_GET_CLASS((o), \
+   G_VFS_TYPE_GOA_VOLUME_MONITOR, GVfsGoaVolumeMonitorClass))
+
+typedef struct _GVfsGoaVolumeMonitor GVfsGoaVolumeMonitor;
+typedef struct _GVfsGoaVolumeMonitorClass GVfsGoaVolumeMonitorClass;
+
+GType g_vfs_goa_volume_monitor_get_type (void) G_GNUC_CONST;
+
+GVolumeMonitor *g_vfs_goa_volume_monitor_new (void);
+
+G_END_DECLS
+
+#endif /* __GOA_VOLUME_MONITOR_H__ */
diff --git a/monitor/goa/goavolumemonitordaemon.c b/monitor/goa/goavolumemonitordaemon.c
new file mode 100644
index 0000000..5765a67
--- /dev/null
+++ b/monitor/goa/goavolumemonitordaemon.c
@@ -0,0 +1,49 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2012 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., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ * Author: Debarshi Ray <debarshir gnome org>
+ */
+
+#include <config.h>
+
+#include <locale.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gio/gio.h>
+
+#include <gvfsproxyvolumemonitordaemon.h>
+#include "goavolumemonitor.h"
+
+int
+main (int argc, char *argv[])
+{
+  setlocale (LC_ALL, "");
+
+  bindtextdomain (GETTEXT_PACKAGE, GVFS_LOCALEDIR);
+  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
+  textdomain (GETTEXT_PACKAGE);
+
+  g_vfs_proxy_volume_monitor_daemon_init ();
+  return g_vfs_proxy_volume_monitor_daemon_main (argc,
+                                                 argv,
+                                                 "org.gtk.Private.GoaVolumeMonitor",
+                                                 G_VFS_TYPE_GOA_VOLUME_MONITOR);
+}
diff --git a/monitor/goa/org.gtk.Private.GoaVolumeMonitor.service.in b/monitor/goa/org.gtk.Private.GoaVolumeMonitor.service.in
new file mode 100644
index 0000000..cb9a351
--- /dev/null
+++ b/monitor/goa/org.gtk.Private.GoaVolumeMonitor.service.in
@@ -0,0 +1,3 @@
+[D-BUS Service]
+Name=org.gtk.Private.GoaVolumeMonitor
+Exec= libexecdir@/gvfs-goa-volume-monitor



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