diff options
author | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2009-10-13 20:32:10 +0100 |
---|---|---|
committer | Simon McVittie <simon.mcvittie@collabora.co.uk> | 2009-10-13 20:32:13 +0100 |
commit | 56f59935ebf2109b84873434d42f936284f7bdce (patch) | |
tree | 286389ebb481721d2f252b3f860378146459e116 | |
parent | 46d72a2e1a46f8bdf6e1c0e36a041ba66f7878ea (diff) | |
parent | 2b44a303999efce4cd5bca1b0efa464f470b10b2 (diff) | |
download | telepathy-mission-control-56f59935ebf2109b84873434d42f936284f7bdce.tar.gz |
Merge branch '52-always-observe-new-channels' into telepathy-mission-control-5.2
Reviewed-by: Alberto Mardegan <alberto.mardegan@nokia.com>
-rw-r--r-- | src/mcd-connection.c | 26 | ||||
-rw-r--r-- | src/mcd-dispatcher-priv.h | 3 | ||||
-rw-r--r-- | src/mcd-dispatcher.c | 36 | ||||
-rw-r--r-- | test/twisted/Makefile.am | 1 | ||||
-rw-r--r-- | test/twisted/dispatcher/created-behind-our-back.py | 106 |
5 files changed, 151 insertions, 21 deletions
diff --git a/src/mcd-connection.c b/src/mcd-connection.c index 442c7683..a4fd0e5d 100644 --- a/src/mcd-connection.c +++ b/src/mcd-connection.c @@ -535,12 +535,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, @@ -549,10 +543,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); } } @@ -1193,6 +1193,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) @@ -1223,10 +1224,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++) @@ -1261,7 +1260,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-dispatcher-priv.h b/src/mcd-dispatcher-priv.h index 9b1fc7df..7509d0f5 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 f67a0545..65af2fc9 100644 --- a/src/mcd-dispatcher.c +++ b/src/mcd-dispatcher.c @@ -1525,7 +1525,8 @@ static void _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher, GList *channels, GStrv possible_handlers, - gboolean requested) + gboolean requested, + gboolean only_observe) { McdDispatcherContext *context; McdDispatcherPrivate *priv; @@ -1563,7 +1564,7 @@ _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher, mcd_channel_get_object_path (context->channels->data)); priv->contexts = g_list_prepend (priv->contexts, context); - if (!requested) + if (!requested && !only_observe) { context->operation = _mcd_dispatch_operation_new (priv->dbus_daemon, channels, @@ -1591,7 +1592,16 @@ _mcd_dispatcher_enter_state_machine (McdDispatcher *dispatcher, context); } - if (priv->filters != NULL) + if (only_observe) + { + DEBUG ("Context %p has channels created behind our back, starting " + "observers only", context); + /* this lock is never released - we specifically don't want to run + * Approvers or Handlers */ + context->client_locks = 1; + mcd_dispatcher_run_observers (context); + } + else if (priv->filters != NULL) { DEBUG ("entering state machine for context %p", context); @@ -3448,7 +3458,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; @@ -3465,6 +3475,15 @@ _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); + return; + } + /* See if there are any handlers that can take all these channels */ possible_handlers = mcd_dispatcher_get_possible_handlers (dispatcher, channels); @@ -3486,7 +3505,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); } } } @@ -3499,7 +3519,8 @@ _mcd_dispatcher_take_channels (McdDispatcher *dispatcher, GList *channels, MCD_CHANNEL_STATUS_DISPATCHING); _mcd_dispatcher_enter_state_machine (dispatcher, channels, - possible_handlers, requested); + possible_handlers, requested, + FALSE); } } @@ -3696,7 +3717,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); } } diff --git a/test/twisted/Makefile.am b/test/twisted/Makefile.am index 67c870b1..3caca1f4 100644 --- a/test/twisted/Makefile.am +++ b/test/twisted/Makefile.am @@ -31,6 +31,7 @@ TWISTED_BASIC_TESTS = \ dispatcher/create-handler-fails.py \ dispatcher/create-no-preferred-handler.py \ dispatcher/create-text.py \ + dispatcher/created-behind-our-back.py \ dispatcher/dispatch-activatable.py \ dispatcher/dispatch-obsolete.py \ dispatcher/dispatch-text.py \ diff --git a/test/twisted/dispatcher/created-behind-our-back.py b/test/twisted/dispatcher/created-behind-our-back.py new file mode 100644 index 00000000..55d1b4b0 --- /dev/null +++ b/test/twisted/dispatcher/created-behind-our-back.py @@ -0,0 +1,106 @@ +# Copyright (C) 2009 Nokia Corporation +# Copyright (C) 2009 Collabora Ltd. +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA +# 02110-1301 USA + +"""Regression test for channels created "by going behind MC's back".""" + +import dbus +import dbus.service + +from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \ + call_async, sync_dbus +from mctest import exec_test, SimulatedConnection, SimulatedClient, \ + create_fakecm_account, enable_fakecm_account, SimulatedChannel, \ + expect_client_setup +import constants as cs + +def test(q, bus, mc): + # Because the channels are handled by another process, we should never be + # asked to approve or handle them. + forbidden = [ + EventPattern('dbus-method-call', method='HandleChannels'), + EventPattern('dbus-method-call', method='AddDispatchOperation'), + ] + q.forbid_events(forbidden) + + params = dbus.Dictionary({"account": "someguy@example.com", + "password": "secrecy"}, signature='sv') + cm_name_ref, account = create_fakecm_account(q, bus, mc, params) + conn = enable_fakecm_account(q, bus, mc, account, params) + + text_fixed_properties = dbus.Dictionary({ + cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT, + cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT, + }, signature='sv') + + empathy = SimulatedClient(q, bus, 'Empathy', + observe=[text_fixed_properties], approve=[text_fixed_properties], + handle=[text_fixed_properties], bypass_approval=False) + kopete = SimulatedClient(q, bus, 'Kopete', + observe=[text_fixed_properties], approve=[text_fixed_properties], + handle=[text_fixed_properties], bypass_approval=False) + + expect_client_setup(q, [empathy, kopete]) + + # a non-MC-using client goes behind our back to call CreateChannel or + # EnsureChannel on the Connection directly + # + # (This is not simulated here: we just behave as though it had happened) + + channel_immutable = dbus.Dictionary(text_fixed_properties) + channel_immutable[cs.CHANNEL + '.InitiatorID'] = conn.self_ident + channel_immutable[cs.CHANNEL + '.InitiatorHandle'] = conn.self_handle + channel_immutable[cs.CHANNEL + '.Requested'] = True + channel_immutable[cs.CHANNEL + '.Interfaces'] = \ + dbus.Array([], signature='s') + channel_immutable[cs.CHANNEL + '.TargetHandle'] = \ + conn.ensure_handle(cs.HT_CONTACT, 'juliet') + channel_immutable[cs.CHANNEL + '.TargetID'] = 'juliet' + channel = SimulatedChannel(conn, channel_immutable) + + channel.announce() + + # Observer should get told, processing waits for it + e, k = q.expect_many( + EventPattern('dbus-method-call', + path=empathy.object_path, + interface=cs.OBSERVER, method='ObserveChannels', + handled=False), + EventPattern('dbus-method-call', + path=kopete.object_path, + interface=cs.OBSERVER, method='ObserveChannels', + handled=False), + ) + assert e.args[0] == account.object_path, e.args + assert e.args[1] == conn.object_path, e.args + assert e.args[3] == '/', e.args # no dispatch operation + assert e.args[4] == [], e.args + channels = e.args[2] + assert len(channels) == 1, channels + assert channels[0][0] == channel.object_path, channels + assert channels[0][1] == channel_immutable, channels + + assert e.args == k.args + + # Observers say "OK, go" + q.dbus_return(k.message, signature='') + q.dbus_return(e.message, signature='') + + sync_dbus(bus, q, mc) + +if __name__ == '__main__': + exec_test(test, {}) |