]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-account-manager.c
Merge branch 'sjoerd-mc5' into mc5
[empathy.git] / libempathy / empathy-account-manager.c
index 727eb7eaf50b1795556709189820f133d49a5a4d..18eff355ff49287f0ada6590a94dba0e97378164 100644 (file)
@@ -55,6 +55,15 @@ typedef struct {
   TpConnectionPresenceType global_presence;
   gchar *global_status;
   gchar *global_status_message;
+
+  /* desired global presence, could be different
+   * from the actual global one.
+   */
+  TpConnectionPresenceType desired_presence;
+  gchar *desired_status;
+  gchar *desired_status_message;
+
+  GHashTable *create_results;
 } EmpathyAccountManagerPriv;
 
 enum {
@@ -97,8 +106,16 @@ emp_account_enabled_cb (EmpathyAccount *account,
   GParamSpec *spec,
   gpointer manager)
 {
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+
   if (empathy_account_is_enabled (account))
-    g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
+    {
+      g_signal_emit (manager, signals[ACCOUNT_ENABLED], 0, account);
+
+      /* set the desired global presence on the account */
+      empathy_account_request_presence (account, priv->desired_presence,
+          priv->desired_status, priv->desired_status_message);
+    }
   else
     g_signal_emit (manager, signals[ACCOUNT_DISABLED], 0, account);
 }
@@ -264,10 +281,14 @@ empathy_account_manager_check_ready (EmpathyAccountManager *manager)
 }
 
 static void
-emp_account_ready_cb (GObject *obj, GParamSpec *spec, gpointer user_data)
+account_manager_account_ready_cb (GObject *obj,
+    GParamSpec *spec,
+    gpointer user_data)
 {
   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (user_data);
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
   EmpathyAccount *account = EMPATHY_ACCOUNT (obj);
+  GSimpleAsyncResult *result;
   gboolean ready;
 
   g_object_get (account, "ready", &ready, NULL);
@@ -275,6 +296,19 @@ emp_account_ready_cb (GObject *obj, GParamSpec *spec, gpointer user_data)
   if (!ready)
     return;
 
+  /* see if there's any pending callbacks for this account */
+  result = g_hash_table_lookup (priv->create_results, account);
+  if (result != NULL)
+    {
+      g_simple_async_result_set_op_res_gpointer (
+          G_SIMPLE_ASYNC_RESULT (result), account, NULL);
+
+      g_simple_async_result_complete (result);
+
+      g_hash_table_remove (priv->create_results, account);
+      g_object_unref (result);
+    }
+
   g_signal_emit (manager, signals[ACCOUNT_CREATED], 0, account);
 
   g_signal_connect (account, "notify::connection",
@@ -310,7 +344,7 @@ account_manager_add_account (EmpathyAccountManager *manager,
   g_hash_table_insert (priv->accounts, g_strdup (path), account);
 
   g_signal_connect (account, "notify::ready",
-    G_CALLBACK (emp_account_ready_cb), manager);
+    G_CALLBACK (account_manager_account_ready_cb), manager);
 
   return account;
 }
@@ -406,6 +440,8 @@ empathy_account_manager_init (EmpathyAccountManager *manager)
   priv->accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
       g_free, (GDestroyNotify) g_object_unref);
 
+  priv->create_results = g_hash_table_new (g_direct_hash, g_direct_equal);
+
   priv->dbus = tp_dbus_daemon_dup (NULL);
 
   tp_dbus_daemon_watch_name_owner (priv->dbus,
@@ -433,8 +469,15 @@ do_finalize (GObject *obj)
   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (obj);
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
 
+  g_hash_table_destroy (priv->create_results);
   g_hash_table_destroy (priv->accounts);
 
+  g_free (priv->global_status);
+  g_free (priv->global_status_message);
+
+  g_free (priv->desired_status);
+  g_free (priv->desired_status_message);
+
   G_OBJECT_CLASS (empathy_account_manager_parent_class)->finalize (obj);
 }
 
@@ -449,12 +492,35 @@ do_dispose (GObject *obj)
 
   priv->dispose_run = TRUE;
 
+  if (priv->create_results != NULL &&
+      g_hash_table_size (priv->create_results) > 0)
+    {
+      /* the manager is being destroyed while there are account creation
+       * processes pending; this should not happen, but emit the callbacks
+       * with an error anyway.
+       */
+      GHashTableIter iter;
+      GSimpleAsyncResult *result;
+
+      g_hash_table_iter_init (&iter, priv->create_results);
+      while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &result))
+       {
+         g_simple_async_result_set_error (result, G_IO_ERROR,
+              G_IO_ERROR_CANCELLED, "The account manager was disposed while "
+              "creating the account");
+         g_simple_async_result_complete (result);
+         g_object_unref (result);
+       }
+    }
+
   tp_dbus_daemon_cancel_name_owner_watch (priv->dbus,
       TP_ACCOUNT_MANAGER_BUS_NAME, account_manager_name_owner_cb, manager);
 
-  if (priv->dbus == NULL)
-    g_object_unref (priv->dbus);
-  priv->dbus = NULL;
+  if (priv->dbus != NULL)
+    {
+      g_object_unref (priv->dbus);
+      priv->dbus = NULL;
+    }
 
   G_OBJECT_CLASS (empathy_account_manager_parent_class)->dispose (obj);
 }
@@ -767,8 +833,6 @@ empathy_account_manager_request_global_presence (
   const gchar *status,
   const gchar *message)
 {
-  /* FIXME should remember requested presence and set it on new accounts
-     as well */
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
   GHashTableIter iter;
   gpointer value;
@@ -784,6 +848,23 @@ empathy_account_manager_request_global_presence (
       if (ready)
         empathy_account_request_presence (account, type, status, message);
     }
+
+  /* save the requested global presence, to use it in case we create
+   * new accounts.
+   */
+  priv->desired_presence = type;
+
+  if (tp_strdiff (priv->desired_status, status))
+    {
+      g_free (priv->desired_status);
+      priv->desired_status = g_strdup (status);
+    }
+
+  if (tp_strdiff (priv->desired_status_message, message))
+    {
+      g_free (priv->desired_status_message);
+      priv->desired_status_message = g_strdup (message);
+    }
 }
 
 TpConnectionPresenceType
@@ -802,22 +883,6 @@ empathy_account_manager_get_global_presence (
   return priv->global_presence;
 }
 
-static void
-empathy_account_manager_created_ready_cb (EmpathyAccount *account,
-  GParamSpec *spec, gpointer user_data)
-{
-  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
-
-  if (!empathy_account_is_ready (account))
-    return;
-
-  g_simple_async_result_set_op_res_gpointer (
-    G_SIMPLE_ASYNC_RESULT (result), account, NULL);
-
-  g_simple_async_result_complete (result);
-  g_object_unref (G_OBJECT (result));
-}
-
 static void
 empathy_account_manager_created_cb (TpAccountManager *proxy,
     const gchar *account_path,
@@ -826,23 +891,23 @@ empathy_account_manager_created_cb (TpAccountManager *proxy,
     GObject *weak_object)
 {
   EmpathyAccountManager *manager = EMPATHY_ACCOUNT_MANAGER (weak_object);
-  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
+  EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
+  GSimpleAsyncResult *my_res = user_data;
   EmpathyAccount *account;
 
   if (error != NULL)
     {
-      g_simple_async_result_set_from_error (result, (GError *) error);
-      g_simple_async_result_complete (result);
-      g_object_unref (G_OBJECT (result));
+      g_simple_async_result_set_from_error (my_res,
+          (GError *) error);
+      g_simple_async_result_complete (my_res);
+      g_object_unref (my_res);
+
       return;
     }
 
   account = account_manager_add_account (manager, account_path);
-  if (empathy_account_is_ready (account))
-    empathy_account_manager_created_ready_cb (account, NULL, result);
-  else
-    g_signal_connect (account, "notify::ready",
-      G_CALLBACK (empathy_account_manager_created_ready_cb), result);
+
+  g_hash_table_insert (priv->create_results, account, my_res);
 }
 
 void
@@ -856,8 +921,11 @@ empathy_account_manager_create_account_async (EmpathyAccountManager *manager,
     gpointer user_data)
 {
   EmpathyAccountManagerPriv *priv = GET_PRIV (manager);
-  GSimpleAsyncResult *result = g_simple_async_result_new (G_OBJECT (manager),
-      callback, user_data, empathy_account_manager_create_account_finish);
+  GSimpleAsyncResult *res;
+
+  res = g_simple_async_result_new
+    (G_OBJECT (manager), callback, user_data,
+     empathy_account_manager_create_account_finish);
 
   tp_cli_account_manager_call_create_account (priv->tp_manager,
       -1,
@@ -867,7 +935,7 @@ empathy_account_manager_create_account_async (EmpathyAccountManager *manager,
       parameters,
       properties,
       empathy_account_manager_created_cb,
-      result,
+      res,
       NULL,
       G_OBJECT (manager));
 }
@@ -876,6 +944,8 @@ EmpathyAccount *
 empathy_account_manager_create_account_finish (
   EmpathyAccountManager *manager, GAsyncResult *result, GError **error)
 {
+  EmpathyAccount *retval;
+
   if (g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result),
       error))
     return NULL;
@@ -883,7 +953,9 @@ empathy_account_manager_create_account_finish (
   g_return_val_if_fail (g_simple_async_result_is_valid (result,
     G_OBJECT (manager), empathy_account_manager_create_account_finish), NULL);
 
-  return EMPATHY_ACCOUNT (g_simple_async_result_get_op_res_gpointer (
+  retval = EMPATHY_ACCOUNT (g_simple_async_result_get_op_res_gpointer (
     G_SIMPLE_ASYNC_RESULT (result)));
+
+  return retval;
 }