diff options
author | Will Thompson <will.thompson@collabora.co.uk> | 2010-04-26 11:36:05 +0100 |
---|---|---|
committer | Will Thompson <will.thompson@collabora.co.uk> | 2010-04-26 11:36:07 +0100 |
commit | dcbf0e1d5e36db7e9615fb653679cbb678b628de (patch) | |
tree | 26931cdff8fc72b872ab98e56aca070a4f4d74d7 | |
parent | 0f2d10e0d236b97355d92f1fc9e826eb17db828b (diff) | |
parent | b18261e0a9f79cad7f29df55bc99b92969dbfc26 (diff) | |
download | telepathy-gabble-dcbf0e1d5e36db7e9615fb653679cbb678b628de.tar.gz |
Merge branch 'device-idle' into telepathy-gabble-0.8
Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk>
-rw-r--r-- | configure.ac | 8 | ||||
-rw-r--r-- | src/Makefile.am | 6 | ||||
-rw-r--r-- | src/conn-slacker.c | 126 | ||||
-rw-r--r-- | src/conn-slacker.h | 36 | ||||
-rw-r--r-- | src/connection.c | 3 | ||||
-rw-r--r-- | src/connection.h | 4 | ||||
-rw-r--r-- | src/debug.h | 1 | ||||
-rw-r--r-- | src/namespaces.h | 1 | ||||
-rw-r--r-- | src/slacker.c | 298 | ||||
-rw-r--r-- | src/slacker.h | 60 | ||||
-rw-r--r-- | tests/twisted/Makefile.am | 8 | ||||
-rw-r--r-- | tests/twisted/device-idleness.py | 91 | ||||
-rw-r--r-- | tests/twisted/ns.py | 1 |
13 files changed, 643 insertions, 0 deletions
diff --git a/configure.ac b/configure.ac index 710903c9e..d4ab9f888 100644 --- a/configure.ac +++ b/configure.ac @@ -237,6 +237,14 @@ else AC_MSG_WARN([libuuid not found, falling back to generating random IDs]) fi +dnl Check for MCE, a Maemo service used by Gabble to determine when the device +dnl is idle. +PKG_CHECK_MODULES([MCE], mce >= 1.5, [HAVE_MCE=yes], [HAVE_MCE=no]) +AM_CONDITIONAL([HAVE_MCE], [test x"$HAVE_MCE" = xyes]) +if test x"$HAVE_MCE" = xyes; then + AC_DEFINE([HAVE_MCE], [1], [Define if mce is available]) +fi + AC_CHECK_FUNCS(getifaddrs memset select strndup setresuid setreuid strerror) SHAVE_INIT(.) diff --git a/src/Makefile.am b/src/Makefile.am index 5a81d3268..e0633fda9 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -7,6 +7,8 @@ BUILT_SOURCES = \ CLEANFILES = $(BUILT_SOURCES) +EXTRA_DIST = + libexec_PROGRAMS=telepathy-gabble noinst_PROGRAMS = write-mgr-file @@ -43,6 +45,8 @@ libgabble_convenience_la_SOURCES = \ conn-olpc.c \ conn-presence.h \ conn-presence.c \ + conn-slacker.h \ + conn-slacker.c \ connection.h \ connection.c \ connection-manager.h \ @@ -126,6 +130,8 @@ libgabble_convenience_la_SOURCES = \ roomlist-channel.c \ roomlist-manager.h \ roomlist-manager.c \ + slacker.h \ + slacker.c \ tube-iface.h \ tube-iface.c \ tubes-channel.h \ diff --git a/src/conn-slacker.c b/src/conn-slacker.c new file mode 100644 index 000000000..fe17ece35 --- /dev/null +++ b/src/conn-slacker.c @@ -0,0 +1,126 @@ +/* + * conn-slacker.h - Header for Gabble connection code handling device idleness + * Copyright (C) 2010 Collabora Ltd. + * Copyright (C) 2010 Nokia Corporation + * + * 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 + */ + +#include "conn-slacker.h" + +#define DEBUG_FLAG GABBLE_DEBUG_CONNECTION +#include "debug.h" +#include "namespaces.h" +#include "util.h" + +static void +conn_slacker_send_command ( + GabbleConnection *conn, + const gchar *command) +{ + LmMessage *stanza = lm_message_build_with_sub_type (NULL, + LM_MESSAGE_TYPE_IQ, LM_MESSAGE_SUB_TYPE_SET, + '(', "query", "", + '@', "xmlns", NS_GOOGLE_QUEUE, + '(', command, "", ')', + ')', + NULL); + + _gabble_connection_send_with_reply (conn, stanza, NULL, NULL, NULL, NULL); + lm_message_unref (stanza); +} + + +static void +conn_slacker_update_inactivity ( + GabbleConnection *conn, + gboolean is_inactive) +{ + if (DEBUGGING) + { + gchar *jid = gabble_connection_get_full_jid (conn); + + DEBUG ("device became %sactive; %sabling presence queueing for %s", + is_inactive ? "in" : "", + is_inactive ? "en" : "dis", + jid); + g_free (jid); + } + + if (is_inactive) + { + conn_slacker_send_command (conn, "enable"); + } + else + { + /* It seems that disabling the queue doesn't flush it, so we need to + * explicitly flush it too. + */ + conn_slacker_send_command (conn, "disable"); + conn_slacker_send_command (conn, "flush"); + } +} + +static void +conn_slacker_inactivity_changed_cb ( + GabbleSlacker *slacker, + gboolean is_inactive, + gpointer user_data) +{ + GabbleConnection *conn = GABBLE_CONNECTION (user_data); + + conn_slacker_update_inactivity (conn, is_inactive); +} + +void +gabble_connection_slacker_start (GabbleConnection *conn) +{ + GabbleSlacker *s; + + /* We can only cork presence updates on Google Talk. Of course, the Google + * Talk server doesn't advertise support for google:queue. So let's use the + * roster again... */ + if (!(conn->features & GABBLE_CONNECTION_FEATURES_GOOGLE_ROSTER)) + return; + + s = conn->slacker = gabble_slacker_new (); + + /* In the unlikely event of having to use an escape slide... */ + if (G_UNLIKELY (s == NULL)) + return; + + conn->slacker_inactivity_changed_id = g_signal_connect (s, + "inactivity-changed", (GCallback) conn_slacker_inactivity_changed_cb, + conn); + + /* If we're already inactive, let's cork right away. (I guess the connection + * flaked out in the user's pocket?) */ + if (gabble_slacker_is_inactive (s)) + conn_slacker_update_inactivity (conn, TRUE); +} + +void +gabble_connection_slacker_stop (GabbleConnection *conn) +{ + if (conn->slacker != NULL) + { + g_signal_handler_disconnect (conn->slacker, + conn->slacker_inactivity_changed_id); + conn->slacker_inactivity_changed_id = 0; + + g_object_unref (conn->slacker); + conn->slacker = NULL; + } +} diff --git a/src/conn-slacker.h b/src/conn-slacker.h new file mode 100644 index 000000000..c38d6cfce --- /dev/null +++ b/src/conn-slacker.h @@ -0,0 +1,36 @@ +/* + * conn-slacker.h - Header for Gabble connection code handling device idleness + * Copyright (C) 2010 Collabora Ltd. + * Copyright (C) 2010 Nokia Corporation + * + * 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 + */ + +#ifndef GABBLE_CONN_SLACKER_H +#define GABBLE_CONN_SLACKER_H + +#include <glib.h> + +#include "connection.h" + +G_BEGIN_DECLS + +void gabble_connection_slacker_start (GabbleConnection *conn); +void gabble_connection_slacker_stop (GabbleConnection *conn); + +G_END_DECLS + +#endif /* GABBLE_CONN_SLACKER_H */ + diff --git a/src/connection.c b/src/connection.c index 907884f25..84011ec1e 100644 --- a/src/connection.c +++ b/src/connection.c @@ -53,6 +53,7 @@ #include "conn-location.h" #include "conn-presence.h" #include "conn-olpc.h" +#include "conn-slacker.h" #include "debug.h" #include "disco.h" #include "media-channel.h" @@ -624,6 +625,7 @@ base_connected_cb (TpBaseConnection *base_conn) GabbleConnection *conn = GABBLE_CONNECTION (base_conn); gabble_connection_connected_olpc (conn); + gabble_connection_slacker_start (conn); } static void @@ -1546,6 +1548,7 @@ connection_shut_down (TpBaseConnection *base) g_assert (GABBLE_IS_CONNECTION (conn)); cancel_connect_timeout (conn); + gabble_connection_slacker_stop (conn); /* If we're shutting down by user request, we don't want to be * unreffed until the LM connection actually closes; the event handler diff --git a/src/connection.h b/src/connection.h index b2a47d0d0..ba4ecce69 100644 --- a/src/connection.h +++ b/src/connection.h @@ -34,6 +34,7 @@ #include "jingle-factory.h" #include "muc-factory.h" #include "olpc-gadget-manager.h" +#include "slacker.h" #include "types.h" G_BEGIN_DECLS @@ -173,6 +174,9 @@ struct _GabbleConnection { GPtrArray *channel_requests; gboolean has_tried_connection; + GabbleSlacker *slacker; + guint slacker_inactivity_changed_id; + GabbleConnectionPrivate *priv; }; diff --git a/src/debug.h b/src/debug.h index f19b7ea54..4d39a63f2 100644 --- a/src/debug.h +++ b/src/debug.h @@ -30,6 +30,7 @@ typedef enum GABBLE_DEBUG_BYTESTREAM = 1 << 16, GABBLE_DEBUG_LOCATION = 1 << 17, GABBLE_DEBUG_FT = 1 << 18, + GABBLE_DEBUG_SLACKER = 1 << 19, } GabbleDebugFlags; void gabble_debug_set_flags_from_env (void); diff --git a/src/namespaces.h b/src/namespaces.h index fdf9ad8ab..5219b1e20 100644 --- a/src/namespaces.h +++ b/src/namespaces.h @@ -36,6 +36,7 @@ #define NS_GOOGLE_FEAT_VIDEO "http://www.google.com/xmpp/protocol/video/v1" #define NS_GOOGLE_JINGLE_INFO "google:jingleinfo" #define NS_GOOGLE_ROSTER "google:roster" +#define NS_GOOGLE_QUEUE "google:queue" #define NS_IBB "http://jabber.org/protocol/ibb" /* Namespaces for XEP-0166 draft v0.15, the most capable Jingle dialect diff --git a/src/slacker.c b/src/slacker.c new file mode 100644 index 000000000..253f1842f --- /dev/null +++ b/src/slacker.c @@ -0,0 +1,298 @@ +/* + * slacker.c - Maemo device state monitor + * Copyright ©2010 Collabora Ltd. + * Copyright ©2008-2010 Nokia Corporation + * + * Derived from code in e-book-backend-tp.c in eds-backend-telepathy; thanks! + * + * 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 + */ + +#include "slacker.h" +#include "config.h" + +#include <dbus/dbus.h> +#include <dbus/dbus-glib.h> +#include <dbus/dbus-glib-lowlevel.h> + +#ifdef HAVE_MCE +#include <mce/dbus-names.h> +#else /* HAVE_MCE */ + +/* Use some dummy interfaces etc. for the test suite. + * + * In a perfect world of sweetness and light these would not be enabled for the + * real build, but we do not live in a perfect world of sweetness and light: we + * live below a dark cloud of bitter ash, the charred remains of a defunct + * economy and cygnine clothing. + */ +#define MCE_SERVICE "org.freedesktop.Telepathy.Gabble.Tests.MCE" + +#define MCE_SIGNAL_IF "org.freedesktop.Telepathy.Gabble.Tests.MCE" +#define MCE_INACTIVITY_SIG "InactivityChanged" + +#define MCE_REQUEST_IF "org.freedesktop.Telepathy.Gabble.Tests.MCE" +#define MCE_REQUEST_PATH "/org/freedesktop/Telepathy/Gabble/Tests/MCE" +#define MCE_INACTIVITY_STATUS_GET "GetInactivity" + +#endif /* HAVE_MCE */ + +#define DEBUG_FLAG GABBLE_DEBUG_SLACKER +#include "debug.h" +#include "gabble-signals-marshal.h" + +struct _GabbleSlackerPrivate { + DBusGConnection *bus; + DBusGProxy *mce_request_proxy; + + gboolean is_inactive; +}; + +G_DEFINE_TYPE (GabbleSlacker, gabble_slacker, G_TYPE_OBJECT) + +enum { + SIG_INACTIVITY_CHANGED = 0, + N_SIGNALS +}; + +static guint signals[N_SIGNALS]; + +/** + * gabble_slacker_is_inactive: + * @self: do some work! + * + * <!-- --> + * + * Returns: %TRUE if the device is known to be inactive; false otherwise. + */ +gboolean +gabble_slacker_is_inactive (GabbleSlacker *self) +{ + g_return_val_if_fail (GABBLE_IS_SLACKER (self), FALSE); + + return self->priv->is_inactive; +} + +static void +slacker_inactivity_changed ( + GabbleSlacker *self, + gboolean is_inactive) +{ + GabbleSlackerPrivate *priv = self->priv; + gboolean old = priv->is_inactive; + + priv->is_inactive = is_inactive; + + if (!!old != !!is_inactive) + { + DEBUG ("device became %s", (is_inactive ? "inactive" : "active")); + g_signal_emit (self, signals[SIG_INACTIVITY_CHANGED], 0, is_inactive); + } +} + +static GQuark mce_signal_interface_quark = 0; +static GQuark mce_inactivity_signal_quark = 0; + +#define INACTIVITY_MATCH_RULE \ + "type='signal',interface='" MCE_SIGNAL_IF "',member='" MCE_INACTIVITY_SIG "'" + +static DBusHandlerResult +slacker_message_filter ( + DBusConnection *connection, + DBusMessage *message, + gpointer user_data) +{ + GabbleSlacker *self = GABBLE_SLACKER (user_data); + GQuark interface, member; + int message_type; + + interface = g_quark_try_string (dbus_message_get_interface (message)); + member = g_quark_try_string (dbus_message_get_member (message)); + message_type = dbus_message_get_type (message); + + if (interface == mce_signal_interface_quark && + message_type == DBUS_MESSAGE_TYPE_SIGNAL && + member == mce_inactivity_signal_quark) + { + gboolean is_inactive; + + dbus_message_get_args (message, NULL, DBUS_TYPE_BOOLEAN, &is_inactive, + DBUS_TYPE_INVALID); + slacker_inactivity_changed (self, is_inactive); + } + + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void +get_inactivity_status_cb ( + DBusGProxy *proxy, + DBusGProxyCall *call, + gpointer user_data) +{ + GabbleSlacker *self = GABBLE_SLACKER (user_data); + gboolean is_inactive; + + if (dbus_g_proxy_end_call (proxy, call, NULL /* ignore errors */, + G_TYPE_BOOLEAN, &is_inactive, + G_TYPE_INVALID)) + slacker_inactivity_changed (self, is_inactive); + + g_object_unref (self->priv->mce_request_proxy); + self->priv->mce_request_proxy = NULL; +} + +static void +slacker_add_filter (GabbleSlacker *self) +{ + GabbleSlackerPrivate *priv = self->priv; + DBusConnection *c = dbus_g_connection_get_connection (self->priv->bus); + + dbus_connection_add_filter (c, slacker_message_filter, self, NULL); + dbus_bus_add_match (c, INACTIVITY_MATCH_RULE, NULL); + + priv->mce_request_proxy = dbus_g_proxy_new_for_name (priv->bus, + MCE_SERVICE, MCE_REQUEST_PATH, MCE_REQUEST_IF); + dbus_g_proxy_begin_call (priv->mce_request_proxy, MCE_INACTIVITY_STATUS_GET, + get_inactivity_status_cb, self, NULL, G_TYPE_INVALID); +} + +static void +slacker_remove_filter (GabbleSlacker *self) +{ + DBusConnection *c = dbus_g_connection_get_connection (self->priv->bus); + + dbus_connection_remove_filter (c, slacker_message_filter, self); + dbus_bus_remove_match (c, INACTIVITY_MATCH_RULE, NULL); +} + +/* GObject boilerplate */ + +static void +gabble_slacker_init (GabbleSlacker *self) +{ + self->priv = G_TYPE_INSTANCE_GET_PRIVATE (self, GABBLE_TYPE_SLACKER, + GabbleSlackerPrivate); +} + +static gpointer slacker = NULL; + +static GObject * +gabble_slacker_constructor ( + GType type, + guint n_construct_properties, + GObjectConstructParam *construct_properties) +{ + GObject *retval; + + if (slacker == NULL) + { + slacker = G_OBJECT_CLASS (gabble_slacker_parent_class)->constructor ( + type, n_construct_properties, construct_properties); + retval = slacker; + g_object_add_weak_pointer (retval, &slacker); + } + else + { + retval = g_object_ref (slacker); + } + + return retval; +} + +static void +gabble_slacker_constructed (GObject *object) +{ + GabbleSlacker *self = GABBLE_SLACKER (object); + GError *error = NULL; + +#ifdef HAVE_MCE + self->priv->bus = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); +#else + self->priv->bus = dbus_g_bus_get (DBUS_BUS_SESSION, &error); +#endif + + if (self->priv->bus == NULL) + { + g_warning ("help! where did my system bus go? %s", error->message); + g_clear_error (&error); + } + else + { + slacker_add_filter (self); + } +} + +static void +gabble_slacker_dispose (GObject *object) +{ + GabbleSlacker *self = GABBLE_SLACKER (object); + GabbleSlackerPrivate *priv = self->priv; + + if (priv->mce_request_proxy != NULL) + { + g_object_unref (priv->mce_request_proxy); /* this cancels pending calls */ + priv->mce_request_proxy = NULL; + } + + if (priv->bus != NULL) + { + slacker_remove_filter (self); + dbus_g_connection_unref (priv->bus); + priv->bus = NULL; + } + + ((GObjectClass *) gabble_slacker_parent_class)->dispose (object); +} + +static void +gabble_slacker_class_init (GabbleSlackerClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructor = gabble_slacker_constructor; + object_class->constructed = gabble_slacker_constructed; + object_class->dispose = gabble_slacker_dispose; + + g_type_class_add_private (klass, sizeof (GabbleSlackerPrivate)); + + /** + * GabbleSlacker::inactivity-changed: + * @self: what a slacker + * @inactive: %TRUE if the device is inactive. + * + * The ::inactivity-changed is emitted whenever MCE declares that the device + * has become active or inactive. Note that there is a lag (of around 30 + * seconds, at the time of writing) between the screen blanking and MCE + * declaring the device inactive. + */ + signals[SIG_INACTIVITY_CHANGED] = g_signal_new ("inactivity-changed", + GABBLE_TYPE_SLACKER, G_SIGNAL_RUN_LAST, 0, NULL, NULL, + gabble_marshal_VOID__BOOLEAN, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + if (!mce_signal_interface_quark) + { + mce_signal_interface_quark = g_quark_from_static_string (MCE_SIGNAL_IF); + mce_inactivity_signal_quark = g_quark_from_static_string ( + MCE_INACTIVITY_SIG); + } +} + +GabbleSlacker * +gabble_slacker_new () +{ + return g_object_new (GABBLE_TYPE_SLACKER, NULL); +} diff --git a/src/slacker.h b/src/slacker.h new file mode 100644 index 000000000..fc57fe4ca --- /dev/null +++ b/src/slacker.h @@ -0,0 +1,60 @@ +/* + * slacker.h - header for Maemo device state monitor + * Copyright ©2010 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 + */ + +#ifndef GABBLE_SLACKER_H +#define GABBLE_SLACKER_H + +#include <glib-object.h> + +typedef struct _GabbleSlacker GabbleSlacker; +typedef struct _GabbleSlackerClass GabbleSlackerClass; +typedef struct _GabbleSlackerPrivate GabbleSlackerPrivate; + +struct _GabbleSlackerClass { + GObjectClass parent_class; +}; + +struct _GabbleSlacker { + GObject parent; + + GabbleSlackerPrivate *priv; +}; + +GType gabble_slacker_get_type (void); + +GabbleSlacker *gabble_slacker_new (void); +gboolean gabble_slacker_is_inactive (GabbleSlacker *self); + +/* TYPE MACROS */ +#define GABBLE_TYPE_SLACKER \ + (gabble_slacker_get_type ()) +#define GABBLE_SLACKER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GABBLE_TYPE_SLACKER, GabbleSlacker)) +#define GABBLE_SLACKER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GABBLE_TYPE_SLACKER,\ + GabbleSlackerClass)) +#define GABBLE_IS_SLACKER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GABBLE_TYPE_SLACKER)) +#define GABBLE_IS_SLACKER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GABBLE_TYPE_SLACKER)) +#define GABBLE_SLACKER_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GABBLE_TYPE_SLACKER, \ + GabbleSlackerClass)) + +#endif /* GABBLE_SLACKER_H */ diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am index f497a9a03..c899b2e2e 100644 --- a/tests/twisted/Makefile.am +++ b/tests/twisted/Makefile.am @@ -15,6 +15,7 @@ TWISTED_TESTS = \ caps/receive-jingle.py \ caps/trust-thyself.py \ caps/tube-caps.py \ + device-idleness.py \ muc/name-conflict.py \ muc/renamed.py \ muc/roomlist.py \ @@ -192,12 +193,19 @@ else ENABLE_ASSUMED_FT_CAP_PYBOOL = False endif +if HAVE_MCE +HAVE_MCE_PYBOOL = True +else +HAVE_MCE_PYBOOL = False +endif + config.py: Makefile $(QUIET_GEN) { \ echo "PACKAGE_STRING = \"$(PACKAGE_STRING)\""; \ echo "CLIENT_TYPE = '$(CLIENT_TYPE)'"; \ echo "DEBUGGING = $(DEBUGGING_PYBOOL)"; \ echo "ENABLE_ASSUMED_FT_CAP = $(ENABLE_ASSUMED_FT_CAP_PYBOOL)"; \ + echo "HAVE_MCE = $(HAVE_MCE_PYBOOL)"; \ } > $@ BUILT_SOURCES = config.py diff --git a/tests/twisted/device-idleness.py b/tests/twisted/device-idleness.py new file mode 100644 index 000000000..48e9e1069 --- /dev/null +++ b/tests/twisted/device-idleness.py @@ -0,0 +1,91 @@ +""" +Test listening to device idleness status changes. + +When we're not building with MCE support, Gabble uses a test suite-specific +service on the session bus. When we *are* building with MCE support, it uses +the system bus, so we can't test it. Hence: +""" + +import config + +if config.HAVE_MCE: + print "NOTE: built with real MCE support; skipping idleness test" + raise SystemExit(77) + +from functools import partial + +from gabbletest import exec_test, GoogleXmlStream +from servicetest import call_async, Event, assertEquals +import ns + +import dbus +import dbus.service + +# Fake MCE constants, cloned from slacker.c +MCE_SERVICE = "org.freedesktop.Telepathy.Gabble.Tests.MCE" + +MCE_SIGNAL_IF = "org.freedesktop.Telepathy.Gabble.Tests.MCE" +MCE_INACTIVITY_SIG = "InactivityChanged" + +MCE_REQUEST_IF = "org.freedesktop.Telepathy.Gabble.Tests.MCE" +MCE_REQUEST_PATH = "/org/freedesktop/Telepathy/Gabble/Tests/MCE" +MCE_INACTIVITY_STATUS_GET = "GetInactivity" + +from twisted.internet import reactor + +class FakeMCE(dbus.service.Object): + def __init__(self, q, bus, inactive=False): + super(FakeMCE, self).__init__(bus, MCE_REQUEST_PATH) + + self.q = q + self.inactive = inactive + + @dbus.service.method(dbus_interface=MCE_REQUEST_IF, + in_signature='', out_signature='b') + def GetInactivity(self): + self.q.append(Event('get-inactivity-called')) + return self.inactive + + @dbus.service.signal(dbus_interface=MCE_SIGNAL_IF, signature='b') + def InactivityChanged(self, new_value): + self.inactive = new_value + + +def expect_command(q, name): + event = q.expect('stream-iq', query_name='query', query_ns=ns.GOOGLE_QUEUE) + command = event.query.firstChildElement() + assertEquals(name, command.name) + +def test(q, bus, conn, stream, initially_inactive=False): + mce = FakeMCE(q, bus, initially_inactive) + + call_async(q, conn, 'Connect') + q.expect('get-inactivity-called') + + if initially_inactive: + expect_command(q, 'enable') + else: + mce.InactivityChanged(True) + expect_command(q, 'enable') + + mce.InactivityChanged(False) + expect_command(q, 'disable') + expect_command(q, 'flush') + + # Just cycle it a bit to check it doesn't blow up slowly + mce.InactivityChanged(True) + expect_command(q, 'enable') + + mce.InactivityChanged(False) + expect_command(q, 'disable') + expect_command(q, 'flush') + + mce.remove_from_connection() + +if __name__ == '__main__': + dbus.SessionBus().request_name(MCE_SERVICE, 0) + try: + exec_test(partial(test, initially_inactive=False), protocol=GoogleXmlStream) + exec_test(partial(test, initially_inactive=True), protocol=GoogleXmlStream) + finally: + dbus.SessionBus().release_name(MCE_SERVICE) diff --git a/tests/twisted/ns.py b/tests/twisted/ns.py index 6d800360c..a36ebb198 100644 --- a/tests/twisted/ns.py +++ b/tests/twisted/ns.py @@ -12,6 +12,7 @@ GOOGLE_FEAT_VOICE = 'http://www.google.com/xmpp/protocol/voice/v1' GOOGLE_FEAT_VIDEO = 'http://www.google.com/xmpp/protocol/video/v1' GOOGLE_JINGLE_INFO = 'google:jingleinfo' GOOGLE_P2P = "http://www.google.com/transport/p2p" +GOOGLE_QUEUE = 'google:queue' GOOGLE_ROSTER = 'google:roster' GOOGLE_SESSION = "http://www.google.com/session" GOOGLE_SESSION_PHONE = "http://www.google.com/session/phone" |