[telepathy-gabble/master] Only construct sidecars once we're connected.

Will Thompson will.thompson at collabora.co.uk
Wed Nov 18 10:13:54 PST 2009


Sidecars need access to the WockySession. While we could add an (async)
accessor to the connection, let's defer that until a plugin needs to be
able to create a sidecar before the connection becomes Connected.
---
 src/conn-sidecars.c       |   79 ++++++++++++++++++++++++++++++--------------
 tests/twisted/sidecars.py |   22 ++++++++----
 2 files changed, 68 insertions(+), 33 deletions(-)

diff --git a/src/conn-sidecars.c b/src/conn-sidecars.c
index 11f2917..e18397e 100644
--- a/src/conn-sidecars.c
+++ b/src/conn-sidecars.c
@@ -199,7 +199,6 @@ gabble_connection_ensure_sidecar (
   TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
   GabbleSidecar *sidecar;
   gpointer key, value;
-  GabblePluginLoader *loader;
   GError *error = NULL;
 
   if (base_conn->status == TP_CONNECTION_STATUS_DISCONNECTED)
@@ -252,13 +251,23 @@ gabble_connection_ensure_sidecar (
       return;
     }
 
-  DEBUG ("requesting %s from the plugin loader", sidecar_iface);
-  loader = gabble_plugin_loader_dup ();
+  DEBUG ("enqueuing first request for %s", sidecar_iface);
   g_hash_table_insert (conn->pending_sidecars, g_strdup (sidecar_iface),
       g_list_prepend (NULL, context));
-  gabble_plugin_loader_create_sidecar (loader, sidecar_iface, base_conn,
-      conn->session, create_sidecar_cb, grr_new (conn, sidecar_iface));
-  g_object_unref (loader);
+
+  if (base_conn->status == TP_CONNECTION_STATUS_CONNECTED)
+    {
+      GabblePluginLoader *loader = gabble_plugin_loader_dup ();
+
+      DEBUG ("requesting %s from the plugin loader", sidecar_iface);
+      gabble_plugin_loader_create_sidecar (loader, sidecar_iface, base_conn,
+          conn->session, create_sidecar_cb, grr_new (conn, sidecar_iface));
+      g_object_unref (loader);
+    }
+  else
+    {
+      DEBUG ("not yet connected; waiting.");
+    }
 }
 
 static void
@@ -272,33 +281,53 @@ sidecars_conn_status_changed_cb (
   GHashTableIter iter;
   gpointer key, value;
 
-  if (status != TP_CONNECTION_STATUS_DISCONNECTED)
-    return;
+  if (status == TP_CONNECTION_STATUS_DISCONNECTED)
+    {
+      g_hash_table_iter_init (&iter, conn->sidecars);
 
-  g_hash_table_iter_init (&iter, conn->sidecars);
+      while (g_hash_table_iter_next (&iter, NULL, &value))
+        {
+          DEBUG ("removing %s from the bus", gabble_sidecar_get_interface (value));
+          dbus_g_connection_unregister_g_object (bus, G_OBJECT (value));
+        }
 
-  while (g_hash_table_iter_next (&iter, NULL, &value))
-    {
-      DEBUG ("removing %s from the bus", gabble_sidecar_get_interface (value));
-      dbus_g_connection_unregister_g_object (bus, G_OBJECT (value));
-    }
+      g_hash_table_iter_init (&iter, conn->pending_sidecars);
 
-  g_hash_table_iter_init (&iter, conn->pending_sidecars);
+      while (g_hash_table_iter_next (&iter, &key, &value))
+        {
+          const gchar *sidecar_iface = key;
+          GList *contexts = value;
+          GError *error = g_error_new (TP_ERRORS, TP_ERROR_CANCELLED,
+              "Disconnected before %s could be created", sidecar_iface);
+
+          DEBUG ("failing all %u requests for %s", g_list_length (contexts),
+              sidecar_iface);
+          g_list_foreach (contexts, (GFunc) dbus_g_method_return_error, error);
+          g_error_free (error);
+        }
 
-  while (g_hash_table_iter_next (&iter, &key, &value))
+      g_hash_table_remove_all (conn->sidecars);
+      g_hash_table_remove_all (conn->pending_sidecars);
+    }
+  else if (status == TP_CONNECTION_STATUS_CONNECTED)
     {
-      const gchar *sidecar_iface = key;
-      GList *contexts = value;
+      TpBaseConnection *base_conn = TP_BASE_CONNECTION (conn);
+      GabblePluginLoader *loader = gabble_plugin_loader_dup ();
 
-      GError *error = g_error_new (TP_ERRORS, TP_ERROR_CANCELLED,
-          "Disconnected before %s could be created", sidecar_iface);
+      DEBUG ("connected; requesting sidecars from plugins");
+      g_hash_table_iter_init (&iter, conn->pending_sidecars);
 
-      g_list_foreach (contexts, (GFunc) dbus_g_method_return_error, error);
-      g_error_free (error);
-    }
+      while (g_hash_table_iter_next (&iter, &key, NULL))
+        {
+          const gchar *sidecar_iface = key;
 
-  g_hash_table_remove_all (conn->sidecars);
-  g_hash_table_remove_all (conn->pending_sidecars);
+          DEBUG ("requesting %s from the plugin loader", sidecar_iface);
+          gabble_plugin_loader_create_sidecar (loader, sidecar_iface, base_conn,
+              conn->session, create_sidecar_cb, grr_new (conn, sidecar_iface));
+        }
+
+      g_object_unref (loader);
+    }
 }
 
 void
diff --git a/tests/twisted/sidecars.py b/tests/twisted/sidecars.py
index 2502c17..6c70bef 100644
--- a/tests/twisted/sidecars.py
+++ b/tests/twisted/sidecars.py
@@ -9,26 +9,32 @@ import constants as cs
 TEST_PLUGIN_IFACE = "org.freedesktop.Telepathy.Gabble.Plugin.Test"
 
 def test(q, bus, conn, stream):
+    # Request a sidecar thate we support before we're connected; it should just
+    # wait around until we're connected.
+    call_async(q, conn.Future, 'EnsureSidecar', TEST_PLUGIN_IFACE)
+
     conn.Connect()
     q.expect('dbus-signal', signal='StatusChanged',
             args=[cs.CONN_STATUS_CONNECTED, cs.CSR_REQUESTED])
 
-    call_async(q, conn.Future, 'EnsureSidecar', 'not an interface')
-    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)
-
-    # The test plugin makes no reference to this interface.
-    call_async(q, conn.Future, 'EnsureSidecar', 'unsupported.sidecar')
-    q.expect('dbus-error', name=cs.NOT_IMPLEMENTED)
-
+    # Now we're connected, the call we made earlier should return.
+    path, props = q.expect('dbus-return', method='EnsureSidecar').value
     # This sidecar doesn't even implement get_immutable_properties; it should
     # just get the empty dict filled in for it.
-    path, props = conn.Future.EnsureSidecar(TEST_PLUGIN_IFACE)
     assertEquals({}, props)
 
     # We should get the same sidecar if we request it again
     path2, props2 = conn.Future.EnsureSidecar(TEST_PLUGIN_IFACE)
     assertEquals((path, props), (path2, props2))
 
+    # This is not a valid interface name
+    call_async(q, conn.Future, 'EnsureSidecar', 'not an interface')
+    q.expect('dbus-error', name=cs.INVALID_ARGUMENT)
+
+    # The test plugin makes no reference to this interface.
+    call_async(q, conn.Future, 'EnsureSidecar', 'unsupported.sidecar')
+    q.expect('dbus-error', name=cs.NOT_IMPLEMENTED)
+
     # This sidecar does have some properties:
     path, props = conn.Future.EnsureSidecar(TEST_PLUGIN_IFACE + ".Props")
     assertContains(TEST_PLUGIN_IFACE + ".Props.Greeting", props)
-- 
1.5.6.5




More information about the telepathy-commits mailing list