[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