[gvfs/wip/goa: 2/2] Add GVfsBackendGoogle



commit 45116d598034152b6b4131bd25f7e6d0959f437c
Author: Debarshi Ray <debarshir gnome org>
Date:   Wed Oct 22 13:53:23 2014 +0200

    Add GVfsBackendGoogle

 configure.ac               |   23 +++
 daemon/Makefile.am         |   20 +++
 daemon/google.mount.in     |    4 +
 daemon/gvfsbackendgoogle.c |  379 ++++++++++++++++++++++++++++++++++++++++++++
 daemon/gvfsbackendgoogle.h |   62 +++++++
 5 files changed, 488 insertions(+), 0 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 1e21fdb..7205ed3 100644
--- a/configure.ac
+++ b/configure.ac
@@ -407,6 +407,28 @@ AC_SUBST(GOA_CFLAGS)
 
 AM_CONDITIONAL(USE_GOA, [test "$msg_goa" = "yes"])
 
+dnl ****************************************************
+dnl *** Check if we should build with Google backend ***
+dnl ****************************************************
+AC_ARG_ENABLE(google, AS_HELP_STRING([--disable-google],[build without Google backend]))
+msg_google=no
+GOOGLE_LIBS=
+GOOGLE_CFLAGS=
+
+if test "x$enable_google" != "xno" ; then
+  PKG_CHECK_EXISTS(libgdata >= 0.13.1, msg_google=yes)
+
+  if test "x$msg_google" = "xyes"; then
+    PKG_CHECK_MODULES(GOOGLE, libgdata)
+    AC_DEFINE(HAVE_GOOGLE, 1, [Define to 1 if Google is going to be built])
+  fi
+fi
+
+AC_SUBST(GOOGLE_LIBS)
+AC_SUBST(GOOGLE_CFLAGS)
+
+AM_CONDITIONAL(USE_GOOGLE, [test "$msg_google" = "yes"])
+
 dnl *****************************************************
 dnl *** Check if we should build with obexftp backend ***
 dnl *****************************************************
@@ -938,6 +960,7 @@ echo "
         hotplug backend:              $msg_hotplug_backend
 
        Blu-ray metadata support:     $msg_bluray
+       Google support:               $msg_google
         HTTP/WebDAV support:          $msg_http
         ObexFTP support               $msg_obexftp
        Samba support:                $msg_samba
diff --git a/daemon/Makefile.am b/daemon/Makefile.am
index a6a9ae1..5cb89ae 100644
--- a/daemon/Makefile.am
+++ b/daemon/Makefile.am
@@ -48,6 +48,12 @@ libexec_PROGRAMS=gvfsd gvfsd-sftp gvfsd-trash gvfsd-computer gvfsd-burn gvfsd-lo
 mount_in_files = sftp.mount.in ftp.mount.in trash.mount.in computer.mount.in burn.mount.in 
localtest.mount.in network.mount.in
 mount_DATA =  sftp.mount ftp.mount trash.mount computer.mount burn.mount localtest.mount network.mount
 
+mount_in_files +=google.mount.in
+if USE_GOOGLE
+mount_DATA += google.mount
+libexec_PROGRAMS += gvfsd-google
+endif
+
 mount_in_files +=recent.mount.in
 if USE_GTK
 mount_DATA += recent.mount
@@ -459,6 +465,20 @@ else
 gvfsd_cdda_LDADD = $(libraries) $(CDDA_LIBS) $(HAL_LIBS)
 endif
 
+gvfsd_google_SOURCES = \
+       gvfsbackendgoogle.c gvfsbackendgoogle.h \
+       daemon-main.c daemon-main.h \
+       daemon-main-generic.c
+
+gvfsd_google_CPPFLAGS = \
+       $(flags) \
+       -DBACKEND_HEADER=gvfsbackendgoogle.h \
+       -DDEFAULT_BACKEND_TYPE=google-drive \
+       -DBACKEND_TYPES='"google-drive", G_VFS_TYPE_BACKEND_GOOGLE,' \
+       $(GOOGLE_CFLAGS)
+
+gvfsd_google_LDADD = $(libraries) $(GOOGLE_LIBS)
+
 gvfsd_gphoto2_SOURCES = \
        gvfsbackendgphoto2.c gvfsbackendgphoto2.h \
        daemon-main.c daemon-main.h \
diff --git a/daemon/google.mount.in b/daemon/google.mount.in
new file mode 100644
index 0000000..059b228
--- /dev/null
+++ b/daemon/google.mount.in
@@ -0,0 +1,4 @@
+[Mount]
+Type=google-drive
+Exec= libexecdir@/gvfsd-google
+AutoMount=false
diff --git a/daemon/gvfsbackendgoogle.c b/daemon/gvfsbackendgoogle.c
new file mode 100644
index 0000000..ef813b4
--- /dev/null
+++ b/daemon/gvfsbackendgoogle.c
@@ -0,0 +1,379 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2014 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 <gdata/gdata.h>
+#include <glib.h>
+#include <gio/gio.h>
+
+#define GOA_API_IS_SUBJECT_TO_CHANGE
+#include <goa/goa.h>
+
+#include "gvfsbackendgoogle.h"
+
+struct _GVfsBackendGoogle
+{
+  GVfsBackend parent;
+};
+
+struct _GVfsBackendGoogleClass
+{
+  GVfsBackendClass parent_class;
+};
+
+G_DEFINE_TYPE(GVfsBackendGoogle, g_vfs_backend_google, G_VFS_TYPE_BACKEND)
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+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 (GVfsBackendGoogle *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 (GVfsBackendGoogle *self, GList **added_accounts, GList **removed_accounts)
+{
+  GList *added;
+  GList *l;
+  GList *new_accounts;
+  GList *new_files_accounts = NULL;
+  GList *removed;
+
+  if (added_accounts != NULL)
+    *added_accounts = NULL;
+
+  if (removed_accounts != NULL)
+    *removed_accounts = NULL;
+
+  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);
+
+  for (l = removed; l != NULL; l = l->next)
+    {
+      GList *llink;
+      GoaObject *object = GOA_OBJECT (l->data);
+
+      if (removed_accounts != NULL)
+        *removed_accounts = g_list_prepend (*removed_accounts, g_object_ref (object));
+
+      llink = g_list_find_custom (self->accounts, object, (GCompareFunc) account_compare);
+      self->accounts = g_list_remove_link (self->accounts, llink);
+      g_list_free_full (llink, g_object_unref);
+    }
+
+  for (l = added; l != NULL; l = l->next)
+    {
+      GoaObject *object = GOA_OBJECT (l->data);
+
+      self->accounts = g_list_prepend (self->accounts, g_object_ref (object));
+
+      if (added_accounts != NULL)
+        *added_accounts = g_list_prepend (*added_accounts, g_object_ref (object));
+    }
+
+  self->accounts = g_list_sort (self->accounts, (GCompareFunc) account_compare);
+
+  g_list_free (added);
+  g_list_free (removed);
+  g_list_free (new_files_accounts);
+  g_list_free_full (new_accounts, g_object_unref);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+static void
+update_volumes (GVfsBackendGoogle *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) volume_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 (GVfsBackendGoogle *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 void
+g_vfs_backend_google_mount (GVfsBackend  *_self,
+                            GVfsJobMount *job,
+                            GMountSpec   *mount_spec,
+                            GMountSource *mount_source,
+                            gboolean      is_automount)
+{
+  g_vfs_job_succeeded (G_VFS_JOB (job));
+}
+
+static void
+g_vfs_backend_google_dispose (GObject *_self)
+{
+  GVfsBackendGoogle *self = G_VFS_BACKEND_GOOGLE (_self);
+
+  G_OBJECT_CLASS (g_vfs_backend_google_parent_class)->dispose (_self);
+}
+
+static void
+g_vfs_backend_google_class_init (GVfsBackendGoogleClass * klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GVfsBackendClass *backend_class = G_VFS_BACKEND_CLASS (klass);
+
+  gobject_class->dispose = g_vfs_backend_google_dispose;
+
+  backend_class->try_mount = NULL;
+  backend_class->mount = g_vfs_backend_google_mount;
+}
+
+static void
+g_vfs_backend_google_init (GVfsBackendGoogle *self)
+{
+  g_vfs_backend_set_user_visible (G_VFS_BACKEND (self), FALSE);
+}
+
+GVfsBackend *
+g_vfs_backend_google_new (void)
+{
+  return g_object_new (G_VFS_TYPE_BACKEND_GOOGLE, NULL);
+}
diff --git a/daemon/gvfsbackendgoogle.h b/daemon/gvfsbackendgoogle.h
new file mode 100644
index 0000000..21b209f
--- /dev/null
+++ b/daemon/gvfsbackendgoogle.h
@@ -0,0 +1,62 @@
+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
+/* gvfs - extensions for gio
+ *
+ * Copyright (C) 2014 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 __G_VFS_BACKEND_GOOGLE_H__
+#define __G_VFS_BACKEND_GOOGLE_H__
+
+#include <gvfsbackend.h>
+
+G_BEGIN_DECLS
+
+#define G_VFS_TYPE_BACKEND_GOOGLE (g_vfs_backend_google_get_type())
+
+#define G_VFS_BACKEND_GOOGLE(o) \
+  (G_TYPE_CHECK_INSTANCE_CAST((o), \
+   G_VFS_TYPE_BACKEND_GOOGLE, GVfsBackendGoogle))
+
+#define G_VFS_BACKEND_GOOGLE_CLASS(k) \
+  (G_TYPE_CHECK_CLASS_CAST((k), \
+   G_VFS_TYPE_BACKEND_GOOGLE, GVfsBackendGoogleClass))
+
+#define G_VFS_IS_BACKEND_GOOGLE(o) \
+  (G_TYPE_CHECK_INSTANCE_TYPE((o), \
+   G_VFS_TYPE_BACKEND_GOOGLE))
+
+#define G_VFS_IS_BACKEND_GOOGLE_CLASS(k) \
+  (G_TYPE_CHECK_CLASS_TYPE((k), \
+   G_VFS_TYPE_BACKEND_GOOGLE))
+
+#define G_VFS_BACKEND_GOOGLE_GET_CLASS(o) \
+  (G_TYPE_INSTANCE_GET_CLASS((o), \
+   G_VFS_TYPE_BACKEND_GOOGLE, GVfsBackendGoogleClass))
+
+typedef struct _GVfsBackendGoogle GVfsBackendGoogle;
+typedef struct _GVfsBackendGoogleClass GVfsBackendGoogleClass;
+
+GType g_vfs_backend_google_get_type (void) G_GNUC_CONST;
+
+GVfsBackend *g_vfs_backend_google_new (void);
+
+G_END_DECLS
+
+#endif /* __G_VFS_BACKEND_GOOGLE_H__ */


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