]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-tp-chat.c
Merge remote-tracking branch 'origin/gnome-3-8'
[empathy.git] / libempathy / empathy-tp-chat.c
index bb465df3588d8659c8f799059d6ef3e3b660ecc7..4711affcb28454b18e6aaca42661295a2dfc7691 100644 (file)
  * Authors: Xavier Claessens <xclaesse@gmail.com>
  */
 
-#include <config.h>
-
-#include <string.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-
-#include <extensions/extensions.h>
-
+#include "config.h"
 #include "empathy-tp-chat.h"
+
 #include "empathy-request-util.h"
-#include "empathy-time.h"
 #include "empathy-utils.h"
 
 #define DEBUG_FLAG EMPATHY_DEBUG_TP | EMPATHY_DEBUG_CHAT
@@ -59,6 +52,7 @@ struct _EmpathyTpChatPrivate
 
   /* GSimpleAsyncResult used when preparing EMPATHY_TP_CHAT_FEATURE_CORE */
   GSimpleAsyncResult *ready_result;
+  gboolean preparing_password;
 };
 
 enum
@@ -135,19 +129,46 @@ tp_chat_async_cb (TpChannel *proxy,
     DEBUG ("Error %s: %s", (gchar *) user_data, error->message);
 }
 
+static void
+update_config_cb (TpChannel *proxy,
+    const GError *error,
+    gpointer user_data,
+    GObject *weak_object)
+{
+  if (error != NULL)
+    DEBUG ("Failed to change config of the room: %s", error->message);
+}
+
 static void
 create_conference_cb (GObject *source,
     GAsyncResult *result,
     gpointer user_data)
 {
+  TpChannel *channel;
   GError *error = NULL;
+  GHashTable *props;
 
-  if (!tp_account_channel_request_create_channel_finish (
-      TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error))
+  channel = tp_account_channel_request_create_and_observe_channel_finish (
+      TP_ACCOUNT_CHANNEL_REQUEST (source), result, &error);
+  if (channel == NULL)
     {
       DEBUG ("Failed to create conference channel: %s", error->message);
       g_error_free (error);
+      return;
     }
+
+  /* Make the channel more confidential as only people invited are supposed to
+   * join it. */
+  props = tp_asv_new (
+      "Private", G_TYPE_BOOLEAN, TRUE,
+      "InviteOnly", G_TYPE_BOOLEAN, TRUE,
+      NULL);
+
+  tp_cli_channel_interface_room_config_call_update_configuration (channel, -1,
+      props, update_config_cb, NULL, NULL, NULL);
+
+  g_object_unref (channel);
+  g_hash_table_unref (props);
 }
 
 void
@@ -200,7 +221,7 @@ empathy_tp_chat_add (EmpathyTpChat *self,
 
       /* Although this is a MUC, it's anonymous, so CreateChannel is
        * valid. */
-      tp_account_channel_request_create_channel_async (req,
+      tp_account_channel_request_create_and_observe_channel_async (req,
           EMPATHY_CHAT_BUS_NAME, NULL, create_conference_cb, NULL);
 
       g_object_unref (req);
@@ -499,7 +520,7 @@ list_pending_messages (EmpathyTpChat *self)
 {
   GList *messages, *l;
 
-  messages = tp_text_channel_get_pending_messages (TP_TEXT_CHANNEL (self));
+  messages = tp_text_channel_dup_pending_messages (TP_TEXT_CHANNEL (self));
 
   for (l = messages; l != NULL; l = g_list_next (l))
     {
@@ -508,7 +529,7 @@ list_pending_messages (EmpathyTpChat *self)
       handle_incoming_message (self, message, FALSE);
     }
 
-  g_list_free (messages);
+  g_list_free_full (messages, g_object_unref);
 }
 
 static void
@@ -703,6 +724,9 @@ check_almost_ready (EmpathyTpChat *self)
   if (self->priv->user == NULL)
     return;
 
+  if (self->priv->preparing_password)
+    return;
+
   /* We need either the members (room) or the remote contact (private chat).
    * If the chat is protected by a password we can't get these information so
    * consider the chat as ready so it can be presented to the user. */
@@ -940,14 +964,13 @@ static const TpProxyFeature *
 tp_chat_list_features (TpProxyClass *cls G_GNUC_UNUSED)
 {
   static TpProxyFeature features[N_FEAT + 1] = { { 0 } };
-  static GQuark need[3] = {0, 0, 0};
+  static GQuark need[2] = {0, 0};
 
   if (G_LIKELY (features[0].name != 0))
     return features;
 
   features[FEAT_READY].name = EMPATHY_TP_CHAT_FEATURE_READY;
   need[0] = TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES;
-  need[1] = TP_CHANNEL_FEATURE_PASSWORD;
   features[FEAT_READY].depends_on = need;
   features[FEAT_READY].prepare_async =
     tp_chat_prepare_ready_async;
@@ -1116,7 +1139,7 @@ empathy_tp_chat_get_account (EmpathyTpChat *self)
 
   g_return_val_if_fail (EMPATHY_IS_TP_CHAT (self), NULL);
 
-  connection = tp_channel_borrow_connection (TP_CHANNEL (self));
+  connection = tp_channel_get_connection (TP_CHANNEL (self));
 
   return tp_connection_get_account (connection);
 }
@@ -1251,21 +1274,47 @@ empathy_tp_chat_get_feature_ready (void)
 }
 
 static void
-tp_chat_prepare_ready_async (TpProxy *proxy,
-  const TpProxyFeature *feature,
-  GAsyncReadyCallback callback,
-  gpointer user_data)
+password_feature_prepare_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
 {
-  EmpathyTpChat *self = (EmpathyTpChat *) proxy;
-  TpChannel *channel = (TpChannel *) proxy;
+  EmpathyTpChat *self = user_data;
+  GError *error = NULL;
+
+  if (!tp_proxy_prepare_finish (source, result, &error))
+    {
+      DEBUG ("Failed to prepare Password: %s", error->message);
+      g_error_free (error);
+    }
+
+  self->priv->preparing_password = FALSE;
+
+  check_almost_ready (self);
+}
+
+static void
+continue_preparing (EmpathyTpChat *self)
+{
+  TpChannel *channel = (TpChannel *) self;
   TpConnection *connection;
   gboolean listen_for_dbus_properties_changed = FALSE;
 
-  g_assert (self->priv->ready_result == NULL);
-  self->priv->ready_result = g_simple_async_result_new (G_OBJECT (self),
-    callback, user_data, tp_chat_prepare_ready_async);
+  connection = tp_channel_get_connection (channel);
 
-  connection = tp_channel_borrow_connection (channel);
+  if (tp_proxy_has_interface_by_id (self,
+        TP_IFACE_QUARK_CHANNEL_INTERFACE_PASSWORD))
+    {
+      /* The password feature can't be a hard dep on our own feature has we
+       * depend on it only if the channel implements the
+       * Password interface.
+       */
+      GQuark features[] = { TP_CHANNEL_FEATURE_PASSWORD , 0 };
+
+      self->priv->preparing_password = TRUE;
+
+      tp_proxy_prepare_async (self, features, password_feature_prepare_cb,
+          self);
+    }
 
   if (tp_proxy_has_interface_by_id (self,
             TP_IFACE_QUARK_CHANNEL_INTERFACE_GROUP))
@@ -1374,3 +1423,49 @@ tp_chat_prepare_ready_async (TpProxy *proxy,
                         G_OBJECT (self), NULL);
     }
 }
+
+static void
+conn_connected_cb (GObject *source,
+    GAsyncResult *result,
+    gpointer user_data)
+{
+  EmpathyTpChat *self = user_data;
+  GError *error = NULL;
+
+  if (!tp_proxy_prepare_finish (source, result, &error))
+    {
+      DEBUG ("Failed to prepare Connected: %s", error->message);
+      g_simple_async_result_take_error (self->priv->ready_result, error);
+      g_simple_async_result_complete (self->priv->ready_result);
+      tp_clear_object (&self->priv->ready_result);
+      return;
+    }
+
+  continue_preparing (self);
+}
+
+static void
+tp_chat_prepare_ready_async (TpProxy *proxy,
+  const TpProxyFeature *feature,
+  GAsyncReadyCallback callback,
+  gpointer user_data)
+{
+  EmpathyTpChat *self = (EmpathyTpChat *) proxy;
+  TpChannel *channel = (TpChannel *) proxy;
+  TpConnection *connection;
+  GQuark features[] = { TP_CONNECTION_FEATURE_CONNECTED, 0 };
+
+  g_assert (self->priv->ready_result == NULL);
+
+  self->priv->ready_result = g_simple_async_result_new (G_OBJECT (self),
+    callback, user_data, tp_chat_prepare_ready_async);
+
+  connection = tp_channel_get_connection (channel);
+
+  /* First we have to make sure that TP_CONNECTION_FEATURE_CONNECTED is
+   * prepared as we rely on TpConnection::self-contact
+   * in continue_preparing().
+   *
+   * It would be nice if tp-glib could do this for us: fdo#59126 */
+  tp_proxy_prepare_async (connection, features, conn_connected_cb, proxy);
+}