summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2009-10-13 20:32:10 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2009-10-13 20:32:13 +0100
commit56f59935ebf2109b84873434d42f936284f7bdce (patch)
tree286389ebb481721d2f252b3f860378146459e116
parent46d72a2e1a46f8bdf6e1c0e36a041ba66f7878ea (diff)
parent2b44a303999efce4cd5bca1b0efa464f470b10b2 (diff)
downloadtelepathy-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.c26
-rw-r--r--src/mcd-dispatcher-priv.h3
-rw-r--r--src/mcd-dispatcher.c36
-rw-r--r--test/twisted/Makefile.am1
-rw-r--r--test/twisted/dispatcher/created-behind-our-back.py106
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, {})