[telepathy-idle/master] Implement respawning for 1-1 channels.
Will Thompson
will.thompson at collabora.co.uk
Fri Aug 28 18:49:33 PDT 2009
---
src/idle-im-channel.c | 32 +++++++++++++++++++++++----
src/idle-im-manager.c | 20 ++++++++++++++--
tests/twisted/channels/requests-create.py | 34 +++++++++++++++++++++++++++-
3 files changed, 76 insertions(+), 10 deletions(-)
diff --git a/src/idle-im-channel.c b/src/idle-im-channel.c
index 82c74ac..edd1868 100644
--- a/src/idle-im-channel.c
+++ b/src/idle-im-channel.c
@@ -172,10 +172,7 @@ static void idle_im_channel_get_property(GObject *object, guint property_id, GVa
break;
case PROP_CHANNEL_DESTROYED:
- /* TODO: this should be FALSE if there are still pending messages, so
- * the channel manager can respawn the channel.
- */
- g_value_set_boolean (value, TRUE);
+ g_value_set_boolean (value, priv->closed);
break;
case PROP_CHANNEL_PROPERTIES:
@@ -390,10 +387,35 @@ static void idle_im_channel_close (TpSvcChannel *iface, DBusGMethodInvocation *c
g_assert(IDLE_IS_IM_CHANNEL(obj));
priv = IDLE_IM_CHANNEL_GET_PRIVATE(obj);
- priv->closed = TRUE;
IDLE_DEBUG("called on %p", obj);
+ /* The IM manager will resurrect the channel if we have pending
+ * messages. When we're resurrected, we want the initiator
+ * to be the contact who sent us those messages, if it isn't already */
+ if (tp_text_mixin_has_pending_messages((GObject *)obj, NULL)) {
+ IDLE_DEBUG("Not really closing, I still have pending messages");
+
+ if (priv->initiator != priv->handle) {
+ TpHandleRepoIface *contact_repo =
+ tp_base_connection_get_handles(
+ (TpBaseConnection *) priv->connection,
+ TP_HANDLE_TYPE_CONTACT);
+
+ g_assert(priv->initiator != 0);
+ g_assert(priv->handle != 0);
+
+ tp_handle_unref(contact_repo, priv->initiator);
+ priv->initiator = priv->handle;
+ tp_handle_ref(contact_repo, priv->initiator);
+ }
+
+ tp_text_mixin_set_rescued((GObject *) obj);
+ } else {
+ IDLE_DEBUG ("Actually closing, I have no pending messages");
+ priv->closed = TRUE;
+ }
+
tp_svc_channel_emit_closed(iface);
tp_svc_channel_return_from_close(context);
diff --git a/src/idle-im-manager.c b/src/idle-im-manager.c
index c8599b5..7970b2c 100644
--- a/src/idle-im-manager.c
+++ b/src/idle-im-manager.c
@@ -411,9 +411,23 @@ _im_channel_closed_cb (IdleIMChannel *chan,
if (priv->channels)
{
- g_object_get (chan, "handle", &handle, NULL);
- IDLE_DEBUG ("Removing channel with handle %u", handle);
- g_hash_table_remove (priv->channels, GUINT_TO_POINTER (handle));
+ gboolean really_destroyed;
+
+ g_object_get (chan,
+ "handle", &handle,
+ "channel-destroyed", &really_destroyed,
+ NULL);
+
+ if (really_destroyed)
+ {
+ IDLE_DEBUG ("removing channel with handle %u", handle);
+ g_hash_table_remove (priv->channels, GUINT_TO_POINTER (handle));
+ } else {
+ IDLE_DEBUG ("reopening channel with handle %u due to pending messages",
+ handle);
+ tp_channel_manager_emit_new_channel (self,
+ (TpExportableChannel *) chan, NULL);
+ }
}
}
diff --git a/tests/twisted/channels/requests-create.py b/tests/twisted/channels/requests-create.py
index 2372756..00f3a1b 100644
--- a/tests/twisted/channels/requests-create.py
+++ b/tests/twisted/channels/requests-create.py
@@ -5,7 +5,7 @@ Most of this test was borrowed from a gabble test and modified to fit idle
"""
from idletest import exec_test
-from servicetest import EventPattern, call_async, tp_name_prefix
+from servicetest import EventPattern, call_async, make_channel_proxy
import dbus
import constants as cs
@@ -42,7 +42,7 @@ def test(q, bus, conn, stream):
)
assert len(ret.value) == 2
- emitted_props = ret.value[1]
+ path, emitted_props = ret.value
assert emitted_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT
assert emitted_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT
assert emitted_props[cs.TARGET_HANDLE] == foo_handle
@@ -69,6 +69,36 @@ def test(q, bus, conn, stream):
assert new_sig.args[0][0] in properties['Channels'], \
(new_sig.args[0][0], properties['Channels'])
+ chan = make_channel_proxy(conn, path, 'Channel')
+
+ stream.sendMessage('PRIVMSG', stream.nick, ":oh hai", prefix=nick)
+ q.expect('dbus-signal', signal='Received')
+
+ # Without acknowledging the message, we close the channel:
+ chan.Close()
+
+ # It should close and respawn!
+ q.expect('dbus-signal', signal='ChannelClosed')
+ chans, = q.expect('dbus-signal', signal='NewChannels').args
+ assert len(chans) == 1
+ new_props = chans[0][1]
+
+ # It should look pretty similar...
+ assert new_props[cs.CHANNEL_TYPE] == cs.CHANNEL_TYPE_TEXT
+ assert new_props[cs.TARGET_HANDLE_TYPE] == cs.HT_CONTACT
+ assert new_props[cs.TARGET_HANDLE] == foo_handle
+ assert new_props[cs.TARGET_ID] == nick
+
+ # ...but this time they started it...
+ assert not new_props[cs.REQUESTED]
+ assert new_props[cs.INITIATOR_HANDLE] == foo_handle
+ assert new_props[cs.INITIATOR_ID] == nick
+
+ # ...and it's got some messages in it!
+ ms = chan.ListPendingMessages(False, dbus_interface=cs.CHANNEL_TYPE_TEXT)
+ assert len(ms) == 1
+ assert ms[0][5] == 'oh hai'
+
call_async(q, conn, 'Disconnect')
q.expect('dbus-signal', signal='StatusChanged', args=[2, 1])
--
1.5.6.5
More information about the telepathy-commits
mailing list