[gnome-online-accounts/wip/rishi/account-remove: 10/10] telepathy: Use GoaProvider:remove_account for deleting the TpAccount



commit 523ad06af216f0631549532cf984b3ff436c739f
Author: Debarshi Ray <debarshir gnome org>
Date:   Wed Jun 1 20:00:08 2016 +0200

    telepathy: Use GoaProvider:remove_account for deleting the TpAccount
    
    ... instead of listening to GoaClient::account-removed.
    
    API was added to GoaTpAccountLinker to explicitly request the removal
    of the TpAccount. This is used by GoaTelepathyProvider in its
    GoaProvider:remove_account implementation.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=766733

 src/goabackend/goatelepathyprovider.c |   63 ++++++++++++
 src/goabackend/goatpaccountlinker.c   |  178 +++++++++++++++++++++++----------
 src/goabackend/goatpaccountlinker.h   |   10 ++
 3 files changed, 200 insertions(+), 51 deletions(-)
---
diff --git a/src/goabackend/goatelepathyprovider.c b/src/goabackend/goatelepathyprovider.c
index 656be3f..77fa82f 100644
--- a/src/goabackend/goatelepathyprovider.c
+++ b/src/goabackend/goatelepathyprovider.c
@@ -765,6 +765,67 @@ out:
 
 /* ---------------------------------------------------------------------------------------------------- */
 
+static void
+remove_account_remove_tp_account_cb (GObject       *source_object,
+                                     GAsyncResult  *res,
+                                     gpointer       user_data)
+{
+  GError *error;
+  GTask *task = G_TASK (user_data);
+
+  error = NULL;
+  if (!goa_tp_account_linker_remove_tp_account_finish (tp_linker, res, &error))
+    {
+      g_task_return_error (task, error);
+      goto out;
+    }
+
+  g_task_return_boolean (task, TRUE);
+
+ out:
+  g_object_unref (task);
+}
+
+static void
+remove_account (GoaProvider          *provider,
+                GoaObject            *object,
+                GCancellable         *cancellable,
+                GAsyncReadyCallback   callback,
+                gpointer              user_data)
+{
+  GoaTelepathyProvider *self = GOA_TELEPATHY_PROVIDER (provider);
+  GTask *task;
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, remove_account);
+
+  goa_tp_account_linker_remove_tp_account (tp_linker,
+                                           object,
+                                           cancellable,
+                                           remove_account_remove_tp_account_cb,
+                                           g_object_ref (task));
+
+  g_object_unref (task);
+}
+
+static gboolean
+remove_account_finish (GoaProvider   *provider,
+                       GAsyncResult  *res,
+                       GError       **error)
+{
+  GoaTelepathyProvider *self = GOA_TELEPATHY_PROVIDER (provider);
+  GTask *task;
+
+  g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+  task = G_TASK (res);
+
+  g_warn_if_fail (g_task_get_source_tag (task) == remove_account);
+
+  return g_task_propagate_boolean (task, error);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
 typedef struct
 {
   guint ref_count;
@@ -1039,6 +1100,8 @@ goa_telepathy_provider_class_init (GoaTelepathyProviderClass *klass)
   provider_class->add_account           = add_account;
   provider_class->refresh_account       = refresh_account;
   provider_class->build_object          = build_object;
+  provider_class->remove_account        = remove_account;
+  provider_class->remove_account_finish = remove_account_finish;
   provider_class->show_account          = show_account;
 
   g_type_class_add_private (object_class, sizeof (GoaTelepathyProviderPrivate));
diff --git a/src/goabackend/goatpaccountlinker.c b/src/goabackend/goatpaccountlinker.c
index 71255ec..aa9f01e 100644
--- a/src/goabackend/goatpaccountlinker.c
+++ b/src/goabackend/goatpaccountlinker.c
@@ -28,7 +28,6 @@
 #include <telepathy-glib/telepathy-glib.h>
 
 #include "goatpaccountlinker.h"
-#include "goa/goa.h"
 #include "goabackend/goautils.h"
 
 #define GOA_TP_ACCOUNT_LINKER_GET_PRIVATE(obj) \
@@ -44,6 +43,8 @@ struct _GoaTpAccountLinkerPrivate
 
   GHashTable *tp_accounts; /* owned gchar *id -> reffed TpAccount * */
   GHashTable *goa_accounts; /* owned gchar *id -> reffed GoaObject * */
+
+  GQueue *remove_tp_account_queue;
 };
 
 /* The path of the Telepathy account is used as common identifier between
@@ -72,9 +73,9 @@ tp_account_removed_by_us_cb (GObject      *object,
                              GAsyncResult *res,
                              gpointer      user_data)
 {
-  /* This callback is only used for debugging */
   TpAccount *tp_account = TP_ACCOUNT (object);
   GError *error = NULL;
+  GTask *task = G_TASK (user_data);
 
   if (!tp_account_remove_finish (tp_account, res, &error))
     {
@@ -83,8 +84,80 @@ tp_account_removed_by_us_cb (GObject      *object,
           error->message,
           g_quark_to_string (error->domain),
           error->code);
-      g_error_free (error);
+      g_task_return_error (task, error);
+      goto out;
+    }
+
+  g_task_return_boolean (task, TRUE);
+
+ out:
+  g_object_unref (task);
+}
+
+static void
+remove_tp_account_queue_check (GoaTpAccountLinker *self)
+{
+  GoaTpAccountLinkerPrivate *priv = self->priv;
+  GList *l;
+
+  if (priv->goa_client == NULL ||
+      priv->account_manager == NULL ||
+      !tp_proxy_is_prepared (priv->account_manager, TP_ACCOUNT_MANAGER_FEATURE_CORE))
+    {
+      /* Not everything is ready yet */
+      return;
+    }
+
+  if (priv->remove_tp_account_queue->length == 0)
+    return;
+
+  for (l = priv->remove_tp_account_queue->head; l != NULL; l = l->next)
+    {
+      GTask *task = G_TASK (l->data);
+      GoaAccount *goa_account;
+      GoaObject *goa_object;
+      TpAccount *tp_account;
+      const gchar *id;
+
+      goa_object = GOA_OBJECT (g_task_get_task_data (task));
+      goa_account = goa_object_peek_account (goa_object);
+
+      id = get_id_from_goa_account (goa_account);
+      if (!g_hash_table_remove (priv->goa_accounts, id))
+        {
+          /* 1 - The user removes the Telepathy account (but not the GOA one)
+           * 2 - We delete the corresponding GOA account and remove it
+           *     from priv->goa_accounts
+           * 3 - The Telepathy provider again tries to remove the
+           *     corresponding Telepathy account
+           */
+          g_debug ("Ignoring removal of GOA account we asked to remove "
+                   "(%s, Telepathy object path: %s)",
+                   goa_account_get_id (goa_account),
+                   id);
+          g_task_return_boolean (task, TRUE);
+          continue;
+        }
+
+      g_info ("GOA account %s for Telepathy account %s removed, "
+              "removing Telepathy account",
+              goa_account_get_id (goa_account), id);
+
+      tp_account = g_hash_table_lookup (priv->tp_accounts, id);
+      if (tp_account == NULL)
+        {
+          g_critical ("There is no Telepathy account for removed GOA "
+                      "account %s (Telepathy object path: %s)",
+                      goa_account_get_id (goa_account), id);
+          g_task_return_boolean (task, TRUE);
+          continue;
+        }
+      tp_account_remove_async (tp_account, tp_account_removed_by_us_cb, g_object_ref (task));
+      g_hash_table_remove (priv->tp_accounts, id);
     }
+
+  g_queue_foreach (priv->remove_tp_account_queue, (GFunc) g_object_unref, NULL);
+  g_queue_clear (priv->remove_tp_account_queue);
 }
 
 static void
@@ -385,52 +458,6 @@ goa_account_added_cb (GoaClient *client,
 }
 
 static void
-goa_account_removed_cb (GoaClient *client,
-                        GoaObject *goa_object,
-                        gpointer   user_data)
-{
-  GoaTpAccountLinker *self = user_data;
-  GoaTpAccountLinkerPrivate *priv = self->priv;
-  GoaAccount *goa_account = goa_object_peek_account (goa_object);
-  const gchar *id = NULL;
-  TpAccount *tp_account = NULL;
-
-  if (!is_telepathy_account (goa_account))
-    return;
-
-  id = get_id_from_goa_account (goa_account);
-  if (!g_hash_table_remove (priv->goa_accounts, id))
-    {
-      /* 1 - The user removes the Telepathy account (but not the GOA one)
-       * 2 - We delete the corresponding GOA account and remove it
-       *     from priv->goa_accounts
-       * 3 - "account-removed" is emitted by the GOA client
-       * 4 - goa_account_removed_cb is called for an unknown account
-       */
-      g_debug ("Ignoring removal of GOA account we asked to remove "
-          "(%s, Telepathy object path: %s)",
-          goa_account_get_id (goa_account),
-          id);
-      return;
-    }
-
-  g_info ("GOA account %s for Telepathy account %s removed, "
-      "removing Telepathy account",
-      goa_account_get_id (goa_account), id);
-
-  tp_account = g_hash_table_lookup (priv->tp_accounts, id);
-  if (tp_account == NULL)
-    {
-      g_critical ("There is no Telepathy account for removed GOA "
-          "account %s (Telepathy object path: %s)",
-          goa_account_get_id (goa_account), id);
-      return;
-    }
-  tp_account_remove_async (tp_account, tp_account_removed_by_us_cb, NULL);
-  g_hash_table_remove (priv->tp_accounts, id);
-}
-
-static void
 start_if_ready (GoaTpAccountLinker *self)
 {
   GoaTpAccountLinkerPrivate *priv = self->priv;
@@ -459,8 +486,6 @@ start_if_ready (GoaTpAccountLinker *self)
 
   g_signal_connect_object (priv->goa_client, "account-added",
       G_CALLBACK (goa_account_added_cb), self, 0);
-  g_signal_connect_object (priv->goa_client, "account-removed",
-      G_CALLBACK (goa_account_removed_cb), self, 0);
 
   /* Telepathy */
   tp_accounts = tp_account_manager_dup_valid_accounts (priv->account_manager);
@@ -491,6 +516,8 @@ start_if_ready (GoaTpAccountLinker *self)
               NULL); /* user data */
         }
     }
+
+  remove_tp_account_queue_check (self);
 }
 
 static void
@@ -539,6 +566,12 @@ goa_tp_account_linker_dispose (GObject *object)
   GoaTpAccountLinker *self = GOA_TP_ACCOUNT_LINKER (object);
   GoaTpAccountLinkerPrivate *priv = self->priv;
 
+  if (priv->remove_tp_account_queue != NULL)
+    {
+      g_queue_free_full (priv->remove_tp_account_queue, g_object_unref);
+      priv->remove_tp_account_queue = NULL;
+    }
+
   g_clear_object (&priv->account_manager);
   g_clear_object (&priv->goa_client);
 
@@ -563,6 +596,8 @@ goa_tp_account_linker_init (GoaTpAccountLinker *self)
   priv->tp_accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, g_object_unref);
 
+  priv->remove_tp_account_queue = g_queue_new ();
+
   priv->account_manager = tp_account_manager_dup ();
   tp_proxy_prepare_async (priv->account_manager, NULL,
       account_manager_prepared_cb, self);
@@ -588,3 +623,44 @@ goa_tp_account_linker_new (void)
 {
   return g_object_new (GOA_TYPE_TP_ACCOUNT_LINKER, NULL);
 }
+
+void
+goa_tp_account_linker_remove_tp_account (GoaTpAccountLinker   *self,
+                                         GoaObject            *object,
+                                         GCancellable         *cancellable,
+                                         GAsyncReadyCallback   callback,
+                                         gpointer              user_data)
+{
+  GoaTpAccountLinkerPrivate *priv;
+  GTask *task;
+
+  g_return_if_fail (GOA_IS_TP_ACCOUNT_LINKER (self));
+  priv = self->priv;
+
+  g_return_if_fail (GOA_IS_OBJECT (object));
+  g_return_if_fail (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, goa_tp_account_linker_remove_tp_account);
+  g_task_set_task_data (task, g_object_ref (object), g_object_unref);
+  g_queue_push_tail (priv->remove_tp_account_queue, g_object_ref (task));
+
+  remove_tp_account_queue_check (self);
+
+  g_object_unref (task);
+}
+
+gboolean
+goa_tp_account_linker_remove_tp_account_finish (GoaTpAccountLinker  *self,
+                                                GAsyncResult        *res,
+                                                GError             **error)
+{
+  GTask *task;
+
+  g_return_val_if_fail (g_task_is_valid (res, self), FALSE);
+  task = G_TASK (res);
+
+  g_warn_if_fail (g_task_get_source_tag (task) == goa_tp_account_linker_remove_tp_account);
+
+  return g_task_propagate_boolean (task, error);
+}
diff --git a/src/goabackend/goatpaccountlinker.h b/src/goabackend/goatpaccountlinker.h
index 3f5b129..8c7efd8 100644
--- a/src/goabackend/goatpaccountlinker.h
+++ b/src/goabackend/goatpaccountlinker.h
@@ -22,6 +22,8 @@
 
 #include <glib-object.h>
 
+#include "goa/goa.h"
+
 G_BEGIN_DECLS
 
 #define GOA_TYPE_TP_ACCOUNT_LINKER           (goa_tp_account_linker_get_type ())
@@ -48,6 +50,14 @@ struct _GoaTpAccountLinkerClass
 
 GType               goa_tp_account_linker_get_type      (void) G_GNUC_CONST;
 GoaTpAccountLinker *goa_tp_account_linker_new           (void);
+void                goa_tp_account_linker_remove_tp_account        (GoaTpAccountLinker   *self,
+                                                                    GoaObject            *object,
+                                                                    GCancellable         *cancellable,
+                                                                    GAsyncReadyCallback   callback,
+                                                                    gpointer              user_data);
+gboolean            goa_tp_account_linker_remove_tp_account_finish (GoaTpAccountLinker   *self,
+                                                                    GAsyncResult         *res,
+                                                                    GError              **error);
 
 G_END_DECLS
 


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