[telepathy-mission-control/master] fd.o#24474: if NewChannels signals Requested channels that we didn't request, observe them but do nothing else

Simon McVittie simon.mcvittie at collabora.co.uk
Mon Nov 2 06:56:19 PST 2009


Requested channels that we don't know about must have been requested by
another process (like Empathy 2.28), by calling Connection methods
directly rather than going via MC. As a result, we should not call
AddDispatchOperation or HandleChannels.

However, we do want to call ObserveChannels, to preserve the invariant
that observers are called for *all* channels. This means that observers
can do things like present some simple UI for *every* channel, regardless
of who the handler is.

Forward-ported from 5.2, with changes to suit the refactored McdDispatcher.
This version should be reviewed separately.
---
 src/mcd-connection.c              |   26 ++++++++++++------------
 src/mcd-dispatch-operation-priv.h |    2 +-
 src/mcd-dispatch-operation.c      |   39 +++++++++++++++++++++++++++++++++++-
 src/mcd-dispatcher-priv.h         |    3 +-
 src/mcd-dispatcher.c              |   25 ++++++++++++++++++-----
 5 files changed, 72 insertions(+), 23 deletions(-)

diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index 9a0c206..f5cb045 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -538,12 +538,6 @@ on_new_channel (TpConnection *proxy, const gchar *chan_obj_path,
            chan_obj_path, chan_type, handle_type, handle,
            suppress_handler ? 'T' : 'F');
 
-    /* ignore all our own requests (they have always suppress_handler = 1) as
-     * well as other requests for which our intervention has not been requested
-     * */
-    if (suppress_handler) return;
-
-    /* It's an incoming channel, so we create a new McdChannel for it */
     if (priv->dispatched_initial_channels)
     {
         channel = mcd_channel_new_from_path (proxy,
@@ -552,10 +546,16 @@ on_new_channel (TpConnection *proxy, const gchar *chan_obj_path,
         if (G_UNLIKELY (!channel)) return;
         mcd_operation_take_mission (MCD_OPERATION (connection),
                                     MCD_MISSION (channel));
-        /* Dispatch the incoming channel */
+
+        /* MC no longer calls RequestChannel. As a result, if suppress_handler
+         * is TRUE, we know that this channel was requested "behind our back",
+         * therefore we should call ObserveChannels, but refrain from calling
+         * AddDispatchOperation or HandleChannels.
+         *
+         * We assume that channels without suppress_handler are incoming. */
         _mcd_dispatcher_take_channels (priv->dispatcher,
                                        g_list_prepend (NULL, channel),
-                                       FALSE);
+                                       suppress_handler, suppress_handler);
     }
 }
 
@@ -1199,6 +1199,7 @@ on_new_channels (TpConnection *proxy, const GPtrArray *channels,
     McdChannel *channel;
     GList *channel_list = NULL;
     gboolean requested = FALSE;
+    gboolean only_observe = FALSE;
     guint i;
 
     if (DEBUGGING)
@@ -1229,10 +1230,8 @@ on_new_channels (TpConnection *proxy, const GPtrArray *channels,
      * FALSE: they'll also be in Channels in the GetAll(Requests) result */
     if (!priv->dispatched_initial_channels) return;
 
-    /* first, check if we have to dispatch the channels at all */
-    if (!MCD_CONNECTION_GET_CLASS (connection)->need_dispatch (connection,
-                                                               channels))
-        return;
+    only_observe = ! MCD_CONNECTION_GET_CLASS (connection)->need_dispatch (
+        connection, channels);
 
     sp_timestamp ("NewChannels received");
     for (i = 0; i < channels->len; i++)
@@ -1267,7 +1266,8 @@ on_new_channels (TpConnection *proxy, const GPtrArray *channels,
         channel_list = g_list_prepend (channel_list, channel);
     }
 
-    _mcd_dispatcher_take_channels (priv->dispatcher, channel_list, requested);
+    _mcd_dispatcher_take_channels (priv->dispatcher, channel_list, requested,
+                                   only_observe);
 }
 
 static void
diff --git a/src/mcd-dispatch-operation-priv.h b/src/mcd-dispatch-operation-priv.h
index e4715ac..4b37db9 100644
--- a/src/mcd-dispatch-operation-priv.h
+++ b/src/mcd-dispatch-operation-priv.h
@@ -70,7 +70,7 @@ G_GNUC_INTERNAL void _mcd_dispatch_operation_approve
 
 G_GNUC_INTERNAL McdDispatchOperation *_mcd_dispatch_operation_new (
     McdClientRegistry *client_registry, McdHandlerMap *handler_map,
-    gboolean needs_approval, GList *channels,
+    gboolean needs_approval, gboolean observe_only, GList *channels,
     const gchar * const *possible_handlers);
 
 G_GNUC_INTERNAL gboolean _mcd_dispatch_operation_has_channel (
diff --git a/src/mcd-dispatch-operation.c b/src/mcd-dispatch-operation.c
index 280c422..aa0dab3 100644
--- a/src/mcd-dispatch-operation.c
+++ b/src/mcd-dispatch-operation.c
@@ -150,6 +150,10 @@ struct _McdDispatchOperationPrivate
 
     /* If TRUE, we're dispatching a channel request and it was cancelled */
     gboolean cancelled;
+
+    /* if TRUE, these channels were requested "behind our back", so stop
+     * after observers */
+    gboolean observe_only;
 };
 
 static void _mcd_dispatch_operation_check_finished (
@@ -253,7 +257,8 @@ _mcd_dispatch_operation_check_client_locks (McdDispatchOperation *self)
         _mcd_dispatch_operation_is_approved (self))
     {
         /* no observers etc. left */
-        if (!self->priv->channels_handled)
+        if (!self->priv->channels_handled &&
+            !self->priv->observe_only)
         {
             self->priv->channels_handled = TRUE;
             _mcd_dispatch_operation_run_handlers (self);
@@ -269,6 +274,7 @@ enum
     PROP_HANDLER_MAP,
     PROP_POSSIBLE_HANDLERS,
     PROP_NEEDS_APPROVAL,
+    PROP_OBSERVE_ONLY,
 };
 
 /*
@@ -608,6 +614,18 @@ mcd_dispatch_operation_constructor (GType type, guint n_params,
     if (!priv->client_registry || !priv->handler_map)
         goto error;
 
+    if (priv->possible_handlers == NULL && !priv->observe_only)
+    {
+        g_critical ("!observe_only => possible_handlers must not be NULL");
+        goto error;
+    }
+
+    if (priv->needs_approval && priv->observe_only)
+    {
+        g_critical ("observe_only => needs_approval must not be TRUE");
+        goto error;
+    }
+
     create_object_path (priv);
 
     DEBUG ("%s/%p: needs_approval=%c", priv->unique_name, object,
@@ -752,13 +770,16 @@ mcd_dispatch_operation_set_property (GObject *obj, guint prop_id,
     case PROP_POSSIBLE_HANDLERS:
         g_assert (priv->possible_handlers == NULL);
         priv->possible_handlers = g_value_dup_boxed (val);
-        g_assert (priv->possible_handlers != NULL);
         break;
 
     case PROP_NEEDS_APPROVAL:
         priv->needs_approval = g_value_get_boolean (val);
         break;
 
+    case PROP_OBSERVE_ONLY:
+        priv->observe_only = g_value_get_boolean (val);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
         break;
@@ -789,6 +810,10 @@ mcd_dispatch_operation_get_property (GObject *obj, guint prop_id,
         g_value_set_boolean (val, priv->needs_approval);
         break;
 
+    case PROP_OBSERVE_ONLY:
+        g_value_set_boolean (val, priv->observe_only);
+        break;
+
     default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
         break;
@@ -915,6 +940,14 @@ _mcd_dispatch_operation_class_init (McdDispatchOperationClass * klass)
                               "appear on D-Bus", FALSE,
                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
                               G_PARAM_STATIC_STRINGS));
+
+    g_object_class_install_property (object_class, PROP_OBSERVE_ONLY,
+        g_param_spec_boolean ("observe-only", "Observe only?",
+                              "TRUE if this CDO should stop dispatching "
+                              "as soon as Observers have been run",
+                              FALSE,
+                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
+                              G_PARAM_STATIC_STRINGS));
 }
 
 static void
@@ -945,6 +978,7 @@ McdDispatchOperation *
 _mcd_dispatch_operation_new (McdClientRegistry *client_registry,
                              McdHandlerMap *handler_map,
                              gboolean needs_approval,
+                             gboolean observe_only,
                              GList *channels,
                              const gchar * const *possible_handlers)
 {
@@ -955,6 +989,7 @@ _mcd_dispatch_operation_new (McdClientRegistry *client_registry,
                         "channels", channels,
                         "possible-handlers", possible_handlers,
                         "needs-approval", needs_approval,
+                        "observe-only", observe_only,
                         NULL);
 
     return MCD_DISPATCH_OPERATION (obj);
diff --git a/src/mcd-dispatcher-priv.h b/src/mcd-dispatcher-priv.h
index 3592f74..073695a 100644
--- a/src/mcd-dispatcher-priv.h
+++ b/src/mcd-dispatcher-priv.h
@@ -46,7 +46,8 @@ G_GNUC_INTERNAL GPtrArray *_mcd_dispatcher_get_channel_enhanced_capabilities (
 void _mcd_dispatcher_add_request (McdDispatcher *dispatcher,
                                   McdAccount *account, McdChannel *channel);
 G_GNUC_INTERNAL void _mcd_dispatcher_take_channels (
-    McdDispatcher *dispatcher, GList *channels, gboolean requested);
+    McdDispatcher *dispatcher, GList *channels, gboolean requested,
+    gboolean only_observe);
 G_GNUC_INTERNAL
 void _mcd_dispatcher_add_channel_request (McdDispatcher *dispatcher,
                                           McdChannel *channel,
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index 98b3a66..2f16e76 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -536,7 +536,8 @@ static void
 _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher,
                                      GList *channels,
                                      const gchar * const *possible_handlers,
-                                     gboolean requested)
+                                     gboolean requested,
+                                     gboolean only_observe)
 {
     McdDispatcherContext *context;
     McdDispatcherPrivate *priv;
@@ -574,7 +575,7 @@ _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher,
      * bundle? */
 
     context->operation = _mcd_dispatch_operation_new (priv->clients,
-        priv->handler_map, !requested, channels,
+        priv->handler_map, !requested, only_observe, channels,
         (const gchar * const *) possible_handlers);
 
     if (!requested)
@@ -1605,7 +1606,7 @@ _mcd_dispatcher_add_request (McdDispatcher *dispatcher, McdAccount *account,
  */
 void
 _mcd_dispatcher_take_channels (McdDispatcher *dispatcher, GList *channels,
-                               gboolean requested)
+                               gboolean requested, gboolean only_observe)
 {
     GList *list;
     GStrv possible_handlers;
@@ -1622,6 +1623,16 @@ _mcd_dispatcher_take_channels (McdDispatcher *dispatcher, GList *channels,
            channels->next == NULL ? "only" : "and more",
            mcd_channel_get_object_path (channels->data));
 
+    if (only_observe)
+    {
+        /* these channels were requested "behind our back", so only call
+         * ObserveChannels on them */
+        _mcd_dispatcher_enter_state_machine (dispatcher, channels, NULL,
+                                             requested, TRUE);
+        g_list_free (channels);
+        return;
+    }
+
     /* See if there are any handlers that can take all these channels */
     possible_handlers = mcd_dispatcher_dup_possible_handlers (dispatcher,
                                                               channels,
@@ -1644,7 +1655,8 @@ _mcd_dispatcher_take_channels (McdDispatcher *dispatcher, GList *channels,
             {
                 list = channels;
                 channels = g_list_remove_link (channels, list);
-                _mcd_dispatcher_take_channels (dispatcher, list, requested);
+                _mcd_dispatcher_take_channels (dispatcher, list, requested,
+                                               FALSE);
             }
         }
     }
@@ -1657,7 +1669,7 @@ _mcd_dispatcher_take_channels (McdDispatcher *dispatcher, GList *channels,
                                      MCD_CHANNEL_STATUS_DISPATCHING);
 
         _mcd_dispatcher_enter_state_machine (dispatcher, channels,
-            (const gchar * const *) possible_handlers, requested);
+            (const gchar * const *) possible_handlers, requested, FALSE);
         g_list_free (channels);
     }
 
@@ -1948,7 +1960,8 @@ _mcd_dispatcher_recover_channel (McdDispatcher *dispatcher,
         requested = mcd_channel_is_requested (channel);
         _mcd_dispatcher_take_channels (dispatcher,
                                        g_list_prepend (NULL, channel),
-                                       requested);
+                                       requested,
+                                       FALSE);
     }
 }
 
-- 
1.5.6.5




More information about the telepathy-commits mailing list