* Authors: Xavier Claessens <xclaesse@gmail.com>
*/
-#include <config.h>
-
-#include <string.h>
-
-#include <telepathy-glib/telepathy-glib.h>
+#include "config.h"
+#include "empathy-tp-chat.h"
-#include <extensions/extensions.h>
+#include <tp-account-widgets/tpaw-utils.h>
+#include <telepathy-glib/telepathy-glib-dbus.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
/* GSimpleAsyncResult used when preparing EMPATHY_TP_CHAT_FEATURE_CORE */
GSimpleAsyncResult *ready_result;
+ gboolean preparing_password;
};
enum
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
else if (self->priv->can_upgrade_to_muc)
{
TpAccountChannelRequest *req;
- GHashTable *props;
- const char *object_path;
- GPtrArray channels = { (gpointer *) &object_path, 1 };
+ const gchar *channels[2] = { NULL, };
const char *invitees[2] = { NULL, };
TpAccount *account;
invitees[0] = empathy_contact_get_id (contact);
- object_path = tp_proxy_get_object_path (self);
-
- props = tp_asv_new (
- TP_PROP_CHANNEL_CHANNEL_TYPE, G_TYPE_STRING,
- TP_IFACE_CHANNEL_TYPE_TEXT,
- TP_PROP_CHANNEL_TARGET_HANDLE_TYPE, G_TYPE_UINT,
- TP_HANDLE_TYPE_NONE,
- TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_CHANNELS,
- TP_ARRAY_TYPE_OBJECT_PATH_LIST, &channels,
- TP_PROP_CHANNEL_INTERFACE_CONFERENCE_INITIAL_INVITEE_IDS,
- G_TYPE_STRV, invitees,
- /* FIXME: InvitationMessage ? */
- NULL);
+ channels[0] = tp_proxy_get_object_path (self);
account = empathy_tp_chat_get_account (self);
- req = tp_account_channel_request_new (account, props,
+ req = tp_account_channel_request_new_text (account,
TP_USER_ACTION_TIME_NOT_USER_ACTION);
+ tp_account_channel_request_set_conference_initial_channels (req,
+ channels);
+
+ tp_account_channel_request_set_initial_invitee_ids (req, invitees);
+
+ /* FIXME: InvitationMessage ? */
+
/* Although this is a MUC, it's anonymous, so CreateChannel is
* valid. */
- tp_account_channel_request_create_channel_async (req,
- EMPATHY_CHAT_BUS_NAME, NULL, create_conference_cb, NULL);
+ tp_account_channel_request_create_and_observe_channel_async (req,
+ EMPATHY_CHAT_TP_BUS_NAME, NULL, create_conference_cb, NULL);
g_object_unref (req);
- g_hash_table_unref (props);
}
else
{
{
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))
{
handle_incoming_message (self, message, FALSE);
}
- g_list_free (messages);
+ g_list_free_full (messages, g_object_unref);
}
static void
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. */
features[FEAT_READY].name = EMPATHY_TP_CHAT_FEATURE_READY;
need[0] = TP_TEXT_CHANNEL_FEATURE_INCOMING_MESSAGES;
- need[1] = TP_CHANNEL_FEATURE_PASSWORD;
+ need[1] = TP_CHANNEL_FEATURE_CONTACTS;
features[FEAT_READY].depends_on = need;
features[FEAT_READY].prepare_async =
tp_chat_prepare_ready_async;
g_return_val_if_fail (EMPATHY_IS_TP_CHAT (self), NULL);
id = tp_channel_get_identifier ((TpChannel *) self);
- if (!EMP_STR_EMPTY (id))
+ if (!TPAW_STR_EMPTY (id))
return id;
else if (self->priv->remote_contact)
return empathy_contact_get_id (self->priv->remote_contact);
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);
}
}
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))
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);
+}