[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