summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore1
-rw-r--r--Makefile.am3
-rw-r--r--NEWS78
-rw-r--r--configure.ac158
-rw-r--r--doc/Makefile.am13
-rw-r--r--doc/reference/mission-control-plugins/Makefile.am12
-rw-r--r--doc/reference/mission-control-plugins/mission-control-plugins-docs.sgml4
-rw-r--r--mission-control-plugins/Makefile.am6
-rw-r--r--mission-control-plugins/account-storage.c914
-rw-r--r--mission-control-plugins/account-storage.h302
-rw-r--r--mission-control-plugins/account.c318
-rw-r--r--mission-control-plugins/account.h56
-rw-r--r--mission-control-plugins/dbus-acl.c431
-rw-r--r--mission-control-plugins/dbus-acl.h134
-rw-r--r--mission-control-plugins/debug.c3
-rw-r--r--mission-control-plugins/debug.h3
-rw-r--r--mission-control-plugins/dispatch-operation.c92
-rw-r--r--mission-control-plugins/dispatch-operation.h11
-rw-r--r--mission-control-plugins/implementation.h62
-rw-r--r--mission-control-plugins/loader.c15
-rw-r--r--mission-control-plugins/mission-control-plugins.h10
-rw-r--r--plugins/Makefile.am14
-rw-r--r--plugins/mcp-dbus-aegis-acl.c441
-rw-r--r--server/Makefile.am2
-rw-r--r--src/Makefile.am179
-rw-r--r--src/connectivity-monitor.c63
-rw-r--r--src/dispatcher.xml7
-rw-r--r--src/gtypes.c10
-rw-r--r--src/mcd-account-addressing.c5
-rw-r--r--src/mcd-account-conditions.c160
-rw-r--r--src/mcd-account-conditions.h34
-rw-r--r--src/mcd-account-config.h4
-rw-r--r--src/mcd-account-connection.c115
-rw-r--r--src/mcd-account-manager-default.c975
-rw-r--r--src/mcd-account-manager-default.h7
-rw-r--r--src/mcd-account-manager-priv.h3
-rw-r--r--src/mcd-account-manager-sso.c1745
-rw-r--r--src/mcd-account-manager-sso.h101
-rw-r--r--src/mcd-account-manager.c705
-rw-r--r--src/mcd-account-manager.h9
-rw-r--r--src/mcd-account-priv.h29
-rw-r--r--src/mcd-account.c1302
-rw-r--r--src/mcd-account.h36
-rw-r--r--src/mcd-channel-priv.h4
-rw-r--r--src/mcd-channel.c91
-rw-r--r--src/mcd-client-priv.h2
-rw-r--r--src/mcd-client.c17
-rw-r--r--src/mcd-connection-service-points.c85
-rw-r--r--src/mcd-connection.c183
-rw-r--r--src/mcd-dispatch-operation-priv.h3
-rw-r--r--src/mcd-dispatch-operation.c64
-rw-r--r--src/mcd-dispatcher.c230
-rw-r--r--src/mcd-master.c1
-rw-r--r--src/mcd-misc.c2
-rw-r--r--src/mcd-service.c4
-rw-r--r--src/mcd-storage-ag-hidden.c99
-rw-r--r--src/mcd-storage-ag-hidden.h59
-rw-r--r--src/mcd-storage.c1773
-rw-r--r--src/mcd-storage.h40
-rw-r--r--src/mcd.xml17
-rw-r--r--src/plugin-dispatch-operation.c40
-rw-r--r--src/plugin-loader.c16
-rw-r--r--src/request.c1
-rw-r--r--tests/Makefile.am15
-rw-r--r--tests/account-store-keyfile.c (renamed from tests/account-store-default.c)14
-rw-r--r--tests/account-store-keyfile.h (renamed from tests/account-store-default.h)16
-rw-r--r--tests/account-store-libaccounts.c629
-rw-r--r--tests/account-store-libaccounts.h44
-rw-r--r--tests/account-store-variant-file.c189
-rw-r--r--tests/account-store-variant-file.h (renamed from plugins/mcp-dbus-aegis-acl.h)21
-rw-r--r--tests/account-store.c41
-rw-r--r--tests/twisted/Makefile.am41
-rw-r--r--tests/twisted/account-manager/account-basics.py39
-rw-r--r--tests/twisted/account-manager/auto-connect.py30
-rw-r--r--tests/twisted/account-manager/avatar-refresh.py48
-rw-r--r--tests/twisted/account-manager/avatar.py2
-rw-r--r--tests/twisted/account-manager/backend-makes-changes.py21
-rw-r--r--tests/twisted/account-manager/bad-cm.py11
-rw-r--r--tests/twisted/account-manager/connectivity.py8
-rw-r--r--tests/twisted/account-manager/crashy-cm.py10
-rw-r--r--tests/twisted/account-manager/create-auto-connect.py6
-rw-r--r--tests/twisted/account-manager/create-twice.py5
-rw-r--r--tests/twisted/account-manager/create-with-properties.py26
-rw-r--r--tests/twisted/account-manager/device-idle.py4
-rw-r--r--tests/twisted/account-manager/enable-auto-connect.py6
-rw-r--r--tests/twisted/account-manager/enable.py6
-rw-r--r--tests/twisted/account-manager/hidden.py110
-rw-r--r--tests/twisted/account-manager/irc.py4
-rw-r--r--tests/twisted/account-manager/make-valid.py17
-rw-r--r--tests/twisted/account-manager/nickname.py2
-rw-r--r--tests/twisted/account-manager/param-types.py8
-rwxr-xr-xtests/twisted/account-manager/presence.py22
-rw-r--r--tests/twisted/account-manager/reconnect.py21
-rw-r--r--tests/twisted/account-manager/recover-from-disconnect.py26
-rw-r--r--tests/twisted/account-manager/req-conn-fails.py6
-rw-r--r--tests/twisted/account-manager/request-online.py18
-rw-r--r--tests/twisted/account-manager/restricted-storage.py185
-rw-r--r--tests/twisted/account-manager/server-drops-us.py23
-rw-r--r--tests/twisted/account-manager/service.py2
-rw-r--r--tests/twisted/account-manager/update-parameters.py17
-rw-r--r--tests/twisted/account-requests/cancel.py2
-rw-r--r--tests/twisted/account-requests/create-text.py2
-rw-r--r--tests/twisted/account-requests/delete-account-during-request.py2
-rw-r--r--tests/twisted/account-storage/5-12.py29
-rw-r--r--tests/twisted/account-storage/5-14.py29
-rw-r--r--tests/twisted/account-storage/create-new.py136
-rw-r--r--tests/twisted/account-storage/default-keyring-storage.py230
-rw-r--r--tests/twisted/account-storage/diverted-storage.py6
-rw-r--r--tests/twisted/account-storage/libaccounts-sso-storage.py89
-rw-r--r--tests/twisted/account-storage/load-keyfiles.py283
-rw-r--r--tests/twisted/account-storage/storage_helper.py174
-rwxr-xr-xtests/twisted/account/addressing.py2
-rw-r--r--tests/twisted/capabilities/contact-caps.py26
-rw-r--r--tests/twisted/constants.py556
-rw-r--r--tests/twisted/crash-recovery/crash-recovery.py2
-rw-r--r--tests/twisted/dbus-account-plugin.c801
-rw-r--r--tests/twisted/dispatcher/already-has-channel.py26
-rw-r--r--tests/twisted/dispatcher/already-has-obsolete.py221
-rw-r--r--tests/twisted/dispatcher/approver-fails.py2
-rw-r--r--tests/twisted/dispatcher/bypass-approval.py2
-rw-r--r--tests/twisted/dispatcher/bypass-observers.py291
-rw-r--r--tests/twisted/dispatcher/cancel.py2
-rw-r--r--tests/twisted/dispatcher/capture-bundle.py4
-rw-r--r--tests/twisted/dispatcher/cdo-claim.py2
-rw-r--r--tests/twisted/dispatcher/connect-for-request.py14
-rw-r--r--tests/twisted/dispatcher/create-at-startup.py7
-rw-r--r--tests/twisted/dispatcher/create-delayed-by-mini-plugin.py22
-rw-r--r--tests/twisted/dispatcher/create-handler-fails.py2
-rw-r--r--tests/twisted/dispatcher/create-hints.py2
-rw-r--r--tests/twisted/dispatcher/create-no-preferred-handler.py2
-rw-r--r--tests/twisted/dispatcher/create-rejected-by-mini-plugin.py2
-rw-r--r--tests/twisted/dispatcher/create-text.py4
-rw-r--r--tests/twisted/dispatcher/created-behind-our-back.py2
-rw-r--r--tests/twisted/dispatcher/delay-approvers.py2
-rw-r--r--tests/twisted/dispatcher/delay-then-call-handle-with.py2
-rw-r--r--tests/twisted/dispatcher/delay-then-dont-call-approvers.py2
-rw-r--r--tests/twisted/dispatcher/dispatch-activatable.py2
-rw-r--r--tests/twisted/dispatcher/dispatch-before-connected.py20
-rw-r--r--tests/twisted/dispatcher/dispatch-delayed-by-mini-plugin.py8
-rw-r--r--tests/twisted/dispatcher/dispatch-obsolete.py154
-rw-r--r--tests/twisted/dispatcher/dispatch-rejected-by-mini-plugin.py7
-rw-r--r--tests/twisted/dispatcher/dispatch-text.py2
-rw-r--r--tests/twisted/dispatcher/ensure-and-redispatch.py2
-rw-r--r--tests/twisted/dispatcher/ensure-is-approval.py2
-rw-r--r--tests/twisted/dispatcher/ensure-rapidly.py2
-rw-r--r--tests/twisted/dispatcher/exploding-bundles.py4
-rw-r--r--tests/twisted/dispatcher/fdo-21034.py2
-rw-r--r--tests/twisted/dispatcher/handle-channels-fails.py2
-rw-r--r--tests/twisted/dispatcher/lose-text.py2
-rw-r--r--tests/twisted/dispatcher/recover-from-disconnect.py21
-rw-r--r--tests/twisted/dispatcher/redispatch-channels.py2
-rw-r--r--tests/twisted/dispatcher/request-disabled-account.py6
-rw-r--r--tests/twisted/dispatcher/respawn-activatable-observers.py2
-rw-r--r--tests/twisted/dispatcher/respawn-observers.py2
-rw-r--r--tests/twisted/dispatcher/some-delay-approvers.py2
-rw-r--r--tests/twisted/dispatcher/undispatchable.py2
-rw-r--r--tests/twisted/dispatcher/vanishing-client.py2
-rw-r--r--tests/twisted/fakeaccountsservice.py105
-rw-r--r--tests/twisted/fakeclient.py99
-rw-r--r--tests/twisted/fakecm.py292
-rw-r--r--tests/twisted/mc-debug-server.c30
-rw-r--r--tests/twisted/mcp-account-diversion.c300
-rw-r--r--tests/twisted/mcp-dbus-caller-permission.c264
-rw-r--r--tests/twisted/mcp-plugin.c16
-rw-r--r--tests/twisted/mctest.py279
-rw-r--r--tests/twisted/run-test.sh.in52
-rw-r--r--tests/twisted/servicetest.py364
-rw-r--r--tests/twisted/tools/Makefile.am8
-rw-r--r--tests/value-is-same.c2
-rw-r--r--tools/Makefile.am27
-rw-r--r--tools/c-constants-generator.xsl299
-rw-r--r--tools/c-interfaces-generator.xsl84
-rw-r--r--tools/doc-generator.xsl1199
-rw-r--r--tools/glib-blocking-client-gen.py1014
-rw-r--r--tools/glib-client-gen.py1217
-rw-r--r--tools/glib-client-marshaller-gen.py60
-rw-r--r--tools/glib-ginterface-gen.py832
-rw-r--r--tools/glib-gtypes-generator.py304
-rw-r--r--tools/glib-interfaces-body-generator.xsl47
-rw-r--r--tools/glib-interfaces-generator.xsl55
-rw-r--r--tools/identity.xsl7
-rw-r--r--tools/lcov.am2
-rw-r--r--tools/libglibcodegen.py216
-rw-r--r--tools/libtpcodegen.py247
-rw-r--r--tools/spec-to-introspect.xsl26
-rw-r--r--util/Makefile.am2
-rw-r--r--xml/Account_Interface_Conditions.xml99
-rw-r--r--xml/Account_Interface_External_Password_Storage.xml58
-rw-r--r--xml/Account_Interface_Hidden.xml65
-rw-r--r--xml/Account_Manager_Interface_Hidden.xml100
-rw-r--r--xml/Channel_Dispatcher_Interface_Messages_DRAFT.xml57
-rw-r--r--xml/Connection_Manager_Interface_Account_Storage.xml120
-rw-r--r--xml/Makefile.am33
-rw-r--r--xml/all.xml35
-rw-r--r--xml/generic-types.xml214
-rw-r--r--xml/nmc5.xml14
-rw-r--r--xml/telepathy-types.xml96
197 files changed, 6683 insertions, 17883 deletions
diff --git a/.gitignore b/.gitignore
index c3abe8e7..23e56bb9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -36,7 +36,6 @@
Android.mk
Makefile
Makefile.in
-_gen/
INSTALL
aclocal.m4
autom4te.cache
diff --git a/Makefile.am b/Makefile.am
index 858f2be7..f0ee6f39 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -10,7 +10,6 @@ SUBDIRS = \
data \
m4 \
tools \
- xml \
mission-control-plugins \
plugins \
src \
@@ -30,7 +29,7 @@ DISTCHECK_CONFIGURE_FLAGS = \
maintainer-upload-release: _maintainer-upload-release-local
_maintainer-upload-release-local: _maintainer-upload-release-check
rsync -rvzPp --chmod=Dg+s,ug+rwX,o=rX doc/reference/mission-control-plugins/html/ \
- telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/doc/mission-control-plugins-5.16.x/
+ telepathy.freedesktop.org:/srv/telepathy.freedesktop.org/www/doc/mission-control-plugins/
include tools/lcov.am
include tools/telepathy.am
diff --git a/NEWS b/NEWS
index 0ecad85a..9f235cf0 100644
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,81 @@
+telepathy-mission-control 5.17.0 (UNRELEASED)
+=============================================
+
+Running this version of Mission Control for the first time will automatically
+migrate some account data to a new format. If you subsequently downgrade
+to an older version, it will no longer understand all account data.
+Taking a backup copy of ~/.local/share/telepathy/mission-control
+before you upgrade is recommended.
+
+Incompatible changes:
+
+• The mission-control-plugins library has broken API/ABI; deprecated functions
+ and the "D-Bus ACL" plugin API have been removed. For plugins not using
+ this functionality (e.g. Empathy's GNOME Online Accounts integration),
+ a simple recompile should be sufficient.
+
+• mcp_dispatch_operation_ref_connection(),
+ mcp_dispatch_operation_find_channel_by_type() and
+ mcp_dispatch_operation_ref_nth_channel() now take a
+ TpSimpleClientFactory argument.
+
+• The mcp_account_storage_create() virtual method now takes a single string
+ (the result of IdentifyAccount()), instead of a GHashTable (containing all
+ the new account's initial parameters).
+
+• Channel requests that specify an emergency service point by handle,
+ rather than by ID, are no longer treated specially. Channel requests
+ to an emergency service point by its normalized identifier (e.g.
+ from a user dialling 911 on a phone keypad) still get special treatment:
+ request policy plugins are bypassed for these requests.
+
+• The Account.I.Hidden and AccountManager.I.Hidden interfaces have been
+ removed. See fd.o #70427 for a somewhat similar idea.
+
+• The BypassObservers feature has been removed. See fd.o #30043
+ for attempts to design a better version.
+
+• The Account.I.Conditions interface has finally been removed.
+ Most of its supporting code was already deleted between 5.14 and 5.16.
+
+• The ChannelDispatcher.I.Messages.DRAFT interface is now called
+ ChannelDispatcher.I.Messages1. This will require some minor changes to
+ Telepathy-Qt, its only known user.
+
+• Support for Maemo features (Aegis, MCE and an old libaccounts-glib
+ account storage plugin) has been removed. Users of modern libaccounts-glib
+ versions (like the one in Ubuntu) should use the UOA plugin in Empathy,
+ or help us to disentangle it from Empathy and add it to Mission Control
+ (fd.o #66459).
+
+• Account.I.ExternalPasswordStorage and CM.I.AccountStorage have been
+ removed (fd.o #33485, #44512, #69006)
+
+Dependencies:
+
+• GLib ≥ 2.36 (including GObject, GModule and GIO) is now required
+• telepathy-glib ≥ 0.23.1 is now required
+
+Enhancements:
+
+• Use IdentifyAccount to name new accounts (fd.o #34640, Simon)
+
+• Store accounts in one file per account, with a GVariant-based
+ text format that preserves data types (fd.o #54875, Simon)
+
+• Re-save parameters with their types when edited, or when we discover
+ what type the connection manager expects (fd.o #71093, Simon)
+
+• Use telepathy-glib 0.23 for CD.I.Messages (fd.o #37380, Simon)
+
+Fixes:
+
+• UPower is no longer an optional dependency, since the API we used
+ has been removed. This version only supports "take accounts offline before
+ suspending" on systems with either systemd-logind, or a reimplementation
+ with the same D-Bus API. (fd.o #70458, Simon)
+
+
telepathy-mission-control 5.16.5 (2019-09-15)
=============================================
diff --git a/configure.ac b/configure.ac
index 4289f333..d1f7e37e 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,12 +1,12 @@
dnl Set the version number to e.g. 5.x.y immediately before a release.
dnl Set the version number to e.g. 5.x.y+ immediately after (this will
dnl enable -Werror).
-AC_INIT([telepathy-mission-control], [5.16.5])
+AC_INIT([telepathy-mission-control], [5.16.99+])
AC_CONFIG_MACRO_DIR([m4])
AC_CONFIG_AUX_DIR([build-aux])
AC_CONFIG_SRCDIR(Makefile.am)
-AM_INIT_AUTOMAKE([1.9 tar-ustar -Wno-portability])
+AM_INIT_AUTOMAKE([1.9 tar-ustar -Wno-portability subdir-objects])
m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES])
AC_CONFIG_HEADERS(config.h)
@@ -17,7 +17,7 @@ AC_PROG_CPP
AC_PROG_CXX
AC_PROG_INSTALL
AC_PROG_LIBTOOL
-AM_PROG_MKDIR_P
+AC_PROG_MKDIR_P
AC_HEADER_STDC
AC_CHECK_HEADERS([sys/stat.h sys/types.h sysexits.h])
@@ -35,7 +35,7 @@ esac
# If API has been removed or changed since last release, change MCP_API (which
# is part of the directory name under /usr/include) to the version that
# changed it
-MCP_API_VERSION=5.5
+MCP_API_VERSION=5.18
AC_SUBST([MCP_API_VERSION])
# If ABI has been removed or changed since last release
@@ -46,9 +46,9 @@ AC_SUBST([MCP_API_VERSION])
# set revision to 0
# else if library source has changed since last release
# increment revision
-MCP_LT_CURRENT=5
-MCP_LT_REVISION=1
-MCP_LT_AGE=5
+MCP_LT_CURRENT=6
+MCP_LT_REVISION=0
+MCP_LT_AGE=0
AC_SUBST([MCP_LT_CURRENT])
AC_SUBST([MCP_LT_REVISION])
AC_SUBST([MCP_LT_AGE])
@@ -74,7 +74,6 @@ TP_COMPILER_WARNINGS([ERROR_CFLAGS],
init-self \
],
[missing-field-initializers \
- deprecated-declarations \
unused-parameter])
AC_SUBST([ERROR_CFLAGS])
@@ -95,24 +94,23 @@ AC_MSG_RESULT([$mc_want_twisted_tests])
AM_CONDITIONAL([WANT_TWISTED_TESTS], test yes = "$mc_want_twisted_tests")
AC_ARG_ENABLE(debug, [ --disable-debug compile without debug code],[enable_debug=${enableval}], enable_debug=yes )
-if test "x$enable_debug" = "xyes"; then
- CFLAGS="$CFLAGS -DENABLE_DEBUG"
-fi
+AS_IF([test "x$enable_debug" = "xyes"],
+ [AC_DEFINE([ENABLE_DEBUG], [1], [Define to compile in debug messages])])
AC_ARG_ENABLE(cast-checks, [ --disable-cast-checks compile with GLIB cast checks disabled],[cchecks=${enableval}],cchecks=yes)
-if test "x$cchecks" = "xno"; then
- CFLAGS="$CFLAGS -DG_DISABLE_CAST_CHECKS"
-fi
+AS_IF([test "x$cchecks" = "xno"],
+ [AC_DEFINE([G_DISABLE_CAST_CHECKS], [1],
+ [Define to disable checked casts (not recommended)])])
AC_ARG_ENABLE(asserts, [ --disable-asserts compile with GLIB assertions disabled],[asserts=${enableval}],asserts=yes)
-if test "x$asserts" = "xno"; then
- CFLAGS="$CFLAGS -DG_DISABLE_ASSERTS"
-fi
+AS_IF([test "x$asserts" = "xno"],
+ [AC_DEFINE([G_DISABLE_ASSERTS], [1],
+ [Define to disable assertions (not recommended)])])
AC_ARG_ENABLE(checks, [ --disable-checks compile with GLIB checks disabled],[checks=${enableval}],checks=yes)
-if test "x$checks" = "xno"; then
- CFLAGS="$CFLAGS -DG_DISABLE_CHECKS"
-fi
+AS_IF([test "x$checks" = "xno"],
+ [AC_DEFINE([G_DISABLE_CHECKS], [1],
+ [Define to disable checks (not recommended)])])
AC_ARG_ENABLE(coverage, [ --enable-coverage compile with coverage info],[enable_coverage=${enableval}],enable_coverage=no)
if test "x$enable_coverage" = "xyes"; then
@@ -152,85 +150,17 @@ fi
AC_SUBST(ACCOUNTS_CACHE_DIR)
AC_DEFINE_UNQUOTED(ACCOUNTS_CACHE_DIR,"$ACCOUNTS_CACHE_DIR", [Directory for account/connection mapping for crash recovery])
-aegis_enabled="no"
-AC_MSG_CHECKING([whether to build with Aegis (libcreds) support])
-AC_ARG_ENABLE(aegis,
- AC_HELP_STRING([--enable-aegis],
- [Aegis security framework support]),
- [
- AC_CHECK_LIB(creds, creds_init,
- [
- AC_DEFINE([ENABLE_AEGIS], [1],
- [Define if Aegis is supported])
- AC_SUBST([AEGIS_LIBS], [-lcreds])
- ],
- [ AC_MSG_ERROR([Aegis: libcreds not found]) ])
- aegis_enabled="yes"
- ],
- [
- aegis_enabled="no"
- AC_MSG_RESULT(no)
- AC_DEFINE([ENABLE_AEGIS], [0], [Define if Aegis is supported])
- ])
-
-AM_CONDITIONAL(ENABLE_AEGIS, [test x$aegis_enabled = xyes])
-
PKG_PROG_PKG_CONFIG()
-dnl libaccounts-glib SSO
-libaccounts_sso_enabled="no"
-AC_MSG_CHECKING(whether to build with libaccounts-glib SSO suport)
-
-AC_ARG_ENABLE([libaccounts-sso],
- AC_HELP_STRING([--enable-libaccounts-sso],
- [build with SSO suport. default=no]),
- [ AC_MSG_RESULT(${enableval})
- libaccounts_sso_enabled="${enableval}" ],
- [ AC_MSG_RESULT(no) ] )
-
-AS_IF([ test "x$libaccounts_sso_enabled" = xauto ],
- [ PKG_CHECK_EXISTS([libaccounts-glib],
- [libaccounts_sso_enabled=yes],
- [libaccounts_sso_enabled=no]) ])
-
-dnl set up the shell/make variable, the #define and check the package version
-AS_IF([ test "x$libaccounts_sso_enabled" = xyes ],
- [ ENABLE_LIBACCOUNTS_SSO=yes
- AC_DEFINE(ENABLE_LIBACCOUNTS_SSO, [1],
- [Define if libaccounts SSO support is required])
- PKG_CHECK_MODULES([LIBACCOUNTS_SSO], [libaccounts-glib >= 0.26]) ],
- [ AC_DEFINE(ENABLE_LIBACCOUNTS_SSO, [0]) ])
-
-dnl export the CFLAGS and LDFLAGS equivalents determined by PKG_CHECK_MODULES
-AC_SUBST(LIBACCOUNTS_SSO_CFLAGS)
-AC_SUBST(LIBACCOUNTS_SSO_LIBS)
-
-dnl the automake conditional
-AM_CONDITIONAL(ENABLE_LIBACCOUNTS_SSO, [test x$libaccounts_sso_enabled = xyes])
-dnl /libaccounts-glib SSO
-
-AC_ARG_WITH([accounts-glib-hidden-service-type],
- [AS_HELP_STRING([--with-accounts-glib-hidden-service-type],
- [mark accounts with the provided service type as hidden @<:@default=no@:>@])],
- [],
- [with_accounts_glib_hidden_service_type=no])
-AS_IF([ test "x$with_accounts_glib_hidden_service_type" != xno ],
- [AC_DEFINE_UNQUOTED(ACCOUNTS_GLIB_HIDDEN_SERVICE_TYPE,
- ["$with_accounts_glib_hidden_service_type"],
- [Defined to the non-IM service type for hidden accounts, if any])])
-
-AM_CONDITIONAL(ENABLE_LIBACCOUNTS_GLIB_HIDDEN,
- [test x$with_accounts_glib_hidden_service_type != xno])
-
PKG_CHECK_MODULES(DBUS, [dbus-1 >= 0.95, dbus-glib-1 >= 0.82])
AC_SUBST(DBUS_CFLAGS)
AC_SUBST(DBUS_LIBS)
-PKG_CHECK_MODULES([TELEPATHY], [telepathy-glib >= 0.20.0])
-AC_DEFINE([TP_VERSION_MIN_REQUIRED], [TP_VERSION_0_18],
- [Ignore post-0.18 deprecations])
-AC_DEFINE([TP_VERSION_MAX_ALLOWED], [TP_VERSION_0_20],
- [Prevent post-0.20 APIs])
+PKG_CHECK_MODULES([TELEPATHY], [telepathy-glib >= 0.23.1])
+AC_DEFINE([TP_VERSION_MIN_REQUIRED], [TP_VERSION_0_24],
+ [Ignore post-0.24 deprecations])
+AC_DEFINE([TP_VERSION_MAX_ALLOWED], [TP_VERSION_0_24],
+ [Prevent post-0.24 APIs])
AC_DEFINE([TP_SEAL_ENABLE], [], [Define to hide deprecated struct fields])
AC_DEFINE([TP_DISABLE_SINGLE_INCLUDE], [], [Avoid individual headers])
@@ -248,13 +178,6 @@ PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0],
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_46], [Ignore post 2.46 deprecations])
AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_46], [Prevent post 2.46 APIs])
-dnl Check for MCE, a Maemo service used to determine when the device 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
-
# -----------------------------------------------------------
# Connectivity integration
# -----------------------------------------------------------
@@ -296,34 +219,6 @@ if test x"$enable_conn_setting" = xyes; then
fi
AM_CONDITIONAL([ENABLE_CONN_SETTING], [test x"$enable_conn_setting" = xyes])
-# -----------------------------------------------------------
-# Suspend/resume tracking goop
-# -----------------------------------------------------------
-
-AC_ARG_ENABLE([upower],
- [AS_HELP_STRING([--enable-upower],
- [monitor device suspending and resuming using upower-glib @<:@default=auto@:>@])],
- [],
- [enable_upower=auto])
-
-if test "x$enable_upower" != xno; then
- PKG_CHECK_MODULES([UPOWER_GLIB], [upower-glib < 0.99],
- [AC_DEFINE([HAVE_UPOWER], [1], [Define to use upower-glib])
- have_upower=yes
- ],
- [if test "x$enable_upower" == xyes; then
- AC_MSG_ERROR([$UPOWER_GLIB_PKG_ERRORS])
- else
- have_upower=no
- fi
- ])
-else
- have_upower=no
-fi
-
-AC_SUBST([UPOWER_GLIB_CFLAGS])
-AC_SUBST([UPOWER_GLIB_LIBS])
-
dnl ***************************************************************************
dnl Check for marshal and enum generators
dnl ***************************************************************************
@@ -356,7 +251,6 @@ tests/twisted/Makefile \
tests/twisted/tools/Makefile \
tools/Makefile \
util/Makefile \
-xml/Makefile \
])
echo "
@@ -377,11 +271,5 @@ Configure summary:
Features:
Plugin API documentation.....: ${enable_gtk_doc}
Network Manager integration..: ${have_nm}
- ConnMan integration..........: ${have_connman}
Connectivity GSetting........: ${enable_conn_setting}
- Suspend tracking with UPower.: ${have_upower}
- Aegis........................: ${aegis_enabled}
- libaccounts-glib backend.....: ${libaccounts_sso_enabled}
- Hidden accounts-glib accounts: ${with_accounts_glib_hidden_service_type}
- Nokia Mode Control Entity....: ${HAVE_MCE}
"
diff --git a/doc/Makefile.am b/doc/Makefile.am
index 41c97bc9..f3ddc22d 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,14 +1 @@
SUBDIRS = reference
-SPECS = $(top_srcdir)/xml/all.xml
-SPECS_DOC = mc-dbus-iface.html
-
-all-local: $(SPECS_DOC)
-
-$(SPECS_DOC): $(top_srcdir)/xml/all.xml $(wildcard $(top_srcdir)/xml/*.xml) $(top_srcdir)/tools/doc-generator.xsl
- $(XSLTPROC) --xinclude --novalid \
- --param allow-undefined-interfaces "true()" \
- $(top_srcdir)/tools/doc-generator.xsl $< > $@
-
-clean-local:
- rm -f $(SPECS_DOC)
-
diff --git a/doc/reference/mission-control-plugins/Makefile.am b/doc/reference/mission-control-plugins/Makefile.am
index 65ec75e2..061d1b77 100644
--- a/doc/reference/mission-control-plugins/Makefile.am
+++ b/doc/reference/mission-control-plugins/Makefile.am
@@ -145,6 +145,14 @@ check-local:
echo "$$file missing from $(DOC_MODULE)-docs.sgml"; \
err=1; \
fi; \
- done
+ done; \
+ case $(ENABLE_DOC_CHECKS)/$$err in \
+ (yes/1) \
+ echo "Documentation check failed" >&2; \
+ exit $$err; \
+ ;; \
+ (*) \
+ exit 0; \
+ ;; \
+ esac
endif
-# ... but don't fail on incomplete documentation, this is a stable branch
diff --git a/doc/reference/mission-control-plugins/mission-control-plugins-docs.sgml b/doc/reference/mission-control-plugins/mission-control-plugins-docs.sgml
index 77e663f7..7ca6b9fc 100644
--- a/doc/reference/mission-control-plugins/mission-control-plugins-docs.sgml
+++ b/doc/reference/mission-control-plugins/mission-control-plugins-docs.sgml
@@ -8,8 +8,8 @@
<bookinfo>
<title>Mission Control Plugins Reference Manual</title>
<releaseinfo>
- The latest version of this documentation in this stable branch can be found on-line at
- <ulink role="online-location" url="http://telepathy.freedesktop.org/doc/mission-control-plugins-5.16.x/">http://telepathy.freedesktop.org/doc/mission-control-plugins-5.16.x/</ulink>.
+ The latest version of this documentation can be found on-line at
+ <ulink role="online-location" url="http://telepathy.freedesktop.org/doc/mission-control-plugins/">http://telepathy.freedesktop.org/doc/mission-control-plugins/</ulink>.
</releaseinfo>
</bookinfo>
diff --git a/mission-control-plugins/Makefile.am b/mission-control-plugins/Makefile.am
index 1c6abf15..ae4c848b 100644
--- a/mission-control-plugins/Makefile.am
+++ b/mission-control-plugins/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = \
+AM_CPPFLAGS = \
$(TELEPATHY_CFLAGS) \
$(DBUS_CFLAGS) \
$(GLIB_CFLAGS) \
@@ -21,7 +21,6 @@ plugins_include_HEADERS = \
mission-control-plugins.h \
account.h \
account-storage.h \
- dbus-acl.h \
debug.h \
dispatch-operation.h \
dispatch-operation-policy.h \
@@ -54,7 +53,6 @@ libmission_control_plugins_la_SOURCES = \
debug.c \
account.c \
account-storage.c \
- dbus-acl.c \
dispatch-operation.c \
dispatch-operation-policy.c \
implementation.h \
@@ -71,7 +69,7 @@ Android.mk: Makefile.am $(BUILT_SOURCES)
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(BUILT_SOURCES) $(libmission_control_plugins_la_SOURCES) \
-:CFLAGS $(DEFAULT_INCLUDES) $(DEFS) $(CFLAGS) $(AM_CFLAGS) \
- -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) $(INCLUDES) \
+ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \
-:LDFLAGS $(libmission_control_plugins_la_LIBADD) \
> $@
diff --git a/mission-control-plugins/account-storage.c b/mission-control-plugins/account-storage.c
index 3991c0cd..081597c8 100644
--- a/mission-control-plugins/account-storage.c
+++ b/mission-control-plugins/account-storage.c
@@ -56,18 +56,19 @@
* iface->desc = "The FOO storage backend";
* iface->provider = "org.freedesktop.Telepathy.MissionControl5.FooStorage";
*
- * iface->get = foo_plugin_get;
- * iface->set = foo_plugin_get;
- * iface->delete = foo_plugin_delete;
+ * iface->get_flags = foo_plugin_get_flags;
+ * iface->delete_async = foo_plugin_delete_async;
+ * iface->delete_finish = foo_plugin_delete_finish;
* iface->commit = foo_plugin_commit;
- * iface->commit_one = foo_plugin_commit_one;
* iface->list = foo_plugin_list;
- * iface->ready = foo_plugin_ready;
* iface->get_identifier = foo_plugin_get_identifier;
* iface->get_additional_info = foo_plugin_get_additional_info;
* iface->get_restrictions = foo_plugin_get_restrictions;
* iface->create = foo_plugin_create;
- * iface->owns = foo_plugin_owns;
+ * iface->get_attribute = foo_plugin_get_attribute;
+ * iface->get_parameter = foo_plugin_get_parameter;
+ * iface->list_typed_parameters = foo_plugin_list_typed_parameters;
+ * iface->list_untyped_parameters = foo_plugin_list_untyped_parameters;
* iface->set_attribute = foo_plugin_set_attribute;
* iface->set_parameter = foo_plugin_set_parameter;
* }
@@ -100,10 +101,18 @@
#endif /* ENABLE_DEBUG */
+/**
+ * McpAccountStorageFlags:
+ * @MCP_ACCOUNT_STORAGE_FLAG_NONE: no particular flags
+ * @MCP_ACCOUNT_STORAGE_FLAG_STORES_TYPES: this backend can store parameter
+ * values' types
+ *
+ * Flags describing the features and capabilities of a backend.
+ */
+
enum
{
CREATED,
- ALTERED,
TOGGLED,
DELETED,
ALTERED_ONE,
@@ -113,17 +122,72 @@ enum
static guint signals[NO_SIGNAL] = { 0 };
-static gboolean
-default_set (const McpAccountStorage *storage,
- const McpAccountManager *am,
+static void
+default_delete_async (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account,
- const gchar *key,
- const gchar *val)
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- return FALSE;
+ g_task_report_new_error (storage, callback, user_data,
+ default_delete_async, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
+ "This storage plugin cannot delete accounts");
+}
+
+static gboolean
+default_delete_finish (McpAccountStorage *storage,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
}
static gboolean
+default_commit (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account)
+{
+ return FALSE;
+}
+
+static gchar *
+default_create (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *manager,
+ const gchar *protocol,
+ const gchar *identification,
+ GError **error)
+{
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
+ "This storage does not implement the create() function");
+ return NULL;
+}
+
+static void
+default_get_identifier (McpAccountStorage *storage,
+ const gchar *account,
+ GValue *identifier)
+{
+ g_value_init (identifier, G_TYPE_STRING);
+ g_value_set_string (identifier, account);
+}
+
+static GHashTable *
+default_get_additional_info (McpAccountStorage *storage,
+ const gchar *account)
+{
+ return g_hash_table_new (g_str_hash, g_str_equal);
+}
+
+static TpStorageRestrictionFlags
+default_get_restrictions (McpAccountStorage *storage,
+ const gchar *account)
+{
+ return 0;
+}
+
+static McpAccountStorageSetResult
default_set_attribute (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
@@ -131,10 +195,10 @@ default_set_attribute (McpAccountStorage *storage,
GVariant *value,
McpAttributeFlags flags)
{
- return FALSE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED;
}
-static gboolean
+static McpAccountStorageSetResult
default_set_parameter (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
@@ -142,20 +206,22 @@ default_set_parameter (McpAccountStorage *storage,
GVariant *value,
McpParameterFlags flags)
{
- return FALSE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED;
}
-static gboolean
-default_owns (McpAccountStorage *storage,
+static gchar **
+default_list_untyped_parameters (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account)
{
- /* This has the side-effect of pushing the "manager" key back into @am,
- * but that should be a no-op in practice: we always call this
- * method in priority order and stop at the first one that says "yes",
- * and @am's idea of what "manager" is should have come from that same
- * plugin anyway. */
- return mcp_account_storage_get (storage, am, account, "manager");
+ return NULL;
+}
+
+static McpAccountStorageFlags
+default_get_flags (McpAccountStorage *storage,
+ const gchar *account)
+{
+ return MCP_ACCOUNT_STORAGE_FLAG_NONE;
}
static void
@@ -165,10 +231,17 @@ class_init (gpointer klass,
GType type = G_TYPE_FROM_CLASS (klass);
McpAccountStorageIface *iface = klass;
- iface->owns = default_owns;
- iface->set = default_set;
+ iface->get_flags = default_get_flags;
+ iface->create = default_create;
+ iface->delete_async = default_delete_async;
+ iface->delete_finish = default_delete_finish;
+ iface->commit = default_commit;
+ iface->get_identifier = default_get_identifier;
+ iface->get_additional_info = default_get_additional_info;
+ iface->get_restrictions = default_get_restrictions;
iface->set_attribute = default_set_attribute;
iface->set_parameter = default_set_parameter;
+ iface->list_untyped_parameters = default_list_untyped_parameters;
if (signals[CREATED] != 0)
{
@@ -183,8 +256,10 @@ class_init (gpointer klass,
* Emitted if an external entity creates an account
* in the backend the emitting plugin handles.
*
- * Should not be fired until mcp_account_storage_ready() has been called
- *
+ * This signal does not need to be emitted before mcp_account_storage_list()
+ * returns (if it is, it will be ignored). All accounts that exist
+ * at the time that mcp_account_storage_list() returns must be included
+ * in its result, even if they were also signalled via this signal.
*/
signals[CREATED] = g_signal_new ("created",
type, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -192,41 +267,23 @@ class_init (gpointer klass,
1, G_TYPE_STRING);
/**
- * McpAccountStorage::altered
- * @account: the unique name of the altered account
- *
- * This signal does not appear to be fully implemented
- * (see <ulink href="https://bugs.freedesktop.org/show_bug.cgi?id=28288"
- * >freedesktop.org bug 28288</ulink>).
- * Emit #McpAccountStorage::altered-one instead.
- *
- * Should not be fired until mcp_account_storage_ready() has been called
- *
- */
- signals[ALTERED] = g_signal_new ("altered",
- type, G_SIGNAL_RUN_LAST | G_SIGNAL_DEPRECATED, 0, NULL, NULL,
- g_cclosure_marshal_VOID__STRING, G_TYPE_NONE,
- 1, G_TYPE_STRING);
-
- /**
* McpAccountStorage::altered-one
* @account: the unique name of the altered account
- * @name: the name of the altered property (its key)
+ * @name: either an attribute name such as DisplayName,
+ * or "param-" plus a parameter name, e.g. "param-require-encryption"
*
* Emitted if an external entity alters an account
* in the backend that the emitting plugin handles.
*
- * Before emitting this signal, the plugin must call
- * either mcp_account_manager_set_attribute(),
- * either mcp_account_manager_set_parameter() or
- * mcp_account_manager_set_value() to push the new value
- * into the account manager.
+ * Before emitting this signal, the plugin must update its
+ * internal cache (if any) so that mcp_account_storage_get_attribute()
+ * or mcp_account_storage_get_parameter() will return the new value
+ * when queried.
*
- * Note that mcp_account_manager_set_parameter() does not use the
- * "param-" prefix, but this signal and mcp_account_manager_set_value()
- * both do.
- *
- * Should not be fired until mcp_account_storage_ready() has been called
+ * Note that mcp_account_storage_get_parameter(),
+ * mcp_account_storage_list_typed_parameters() and
+ * mcp_account_storage_set_parameter() do not use the
+ * "param-" prefix, but this signal does.
*/
signals[ALTERED_ONE] = g_signal_new ("altered-one",
type, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -240,9 +297,6 @@ class_init (gpointer klass,
*
* Emitted if an external entity deletes an account
* in the backend the emitting plugin handles.
- *
- * Should not be fired until mcp_account_storage_ready() has been called
- *
*/
signals[DELETED] = g_signal_new ("deleted",
type, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -257,11 +311,11 @@ class_init (gpointer klass,
* Emitted if an external entity enables/disables an account
* in the backend the emitting plugin handles. This is similar to
* emitting #McpAccountStorage::altered-one for the attribute
- * "Enabled", except that the plugin is not required to call
- * a function like mcp_account_manager_set_value() first.
- *
- * Should not be fired until mcp_account_storage_ready() has been called
+ * "Enabled".
*
+ * Before emitting this signal, the plugin must update its
+ * internal cache (if any) so that mcp_account_storage_get_attribute()
+ * will return the new value for Enabled when queried.
*/
signals[TOGGLED] = g_signal_new ("toggled",
type, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -274,8 +328,6 @@ class_init (gpointer klass,
*
* emitted if an external entity modified important parameters of the
* account and a reconnection is required in order to apply them.
- *
- * Should not be fired until mcp_account_storage_ready() has been called
**/
signals[RECONNECT] = g_signal_new ("reconnect",
type, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
@@ -328,131 +380,28 @@ mcp_account_storage_get_type (void)
* @name: returned by mcp_account_storage_name()
* @desc: returned by mcp_account_storage_description()
* @provider: returned by mcp_account_storage_provider()
- * @set: implementation of mcp_account_storage_set()
- * @get: implementation of mcp_account_storage_get()
- * @delete: implementation of mcp_account_storage_delete()
+ * @delete_async: implementation of mcp_account_storage_delete_async()
+ * @delete_finish: implementation of mcp_account_storage_delete_finish()
* @commit: implementation of mcp_account_storage_commit()
* @list: implementation of mcp_account_storage_list()
- * @ready: implementation of mcp_account_storage_ready()
- * @commit_one: implementation of mcp_account_storage_commit_one()
* @get_identifier: implementation of mcp_account_storage_get_identifier()
* @get_additional_info: implementation of
* mcp_account_storage_get_additional_info()
* @get_restrictions: implementation of mcp_account_storage_get_restrictions()
* @create: implementation of mcp_account_storage_create()
+ * @get_attribute: implementation of mcp_account_storage_get_attribute()
+ * @get_parameter: implementation of mcp_account_storage_get_parameter()
+ * @set_attribute: implementation of mcp_account_storage_set_attribute()
+ * @set_parameter: implementation of mcp_account_storage_set_parameter()
+ * @list_typed_parameters: implementation
+ * of mcp_account_storage_list_typed_parameters()
+ * @list_untyped_parameters: implementation
+ * of mcp_account_storage_list_untyped_parameters()
+ * @get_flags: implementation of mcp_account_storage_get_flags()
*
* The interface vtable for an account storage plugin.
*/
-void
-mcp_account_storage_iface_set_priority (McpAccountStorageIface *iface,
- guint prio)
-{
- iface->priority = prio;
-}
-
-void
-mcp_account_storage_iface_set_name (McpAccountStorageIface *iface,
- const gchar *name)
-{
- iface->name = name;
-}
-
-void
-mcp_account_storage_iface_set_desc (McpAccountStorageIface *iface,
- const gchar *desc)
-{
- iface->desc = desc;
-}
-
-void
-mcp_account_storage_iface_set_provider (McpAccountStorageIface *iface,
- const gchar *provider)
-{
- iface->provider = provider;
-}
-
-void
-mcp_account_storage_iface_implement_get (McpAccountStorageIface *iface,
- McpAccountStorageGetFunc method)
-{
- iface->get = method;
-}
-
-void
-mcp_account_storage_iface_implement_set (McpAccountStorageIface *iface,
- McpAccountStorageSetFunc method)
-{
- iface->set = method;
-}
-
-void
-mcp_account_storage_iface_implement_delete (McpAccountStorageIface *iface,
- McpAccountStorageDeleteFunc method)
-{
- iface->delete = method;
-}
-
-void
-mcp_account_storage_iface_implement_commit (McpAccountStorageIface *iface,
- McpAccountStorageCommitFunc method)
-{
- iface->commit = method;
-}
-
-void
-mcp_account_storage_iface_implement_commit_one (McpAccountStorageIface *iface,
- McpAccountStorageCommitOneFunc method)
-{
- iface->commit_one = method;
-}
-
-void
-mcp_account_storage_iface_implement_list (McpAccountStorageIface *iface,
- McpAccountStorageListFunc method)
-{
- iface->list = method;
-}
-
-void
-mcp_account_storage_iface_implement_ready (McpAccountStorageIface *iface,
- McpAccountStorageReadyFunc method)
-{
- iface->ready = method;
-}
-
-void
-mcp_account_storage_iface_implement_get_identifier (
- McpAccountStorageIface *iface,
- McpAccountStorageGetIdentifierFunc method)
-{
- iface->get_identifier = method;
-}
-
-void
-mcp_account_storage_iface_implement_get_additional_info (
- McpAccountStorageIface *iface,
- McpAccountStorageGetAdditionalInfoFunc method)
-{
- iface->get_additional_info = method;
-}
-
-void
-mcp_account_storage_iface_implement_get_restrictions (
- McpAccountStorageIface *iface,
- McpAccountStorageGetRestrictionsFunc method)
-{
- iface->get_restrictions = method;
-}
-
-void
-mcp_account_storage_iface_implement_create (
- McpAccountStorageIface *iface,
- McpAccountStorageCreate method)
-{
- iface->create = method;
-}
-
/**
* mcp_account_storage_priority:
* @storage: an #McpAccountStorage instance
@@ -488,7 +437,7 @@ mcp_account_storage_iface_implement_create (
* Returns: the priority of this plugin
**/
gint
-mcp_account_storage_priority (const McpAccountStorage *storage)
+mcp_account_storage_priority (McpAccountStorage *storage)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
@@ -498,111 +447,168 @@ mcp_account_storage_priority (const McpAccountStorage *storage)
}
/**
- * McpAccountStorageGetFunc:
- * @storage: the account storage plugin
- * @am: object used to call back into the account manager
+ * mcp_account_storage_get_attribute:
+ * @storage: an #McpAccountStorage instance
+ * @am: an #McpAccountManager instance
* @account: the unique name of the account
- * @key: the setting whose value we wish to fetch: either an attribute
- * like "DisplayName", or "param-" plus a parameter like "account"
+ * @attribute: the name of an attribute, e.g. "DisplayName"
+ * @type: the expected type of @attribute, as a hint for
+ * legacy account storage plugins that do not store attributes' types
+ * @flags: (allow-none) (out): used to return attribute flags
+ *
+ * Retrieve an attribute.
+ *
+ * There is no default implementation.
+ * All account storage plugins must override this method.
*
- * An implementation of mcp_account_storage_get().
+ * The returned variant does not necessarily have to match @type:
+ * Mission Control will coerce it to an appropriate type if required. In
+ * particular, plugins that store strongly-typed attributes may return
+ * the stored type, not the expected type, if they differ.
*
- * Returns: %TRUE if @storage is responsible for @account
+ * Returns: (transfer full): the value of the attribute, or %NULL if it
+ * is not present
*/
+GVariant *
+mcp_account_storage_get_attribute (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *attribute,
+ const GVariantType *type,
+ McpAttributeFlags *flags)
+{
+ McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
+
+ SDEBUG (storage, "%s.%s (type '%.*s')", account, attribute,
+ (int) g_variant_type_get_string_length (type),
+ g_variant_type_peek_string (type));
+
+ g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (iface->get_attribute != NULL, FALSE);
+
+ return iface->get_attribute (storage, am, account, attribute, type, flags);
+}
/**
- * mcp_account_storage_get:
+ * mcp_account_storage_get_parameter:
* @storage: an #McpAccountStorage instance
* @am: an #McpAccountManager instance
* @account: the unique name of the account
- * @key: the setting whose value we wish to fetch: either an attribute
- * like "DisplayName", or "param-" plus a parameter like "account"
- *
- * Get a value from the plugin's in-memory cache.
- * Before emitting this signal, the plugin must call
- * either mcp_account_manager_set_attribute(),
- * mcp_account_manager_set_parameter(),
- * or mcp_account_manager_set_value() and (if appropriate)
- * mcp_account_manager_parameter_make_secret()
- * before returning from this method call.
- *
- * Note that mcp_account_manager_set_parameter() does not use the
- * "param-" prefix, even if called from this function.
- *
- * If @key is %NULL the plugin should iterate through all attributes and
- * parameters, and push each of them into @am, as if this method had
- * been called once for each attribute or parameter. It must then return
- * %TRUE if any attributes or parameters were found, or %FALSE if it
- * was not responsible for @account.
- *
- * Returns: %TRUE if @storage is responsible for @account
+ * @parameter: the name of a parameter, e.g. "require-encryption"
+ * @type: (allow-none): the expected type of @parameter, as a hint for
+ * legacy account storage plugins that do not store parameters' types
+ * @flags: (allow-none) (out): used to return parameter flags
+ *
+ * Retrieve a parameter.
+ *
+ * There is no default implementation.
+ * All account storage plugins must override this method.
+ *
+ * The returned variant does not necessarily have to match @type:
+ * Mission Control will coerce it to an appropriate type if required. In
+ * particular, plugins that store strongly-typed parameters may return
+ * the stored type, not the expected type, if they differ.
+ *
+ * If @type is %NULL, the plugin must return the parameter with its stored
+ * type, or return %NULL if the type is not stored.
+ *
+ * Returns: (transfer full): the value of the parameter, or %NULL if it
+ * is not present
*/
-gboolean
-mcp_account_storage_get (const McpAccountStorage *storage,
+GVariant *
+mcp_account_storage_get_parameter (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
- const gchar *key)
+ const gchar *parameter,
+ const GVariantType *type,
+ McpParameterFlags *flags)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- SDEBUG (storage, "");
+ if (type == NULL)
+ SDEBUG (storage, "%s.%s (if type is stored)", account, parameter);
+ else
+ SDEBUG (storage, "%s.%s (type '%.*s')", account, parameter,
+ (int) g_variant_type_get_string_length (type),
+ g_variant_type_peek_string (type));
+
g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->get != NULL, FALSE);
+ g_return_val_if_fail (iface->get_parameter != NULL, FALSE);
- return iface->get (storage, am, account, key);
+ return iface->get_parameter (storage, am, account, parameter, type, flags);
}
/**
- * McpAccountStorageSetFunc:
+ * mcp_account_storage_list_typed_parameters:
* @storage: an #McpAccountStorage instance
* @am: an #McpAccountManager instance
* @account: the unique name of the account
- * @key: the setting whose value we wish to store: either an attribute
- * like "DisplayName", or "param-" plus a parameter like "account"
- * @val: a non-%NULL value for @key
*
- * An implementation of mcp_account_storage_set().
+ * List the names of all parameters whose corresponding types are known.
+ *
+ * Ideally, all parameters are <firstterm>typed parameters</firstterm>, whose
+ * types are stored alongside the values. This function produces
+ * those as its return value.
+ *
+ * However, the Mission Control API has not traditionally required
+ * account-storage backends to store parameters' types, so some backends
+ * will contain <firstterm>untyped parameters</firstterm>,
+ * returned by mcp_account_storage_list_untyped_parameters().
*
- * Returns: %TRUE if @storage is responsible for @account
+ * This method is mandatory to implement.
+ *
+ * Returns: (array zero-terminated=1) (transfer full) (element-type utf8): a #GStrv
+ * containing the typed parameters; %NULL or empty if there are no
+ * typed parameters
*/
+gchar **
+mcp_account_storage_list_typed_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account)
+{
+ McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
+
+ SDEBUG (storage, "%s", account);
+
+ g_return_val_if_fail (iface != NULL, NULL);
+ g_return_val_if_fail (iface->list_typed_parameters != NULL, NULL);
+
+ return iface->list_typed_parameters (storage, am, account);
+}
/**
- * mcp_account_storage_set:
+ * mcp_account_storage_list_untyped_parameters:
* @storage: an #McpAccountStorage instance
* @am: an #McpAccountManager instance
* @account: the unique name of the account
- * @key: the non-%NULL setting whose value we wish to store: either an
- * attribute like "DisplayName", or "param-" plus a parameter like "account"
- * @value: a value to associate with @key, escaped as if for a #GKeyFile
*
- * The plugin is expected to either quickly and synchronously
- * update its internal cache of values with @value, or to
- * decline to store the setting.
+ * List the names of all parameters whose types are unknown.
+ * The values are not listed, because interpreting the value
+ * correctly requires a type.
*
- * The plugin is not expected to write to its long term storage
- * at this point. It can expect Mission Control to call either
- * mcp_account_storage_commit() or mcp_account_storage_commit_one()
- * after a short delay.
+ * See mcp_account_storage_list_typed_parameters() for more on
+ * typed vs. untyped parameters.
*
- * Plugins that implement mcp_storage_set_attribute() and
- * mcp_account_storage_set_parameter() can just return %FALSE here.
- * There is a default implementation, which just returns %FALSE.
+ * The default implementation just returns %NULL, and is appropriate
+ * for "legacy-free" backends that store a type with every parameter.
*
- * Returns: %TRUE if the attribute was claimed, %FALSE otherwise
+ * Returns: (array zero-terminated=1) (transfer full) (element-type utf8): a #GStrv
+ * containing the untyped parameters; %NULL or empty if there are no
+ * untyped parameters
*/
-gboolean
-mcp_account_storage_set (const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key,
- const gchar *value)
+gchar **
+mcp_account_storage_list_untyped_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- SDEBUG (storage, "");
- g_return_val_if_fail (iface != NULL, FALSE);
+ SDEBUG (storage, "%s", account);
+
+ g_return_val_if_fail (iface != NULL, NULL);
+ g_return_val_if_fail (iface->list_untyped_parameters != NULL, NULL);
- return iface->set (storage, am, account, key, value);
+ return iface->list_untyped_parameters (storage, am, account);
}
/**
@@ -611,7 +617,8 @@ mcp_account_storage_set (const McpAccountStorage *storage,
* @am: an #McpAccountManager instance
* @account: the unique name of the account
* @attribute: the name of an attribute, e.g. "DisplayName"
- * @value: a value to associate with @attribute
+ * @value: (allow-none): a value to associate with @attribute,
+ * or %NULL to delete
* @flags: flags influencing how the attribute is to be stored
*
* Store an attribute.
@@ -623,15 +630,14 @@ mcp_account_storage_set (const McpAccountStorage *storage,
* The plugin is not expected to write to its long term storage
* at this point.
*
- * There is a default implementation, which just returns %FALSE.
- * Mission Control will call mcp_account_storage_set() instead,
- * using a keyfile-escaped version of @value.
+ * There is a default implementation, which just returns %FALSE for read-only
+ * storage plugins.
*
* Returns: %TRUE if the attribute was claimed, %FALSE otherwise
*
* Since: 5.15.0
*/
-gboolean
+McpAccountStorageSetResult
mcp_account_storage_set_attribute (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
@@ -641,9 +647,13 @@ mcp_account_storage_set_attribute (McpAccountStorage *storage,
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- SDEBUG (storage, "");
- g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->set_attribute != NULL, FALSE);
+ SDEBUG (storage, "%s.%s (type '%s')", account, attribute,
+ value == NULL ? "null" : g_variant_get_type_string (value));
+
+ g_return_val_if_fail (iface != NULL,
+ MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+ g_return_val_if_fail (iface->set_attribute != NULL,
+ MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
return iface->set_attribute (storage, am, account, attribute, value, flags);
}
@@ -655,7 +665,8 @@ mcp_account_storage_set_attribute (McpAccountStorage *storage,
* @account: the unique name of the account
* @parameter: the name of a parameter, e.g. "account" (note that there
* is no "param-" prefix here)
- * @value: a value to associate with @parameter
+ * @value: (allow-none): a value to associate with @parameter,
+ * or %NULL to delete
* @flags: flags influencing how the parameter is to be stored
*
* Store a parameter.
@@ -667,16 +678,14 @@ mcp_account_storage_set_attribute (McpAccountStorage *storage,
* The plugin is not expected to write to its long term storage
* at this point.
*
- * There is a default implementation, which just returns %FALSE.
- * Mission Control will call mcp_account_storage_set() instead,
- * using "param-" + @parameter as key and a keyfile-escaped version
- * of @value as value.
+ * There is a default implementation, which just returns %FALSE for read-only
+ * storage plugins.
*
* Returns: %TRUE if the parameter was claimed, %FALSE otherwise
*
* Since: 5.15.0
*/
-gboolean
+McpAccountStorageSetResult
mcp_account_storage_set_parameter (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
@@ -686,9 +695,14 @@ mcp_account_storage_set_parameter (McpAccountStorage *storage,
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- SDEBUG (storage, "");
+ SDEBUG (storage, "%s.%s (type '%s')", account, parameter,
+ value == NULL ? "null" : g_variant_get_type_string (value));
+
g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->set_parameter != NULL, FALSE);
+ g_return_val_if_fail (iface != NULL,
+ MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+ g_return_val_if_fail (iface->set_parameter != NULL,
+ MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
return iface->set_parameter (storage, am, account, parameter, value, flags);
}
@@ -713,13 +727,14 @@ mcp_account_storage_set_parameter (McpAccountStorage *storage,
* @am: an object which can be used to call back into the account manager
* @manager: the name of the manager
* @protocol: the name of the protocol
- * @params: A gchar * / GValue * hash table of account parameters
+ * @identification: a normalized form of the account name, or "account"
+ * if nothing is suitable (e.g. for telepathy-salut)
* @error: a GError to fill
*
* Inform the plugin that a new account is being created. @manager, @protocol
- * and @params are given to help determining the account's unique name, but does
- * not need to be stored on the account yet, mcp_account_storage_set() and
- * mcp_account_storage_commit() will be called later.
+ * and @identification are given to help determining the account's unique name,
+ * but does not need to be stored on the account yet, mcp_account_storage_set()
+ * and mcp_account_storage_commit() will be called later.
*
* It is recommended to use mcp_account_manager_get_unique_name() to create the
* unique name, but it's not mandatory. One could base the unique name on an
@@ -729,90 +744,105 @@ mcp_account_storage_set_parameter (McpAccountStorage *storage,
* #McpAccountStorage::created signal should not be emitted for this account,
* not even when mcp_account_storage_commit() will be called.
*
+ * The default implementation just returns %NULL, and is appropriate for
+ * read-only storage.
+ *
+ * Since Mission Control 5.17, all storage plugins in which new accounts
+ * can be created by Mission Control must implement this method.
+ * Previously, it was not mandatory.
+ *
* Returns: (transfer full): the newly allocated account name, which should
* be freed once the caller is done with it, or %NULL if that couldn't
* be done.
*/
gchar *
-mcp_account_storage_create (const McpAccountStorage *storage,
- const McpAccountManager *am,
+mcp_account_storage_create (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identification,
GError **error)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- g_return_val_if_fail (iface != NULL, NULL);
+ SDEBUG (storage, "%s/%s \"%s\"", manager, protocol, identification);
- if (iface->create == NULL)
- {
- g_set_error (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "This storage does not implement create function");
- return NULL;
- }
+ g_return_val_if_fail (iface != NULL, NULL);
+ g_return_val_if_fail (iface->create != NULL, NULL);
- return iface->create (storage, am, manager, protocol, params, error);
+ return iface->create (storage, am, manager, protocol, identification, error);
}
/**
- * McpAccountStorageDeleteFunc:
+ * mcp_account_storage_delete_async:
* @storage: an #McpAccountStorage instance
* @am: an #McpAccountManager instance
* @account: the unique name of the account
- * @key: (allow-none): the setting whose value we wish to store - either an
- * attribute like "DisplayName", or "param-" plus a parameter like
- * "account" - or %NULL to delete the entire account
+ * @cancellable: (allow-none): optionally used to (try to) cancel the operation
+ * @callback: called on success or failure
+ * @user_data: data for @callback
+ *
+ * Delete the account @account, and commit the change,
+ * emitting #McpAccountStorage::deleted afterwards.
+ *
+ * Unlike the 'delete' virtual method in earlier MC versions, this
+ * function is expected to commit the change to long-term storage,
+ * is expected to emit #McpAccountStorage::deleted, and is
+ * not called for the deletion of individual attributes or parameters.
*
- * An implementation of mcp_account_storage_delete().
+ * The default implementation just returns failure (asynchronously),
+ * and is appropriate for read-only storage.
*
- * Returns: %TRUE if the setting or settings are not
- * the plugin's cache after this operation, %FALSE otherwise.
+ * Implementations that override delete_async must also override
+ * delete_finish.
*/
+void
+mcp_account_storage_delete_async (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
+
+ SDEBUG (storage, "%s", account);
+
+ g_return_if_fail (iface != NULL);
+ g_return_if_fail (iface->delete_async != NULL);
+
+ iface->delete_async (storage, am, account, cancellable, callback, user_data);
+}
/**
- * mcp_account_storage_delete:
+ * mcp_account_storage_delete_finish:
* @storage: an #McpAccountStorage instance
- * @am: an #McpAccountManager instance
- * @account: the unique name of the account
- * @key: (allow-none): the setting whose value we wish to store - either an
- * attribute like "DisplayName", or "param-" plus a parameter like
- * "account" - or %NULL to delete the entire account
- *
- * The plugin is expected to remove the setting for @key from its
- * internal cache and to remember that its state has changed, so
- * that it can delete said setting from its long term storage if
- * its long term storage method makes this necessary.
- *
- * If @key is %NULL, the plugin should forget all its settings for
- * @account,and remember to delete the entire account from its storage later.
+ * @res: the result of mcp_account_storage_delete_async()
+ * @error: used to raise an error if %FALSE is returned
*
- * The plugin is not expected to update its long term storage at
- * this point.
+ * Process the result of mcp_account_storage_delete_async().
*
- * Returns: %TRUE if the setting or settings are not
- * the plugin's cache after this operation, %FALSE otherwise.
- * This is very unlikely to ever be %FALSE, as a plugin is always
- * expected to be able to manipulate its own cache.
+ * Returns: %TRUE on success, %FALSE if the account could not be deleted
*/
gboolean
-mcp_account_storage_delete (const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key)
+mcp_account_storage_delete_finish (McpAccountStorage *storage,
+ GAsyncResult *result,
+ GError **error)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
SDEBUG (storage, "");
g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (iface->delete_finish != NULL, FALSE);
- return iface->delete (storage, am, account, key);
+ return iface->delete_finish (storage, result, error);
}
/**
* McpAccountStorageCommitFunc:
* @storage: an #McpAccountStorage instance
* @am: an #McpAccountManager instance
+ * @account: the unique suffix of an account's object path
*
* An implementation of mcp_account_storage_commit().
*
@@ -823,6 +853,7 @@ mcp_account_storage_delete (const McpAccountStorage *storage,
* mcp_account_storage_commit:
* @storage: an #McpAccountStorage instance
* @am: an #McpAccountManager instance
+ * @account: the unique suffix of an account's object path
*
* The plugin is expected to write its cache to long term storage,
* deleting, adding or updating entries in said storage as needed.
@@ -831,87 +862,28 @@ mcp_account_storage_delete (const McpAccountStorage *storage,
* not required to have finished its commit operation when it returns,
* merely to have started the operation.
*
- * If the @commit_one method is implemented, it will be called preferentially
- * if only one account is to be committed. If the @commit_one method is
- * implemented but @commit is not, @commit_one will be called with
- * @account_name = %NULL to commit all accounts.
- *
- * Returns: %TRUE if the commit process was started (but not necessarily
- * completed) successfully; %FALSE if there was a problem that was immediately
- * obvious.
- */
-gboolean
-mcp_account_storage_commit (const McpAccountStorage *storage,
- const McpAccountManager *am)
-{
- McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
-
- SDEBUG (storage, "committing all accounts");
- g_return_val_if_fail (iface != NULL, FALSE);
-
- if (iface->commit != NULL)
- {
- return iface->commit (storage, am);
- }
- else if (iface->commit_one != NULL)
- {
- return iface->commit_one (storage, am, NULL);
- }
- else
- {
- SDEBUG (storage,
- "neither commit nor commit_one is implemented; cannot save accounts");
- return FALSE;
- }
-}
-
-/**
- * McpAccountStorageCommitOneFunc:
- * @storage: an #McpAccountStorage instance
- * @am: an #McpAccountManager instance
- * @account: (allow-none): the unique suffix of an account's object path,
- * or %NULL
- *
- * An implementation of mcp_account_storage_commit_one().
- *
- * Returns: %TRUE if the commit process was started successfully
- */
-
-/**
- * mcp_account_storage_commit_one:
- * @storage: an #McpAccountStorage instance
- * @am: an #McpAccountManager instance
- * @account: (allow-none): the unique suffix of an account's object path,
- * or %NULL if all accounts are to be committed and
- * mcp_account_storage_commit() is unimplemented
- *
- * The same as mcp_account_storage_commit(), but only commit the given
- * account. This is optional to implement; the default implementation
- * is to call @commit.
+ * The default implementation just returns %FALSE, and is appropriate for
+ * read-only storage.
*
- * If both mcp_account_storage_commit_one() and mcp_account_storage_commit()
- * are implemented, Mission Control will never pass @account = %NULL to
- * this method.
+ * Mission Control 5.17+ no longer requires plugins to cope with
+ * account == NULL.
*
* Returns: %TRUE if the commit process was started (but not necessarily
* completed) successfully; %FALSE if there was a problem that was immediately
* obvious.
*/
gboolean
-mcp_account_storage_commit_one (const McpAccountStorage *storage,
- const McpAccountManager *am,
+mcp_account_storage_commit (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
SDEBUG (storage, "called for %s", account ? account : "<all accounts>");
g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (iface->commit != NULL, FALSE);
- if (iface->commit_one != NULL)
- return iface->commit_one (storage, am, account);
- else
- /* Fall back to plain ->commit() */
- return mcp_account_storage_commit (storage, am);
+ return iface->commit (storage, am, account);
}
/**
@@ -935,56 +907,28 @@ mcp_account_storage_commit_one (const McpAccountStorage *storage,
* This method is called only at initialisation time, before the dbus name
* has been claimed, and is the only one permitted to block.
*
+ * There is no default implementation. All implementations of this interface
+ * must override this method.
+ *
* Returns: (element-type utf8) (transfer full): a list of account names that
* the plugin has settings for. The account names should be freed with
* g_free(), and the list with g_list_free(), when the caller is done with
* them.
*/
GList *
-mcp_account_storage_list (const McpAccountStorage *storage,
- const McpAccountManager *am)
+mcp_account_storage_list (McpAccountStorage *storage,
+ McpAccountManager *am)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
SDEBUG (storage, "");
g_return_val_if_fail (iface != NULL, NULL);
+ g_return_val_if_fail (iface->list != NULL, NULL);
return iface->list (storage, am);
}
/**
- * McpAccountStorageReadyFunc:
- * @storage: an #McpAccountStorage instance
- * @am: an #McpAccountManager instance
- *
- * An implementation of mcp_account_storage_ready().
- */
-
-/**
- * mcp_account_storage_ready:
- * @storage: an #McpAccountStorage instance
- * @am: an #McpAccountManager instance
- *
- * Informs the plugin that it is now permitted to create new accounts,
- * ie it can now fire its "created", "altered", "toggled" and "deleted"
- * signals.
- */
-void
-mcp_account_storage_ready (const McpAccountStorage *storage,
- const McpAccountManager *am)
-{
- McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
-
- g_return_if_fail (iface != NULL);
-
- /* plugins that can't create accounts from external sources don't *
- * need to implement this method, as they can never fire the async *
- * account change signals: */
- if (iface->ready != NULL)
- iface->ready (storage, am);
-}
-
-/**
* McpAccountStorageGetIdentifierFunc:
* @storage: an #McpAccountStorage instance
* @account: the unique name of the account
@@ -1004,30 +948,25 @@ mcp_account_storage_ready (const McpAccountStorage *storage,
* Get the storage-specific identifier for this account. The type is variant,
* hence the GValue.
*
+ * The default implementation returns @account as a %G_TYPE_STRING.
+ *
* This method will only be called for the storage plugin that "owns"
* the account.
*/
void
-mcp_account_storage_get_identifier (const McpAccountStorage *storage,
+mcp_account_storage_get_identifier (McpAccountStorage *storage,
const gchar *account,
GValue *identifier)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- SDEBUG (storage, "");
+ SDEBUG (storage, "%s", account);
g_return_if_fail (iface != NULL);
+ g_return_if_fail (iface->get_identifier != NULL);
g_return_if_fail (identifier != NULL);
g_return_if_fail (!G_IS_VALUE (identifier));
- if (iface->get_identifier == NULL)
- {
- g_value_init (identifier, G_TYPE_STRING);
- g_value_set_string (identifier, account);
- }
- else
- {
- iface->get_identifier (storage, account, identifier);
- }
+ iface->get_identifier (storage, account, identifier);
}
/**
@@ -1052,26 +991,22 @@ mcp_account_storage_get_identifier (const McpAccountStorage *storage,
* This method will only be called for the storage plugin that "owns"
* the account.
*
+ * The default implementation returns an empty map.
+ *
* Returns: (transfer container) (element-type utf8 GObject.Value): additional
- * storage-specific information
+ * storage-specific information, which must not be %NULL
*/
GHashTable *
-mcp_account_storage_get_additional_info (const McpAccountStorage *storage,
+mcp_account_storage_get_additional_info (McpAccountStorage *storage,
const gchar *account)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
- GHashTable *ret = NULL;
- SDEBUG (storage, "");
+ SDEBUG (storage, "%s", account);
g_return_val_if_fail (iface != NULL, FALSE);
+ g_return_val_if_fail (iface->get_additional_info != NULL, FALSE);
- if (iface->get_additional_info != NULL)
- ret = iface->get_additional_info (storage, account);
-
- if (ret == NULL)
- ret = g_hash_table_new (g_str_hash, g_str_equal);
-
- return ret;
+ return iface->get_additional_info (storage, account);
}
/**
@@ -1092,22 +1027,22 @@ mcp_account_storage_get_additional_info (const McpAccountStorage *storage,
* This method will only be called for the storage plugin that "owns"
* the account.
*
+ * The default implementation returns 0, i.e. no restrictions.
+ *
* Returns: a bitmask of %TpStorageRestrictionFlags with the restrictions to
* account storage.
*/
-/* FIXME: when breaking API, make this return TpStorageRestrictionFlags */
-guint
-mcp_account_storage_get_restrictions (const McpAccountStorage *storage,
+TpStorageRestrictionFlags
+mcp_account_storage_get_restrictions (McpAccountStorage *storage,
const gchar *account)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
+ SDEBUG (storage, "%s", account);
g_return_val_if_fail (iface != NULL, 0);
+ g_return_val_if_fail (iface->get_restrictions != NULL, 0);
- if (iface->get_restrictions == NULL)
- return 0;
- else
- return iface->get_restrictions (storage, account);
+ return iface->get_restrictions (storage, account);
}
/**
@@ -1119,7 +1054,7 @@ mcp_account_storage_get_restrictions (const McpAccountStorage *storage,
* Returns: the plugin's name (for logging etc)
*/
const gchar *
-mcp_account_storage_name (const McpAccountStorage *storage)
+mcp_account_storage_name (McpAccountStorage *storage)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
@@ -1137,7 +1072,7 @@ mcp_account_storage_name (const McpAccountStorage *storage)
* Returns: the plugin's description (for logging etc)
*/
const gchar *
-mcp_account_storage_description (const McpAccountStorage *storage)
+mcp_account_storage_description (McpAccountStorage *storage)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
@@ -1156,7 +1091,7 @@ mcp_account_storage_description (const McpAccountStorage *storage)
* was provided in #McpAccountStorageIface.provider.
*/
const gchar *
-mcp_account_storage_provider (const McpAccountStorage *storage)
+mcp_account_storage_provider (McpAccountStorage *storage)
{
McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
@@ -1166,7 +1101,7 @@ mcp_account_storage_provider (const McpAccountStorage *storage)
}
/**
- * mcp_account_storage_emit_create:
+ * mcp_account_storage_emit_created:
* @storage: an #McpAccountStorage instance
* @account: the unique name of the created account
*
@@ -1176,24 +1111,11 @@ void
mcp_account_storage_emit_created (McpAccountStorage *storage,
const gchar *account)
{
+ SDEBUG (storage, "%s", account);
g_signal_emit (storage, signals[CREATED], 0, account);
}
/**
- * mcp_account_storage_emit_altered:
- * @storage: an #McpAccountStorage instance
- * @account: the unique name of the altered account
- *
- * Emits the #McpAccountStorage::altered signal
- */
-void
-mcp_account_storage_emit_altered (McpAccountStorage *storage,
- const gchar *account)
-{
- g_signal_emit (storage, signals[ALTERED], 0, account);
-}
-
-/**
* mcp_account_storage_emit_altered_one:
* @storage: an #McpAccountStorage instance
* @account: the unique name of the altered account
@@ -1207,6 +1129,7 @@ mcp_account_storage_emit_altered_one (McpAccountStorage *storage,
const gchar *account,
const gchar *key)
{
+ SDEBUG (storage, "%s", account);
g_signal_emit (storage, signals[ALTERED_ONE], 0, account, key);
}
@@ -1221,6 +1144,7 @@ void
mcp_account_storage_emit_deleted (McpAccountStorage *storage,
const gchar *account)
{
+ SDEBUG (storage, "%s", account);
g_signal_emit (storage, signals[DELETED], 0, account);
}
@@ -1237,6 +1161,7 @@ mcp_account_storage_emit_toggled (McpAccountStorage *storage,
const gchar *account,
gboolean enabled)
{
+ SDEBUG (storage, "%s: Enabled=%s", account, enabled ? "True" : "False");
g_signal_emit (storage, signals[TOGGLED], 0, account, enabled);
}
@@ -1251,35 +1176,78 @@ void
mcp_account_storage_emit_reconnect (McpAccountStorage *storage,
const gchar *account)
{
+ SDEBUG (storage, "%s", account);
g_signal_emit (storage, signals[RECONNECT], 0, account);
}
/**
- * mcp_account_storage_owns:
+ * mcp_account_storage_get_flags:
* @storage: an #McpAccountStorage instance
- * @am: an #McpAccountManager instance
- * @account: the unique name (object-path tail) of an account
+ * @account: the unique name of the account to inspect
*
- * Check whether @account is stored in @storage. The highest-priority
- * plugin for which this function returns %TRUE is considered to be
- * responsible for @account.
+ * Get the backend's features and capabilities. The default implementation
+ * returns %MCP_ACCOUNT_STORAGE_FLAG_NONE. Additionally providing
+ * %MCP_ACCOUNT_STORAGE_FLAG_STORES_TYPES is strongly recommended.
*
- * There is a default implementation, which calls mcp_account_storage_get()
- * for the well-known key "manager".
+ * Returns: a bitmask of API features that apply to @account
+ */
+McpAccountStorageFlags
+mcp_account_storage_get_flags (McpAccountStorage *storage,
+ const gchar *account)
+{
+ McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
+
+ g_return_val_if_fail (iface != NULL, MCP_ACCOUNT_STORAGE_FLAG_NONE);
+ g_return_val_if_fail (iface->get_flags != NULL,
+ MCP_ACCOUNT_STORAGE_FLAG_NONE);
+
+ return iface->get_flags (storage, account);
+}
+
+/**
+ * mcp_account_storage_has_all_flags:
+ * @storage: an #McpAccountStorage instance
+ * @account: the unique name of the account to inspect
+ * @require_all: bitwise "or" of zero or more flags
*
- * Returns: %TRUE if @account is stored in @storage
+ * Return whether this account has all of the specified flags,
+ * according to mcp_account_storage_get_flags().
*
- * Since: 5.15.0
+ * If @require_all is 0, the result will always be %TRUE
+ * (the account has all of the flags in the empty set).
+ *
+ * Returns: %TRUE if @account has every flag in @require_all
*/
gboolean
-mcp_account_storage_owns (McpAccountStorage *storage,
- McpAccountManager *am,
- const gchar *account)
+mcp_account_storage_has_all_flags (McpAccountStorage *storage,
+ const gchar *account,
+ McpAccountStorageFlags require_all)
{
- McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage);
+ return ((mcp_account_storage_get_flags (storage, account) & require_all) ==
+ require_all);
+}
- g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->owns != NULL, FALSE);
- return iface->owns (storage, am, account);
+/**
+ * mcp_account_storage_has_any_flag:
+ * @storage: an #McpAccountStorage instance
+ * @account: the unique name of the account to inspect
+ * @require_one: bitwise "or" of one or more flags
+ *
+ * Return whether this account has at least one of the required flags,
+ * according to mcp_account_storage_get_flags().
+ *
+ * If @require_one is 0, the result will always be %FALSE
+ * (it is not true that the account has at least one of the flags
+ * in the empty set).
+ *
+ * Returns: %TRUE if @account has every flag in @require_all
+ */
+gboolean
+mcp_account_storage_has_any_flag (McpAccountStorage *storage,
+ const gchar *account,
+ McpAccountStorageFlags require_one)
+{
+ return ((mcp_account_storage_get_flags (storage, account) & require_one)
+ != 0);
}
diff --git a/mission-control-plugins/account-storage.h b/mission-control-plugins/account-storage.h
index 91cdd78a..b8015217 100644
--- a/mission-control-plugins/account-storage.h
+++ b/mission-control-plugins/account-storage.h
@@ -30,7 +30,28 @@ G_BEGIN_DECLS
#define MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_READONLY -1
#define MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_DEFAULT 0
#define MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_NORMAL 100
-#define MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_KEYRING 10000
+
+typedef enum /*< flags >*/
+{
+ MCP_PARAMETER_FLAG_NONE = 0
+} McpParameterFlags;
+
+typedef enum /*< flags >*/
+{
+ MCP_ATTRIBUTE_FLAG_NONE = 0
+} McpAttributeFlags;
+
+typedef enum {
+ MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED = 0,
+ MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED,
+ MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED
+} McpAccountStorageSetResult;
+
+typedef enum /*< flags >*/
+{
+ MCP_ACCOUNT_STORAGE_FLAG_NONE = 0,
+ MCP_ACCOUNT_STORAGE_FLAG_STORES_TYPES = (1 << 0)
+} McpAccountStorageFlags;
/* API for plugins to implement */
typedef struct _McpAccountStorage McpAccountStorage;
@@ -58,53 +79,15 @@ struct _McpAccountStorage { };
GType mcp_account_storage_get_type (void);
-/* Virtual method implementation signatures */
-typedef gboolean (*McpAccountStorageGetFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key);
-typedef gboolean (*McpAccountStorageSetFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key,
- const gchar *val);
typedef gchar * (*McpAccountStorageCreate) (
- const McpAccountStorage *storage,
- const McpAccountManager *am,
+ McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identification,
GError **error);
-typedef gboolean (*McpAccountStorageDeleteFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key);
-typedef GList * (*McpAccountStorageListFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am);
-typedef gboolean (*McpAccountStorageCommitFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am);
-typedef gboolean (*McpAccountStorageCommitOneFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account);
-typedef void (*McpAccountStorageReadyFunc) (
- const McpAccountStorage *storage,
- const McpAccountManager *am);
-typedef void (*McpAccountStorageGetIdentifierFunc) (
- const McpAccountStorage *storage,
- const gchar *account,
- GValue *identifier);
-typedef GHashTable * (*McpAccountStorageGetAdditionalInfoFunc) (
- const McpAccountStorage *storage,
- const gchar *account);
-/* FIXME: when breaking API, make this return TpStorageRestrictionFlags */
-typedef guint (*McpAccountStorageGetRestrictionsFunc) (
- const McpAccountStorage *storage,
+typedef TpStorageRestrictionFlags (*McpAccountStorageGetRestrictionsFunc) (
+ McpAccountStorage *storage,
const gchar *account);
struct _McpAccountStorageIface
@@ -116,176 +99,169 @@ struct _McpAccountStorageIface
const gchar *desc;
const gchar *provider;
- McpAccountStorageSetFunc set;
- McpAccountStorageGetFunc get;
- McpAccountStorageDeleteFunc delete;
- McpAccountStorageCommitFunc commit;
- McpAccountStorageListFunc list;
- McpAccountStorageReadyFunc ready;
- McpAccountStorageCommitOneFunc commit_one;
- McpAccountStorageGetIdentifierFunc get_identifier;
- McpAccountStorageGetAdditionalInfoFunc get_additional_info;
- McpAccountStorageGetRestrictionsFunc get_restrictions;
- McpAccountStorageCreate create;
-
- /* Since 5.15.0 */
- gboolean (*owns) (McpAccountStorage *storage,
+ void (*delete_async) (McpAccountStorage *storage,
McpAccountManager *am,
- const gchar *account);
- gboolean (*set_attribute) (McpAccountStorage *storage,
+ const gchar *account,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gboolean (*delete_finish) (McpAccountStorage *storage,
+ GAsyncResult *res,
+ GError **error);
+
+ gboolean (*commit) (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account);
+
+ GList * (*list) (McpAccountStorage *storage,
+ McpAccountManager *am);
+
+ void (*get_identifier) (McpAccountStorage *storage,
+ const gchar *account,
+ GValue *identifier);
+
+ GHashTable * (*get_additional_info) (McpAccountStorage *storage,
+ const gchar *account);
+
+ TpStorageRestrictionFlags (*get_restrictions) (McpAccountStorage *storage,
+ const gchar *account);
+
+ gchar * (*create) (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *manager,
+ const gchar *protocol,
+ const gchar *identification,
+ GError **error);
+
+ GVariant *(*get_attribute) (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *attribute,
+ const GVariantType *type,
+ McpAttributeFlags *flags);
+ GVariant *(*get_parameter) (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *parameter,
+ const GVariantType *type,
+ McpParameterFlags *flags);
+
+ McpAccountStorageSetResult (*set_attribute) (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
const gchar *attribute,
GVariant *val,
McpAttributeFlags flags);
- gboolean (*set_parameter) (McpAccountStorage *storage,
+ McpAccountStorageSetResult (*set_parameter) (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
const gchar *parameter,
GVariant *val,
McpParameterFlags flags);
-};
-#ifndef __GTK_DOC_IGNORE__
-#ifndef MC_DISABLE_DEPRECATED
-
-/* functions with which to fill in the vtable */
-G_DEPRECATED_FOR (iface->priority = prio)
-void mcp_account_storage_iface_set_priority (McpAccountStorageIface *iface,
- guint prio);
-
-G_DEPRECATED_FOR (iface->name = name)
-void mcp_account_storage_iface_set_name (McpAccountStorageIface *iface,
- const gchar *name);
-
-G_DEPRECATED_FOR (iface->desc = desc)
-void mcp_account_storage_iface_set_desc (McpAccountStorageIface *iface,
- const gchar *desc);
-
-G_DEPRECATED_FOR (iface->provider = provider)
-void mcp_account_storage_iface_set_provider (McpAccountStorageIface *iface,
- const gchar *provider);
-
-G_DEPRECATED_FOR (iface->get = method)
-void mcp_account_storage_iface_implement_get (McpAccountStorageIface *iface,
- McpAccountStorageGetFunc method);
-G_DEPRECATED_FOR (iface->set = method)
-void mcp_account_storage_iface_implement_set (McpAccountStorageIface *iface,
- McpAccountStorageSetFunc method);
-G_DEPRECATED_FOR (iface->create = method)
-void mcp_account_storage_iface_implement_create (
- McpAccountStorageIface *iface,
- McpAccountStorageCreate method);
-G_DEPRECATED_FOR (iface->delete = method)
-void mcp_account_storage_iface_implement_delete (McpAccountStorageIface *iface,
- McpAccountStorageDeleteFunc method);
-G_DEPRECATED_FOR (iface->list = method)
-void mcp_account_storage_iface_implement_list (McpAccountStorageIface *iface,
- McpAccountStorageListFunc method);
-G_DEPRECATED_FOR (iface->commit = method)
-void mcp_account_storage_iface_implement_commit (McpAccountStorageIface *iface,
- McpAccountStorageCommitFunc method);
-G_DEPRECATED_FOR (iface->commit_one = method)
-void mcp_account_storage_iface_implement_commit_one (
- McpAccountStorageIface *iface,
- McpAccountStorageCommitOneFunc method);
-G_DEPRECATED_FOR (iface->ready = method)
-void mcp_account_storage_iface_implement_ready (McpAccountStorageIface *iface,
- McpAccountStorageReadyFunc method);
-G_DEPRECATED_FOR (iface->get_identifier = method)
-void mcp_account_storage_iface_implement_get_identifier (
- McpAccountStorageIface *iface,
- McpAccountStorageGetIdentifierFunc method);
-G_DEPRECATED_FOR (iface->get_additional_info = method)
-void mcp_account_storage_iface_implement_get_additional_info (
- McpAccountStorageIface *iface,
- McpAccountStorageGetAdditionalInfoFunc method);
-G_DEPRECATED_FOR (iface->get_restrictions = method)
-void mcp_account_storage_iface_implement_get_restrictions (
- McpAccountStorageIface *iface,
- McpAccountStorageGetRestrictionsFunc method);
-
-#endif /* !defined(MC_DISABLE_DEPRECATED) */
-#endif /* !defined(__GTK_DOC_IGNORE__) */
+ gchar **(*list_typed_parameters) (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account);
+ gchar **(*list_untyped_parameters) (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account);
+
+ McpAccountStorageFlags (*get_flags) (McpAccountStorage *storage,
+ const gchar *account);
+};
/* virtual methods */
-gint mcp_account_storage_priority (const McpAccountStorage *storage);
+gint mcp_account_storage_priority (McpAccountStorage *storage);
-gboolean mcp_account_storage_get (const McpAccountStorage *storage,
+gchar * mcp_account_storage_create (McpAccountStorage *storage,
McpAccountManager *am,
- const gchar *account,
- const gchar *key);
-
-gboolean mcp_account_storage_set (const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key,
- const gchar *value);
-
-gchar * mcp_account_storage_create (const McpAccountStorage *storage,
- const McpAccountManager *am,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identification,
GError **error);
-gboolean mcp_account_storage_delete (const McpAccountStorage *storage,
- const McpAccountManager *am,
+void mcp_account_storage_delete_async (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account,
- const gchar *key);
-
-void mcp_account_storage_ready (const McpAccountStorage *storage,
- const McpAccountManager *am);
-
-gboolean
-mcp_account_storage_commit (const McpAccountStorage *storage,
- const McpAccountManager *am);
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mcp_account_storage_delete_finish (McpAccountStorage *storage,
+ GAsyncResult *result,
+ GError **error);
gboolean
-mcp_account_storage_commit_one (const McpAccountStorage *storage,
- const McpAccountManager *am,
+mcp_account_storage_commit (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account);
-GList *mcp_account_storage_list (const McpAccountStorage *storage,
- const McpAccountManager *am);
+GList *mcp_account_storage_list (McpAccountStorage *storage,
+ McpAccountManager *am);
-void mcp_account_storage_get_identifier (const McpAccountStorage *storage,
+void mcp_account_storage_get_identifier (McpAccountStorage *storage,
const gchar *account,
GValue *identifier);
GHashTable *mcp_account_storage_get_additional_info (
- const McpAccountStorage *storage,
+ McpAccountStorage *storage,
const gchar *account);
-guint mcp_account_storage_get_restrictions (const McpAccountStorage *storage,
+TpStorageRestrictionFlags mcp_account_storage_get_restrictions (
+ McpAccountStorage *storage,
const gchar *account);
-const gchar *mcp_account_storage_name (const McpAccountStorage *storage);
+const gchar *mcp_account_storage_name (McpAccountStorage *storage);
-const gchar *mcp_account_storage_description (const McpAccountStorage *storage);
-const gchar *mcp_account_storage_provider (const McpAccountStorage *storage);
+const gchar *mcp_account_storage_description (McpAccountStorage *storage);
+const gchar *mcp_account_storage_provider (McpAccountStorage *storage);
-gboolean mcp_account_storage_owns (McpAccountStorage *storage,
+GVariant *mcp_account_storage_get_attribute (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *attribute,
+ const GVariantType *type,
+ McpAttributeFlags *flags);
+GVariant *mcp_account_storage_get_parameter (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *parameter,
+ const GVariantType *type,
+ McpParameterFlags *flags);
+gchar **mcp_account_storage_list_typed_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account);
+gchar **mcp_account_storage_list_untyped_parameters (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account);
-gboolean mcp_account_storage_set_attribute (McpAccountStorage *storage,
+McpAccountStorageSetResult mcp_account_storage_set_attribute (
+ McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
const gchar *attribute,
GVariant *value,
McpAttributeFlags flags);
-gboolean mcp_account_storage_set_parameter (McpAccountStorage *storage,
+McpAccountStorageSetResult mcp_account_storage_set_parameter (
+ McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account,
const gchar *parameter,
GVariant *value,
McpParameterFlags flags);
-void mcp_account_storage_emit_created (McpAccountStorage *storage,
+McpAccountStorageFlags mcp_account_storage_get_flags (
+ McpAccountStorage *storage,
const gchar *account);
-G_DEPRECATED_FOR (something that is actually implemented)
-void mcp_account_storage_emit_altered (McpAccountStorage *storage,
+gboolean mcp_account_storage_has_all_flags (
+ McpAccountStorage *storage,
+ const gchar *account,
+ McpAccountStorageFlags require_all);
+gboolean mcp_account_storage_has_any_flag (
+ McpAccountStorage *storage,
+ const gchar *account,
+ McpAccountStorageFlags require_one);
+
+void mcp_account_storage_emit_created (McpAccountStorage *storage,
const gchar *account);
void mcp_account_storage_emit_altered_one (McpAccountStorage *storage,
const gchar *account,
diff --git a/mission-control-plugins/account.c b/mission-control-plugins/account.c
index e962857c..2c194616 100644
--- a/mission-control-plugins/account.c
+++ b/mission-control-plugins/account.c
@@ -74,212 +74,11 @@ mcp_account_manager_get_type (void)
}
/**
- * mcp_account_manager_set_value:
- * @mcpa: an #McpAccountManager instance
- * @account: the unique name of an account
- * @key: the setting whose value we wish to change: either an attribute
- * like "DisplayName", or "param-" plus a parameter like "account"
- * @value: the new value, escaped as if for a #GKeyFile, or %NULL to delete
- * the setting/parameter
- *
- * Inform Mission Control that @key has changed its value to @value.
- *
- * This function may either be called from mcp_account_storage_get(),
- * or just before emitting #McpAccountStorage::altered-one.
- *
- * New plugins should call mcp_account_manager_set_attribute() or
- * mcp_account_manager_set_parameter() instead.
- */
-void
-mcp_account_manager_set_value (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key,
- const gchar *value)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_if_fail (iface != NULL);
- g_return_if_fail (iface->set_value != NULL);
-
- iface->set_value (mcpa, account, key, value);
-}
-
-/**
- * mcp_account_manager_set_attribute:
- * @mcpa: an #McpAccountManager instance
- * @account: the unique name of an account
- * @attribute: the name of an attribute, such as "DisplayName"
- * @value: (allow-none): the new value, or %NULL to delete the attribute
- * @flags: flags for the new value (only used if @value is non-%NULL)
- *
- * Inform Mission Control that @attribute has changed its value to @value.
- *
- * If @value is a floating reference, Mission Control will take ownership
- * of it, much like g_variant_builder_add_value().
- *
- * This function may either be called from mcp_account_storage_get(),
- * or just before emitting #McpAccountStorage::altered-one.
- */
-void
-mcp_account_manager_set_attribute (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *attribute,
- GVariant *value,
- McpAttributeFlags flags)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_if_fail (iface != NULL);
- g_return_if_fail (iface->set_attribute != NULL);
-
- iface->set_attribute (mcpa, account, attribute, value, flags);
-}
-
-/**
- * mcp_account_manager_set_parameter:
- * @mcpa: an #McpAccountManager instance
- * @account: the unique name of an account
- * @parameter: the name of a parameter, such as "account", without
- * the "param-" prefix
- * @value: (allow-none): the new value, or %NULL to delete the parameter
- * @flags: flags for the new value (only used if @value is non-%NULL)
- *
- * Inform Mission Control that @parameter has changed its value to @value.
- *
- * If @value is a floating reference, Mission Control will take ownership
- * of it, much like g_variant_builder_add_value().
- *
- * This function may either be called from mcp_account_storage_get(),
- * or just before emitting #McpAccountStorage::altered-one.
- */
-void
-mcp_account_manager_set_parameter (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *parameter,
- GVariant *value,
- McpParameterFlags flags)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_if_fail (iface != NULL);
- g_return_if_fail (iface->set_parameter != NULL);
-
- iface->set_parameter (mcpa, account, parameter, value, flags);
-}
-
-/**
- * mcp_account_manage_list_keys:
- * @mcpa: a #McpAccountManager instance
- * @account: the unique name of an account
- *
- * <!-- -->
- *
- * Returns: (transfer full): a list of all keys (attributes and
- * "param-"-prefixed parameters) stored for @account by any plugin
- */
-GStrv
-mcp_account_manager_list_keys (const McpAccountManager *mcpa,
- const gchar *account)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_val_if_fail (iface != NULL, NULL);
- g_return_val_if_fail (iface->list_keys != NULL, NULL);
- g_return_val_if_fail (account != NULL, NULL);
-
- return iface->list_keys (mcpa, account);
-}
-
-/**
- * mcp_account_manager_get_value:
- * @mcpa: an #McpAccountManager instance
- * @account: the unique name of an account
- * @key: the setting whose value we wish to fetch: either an attribute
- * like "DisplayName", or "param-" plus a parameter like "account"
- *
- * Fetch a copy of the current value of an account setting held by
- * the account manager.
- *
- * Returns: (transfer full): the value of @key
- */
-gchar *
-mcp_account_manager_get_value (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_val_if_fail (iface != NULL, NULL);
- g_return_val_if_fail (iface->set_value != NULL, NULL);
-
- return iface->get_value (mcpa, account, key);
-}
-
-/**
- * mcp_account_manager_parameter_is_secret:
- * @mcpa: an #McpAccountManager instance
- * @account: the unique name of an account
- * @key: the constant string "param-", plus a parameter name like
- * "account" or "password"
- *
- * Determine whether a given account parameter is secret.
- * Generally this is determined by MC and passed down to plugins,
- * but any #McpAccountStorage plugin may decide a parameter is
- * secret, in which case the return value for this call will
- * indicate that fact too.
- *
- * For historical reasons, this function only operates on parameters,
- * but requires its argument to be prefixed with "param-".
- *
- * Returns: %TRUE for secret settings, %FALSE otherwise
- */
-gboolean
-mcp_account_manager_parameter_is_secret (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->is_secret != NULL, FALSE);
-
- return iface->is_secret (mcpa, account, key);
-}
-
-/**
- * mcp_account_manager_parameter_make_secret:
- * @mcpa: an #McpAccountManager instance
- * @account: the unique name of an account
- * @key: the constant string "param-", plus a parameter name like
- * "account" or "password"
- *
- * Flag an account setting as secret for the lifetime of this
- * #McpAccountManager. For instance, this should be called if
- * @key has been retrieved from gnome-keyring.
- *
- * For historical reasons, this function only operates on parameters,
- * but requires its argument to be prefixed with "param-".
- */
-void
-mcp_account_manager_parameter_make_secret (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_if_fail (iface != NULL);
- g_return_if_fail (iface->make_secret != NULL);
-
- g_debug ("%s.%s should be secret", account, key);
- iface->make_secret (mcpa, account, key);
-}
-
-/**
* mcp_account_manager_get_unique_name:
* @mcpa: an #McpAccountManager instance
* @manager: the name of the manager
* @protocol: the name of the protocol
- * @params: A gchar * / GValue * hash table of account parameters.
+ * @identification: the result of calling IdentifyAccount for this account
*
* Generate and return the canonical unique name of this [new] account.
* Should not be called for accounts which have already had a name
@@ -287,6 +86,11 @@ mcp_account_manager_parameter_make_secret (const McpAccountManager *mcpa,
* MC has not previously seen before (ie one created by a 3rd party
* in the back-end that the plugin in question provides an interface to).
*
+ * Changed in 5.17: instead of a map from string to GValue, the last
+ * argument is the result of calling IdentifyAccount on the parameters,
+ * which normalizes the account's name in a protocol-dependent way.
+ * Use mcp_account_manager_identify_account_async() to do that.
+ *
* Returns: the newly allocated account name, which should be freed
* once the caller is done with it.
*/
@@ -294,42 +98,55 @@ gchar *
mcp_account_manager_get_unique_name (McpAccountManager *mcpa,
const gchar *manager,
const gchar *protocol,
- const GHashTable *params)
+ const gchar *identification)
{
McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
g_return_val_if_fail (iface != NULL, NULL);
g_return_val_if_fail (iface->unique_name != NULL, NULL);
- return iface->unique_name (mcpa, manager, protocol, params);
+ return iface->unique_name (mcpa, manager, protocol, identification);
+}
+
+void
+mcp_account_manager_identify_account_async (McpAccountManager *mcpa,
+ const gchar *manager,
+ const gchar *protocol,
+ GVariant *parameters,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
+
+ g_return_if_fail (iface != NULL);
+ g_return_if_fail (iface->identify_account_async != NULL);
+ g_return_if_fail (iface->identify_account_finish != NULL);
+
+ g_return_if_fail (manager != NULL);
+ g_return_if_fail (protocol != NULL);
+ g_return_if_fail (parameters != NULL);
+ g_return_if_fail (g_variant_is_of_type (parameters, G_VARIANT_TYPE_VARDICT));
+
+ iface->identify_account_async (mcpa, manager, protocol, parameters,
+ cancellable, callback, user_data);
}
/**
- * mcp_account_manager_escape_value_from_keyfile:
- * @mcpa: a #McpAccountManager
- * @value: a value with a supported #GType
- *
- * Escape @value so it could be passed to g_key_file_set_value().
- * For instance, escaping the boolean value TRUE returns "true",
- * and escaping the string value containing one space returns "\s".
- *
- * It is a programming error to use an unsupported type.
- * The supported types are currently %G_TYPE_STRING, %G_TYPE_BOOLEAN,
- * %G_TYPE_INT, %G_TYPE_UINT, %G_TYPE_INT64, %G_TYPE_UINT64, %G_TYPE_UCHAR,
- * %G_TYPE_STRV, %DBUS_TYPE_G_OBJECT_PATH and %TP_ARRAY_TYPE_OBJECT_PATH_LIST.
- *
- * Returns: the escaped form of @value
+ * Returns: (transfer full): a newly allocated string, free with g_free()
*/
gchar *
-mcp_account_manager_escape_value_for_keyfile (const McpAccountManager *mcpa,
- const GValue *value)
+mcp_account_manager_identify_account_finish (McpAccountManager *mcpa,
+ GAsyncResult *res,
+ GError **error)
{
McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
g_return_val_if_fail (iface != NULL, NULL);
- g_return_val_if_fail (iface->escape_value_for_keyfile != NULL, NULL);
+ g_return_val_if_fail (iface->identify_account_async != NULL, NULL);
+ g_return_val_if_fail (iface->identify_account_finish != NULL, NULL);
- return iface->escape_value_for_keyfile (mcpa, value);
+ return iface->identify_account_finish (mcpa, res, error);
}
/**
@@ -363,57 +180,30 @@ mcp_account_manager_escape_variant_for_keyfile (const McpAccountManager *mcpa,
}
/**
- * mcp_account_manager_unescape_value_from_keyfile:
+ * mcp_account_manager_unescape_variant_from_keyfile:
* @mcpa: a #McpAccountManager
- * @escaped: an escaped string as returned by g_key_file_get_value()
- * @value: a value to populate, with a supported #GType
- * @error: used to raise an error if %FALSE is returned
+ * @escaped: a string that could have come from g_key_file_get_value()
+ * @type: the type of the variant to which to unescape
*
- * Attempt to interpret @escaped as a value of @value's type.
- * If successful, put it in @value and return %TRUE.
+ * Unescape @escaped as if it had appeared in a #GKeyFile, with syntax
+ * appropriate for @type.
*
- * It is a programming error to try to escape an unsupported type.
- * The supported types are currently %G_TYPE_STRING, %G_TYPE_BOOLEAN,
- * %G_TYPE_INT, %G_TYPE_UINT, %G_TYPE_INT64, %G_TYPE_UINT64, %G_TYPE_UCHAR,
- * %G_TYPE_STRV, %DBUS_TYPE_G_OBJECT_PATH and %TP_ARRAY_TYPE_OBJECT_PATH_LIST.
+ * It is a programming error to use an unsupported type.
*
- * Returns: %TRUE if @value was filled in
+ * Returns: (transfer full): the unescaped form of @escaped
+ * (*not* a floating reference)
*/
-gboolean
-mcp_account_manager_unescape_value_from_keyfile (const McpAccountManager *mcpa,
+GVariant *
+mcp_account_manager_unescape_variant_from_keyfile (
+ const McpAccountManager *mcpa,
const gchar *escaped,
- GValue *value,
+ const GVariantType *type,
GError **error)
{
McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
- g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->unescape_value_from_keyfile != NULL, FALSE);
-
- return iface->unescape_value_from_keyfile (mcpa, escaped, value, error);
-}
-
-/**
- * mcp_account_manager_init_value_for_attribute:
- * @mcpa: a #McpAccountManager
- * @value: a zero-filled value to initialize
- * @attribute: a supported Mission Control attribute
- *
- * If @attribute is a known Mission Control attribute, initialize @value
- * with an appropriate type for @attribute and return %TRUE. Otherwise,
- * return %FALSE.
- *
- * Returns: %TRUE if @value was initialized
- */
-gboolean
-mcp_account_manager_init_value_for_attribute (const McpAccountManager *mcpa,
- GValue *value,
- const gchar *attribute)
-{
- McpAccountManagerIface *iface = MCP_ACCOUNT_MANAGER_GET_IFACE (mcpa);
-
- g_return_val_if_fail (iface != NULL, FALSE);
- g_return_val_if_fail (iface->init_value_for_attribute != NULL, FALSE);
+ g_return_val_if_fail (iface != NULL, NULL);
+ g_return_val_if_fail (iface->unescape_variant_from_keyfile != NULL, NULL);
- return iface->init_value_for_attribute (mcpa, value, attribute);
+ return iface->unescape_variant_from_keyfile (mcpa, escaped, type, error);
}
diff --git a/mission-control-plugins/account.h b/mission-control-plugins/account.h
index 69a33d56..2a46c3ab 100644
--- a/mission-control-plugins/account.h
+++ b/mission-control-plugins/account.h
@@ -45,61 +45,31 @@ typedef struct _McpAccountManagerIface McpAccountManagerIface;
GType mcp_account_manager_get_type (void) G_GNUC_CONST;
-void mcp_account_manager_set_value (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key,
- const gchar *value);
-
-void mcp_account_manager_set_attribute (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *attribute,
- GVariant *value,
- McpAttributeFlags flags);
-
-void mcp_account_manager_set_parameter (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *parameter,
- GVariant *value,
- McpParameterFlags flags);
-
-gchar * mcp_account_manager_get_value (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key);
-
-gboolean mcp_account_manager_parameter_is_secret (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key);
-
-void mcp_account_manager_parameter_make_secret (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *key);
-
gchar * mcp_account_manager_get_unique_name (McpAccountManager *mcpa,
const gchar *manager,
const gchar *protocol,
- const GHashTable *params);
-
-GStrv mcp_account_manager_list_keys (const McpAccountManager *mcpa,
- const gchar *account);
-
-gchar *mcp_account_manager_escape_value_for_keyfile (
- const McpAccountManager *mcpa,
- const GValue *value);
+ const gchar *identification);
gchar *mcp_account_manager_escape_variant_for_keyfile (
const McpAccountManager *mcpa,
GVariant *variant);
-gboolean mcp_account_manager_unescape_value_from_keyfile (
+GVariant *mcp_account_manager_unescape_variant_from_keyfile (
const McpAccountManager *mcpa,
const gchar *escaped,
- GValue *value,
+ const GVariantType *type,
GError **error);
-gboolean mcp_account_manager_init_value_for_attribute (
- const McpAccountManager *mcpa,
- GValue *value,
- const gchar *attribute);
+void mcp_account_manager_identify_account_async (McpAccountManager *mcpa,
+ const gchar *manager,
+ const gchar *protocol,
+ GVariant *parameters,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gchar *mcp_account_manager_identify_account_finish (McpAccountManager *mcpa,
+ GAsyncResult *res,
+ GError **error);
G_END_DECLS
diff --git a/mission-control-plugins/dbus-acl.c b/mission-control-plugins/dbus-acl.c
deleted file mode 100644
index 82ef0a27..00000000
--- a/mission-control-plugins/dbus-acl.c
+++ /dev/null
@@ -1,431 +0,0 @@
-/* Mission Control plugin API - DBus Caller ID.
- *
- * Copyright © 2010 Nokia Corporation
- * 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
- */
-
-/**
- * SECTION:dbus-acl
- * @title: McpDBusAcl
- * @short_description: DBus ACLs, implemented by plugins
- * @see_also:
- * @include: mission-control-plugins/mission-control-plugins.h
- *
- * Plugins may implement #McpDBusAcl in order to provide checks on whether
- * a DBus method call or property get/set operation should be allowed.
- *
- * To do so, the plugin must implement a #GObject subclass that implements
- * #McpDBusAcl, then return an instance of that subclass from
- * mcp_plugin_ref_nth_object().
- *
- * An implementation of this interface might look like this:
- *
- * <example><programlisting>
- * G_DEFINE_TYPE_WITH_CODE (APlugin, a_plugin,
- * G_TYPE_OBJECT,
- * G_IMPLEMENT_INTERFACE (...);
- * G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, dbus_acl_iface_init);
- * G_IMPLEMENT_INTERFACE (...))
- * /<!-- -->* ... *<!-- -->/
- * static void
- * dbus_acl_iface_init (McpDBusAclIface *iface,
- * gpointer unused G_GNUC_UNUSED)
- * {
- * iface-&gt;name = "APlugin";
- * iface-&gt;desc = "A plugin that checks some conditions";
- * iface-&gt;authorised = _authorised;
- * iface-&gt;authorised_async = _authorised_async;
- * }
- * </programlisting></example>
- *
- * A single object can implement more than one interface.
- */
-
-#include "config.h"
-
-#include <mission-control-plugins/mission-control-plugins.h>
-#include <mission-control-plugins/debug-internal.h>
-#include <mission-control-plugins/mcp-signals-marshal.h>
-#include <glib.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-#define MCP_DEBUG_TYPE MCP_DEBUG_DBUS_ACL
-#define ACL_DEBUG(_p, _format, ...) \
- DEBUG("%s: " _format, \
- (_p != NULL) ? mcp_dbus_acl_name (_p) : "-", ##__VA_ARGS__)
-
-/**
- * McpDBusAclIface:
- * @parent: the parent type
- * @name: the name of the plugin, or %NULL to use the GObject class name
- * @desc: the description of the plugin, or %NULL
- * @authorised: an implementation of part of mcp_dbus_acl_authorised()
- * @authorised_async: an implementation of part of
- * mcp_dbus_acl_authorised_async()
- */
-
-GType
-mcp_dbus_acl_get_type (void)
-{
- static gsize once = 0;
- static GType type = 0;
-
- if (g_once_init_enter (&once))
- {
- static const GTypeInfo info =
- {
- sizeof (McpDBusAclIface),
- NULL, /* base_init */
- NULL, /* base_finalize */
- NULL, /* class_init */
- NULL, /* class_finalize */
- NULL, /* class_data */
- 0, /* instance_size */
- 0, /* n_preallocs */
- NULL, /* instance_init */
- NULL /* value_table */
- };
-
- type = g_type_register_static (G_TYPE_INTERFACE,
- "McpDBusAcl", &info, 0);
- g_type_interface_add_prerequisite (type, G_TYPE_OBJECT);
-
- g_once_init_leave (&once, 1);
- }
-
- return type;
-}
-
-static GList *
-cached_acls (void)
-{
- static gboolean acl_plugins_cached = FALSE;
- static GList *dbus_acls = NULL;
-
- const GList *p;
-
- if (acl_plugins_cached)
- return dbus_acls;
-
- /* insert the default storage plugin into the sorted plugin list */
- for (p = mcp_list_objects(); p != NULL; p = g_list_next (p))
- {
- if (MCP_IS_DBUS_ACL (p->data))
- {
- dbus_acls = g_list_prepend (dbus_acls, g_object_ref (p->data));
- }
- }
-
- acl_plugins_cached = TRUE;
-
- return dbus_acls;
-}
-
-
-static DBusAclAuthData *
-auth_data_new (TpDBusDaemon *dbus, const gchar *name, GHashTable *params)
-{
- DBusAclAuthData *data = g_slice_new0 (DBusAclAuthData);
-
- data->dbus = g_object_ref (dbus);
- data->params = (params != NULL) ? g_hash_table_ref (params) : NULL;
- data->name = g_strdup (name);
-
- return data;
-}
-
-static void
-auth_data_free (DBusAclAuthData *data)
-{
- data->cleanup (data->data); /* free the callback data */
-
- tp_clear_pointer (&data->params, g_hash_table_unref);
- tp_clear_object (&data->dbus);
- g_free (data->name);
-
- g_slice_free (DBusAclAuthData, data);
-}
-/**
- * mcp_dbus_acl_iface_set_name:
- * @iface: an instance implementing McpDBusAclIface
- * @name: the plugin's name (used in debugging and some return values)
- *
- * Sets the name of the plugin. Intended for use by the plugin implementor.
- *
- * This is no longer necessary: just use "iface->name = name".
- **/
-void
-mcp_dbus_acl_iface_set_name (McpDBusAclIface *iface,
- const gchar *name)
-{
- iface->name = name;
-}
-
-/**
- * mcp_dbus_acl_iface_set_desc:
- * @iface: an instance implementing McpDBusAclIface
- * @desc: the plugin's description
- *
- * Sets the plugin's description. Intended for use by the plugin implementor.
- *
- * This is no longer necessary: just use "iface->desc = desc".
- **/
-void
-mcp_dbus_acl_iface_set_desc (McpDBusAclIface *iface,
- const gchar *desc)
-{
- iface->desc = desc;
-}
-
-/**
- * mcp_dbus_acl_iface_implement_authorised:
- * @iface: an instance implementing McpDBusAclIface
- * @method: the plugin's description
- *
- * Implements this plugin's part of the mcp_dbus_acl_authorised() method.
- *
- * This is no longer necessary: just use "iface->authorised = method".
- **/
-void
-mcp_dbus_acl_iface_implement_authorised (McpDBusAclIface *iface,
- DBusAclAuthoriser method)
-{
- iface->authorised = method;
-}
-
-/**
- * mcp_dbus_acl_iface_implement_authorised_async:
- * @iface: an instance implementing McpDBusAclIface
- * @method: the plugin's description
- *
- * Implements this plugin's part of the mcp_dbus_acl_authorised_async() method.
- *
- * This is no longer necessary: just use "iface->authorised_async = method".
- **/
-void
-mcp_dbus_acl_iface_implement_authorised_async (McpDBusAclIface *iface,
- DBusAclAsyncAuthoriser method)
-{
- iface->authorised_async = method;
-}
-
-/* FIXME: when we break ABI, this should move to src/ under a different name,
- * and mcp_dbus_acl_authorised() should be a trivial wrapper around
- * iface->authorised() */
-/**
- * mcp_dbus_acl_authorised:
- * @dbus: a #TpDBusDaemon instance
- * @context: a #DBusGMethodInvocation corresponding to the DBus call
- * @type: a #DBusAclType value (method call, get or set property)
- * @name: the name of the method or property in question
- * @params: A #GHashTable of #gchar * / #GValue parameters relating to the
- * call which are deemed to be "of interest" for ACL plugins, or %NULL
- *
- * This method calls each #DBusAcl plugin's authorised method, set by
- * mcp_dbus_acl_iface_implement_authorised()
- *
- * How a plugin deals with @params is entirely plugin dependent.
- *
- * If any plugin returns %FALSE, the call is considered to be forbidden.
- *
- * Returns: a #gboolean - %TRUE for permitted, %FALSE for forbidden.
- **/
-gboolean
-mcp_dbus_acl_authorised (const TpDBusDaemon *dbus,
- DBusGMethodInvocation *context,
- DBusAclType type,
- const gchar *name,
- const GHashTable *params)
-{
- GList *p;
- GList *acls = cached_acls ();
- gboolean permitted = TRUE;
-
- for (p = acls; permitted && p != NULL; p = g_list_next (p))
- {
- McpDBusAcl *plugin = MCP_DBUS_ACL (p->data);
- McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (p->data);
-
- ACL_DEBUG (plugin, "checking ACL for %s", name);
-
- if (iface->authorised != NULL)
- permitted = iface->authorised (plugin, dbus, context, type, name, params);
-
- if (!permitted)
- break;
- }
-
- if (!permitted)
- {
- GError *denied = NULL;
- const gchar *denier = mcp_dbus_acl_name (p->data);
-
- denied = g_error_new (DBUS_GERROR, DBUS_GERROR_ACCESS_DENIED,
- "permission denied by DBus ACL plugin '%s'", denier);
-
- dbus_g_method_return_error (context, denied);
-
- g_error_free (denied);
- }
-
- return permitted;
-}
-
-/**
- * mcp_dbus_acl_authorised_async_step:
- * @ad: a #DBusAclAuthData pointer
- * @permitted: whether the last plugin permitted the call being inspected
- *
- * This call is intended for use in the authorised_async mehod of a
- * #DBusAcl plugin - it allows the plugin to hand control back to the
- * overall ACL infrastructure, informing it of its decision as it does.
- **/
-void
-mcp_dbus_acl_authorised_async_step (DBusAclAuthData *ad,
- gboolean permitted)
-{
- if (permitted)
- {
- while (ad->next_acl != NULL && ad->next_acl->data != NULL)
- {
- McpDBusAcl *plugin = MCP_DBUS_ACL (ad->next_acl->data);
- McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (plugin);
-
- if (ad->acl != NULL)
- ACL_DEBUG (ad->acl, "passed ACL for %s", ad->name);
-
- /* take the next plugin off the next_acl list */
- ad->next_acl = g_list_next (ad->next_acl);
- ad->acl = plugin;
-
- if (iface->authorised_async != NULL)
- {
- /* kick off the next async authoriser in the chain */
- iface->authorised_async (plugin, ad);
-
- /* don't clean up, the next async acl will call us when it's
- * done: */
- return;
- }
- }
-
- if (ad->acl != NULL)
- ACL_DEBUG (ad->acl, "passed final ACL for %s", ad->name);
-
- ad->handler (ad->context, ad->data);
- }
- else
- {
- const gchar *who = (ad->acl != NULL) ? mcp_dbus_acl_name (ad->acl) : NULL;
- GError *denied = g_error_new (DBUS_GERROR, DBUS_GERROR_ACCESS_DENIED,
- "%s permission denied by DBus ACL plugin '%s'",
- ad->name,
- (who != NULL) ? who : "*unknown*");
-
- dbus_g_method_return_error (ad->context, denied);
-
- g_error_free (denied);
- }
-
- auth_data_free (ad); /* done with internal bookkeeping */
-}
-
-/* FIXME: when we break ABI, this should move to src/ under a different name,
- * and mcp_dbus_acl_authorised_async() should be a trivial wrapper around
- * iface->authorised_async(); it should also use GIO-style asynchronicity */
-/**
- * mcp_dbus_acl_authorised_async:
- * @dbus: a #TpDBusDaemon instance
- * @context: a #DBusGMethodInvocation corresponding to the DBus call
- * @type: a #DBusAclType value (method call, get or set property)
- * @name: the name of the method or property in question
- * @params: A #GHashTable of #gchar * / #GValue parameters relating to the
- * call which are deemed to be "of interest" for ACL plugins, or %NULL
- * @handler: callback to call if the ACL decides the call is permitted
- * @data: a #gpointer to pass to the @handler
- * @cleanup: a #GDestroyNotify to use to deallocate @data
- *
- * This method calls each #DBusAcl plugin's authorised_async method, set by
- * mcp_dbus_acl_iface_implement_authorised_async()
- *
- * How a plugin deals with @parameters is entirely plugin dependent.
- *
- * The plugin should implement an async (or at least non-blocking)
- * check, which should signal that it has finished by calling
- * mcp_dbus_acl_authorised_async_step()
- *
- * If all the plugins permit this call, then @handler will be invoked
- * with @context and @data as its arguments.
- *
- * @cleanup wll be called if the call is forbidden, or after @handler is
- * invoked. If the call is forbidden, a DBus error will be returned to the
- * caller automatically.
- *
- **/
-void
-mcp_dbus_acl_authorised_async (TpDBusDaemon *dbus,
- DBusGMethodInvocation *context,
- DBusAclType type,
- const gchar *name,
- GHashTable *params,
- DBusAclAuthorised handler,
- gpointer data,
- GDestroyNotify cleanup)
-{
- GList *acls = cached_acls ();
- DBusAclAuthData *ad = auth_data_new (dbus, name, params);
-
- ad->acl = NULL; /* first step, there's no current ACL yet */
- ad->type = type;
- ad->data = data;
- ad->cleanup = cleanup;
- ad->context = context;
- ad->handler = handler;
- ad->next_acl = acls;
-
- ACL_DEBUG (NULL, "DBus access ACL verification: %u rules for %s",
- g_list_length (acls),
- name);
- mcp_dbus_acl_authorised_async_step (ad, TRUE);
-}
-
-/* plugin meta-data */
-const gchar *
-mcp_dbus_acl_name (const McpDBusAcl *self)
-{
- McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (self);
-
- g_return_val_if_fail (iface != NULL, FALSE);
-
- if (iface->name == NULL)
- return G_OBJECT_TYPE_NAME (self);
-
- return iface->name;
-}
-
-const gchar *
-mcp_dbus_acl_description (const McpDBusAcl *self)
-{
- McpDBusAclIface *iface = MCP_DBUS_ACL_GET_IFACE (self);
-
- g_return_val_if_fail (iface != NULL, FALSE);
-
- if (iface->desc == NULL)
- return "(no description)";
-
- return iface->desc;
-}
diff --git a/mission-control-plugins/dbus-acl.h b/mission-control-plugins/dbus-acl.h
deleted file mode 100644
index deba7b72..00000000
--- a/mission-control-plugins/dbus-acl.h
+++ /dev/null
@@ -1,134 +0,0 @@
-/* Mission Control plugin API - DBus Caller ID.
- *
- * Copyright © 2010 Nokia Corporation
- * 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 MCP_DBUS_ACL_H
-#define MCP_DBUS_ACL_H
-
-#ifndef _MCP_IN_MISSION_CONTROL_PLUGINS_H
-#error Use <mission-control-plugins/mission-control-plugins.h> instead
-#endif
-
-#include <dbus/dbus-glib-lowlevel.h>
-#include <telepathy-glib/telepathy-glib.h>
-
-G_BEGIN_DECLS
-
-/* API for plugins to implement */
-typedef struct _McpDBusAcl McpDBusAcl;
-typedef struct _McpDBusAclIface McpDBusAclIface;
-
-#define MCP_TYPE_DBUS_ACL (mcp_dbus_acl_get_type ())
-
-#define MCP_DBUS_ACL(o) \
- (G_TYPE_CHECK_INSTANCE_CAST ((o), MCP_TYPE_DBUS_ACL, McpDBusAcl))
-
-#define MCP_IS_DBUS_ACL(o) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((o), MCP_TYPE_DBUS_ACL))
-
-#define MCP_DBUS_ACL_GET_IFACE(o) \
- (G_TYPE_INSTANCE_GET_INTERFACE ((o), MCP_TYPE_DBUS_ACL, \
- McpDBusAclIface))
-
-GType mcp_dbus_acl_get_type (void) G_GNUC_CONST;
-
-/* FIXME: when we break API, rename all types to start with Mcp */
-
-typedef void (*DBusAclAuthorised) (DBusGMethodInvocation *call, gpointer data);
-
-typedef enum {
- DBUS_ACL_TYPE_UNKNOWN = 0,
- DBUS_ACL_TYPE_METHOD,
- DBUS_ACL_TYPE_GET_PROPERTY,
- DBUS_ACL_TYPE_SET_PROPERTY,
-} DBusAclType;
-
-typedef struct {
- McpDBusAcl *acl;
- const GList *next_acl;
- DBusGMethodInvocation *context;
- DBusAclType type;
- gchar *name;
- GHashTable *params;
- TpDBusDaemon *dbus;
- DBusAclAuthorised handler;
- gpointer data;
- GDestroyNotify cleanup;
-} DBusAclAuthData;
-
-typedef gboolean (*DBusAclAuthoriser) (const McpDBusAcl *,
- const TpDBusDaemon *,
- const DBusGMethodInvocation *,
- DBusAclType type,
- const gchar *name,
- const GHashTable *);
-
-typedef void (*DBusAclAsyncAuthoriser) (const McpDBusAcl *,
- DBusAclAuthData *);
-
-/* real functions that handle multi-plugin acl logic */
-void mcp_dbus_acl_authorised_async_step (DBusAclAuthData *ad,
- gboolean permitted);
-
-void mcp_dbus_acl_authorised_async (TpDBusDaemon *dbus,
- DBusGMethodInvocation *context,
- DBusAclType type,
- const gchar *name,
- GHashTable *params,
- DBusAclAuthorised handler,
- gpointer data,
- GDestroyNotify cleanup);
-
-gboolean mcp_dbus_acl_authorised (const TpDBusDaemon *dbus,
- DBusGMethodInvocation *context,
- DBusAclType type,
- const gchar *name,
- const GHashTable *params);
-
-/* virtual methods */
-void mcp_dbus_acl_iface_set_name (McpDBusAclIface *iface,
- const gchar *name);
-
-void mcp_dbus_acl_iface_set_desc (McpDBusAclIface *iface,
- const gchar *desc);
-
-void mcp_dbus_acl_iface_implement_authorised (McpDBusAclIface *iface,
- DBusAclAuthoriser method);
-
-void mcp_dbus_acl_iface_implement_authorised_async (McpDBusAclIface *iface,
- DBusAclAsyncAuthoriser method);
-
-const gchar *mcp_dbus_acl_name (const McpDBusAcl *acl);
-
-const gchar *mcp_dbus_acl_description (const McpDBusAcl *acl);
-
-struct _McpDBusAclIface
-{
- GTypeInterface parent;
-
- const gchar *name;
- const gchar *desc;
-
- DBusAclAuthoriser authorised;
- DBusAclAsyncAuthoriser authorised_async;
-};
-
-G_END_DECLS
-
-#endif
diff --git a/mission-control-plugins/debug.c b/mission-control-plugins/debug.c
index af0f1df1..177e1d66 100644
--- a/mission-control-plugins/debug.c
+++ b/mission-control-plugins/debug.c
@@ -26,12 +26,11 @@ static McpDebugFlags debug_flags;
static GDebugKey const keys[] = {
{ "account", MCP_DEBUG_ACCOUNT },
{ "account-storage", MCP_DEBUG_ACCOUNT_STORAGE },
- { "dbus-acl", MCP_DEBUG_DBUS_ACL },
+ { "request-policy", MCP_DEBUG_REQUEST_POLICY },
{ "dispatch-operation", MCP_DEBUG_DISPATCH_OPERATION },
{ "dispatch-operation-policy", MCP_DEBUG_DISPATCH_OPERATION_POLICY },
{ "loader", MCP_DEBUG_LOADER },
{ "request", MCP_DEBUG_REQUEST },
- { "request-policy", MCP_DEBUG_REQUEST_POLICY },
{ NULL, 0 }
};
diff --git a/mission-control-plugins/debug.h b/mission-control-plugins/debug.h
index ced40bb8..8d3cec87 100644
--- a/mission-control-plugins/debug.h
+++ b/mission-control-plugins/debug.h
@@ -35,12 +35,11 @@ typedef enum {
MCP_DEBUG_NONE = 0,
MCP_DEBUG_ACCOUNT = 1 << 0,
MCP_DEBUG_ACCOUNT_STORAGE = 1 << 1,
- MCP_DEBUG_DBUS_ACL = 1 << 2,
+ MCP_DEBUG_REQUEST_POLICY = 1 << 2,
MCP_DEBUG_DISPATCH_OPERATION = 1 << 3,
MCP_DEBUG_DISPATCH_OPERATION_POLICY = 1 << 4,
MCP_DEBUG_LOADER = 1 << 5,
MCP_DEBUG_REQUEST = 1 << 6,
- MCP_DEBUG_REQUEST_POLICY = 1 << 7,
} McpDebugFlags;
gboolean mcp_is_debugging (McpDebugFlags type);
diff --git a/mission-control-plugins/dispatch-operation.c b/mission-control-plugins/dispatch-operation.c
index 2bd2ab2b..1fced1aa 100644
--- a/mission-control-plugins/dispatch-operation.c
+++ b/mission-control-plugins/dispatch-operation.c
@@ -285,45 +285,6 @@ mcp_dispatch_operation_end_delay (McpDispatchOperation *self,
}
/**
- * mcp_dispatch_operation_leave_channels:
- * @self: a dispatch operation
- * @wait_for_observers: if %FALSE, leave the channels immediately; if %TRUE
- * (usually recommended), wait for Observers to reply first
- * @reason: the reason code to give
- * @message: a human-readable message provided by the user, or either the
- * empty string or %NULL if no message has been provided
- *
- * Leave all channels in this bundle by using RemoveMembersWithReason if the
- * channel has the Group interface, or Close if not.
- *
- * This method was intended for StreamedMedia channels, which (ab)used the
- * Group interface for call control. StreamedMedia channels have been
- * superseded by Call channels, which have a proper "hang up" method which
- * should be used instead.
- *
- * Deprecated: 5.15.1: Use tp_call_channel_hangup_async() to
- * hang up Call channels, mcp_dispatch_operation_close_channels() to close
- * generic channels, or mcp_dispatch_operation_destroy_channels() to
- * terminate the channel destructively.
- */
-void
-mcp_dispatch_operation_leave_channels (McpDispatchOperation *self,
- gboolean wait_for_observers,
- TpChannelGroupChangeReason reason,
- const gchar *message)
-{
- McpDispatchOperationIface *iface = MCP_DISPATCH_OPERATION_GET_IFACE (self);
-
- g_return_if_fail (iface != NULL);
- g_return_if_fail (iface->leave_channels != NULL);
-
- if (message == NULL)
- message = "";
-
- iface->leave_channels (self, wait_for_observers, reason, message);
-}
-
-/**
* mcp_dispatch_operation_close_channels:
* @self: a dispatch operation
* @wait_for_observers: if %FALSE, close the channels immediately; if %TRUE
@@ -371,6 +332,9 @@ mcp_dispatch_operation_destroy_channels (McpDispatchOperation *self,
/**
* mcp_dispatch_operation_find_channel_by_type:
* @self: a dispatch operation
+ * @client_factory: used to construct @ret_ref_channel. In high-level
+ * language bindings using gobject-introspection, this must not be %NULL.
+ * In C, this may be %NULL, but only if @ret_ref_channel is also %NULL.
* @start_from: index at which to start searching, usually 0
* @handle_type: the handle type to match
* @channel_type: the channel type to match
@@ -397,6 +361,7 @@ mcp_dispatch_operation_destroy_channels (McpDispatchOperation *self,
*/
gboolean
mcp_dispatch_operation_find_channel_by_type (McpDispatchOperation *self,
+ TpSimpleClientFactory *client_factory,
guint start_from,
TpHandleType handle_type,
GQuark channel_type,
@@ -411,6 +376,8 @@ mcp_dispatch_operation_find_channel_by_type (McpDispatchOperation *self,
g_return_val_if_fail (MCP_IS_DISPATCH_OPERATION (self), FALSE);
g_return_val_if_fail (channel_type != 0, FALSE);
+ g_return_val_if_fail (client_factory != NULL || ret_ref_channel == NULL,
+ FALSE);
for (i = start_from; i < mcp_dispatch_operation_get_n_channels (self); i++)
{
@@ -441,14 +408,11 @@ mcp_dispatch_operation_find_channel_by_type (McpDispatchOperation *self,
if (ret_ref_channel != NULL)
{
- /* FIXME: in next, this method should take a TpClientFactory
- * argument, and pass it on here */
TpConnection *connection =
- mcp_dispatch_operation_ref_connection (self);
+ mcp_dispatch_operation_ref_connection (self, client_factory);
*ret_ref_channel = tp_simple_client_factory_ensure_channel (
- tp_proxy_get_factory (connection), connection,
- channel_path, properties, NULL);
+ client_factory, connection, channel_path, properties, NULL);
g_object_unref (connection);
}
@@ -465,35 +429,31 @@ mcp_dispatch_operation_find_channel_by_type (McpDispatchOperation *self,
/**
* mcp_dispatch_operation_ref_connection:
* @self: a dispatch operation
+ * @client_factory: the client factory to use to construct the #TpConnection
*
- * Return a #TpConnection object. It is not guaranteed to be ready immediately;
- * use tp_connection_call_when_ready().
+ * Return a #TpConnection object. It is not guaranteed to be prepared;
+ * use tp_proxy_prepare_async().
*
* Returns: a reference to a #TpConnection, which must be released with
* g_object_unref() by the caller
*/
TpConnection *
-mcp_dispatch_operation_ref_connection (McpDispatchOperation *self)
+mcp_dispatch_operation_ref_connection (McpDispatchOperation *self,
+ TpSimpleClientFactory *client_factory)
{
- TpDBusDaemon *dbus = tp_dbus_daemon_dup (NULL);
- TpConnection *connection = NULL;
const gchar *conn_path;
+ g_return_val_if_fail (client_factory != NULL, NULL);
+
conn_path = mcp_dispatch_operation_get_connection_path (self);
- if (conn_path != NULL && dbus != NULL)
+ if (conn_path != NULL)
{
- /* FIXME: in next, this method should take a TpClientFactory argument
- * instead of making a new one here */
- TpSimpleClientFactory *factory = tp_simple_client_factory_new (dbus);
-
- connection = tp_simple_client_factory_ensure_connection (factory,
+ return tp_simple_client_factory_ensure_connection (client_factory,
conn_path, NULL, NULL);
- g_object_unref (factory);
}
- g_object_unref (dbus);
- return connection;
+ return NULL;
}
/**
@@ -501,23 +461,26 @@ mcp_dispatch_operation_ref_connection (McpDispatchOperation *self)
* @self: a dispatch operation
* @n: index of the channel to inspect
*
- * Return a #TpChannel object. It is not guaranteed to be ready immediately;
- * use tp_channel_call_when_ready().
+ * Return a #TpChannel object. It is not guaranteed to be prepared;
+ * use tp_proxy_prepare_async().
*
* Returns: a reference to a #TpChannel, which must be released with
* g_object_unref() by the caller, or %NULL if @n is too large
*/
TpChannel *
mcp_dispatch_operation_ref_nth_channel (McpDispatchOperation *self,
+ TpSimpleClientFactory *client_factory,
guint n)
{
- /* FIXME: in next, this method should take a TpClientFactory argument,
- * and pass it on here */
- TpConnection *connection = mcp_dispatch_operation_ref_connection (self);
+ TpConnection *connection;
GHashTable *channel_properties = NULL;
const gchar *channel_path = NULL;
TpChannel *channel = NULL;
+ g_return_val_if_fail (client_factory != NULL, NULL);
+
+ connection = mcp_dispatch_operation_ref_connection (self, client_factory);
+
if (connection == NULL)
goto finally;
@@ -532,8 +495,7 @@ mcp_dispatch_operation_ref_nth_channel (McpDispatchOperation *self,
if (channel_properties == NULL)
goto finally;
- channel = tp_simple_client_factory_ensure_channel (
- tp_proxy_get_factory (connection),
+ channel = tp_simple_client_factory_ensure_channel (client_factory,
connection, channel_path, channel_properties, NULL);
finally:
diff --git a/mission-control-plugins/dispatch-operation.h b/mission-control-plugins/dispatch-operation.h
index 5ad12d9b..889f5fd2 100644
--- a/mission-control-plugins/dispatch-operation.h
+++ b/mission-control-plugins/dispatch-operation.h
@@ -53,13 +53,15 @@ GType mcp_dispatch_operation_get_type (void) G_GNUC_CONST;
gboolean mcp_dispatch_operation_find_channel_by_type (
McpDispatchOperation *self,
+ TpSimpleClientFactory *client_factory,
guint start_from, TpHandleType handle_type, GQuark channel_type,
guint *ret_index, gchar **ret_dup_path,
GHashTable **ret_ref_immutable_properties, TpChannel **ret_ref_channel);
TpConnection *mcp_dispatch_operation_ref_connection (
- McpDispatchOperation *self);
+ McpDispatchOperation *self, TpSimpleClientFactory *client_factory);
TpChannel *mcp_dispatch_operation_ref_nth_channel (McpDispatchOperation *self,
+ TpSimpleClientFactory *client_factory,
guint n);
/* virtual methods */
@@ -85,13 +87,6 @@ McpDispatchOperationDelay *mcp_dispatch_operation_start_delay (
void mcp_dispatch_operation_end_delay (McpDispatchOperation *self,
McpDispatchOperationDelay *delay);
-#ifndef MC_DISABLE_DEPRECATED
-G_DEPRECATED_FOR (mcp_dispatch_operation_close_channels or tp_call_channel_hangup_async)
-void mcp_dispatch_operation_leave_channels (McpDispatchOperation *self,
- gboolean wait_for_observers, TpChannelGroupChangeReason reason,
- const gchar *message);
-#endif
-
void mcp_dispatch_operation_close_channels (McpDispatchOperation *self,
gboolean wait_for_observers);
void mcp_dispatch_operation_destroy_channels (McpDispatchOperation *self,
diff --git a/mission-control-plugins/implementation.h b/mission-control-plugins/implementation.h
index 20c5fdf4..59096f93 100644
--- a/mission-control-plugins/implementation.h
+++ b/mission-control-plugins/implementation.h
@@ -68,9 +68,6 @@ struct _McpDispatchOperationIface {
McpDispatchOperationDelay *delay);
/* Close */
- void (*leave_channels) (McpDispatchOperation *self,
- gboolean wait_for_observers, TpChannelGroupChangeReason reason,
- const gchar *message);
void (*close_channels) (McpDispatchOperation *self,
gboolean wait_for_observers);
void (*destroy_channels) (McpDispatchOperation *self,
@@ -80,57 +77,28 @@ struct _McpDispatchOperationIface {
struct _McpAccountManagerIface {
GTypeInterface parent;
- void (*set_value) (const McpAccountManager *ma,
- const gchar *acct,
- const gchar *key,
- const gchar *value);
-
- gchar * (*get_value) (const McpAccountManager *ma,
- const gchar *acct,
- const gchar *key);
-
- gboolean (*is_secret) (const McpAccountManager *ma,
- const gchar *acct,
- const gchar *key);
-
- void (* make_secret) (const McpAccountManager *ma,
- const gchar *acct,
- const gchar *key);
-
gchar * (* unique_name) (const McpAccountManager *ma,
const gchar *manager,
const gchar *protocol,
- const GHashTable *params);
-
- GStrv (* list_keys) (const McpAccountManager *ma,
- const gchar *acct);
-
- gchar * (* escape_value_for_keyfile) (const McpAccountManager *mcpa,
- const GValue *value);
-
- gboolean (* unescape_value_from_keyfile) (const McpAccountManager *mcpa,
- const gchar *escaped,
- GValue *value,
- GError **error);
-
- gboolean (* init_value_for_attribute) (const McpAccountManager *mcpa,
- GValue *value,
- const gchar *attribute);
+ const gchar *identification);
gchar * (* escape_variant_for_keyfile) (const McpAccountManager *mcpa,
GVariant *variant);
+ GVariant *(* unescape_variant_from_keyfile) (const McpAccountManager *mcpa,
+ const gchar *escaped,
+ const GVariantType *type,
+ GError **error);
- void (* set_attribute) (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *attribute,
- GVariant *value,
- McpAttributeFlags flags);
-
- void (* set_parameter) (const McpAccountManager *mcpa,
- const gchar *account,
- const gchar *parameter,
- GVariant *value,
- McpParameterFlags flags);
+ void (* identify_account_async) (McpAccountManager *mcpa,
+ const gchar *manager,
+ const gchar *protocol,
+ GVariant *parameters,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+ gchar * (* identify_account_finish) (McpAccountManager *mcpa,
+ GAsyncResult *res,
+ GError **error);
};
G_END_DECLS
diff --git a/mission-control-plugins/loader.c b/mission-control-plugins/loader.c
index 640d1d87..a23028b3 100644
--- a/mission-control-plugins/loader.c
+++ b/mission-control-plugins/loader.c
@@ -62,6 +62,21 @@ static gboolean debugging = FALSE;
#endif
/**
+ * MCP_API_VERSION_5_18:
+ *
+ * Defined to allow simple plugin implementations to support both Mission
+ * Control 5.16 and 5.18 plugin APIs:
+ *
+ * |[
+ * #ifdef MCP_API_VERSION_5_18
+ * ... // implement MC 5.18 API
+ * #else
+ * ... // implement MC 5.16 API
+ * #endif
+ * ]|
+ */
+
+/**
* mcp_set_debug:
* @debug: whether to log debug output
*
diff --git a/mission-control-plugins/mission-control-plugins.h b/mission-control-plugins/mission-control-plugins.h
index d875199c..186da91d 100644
--- a/mission-control-plugins/mission-control-plugins.h
+++ b/mission-control-plugins/mission-control-plugins.h
@@ -25,19 +25,11 @@
#include <glib-object.h>
#include <telepathy-glib/telepathy-glib.h>
-typedef enum {
- MCP_PARAMETER_FLAG_NONE = 0,
- MCP_PARAMETER_FLAG_SECRET = TP_CONN_MGR_PARAM_FLAG_SECRET
-} McpParameterFlags;
-
-typedef enum {
- MCP_ATTRIBUTE_FLAG_NONE = 0
-} McpAttributeFlags;
+#define MCP_API_VERSION_5_18 (518)
#define _MCP_IN_MISSION_CONTROL_PLUGINS_H
#include <mission-control-plugins/account.h>
#include <mission-control-plugins/account-storage.h>
-#include <mission-control-plugins/dbus-acl.h>
#include <mission-control-plugins/dispatch-operation.h>
#include <mission-control-plugins/dispatch-operation-policy.h>
#include <mission-control-plugins/loader.h>
diff --git a/plugins/Makefile.am b/plugins/Makefile.am
index 23ccc6c0..42a5a3e4 100644
--- a/plugins/Makefile.am
+++ b/plugins/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = \
+AM_CPPFLAGS = \
$(TELEPATHY_CFLAGS) \
$(DBUS_CFLAGS) \
$(GLIB_CFLAGS) \
@@ -8,15 +8,3 @@ INCLUDES = \
-DLIBVERSION="@MCP_ABI_VERSION@"
noinst_LTLIBRARIES =
-
-if ENABLE_AEGIS
-
-noinst_LTLIBRARIES += libmcp-aegis.la
-libmcp_aegis_la_SOURCES = mcp-dbus-aegis-acl.c
-libmcp_aegis_la_LIBADD = \
- $(top_builddir)/mission-control-plugins/libmission-control-plugins.la \
- $(TELEPATHY_LIBS) \
- $(DBUS_LIBS) \
- $(AEGIS_LIBS)
-
-endif
diff --git a/plugins/mcp-dbus-aegis-acl.c b/plugins/mcp-dbus-aegis-acl.c
deleted file mode 100644
index 1eda98e6..00000000
--- a/plugins/mcp-dbus-aegis-acl.c
+++ /dev/null
@@ -1,441 +0,0 @@
-/*
- * A pseudo-plugin that checks the caller's Aegis permission tokens
- *
- * Copyright © 2010-2011 Nokia Corporation
- * Copyright © 2010-2011 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
- */
-
-#include "config.h"
-
-#ifdef G_LOG_DOMAIN
-#undef G_LOG_DOMAIN
-#endif
-#define G_LOG_DOMAIN "mission-control-DBus-Access-ACL"
-
-#define DEBUG(_f, ...) MCP_DEBUG (MCP_DEBUG_DBUS_ACL, _f, ##__VA_ARGS__)
-
-#include <dbus/dbus-glib.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-#include <telepathy-glib/telepathy-glib-dbus.h>
-
-#include <mission-control-plugins/mission-control-plugins.h>
-
-#include <sys/types.h>
-#include <sys/creds.h>
-
-typedef struct _AegisAcl AegisAcl;
-typedef struct _AegisAclClass AegisAclClass;
-
-struct _AegisAcl {
- GObject parent;
-};
-
-struct _AegisAclClass {
- GObjectClass parent_class;
-};
-
-#define CREATE_CHANNEL TP_IFACE_CONNECTION_INTERFACE_REQUESTS ".CreateChannel"
-#define ENSURE_CHANNEL TP_IFACE_CONNECTION_INTERFACE_REQUESTS ".EnsureChannel"
-#define SEND_MESSAGE \
- TP_IFACE_CHANNEL_DISPATCHER ".Interface.Messages.DRAFT.SendMessage"
-
-#define AEGIS_CALL_TOKEN "Cellular"
-
-/* implemented by the Aegis-patched dbus-daemon */
-#define AEGIS_INTERFACE "com.meego.DBus.Creds"
-
-#define PLUGIN_NAME "dbus-aegis-acl"
-#define PLUGIN_DESCRIPTION \
- "This plugin uses libcreds to check the aegis security tokens " \
- "associated with the calling process ID and determine whether " \
- "the DBus call or property access should be allowed"
-
-static creds_value_t aegis_token = CREDS_BAD;
-static creds_type_t aegis_type = CREDS_BAD;
-
-static void aegis_acl_iface_init (McpDBusAclIface *,
- gpointer);
-static void aegis_cdo_policy_iface_init (McpDispatchOperationPolicyIface *,
- gpointer);
-
-static GType aegis_acl_get_type (void);
-
-G_DEFINE_TYPE_WITH_CODE (AegisAcl, aegis_acl,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, aegis_acl_iface_init);
- G_IMPLEMENT_INTERFACE (MCP_TYPE_DISPATCH_OPERATION_POLICY,
- aegis_cdo_policy_iface_init))
-
-static void
-aegis_acl_init (AegisAcl *self)
-{
-}
-
-static void
-aegis_acl_class_init (AegisAclClass *cls)
-{
- if (aegis_type != CREDS_BAD)
- return;
-
- aegis_type = creds_str2creds (AEGIS_CALL_TOKEN, &aegis_token);
-}
-
-static gchar *restricted_methods[] =
- {
- CREATE_CHANNEL,
- ENSURE_CHANNEL,
- SEND_MESSAGE,
- NULL
- };
-
-static gboolean
-method_is_filtered (const gchar *method)
-{
- guint i;
-
- for (i = 0; restricted_methods[i] != NULL; i++)
- {
- if (!tp_strdiff (method, restricted_methods[i]))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static gboolean
-is_filtered (DBusAclType type,
- const gchar *name,
- const GHashTable *params)
-{
- const GValue *account = NULL;
- const gchar *path = NULL;
-
- /* only bothered with method calls */
- if (type != DBUS_ACL_TYPE_METHOD)
- return FALSE;
-
- /* only create/ensure channel concern us (and send message, now): */
- if (!method_is_filtered (name))
- return FALSE;
-
- /* must have at least the account-path to check */
- if (params == NULL)
- return FALSE;
-
- account = g_hash_table_lookup ((GHashTable *) params, "account-path");
-
- if (account == NULL)
- return FALSE;
-
- path = g_value_get_string (account);
-
- DEBUG ("should we check account %s?", path);
- /* account must belong to the ring or MMS connection manager: */
- if (g_str_has_prefix (path, TP_ACCOUNT_OBJECT_PATH_BASE "ring/") ||
- g_str_has_prefix (path, TP_ACCOUNT_OBJECT_PATH_BASE "mmscm/"))
- return TRUE;
-
- return FALSE;
-}
-
-/* For simplicity we don't implement non-trivial conversion between
- * dbus-glib's arrays of guint, and libcreds' arrays of uint32_t.
- * If this assertion fails on your platform, you'll need to implement it. */
-G_STATIC_ASSERT (sizeof (guint) == sizeof (uint32_t));
-
-static gboolean
-caller_creds_are_enough (const gchar *name,
- const GArray *au)
-{
- creds_t caller_creds = creds_import ((const uint32_t *) au->data, au->len);
- gboolean ok = creds_have_p (caller_creds, aegis_type, aegis_token);
-
-#ifdef ENABLE_DEBUG
- if (ok)
- {
- DEBUG ("Caller %s is appropriately privileged", name);
- }
- else
- {
- char buf[1024];
- creds_type_t debug_type;
- creds_value_t debug_value;
- int i = 0;
-
- DEBUG ("Caller %s has these credentials:", name);
-
- while ((debug_type = creds_list (caller_creds, i++, &debug_value))
- != CREDS_BAD)
- {
- creds_creds2str (debug_type, debug_value, buf, sizeof (buf));
- DEBUG ("- %s", buf);
- }
-
- DEBUG ("but they are insufficient");
- }
-#endif
-
- creds_free (caller_creds);
- return ok;
-}
-
-static gboolean
-check_peer_creds_sync (DBusGConnection *dgc,
- const gchar *bus_name,
- gboolean activate)
-{
- DBusGProxy *proxy = dbus_g_proxy_new_for_name (dgc,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- AEGIS_INTERFACE);
- GArray *au = NULL;
- GError *error = NULL;
- gboolean ok = FALSE;
-
- if (dbus_g_proxy_call (proxy, "GetConnectionCredentials", &error,
- G_TYPE_STRING, bus_name,
- G_TYPE_INVALID,
- DBUS_TYPE_G_UINT_ARRAY, &au,
- G_TYPE_INVALID))
- {
- ok = caller_creds_are_enough (bus_name, au);
- g_array_unref (au);
- }
- else if (activate && error->code == DBUS_GERROR_NAME_HAS_NO_OWNER)
- {
- guint status;
- GError *start_error = NULL;
- DBusGProxy *dbus = dbus_g_proxy_new_for_name (dgc,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- DEBUG ("Trying to activate %s for aegis credentials check", bus_name);
- if (dbus_g_proxy_call (dbus, "StartServiceByName", &start_error,
- G_TYPE_STRING, bus_name,
- G_TYPE_UINT, 0,
- G_TYPE_INVALID,
- G_TYPE_UINT, &status,
- G_TYPE_INVALID))
- {
- ok = check_peer_creds_sync (dgc, bus_name, FALSE);
- }
- else
- {
- DEBUG ("GetConnectionCredentials failed: %s", start_error->message);
- g_clear_error (&start_error);
- }
-
- g_object_unref (dbus);
- g_clear_error (&error);
- }
- else
- {
- DEBUG ("GetConnectionCredentials failed: %s", error->message);
- g_clear_error (&error);
- ok = FALSE;
- }
-
- g_object_unref (proxy);
- return ok;
-}
-
-static gboolean
-caller_authorised (const McpDBusAcl *self,
- const TpDBusDaemon *dbus,
- const DBusGMethodInvocation *call,
- DBusAclType type,
- const gchar *name,
- const GHashTable *params)
-{
- DBusGConnection *dgc = tp_proxy_get_dbus_connection ((TpDBusDaemon *)dbus);
- gboolean ok = TRUE;
-
- if (is_filtered (type, name, params))
- {
- gchar *caller = dbus_g_method_get_sender ((DBusGMethodInvocation *) call);
-
- ok = check_peer_creds_sync (dgc, caller, FALSE);
-
- g_free (caller);
- }
-
- DEBUG ("sync Aegis ACL check [%s]", ok ? "Allowed" : "Forbidden");
-
- return ok;
-}
-
-static void
-async_authorised_cb (DBusGProxy *proxy,
- DBusGProxyCall *call,
- gpointer data)
-{
- GError *error = NULL;
- DBusAclAuthData *ad = data;
- GArray *au = NULL;
- const McpDBusAcl *self = ad->acl;
- gboolean permitted = FALSE;
-
- /* if this returns FALSE, there are no credentials, which means something
- * untrustworthy is going on, which in turn means we must deny: can't
- * authorise without first authenticating */
- permitted = dbus_g_proxy_end_call (proxy, call, &error,
- DBUS_TYPE_G_UINT_ARRAY, &au,
- G_TYPE_INVALID);
-
- if (permitted)
- {
- permitted = caller_creds_are_enough (ad->name, au);
- g_array_unref (au);
- }
- else
- {
- DEBUG ("GetConnectionCredentials failed: %s", error->message);
- g_clear_error (&error);
- }
-
- DEBUG ("finished async Aegis ACL check [%s]",
- permitted ? "Allowed" : "Forbidden");
-
- mcp_dbus_acl_authorised_async_step (ad, permitted);
-
- g_object_unref (proxy);
-}
-
-static void
-caller_async_authorised (const McpDBusAcl *self,
- DBusAclAuthData *data)
-{
- DEBUG ("starting async caller-permission ACL check");
-
- if (is_filtered (data->type, data->name, data->params))
- {
- DBusGConnection *dgc;
- DBusGProxy *proxy;
- gchar *caller = dbus_g_method_get_sender (data->context);
-
- dgc = tp_proxy_get_dbus_connection (data->dbus);
- proxy = dbus_g_proxy_new_for_name (dgc,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- AEGIS_INTERFACE);
-
- dbus_g_proxy_begin_call (proxy, "GetConnectionCredentials",
- async_authorised_cb,
- data,
- NULL,
- G_TYPE_STRING, caller,
- G_TYPE_INVALID);
-
- g_free (caller);
- }
- else
- {
- mcp_dbus_acl_authorised_async_step (data, TRUE);
- }
-}
-
-
-static void
-aegis_acl_iface_init (McpDBusAclIface *iface,
- gpointer unused G_GNUC_UNUSED)
-{
- mcp_dbus_acl_iface_set_name (iface, PLUGIN_NAME);
- mcp_dbus_acl_iface_set_desc (iface, PLUGIN_DESCRIPTION);
-
- mcp_dbus_acl_iface_implement_authorised (iface, caller_authorised);
- mcp_dbus_acl_iface_implement_authorised_async (iface, caller_async_authorised);
-}
-
-static gchar *restricted_cms[] = { "ring", "mmscm", NULL };
-
-static inline gboolean
-cm_is_restricted (const gchar *cm_name)
-{
- guint i;
-
- for (i = 0; restricted_cms[i] != NULL; i++)
- {
- if (!tp_strdiff (restricted_cms[i], cm_name))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-handler_is_suitable_async (McpDispatchOperationPolicy *self,
- TpClient *recipient,
- const gchar *unique_name,
- McpDispatchOperation *dispatch_op,
- GAsyncReadyCallback callback,
- gpointer user_data)
-{
- const gchar *manager = mcp_dispatch_operation_get_cm_name (dispatch_op);
- GSimpleAsyncResult *simple = g_simple_async_result_new ((GObject *) self,
- callback, user_data, handler_is_suitable_async);
- gboolean ok = TRUE;
-
- if (cm_is_restricted (manager))
- {
- TpDBusDaemon *dbus = tp_dbus_daemon_dup (NULL);
-
- /* if MC started successfully, we ought to have one */
- g_assert (dbus != NULL);
-
- if (!tp_str_empty (unique_name))
- {
- ok = check_peer_creds_sync (tp_proxy_get_dbus_connection (dbus),
- unique_name, TRUE);
- }
- else
- {
- g_assert (recipient != NULL);
-
- ok = check_peer_creds_sync (tp_proxy_get_dbus_connection (dbus),
- tp_proxy_get_bus_name (recipient), TRUE);
- }
-
- if (!ok)
- {
- g_simple_async_result_set_error (simple, TP_ERROR,
- TP_ERROR_PERMISSION_DENIED, "insufficient Aegis credentials");
- }
-
- g_object_unref (dbus);
- }
-
- DEBUG ("sync Aegis CDO policy check [%s]", ok ? "Allowed" : "Forbidden");
-
- g_simple_async_result_complete_in_idle (simple);
- g_object_unref (simple);
-}
-
-static void
-aegis_cdo_policy_iface_init (McpDispatchOperationPolicyIface *iface,
- gpointer unused G_GNUC_UNUSED)
-{
- iface->handler_is_suitable_async = handler_is_suitable_async;
- /* the default finish function accepts our GSimpleAsyncResult */
-}
-
-GObject *
-aegis_acl_new (void)
-{
- return g_object_new (aegis_acl_get_type (), NULL);
-}
diff --git a/server/Makefile.am b/server/Makefile.am
index 5be1cdc1..b18a442b 100644
--- a/server/Makefile.am
+++ b/server/Makefile.am
@@ -47,7 +47,7 @@ Android.mk: Makefile.am
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(mission_control_5_SOURCES) \
-:CFLAGS $(DEFAULT_INCLUDES) $(DEFS) $(CFLAGS) $(AM_CFLAGS) \
- -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) $(INCLUDES) \
+ -:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \
-DBUILD_AS_ANDROID_SERVICE \
-:LDFLAGS $(mission_control_5_LDADD) \
-:LIBFILTER_STATIC mcd-convenience mission-control-plugins \
diff --git a/src/Makefile.am b/src/Makefile.am
index ae1de3e4..17c22f22 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -1,10 +1,8 @@
-INCLUDES = \
+AM_CPPFLAGS = \
$(TELEPATHY_CFLAGS) \
$(DBUS_CFLAGS) \
$(GLIB_CFLAGS) \
$(NETWORK_MANAGER_CFLAGS) \
- $(CONNMAN_CFLAGS) \
- $(UPOWER_GLIB_CFLAGS) \
-DG_LOG_DOMAIN=\"mcd\" \
-DMCD_PLUGIN_LOADER_DIR=\"@libdir@/mission-control-plugins.@MCP_ABI_VERSION@\" \
-DMC_DISABLE_DEPRECATED -I$(top_srcdir)
@@ -13,7 +11,6 @@ AM_CFLAGS = $(ERROR_CFLAGS)
mc_headers = \
mcd-account.h \
- mcd-account-conditions.h \
mcd-account-manager.h \
mcd-account-manager-default.h \
mcd-debug.h \
@@ -28,58 +25,17 @@ mc_headers = \
mcd-service.h \
mcd-storage.h
-if ENABLE_LIBACCOUNTS_SSO
-mc_headers += \
- mcd-account-manager-sso.h \
- $(NULL)
-
-if ENABLE_LIBACCOUNTS_GLIB_HIDDEN
-mc_headers += \
- mcd-storage-ag-hidden.h \
- $(NULL)
-endif
-
-endif
-
-mc_gen_headers = \
- _gen/cli-Connection_Manager_Interface_Account_Storage.h \
- _gen/enums.h \
- _gen/gtypes.h \
- _gen/interfaces.h \
- _gen/svc-Account_Interface_Conditions.h \
- _gen/svc-Account_Interface_External_Password_Storage.h \
- _gen/svc-Account_Interface_Hidden.h \
- _gen/svc-Account_Manager_Interface_Hidden.h \
- _gen/svc-dispatcher.h
-
nodist_libmcd_convenience_la_SOURCES = \
- _gen/cli-Connection_Manager_Interface_Account_Storage-body.h \
- _gen/gtypes-body.h \
- _gen/interfaces-body.h \
- _gen/register-dbus-glib-marshallers-body.h \
- _gen/svc-Account_Interface_Conditions.c \
- _gen/svc-Account_Interface_External_Password_Storage.c \
- _gen/svc-Account_Interface_Hidden.c \
- _gen/svc-Account_Manager_Interface_Hidden.c \
- _gen/svc-dispatcher.c \
mcd-enum-types.c \
mcd-enum-types.h \
- $(mc_gen_headers)
+ $(NULL)
BUILT_SOURCES = \
- _gen/mcd.xml \
stamp-mcd-enum-types.h \
$(nodist_libmcd_convenience_la_SOURCES)
CLEANFILES = \
$(BUILT_SOURCES) \
- _gen/cli-Connection_Manager_Interface_Account_Storage-gtk-doc.h \
- _gen/svc-dispatcher-gtk-doc.h \
- _gen/svc-Account_Interface_Hidden-gtk-doc.h \
- _gen/svc-Account_Interface_External_Password_Storage-gtk-doc.h \
- _gen/svc-Account_Interface_Conditions-gtk-doc.h \
- _gen/svc-Account_Manager_Interface_Hidden-gtk-doc.h \
- _gen/gtypes-gtk-doc.h \
$(NULL)
libmcd_convenience_la_LIBADD = \
@@ -88,27 +44,14 @@ libmcd_convenience_la_LIBADD = \
$(DBUS_LIBS) \
$(GLIB_LIBS) \
$(NETWORK_MANAGER_LIBS) \
- $(CONNMAN_LIBS) \
- $(UPOWER_GLIB_LIBS) \
$(NULL)
-if ENABLE_LIBACCOUNTS_SSO
-libmcd_convenience_la_LIBADD += $(LIBACCOUNTS_SSO_LIBS)
-INCLUDES += $(LIBACCOUNTS_SSO_CFLAGS)
-endif
-
-if ENABLE_AEGIS
-libmcd_convenience_la_LIBADD += $(top_builddir)/plugins/libmcp-aegis.la
-endif
-
noinst_LTLIBRARIES = libmcd-convenience.la
libmcd_convenience_la_SOURCES = \
mcd-account.c \
mcd-account-addressing.h \
- mcd-account-conditions.c \
mcd-account-config.h \
- mcd-account-connection.c \
mcd-account-requests.c \
mcd-account-addressing.c \
mcd-account-manager.c \
@@ -123,7 +66,6 @@ libmcd_convenience_la_SOURCES = \
client-registry.h \
connectivity-monitor.c \
connectivity-monitor.h \
- gtypes.c \
mcd-dbusprop.c \
mcd-dbusprop.h \
mcd-debug.c \
@@ -163,19 +105,6 @@ libmcd_convenience_la_SOURCES = \
sp_timestamp.h \
$(mc_headers)
-if ENABLE_LIBACCOUNTS_SSO
-libmcd_convenience_la_SOURCES += \
- mcd-account-manager-sso.c \
- $(NULL)
-
-if ENABLE_LIBACCOUNTS_GLIB_HIDDEN
-libmcd_convenience_la_SOURCES += \
- mcd-storage-ag-hidden.c \
- $(NULL)
-endif
-
-endif
-
mcd-enum-types.h: stamp-mcd-enum-types.h
$(AM_V_GEN)true
stamp-mcd-enum-types.h: Makefile $(mc_headers) mcd-enum-types.c
@@ -202,8 +131,6 @@ mcd-enum-types.c: Makefile $(mc_headers)
&& rm -f xgen-getc
EXTRA_DIST = \
- mcd.xml \
- dispatcher.xml \
stamp-mcd-enum-types.h
Android.mk: Makefile.am $(nodist_libmcd_convenience_la_SOURCES)
@@ -212,111 +139,11 @@ Android.mk: Makefile.am $(nodist_libmcd_convenience_la_SOURCES)
-:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(libmcd_convenience_la_SOURCES) $(nodist_libmcd_convenience_la_SOURCES) \
- -:CFLAGS $(DEFAULT_INCLUDES) $(INCLUDES) $(DEFS) $(CFLAGS) $(AM_CFLAGS) \
+ -:CFLAGS $(DEFAULT_INCLUDES) $(DEFS) $(CFLAGS) $(AM_CFLAGS) \
-:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \
-:LDFLAGS $(libmcd_convenience_la_LIBADD) \
> $@
-# ---- telepathy-glib-style code generation ----
-
-tools_dir = $(top_srcdir)/tools
-
-_gen/mcd.xml: mcd.xml $(wildcard $(top_srcdir)/xml/*.xml)
- $(AM_V_at)$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
- $< > $@
-
-_gen/%.xml: $(top_srcdir)/xml/%.xml $(wildcard $(top_srcdir)/xml/*.xml)
- $(AM_V_at)$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
- $< > $@
-
-# Generated files which can be done for all "classes" at once
-
-_gen/register-dbus-glib-marshallers-body.h: _gen/mcd.xml \
- $(tools_dir)/glib-client-marshaller-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-marshaller-gen.py $< \
- _mcd_ext > $@
-
-_gen/enums.h: _gen/mcd.xml $(tools_dir)/c-constants-generator.xsl
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \
- --stringparam mixed-case-prefix mc \
- $(tools_dir)/c-constants-generator.xsl \
- $< > $@
-
-_gen/interfaces.h: _gen/mcd.xml \
- $(tools_dir)/glib-interfaces-generator.xsl \
- $(tools_dir)/c-interfaces-generator.xsl
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \
- --stringparam mixed-case-prefix mc \
- $(tools_dir)/glib-interfaces-generator.xsl \
- $< > $@
-
-_gen/interfaces-body.h: _gen/mcd.xml \
- $(tools_dir)/glib-interfaces-body-generator.xsl \
- $(tools_dir)/c-interfaces-generator.xsl
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) \
- --stringparam mixed-case-prefix mc \
- $(tools_dir)/glib-interfaces-body-generator.xsl \
- $< > $@
-
-_gen/gtypes.h: _gen/gtypes-gtk-doc.h
- @: # generated as a side-effect
-
-_gen/gtypes-body.h: _gen/gtypes-gtk-doc.h
- @: # generated as a side-effect
-
-_gen/gtypes-gtk-doc.h: _gen/mcd.xml \
- $(top_srcdir)/tools/glib-gtypes-generator.py
- $(AM_V_GEN)$(PYTHON) $(top_srcdir)/tools/glib-gtypes-generator.py \
- $< _gen/gtypes mc
-
-
-
-# Generated files which must be generated per "class".
-# (Currently the only "class" is nmc4, but the new API will need "classes"
-# like account, account-manager, ...)
-
-_gen/%.xml: $(top_srcdir)/xml/%.xml $(wildcard $(top_srcdir)/xml/*.xml) Makefile.am
- $(AM_V_at)$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
- $< > $@
-
-_gen/%.xml: %.xml $(wildcard $(top_srcdir)/xml/*.xml) Makefile.am
- $(AM_V_at)$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTPROCFLAGS) --xinclude $(tools_dir)/identity.xsl \
- $< > $@
-
-_gen/cli-%-body.h: _gen/cli-%-gtk-doc.h
- @: # generated as a side-effect
-
-_gen/cli-%.h: _gen/cli-%-gtk-doc.h
- @: # generated as a side-effect
-
-_gen/cli-%-gtk-doc.h: _gen/%.xml \
- $(tools_dir)/glib-client-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-client-gen.py \
- --group=`echo $* | tr x- x_` \
- --iface-quark-prefix=MC_IFACE_QUARK \
- --tp-proxy-api=0.7.6 \
- $< Mc_Cli _gen/cli-$*
-
-_gen/svc-%.c: _gen/svc-%-gtk-doc.h
- @: # generated as a side-effect
-
-_gen/svc-%.h: _gen/svc-%-gtk-doc.h
- @: # generated as a side-effect
-
-_gen/svc-%-gtk-doc.h: _gen/%.xml \
- $(tools_dir)/glib-ginterface-gen.py Makefile.am
- $(AM_V_GEN)$(PYTHON) $(tools_dir)/glib-ginterface-gen.py \
- --filename=_gen/svc-$* \
- --signal-marshal-prefix=_mcd_ext \
- --include='<telepathy-glib/telepathy-glib.h>' \
- --not-implemented-func='tp_dbus_g_method_return_not_implemented' \
- --allow-unstable \
- $< Mc_Svc_
-
include ../tools/header-checks.am
check-local: header-decl-macro-check
diff --git a/src/connectivity-monitor.c b/src/connectivity-monitor.c
index 6d699723..e4af960a 100644
--- a/src/connectivity-monitor.c
+++ b/src/connectivity-monitor.c
@@ -35,10 +35,6 @@
#include <NetworkManager.h>
#endif
-#ifdef HAVE_UPOWER
-#include <upower.h>
-#endif
-
#include <telepathy-glib/telepathy-glib.h>
#include "mcd-debug.h"
@@ -96,10 +92,6 @@ struct _McdConnectivityMonitorPrivate {
gulong state_change_signal_id;
#endif
-#ifdef HAVE_UPOWER
- UpClient *upower_client;
-#endif
-
#ifdef ENABLE_CONN_SETTING
/* Application settings we steal from under Empathy's nose. */
GSettings *settings;
@@ -258,43 +250,6 @@ connectivity_monitor_network_changed (GNetworkMonitor *monitor,
}
}
-#ifdef HAVE_UPOWER
-static void
-connectivity_monitor_set_awake (
- McdConnectivityMonitor *self,
- gboolean awake)
-{
- if (awake)
- connectivity_monitor_add_states (self, CONNECTIVITY_AWAKE, NULL);
- else
- connectivity_monitor_remove_states (self, CONNECTIVITY_AWAKE, NULL);
-}
-
-static void
-notify_sleep_cb (
- UpClient *upower_client,
- UpSleepKind sleep_kind,
- gpointer user_data)
-{
- McdConnectivityMonitor *self = MCD_CONNECTIVITY_MONITOR (user_data);
-
- DEBUG ("about to sleep! sleep_kind=%s", up_sleep_kind_to_string (sleep_kind));
- connectivity_monitor_set_awake (self, FALSE);
-}
-
-static void
-notify_resume_cb (
- UpClient *upower_client,
- UpSleepKind sleep_kind,
- gpointer user_data)
-{
- McdConnectivityMonitor *self = MCD_CONNECTIVITY_MONITOR (user_data);
-
- DEBUG ("woke up! sleep_kind=%s", up_sleep_kind_to_string (sleep_kind));
- connectivity_monitor_set_awake (self, TRUE);
-}
-#endif
-
#ifdef HAVE_GIO_UNIX
static void
login1_inhibit_cb (GObject *source G_GNUC_UNUSED,
@@ -546,16 +501,6 @@ mcd_connectivity_monitor_init (McdConnectivityMonitor *connectivity_monitor)
}
#endif
-#ifdef HAVE_UPOWER
- priv->upower_client = up_client_new ();
- tp_g_signal_connect_object (priv->upower_client,
- "notify-sleep", G_CALLBACK (notify_sleep_cb), connectivity_monitor,
- G_CONNECT_AFTER);
- tp_g_signal_connect_object (priv->upower_client,
- "notify-resume", G_CALLBACK (notify_resume_cb), connectivity_monitor,
- G_CONNECT_AFTER);
-#endif
-
g_bus_get (G_BUS_TYPE_SYSTEM, NULL, got_system_bus_cb,
g_object_ref (connectivity_monitor));
}
@@ -574,12 +519,10 @@ connectivity_monitor_constructed (GObject *object)
static void
connectivity_monitor_finalize (GObject *object)
{
-#if defined(HAVE_NM) || defined(HAVE_UPOWER)
+#if defined(HAVE_NM)
McdConnectivityMonitor *connectivity_monitor = MCD_CONNECTIVITY_MONITOR (object);
McdConnectivityMonitorPrivate *priv = connectivity_monitor->priv;
-#endif
-#ifdef HAVE_NM
if (priv->nm_client != NULL)
{
g_signal_handler_disconnect (priv->nm_client,
@@ -590,10 +533,6 @@ connectivity_monitor_finalize (GObject *object)
}
#endif
-#ifdef HAVE_UPOWER
- tp_clear_object (&priv->upower_client);
-#endif
-
G_OBJECT_CLASS (mcd_connectivity_monitor_parent_class)->finalize (object);
}
diff --git a/src/dispatcher.xml b/src/dispatcher.xml
deleted file mode 100644
index 19535a6d..00000000
--- a/src/dispatcher.xml
+++ /dev/null
@@ -1,7 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<xi:include href="../xml/Channel_Dispatcher_Interface_Messages_DRAFT.xml"/>
-
-</tp:spec>
diff --git a/src/gtypes.c b/src/gtypes.c
deleted file mode 100644
index 90c4fb18..00000000
--- a/src/gtypes.c
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "config.h"
-
-#include <dbus/dbus-glib.h>
-
-#include "_gen/gtypes.h"
-#include "_gen/gtypes-body.h"
-
-/* Because I'm too lazy to have a separate file for these. */
-#include "_gen/interfaces.h"
-#include "_gen/interfaces-body.h"
diff --git a/src/mcd-account-addressing.c b/src/mcd-account-addressing.c
index ec3d8f5e..e1a0fb77 100644
--- a/src/mcd-account-addressing.c
+++ b/src/mcd-account-addressing.c
@@ -30,7 +30,6 @@
#include "mcd-account.h"
#include "mcd-account-priv.h"
-#include "_gen/interfaces.h"
static void
addressing_set_uri_scheme_association (TpSvcAccountInterfaceAddressing *iface,
@@ -48,7 +47,7 @@ addressing_set_uri_scheme_association (TpSvcAccountInterfaceAddressing *iface,
g_value_init (&value, G_TYPE_STRV);
if (mcd_storage_get_attribute (storage, account, MC_ACCOUNTS_KEY_URI_SCHEMES,
- &value, NULL))
+ G_VARIANT_TYPE_STRING_ARRAY, &value, NULL))
{
schemes = g_value_get_boxed (&value);
old_association = tp_strv_contains ((const gchar * const *) schemes,
@@ -109,7 +108,7 @@ addressing_get_uri_schemes (TpSvcDBusProperties *iface,
g_value_init (value, G_TYPE_STRV);
if (!mcd_storage_get_attribute (storage, account, MC_ACCOUNTS_KEY_URI_SCHEMES,
- value, NULL))
+ G_VARIANT_TYPE_STRING_ARRAY, value, NULL))
{
g_value_set_boxed (value, NULL);
}
diff --git a/src/mcd-account-conditions.c b/src/mcd-account-conditions.c
deleted file mode 100644
index e40dccf9..00000000
--- a/src/mcd-account-conditions.c
+++ /dev/null
@@ -1,160 +0,0 @@
-/* vi: set et sw=4 ts=8 cino=t0,(0: */
-/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
-/*
- * This file is part of mission-control
- *
- * Copyright (C) 2008-2009 Nokia Corporation.
- * Copyright (C) 2009 Collabora Ltd.
- *
- * Contact: Alberto Mardegan <alberto.mardegan@nokia.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public License
- * version 2.1 as published by the Free Software Foundation.
- *
- * 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 "config.h"
-
-#include <stdio.h>
-#include <string.h>
-#include <glib/gstdio.h>
-
-#include <telepathy-glib/telepathy-glib.h>
-#include <telepathy-glib/telepathy-glib-dbus.h>
-
-#include "mcd-account.h"
-#include "mcd-account-priv.h"
-#include "mcd-account-conditions.h"
-#include "mcd-account-manager.h"
-
-
-static void
-store_condition (gpointer key, gpointer value, gpointer userdata)
-{
- McdAccount *account = MCD_ACCOUNT (userdata);
- McdStorage *storage = _mcd_account_get_storage (account);
- const gchar *account_name = mcd_account_get_unique_name (account);
- const gchar *name = key, *condition = value;
- gchar condition_key[256];
-
- g_snprintf (condition_key, sizeof (condition_key), "condition-%s", name);
- mcd_storage_set_string (storage, account_name, condition_key, condition);
-}
-
-static gboolean
-set_condition (TpSvcDBusProperties *self,
- const gchar *name,
- const GValue *value,
- McdDBusPropSetFlags flags,
- GError **error)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- McdStorage *storage = _mcd_account_get_storage (account);
- const gchar *account_name = mcd_account_get_unique_name (account);
- gchar **keys, **key;
- GHashTable *conditions;
-
- /* FIXME: some sort of validation beyond just the type? */
-
- if (!G_VALUE_HOLDS (value, TP_HASH_TYPE_STRING_STRING_MAP))
- {
- g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Expected a{s:s} for Condition, but got %s",
- G_VALUE_TYPE_NAME (value));
- return FALSE;
- }
-
- if (_mcd_account_get_always_on (account))
- {
- g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
- "Account %s conditions cannot be changed",
- mcd_account_get_unique_name (account));
- return FALSE;
- }
-
- conditions = g_value_get_boxed (value);
-
- /* first, delete existing conditions */
- keys = mcd_storage_dup_attributes (storage, account_name, NULL);
-
- for (key = keys; *key != NULL; key++)
- {
- if (strncmp (*key, "condition-", 10) != 0)
- continue;
-
- mcd_storage_set_attribute (storage, account_name, *key, NULL);
- }
-
- g_strfreev (keys);
-
- if (!(flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE))
- {
- g_hash_table_foreach (conditions, store_condition, account);
-
- mcd_storage_commit (storage, account_name);
- }
-
- return TRUE;
-}
-
-static void
-get_condition (TpSvcDBusProperties *self, const gchar *name, GValue *value)
-{
- GHashTable *conditions;
-
- conditions = mcd_account_get_conditions (MCD_ACCOUNT (self));
-
- g_value_init (value, DBUS_TYPE_G_STRING_STRING_HASHTABLE);
- g_value_take_boxed (value, conditions);
-}
-
-
-const McdDBusProp account_conditions_properties[] = {
- { "Condition", set_condition, get_condition },
- { 0 },
-};
-
-void
-account_conditions_iface_init (McSvcAccountInterfaceConditionsClass *iface,
- gpointer iface_data)
-{
-}
-
-GHashTable *mcd_account_get_conditions (McdAccount *account)
-{
- gchar **keys, **key, *condition;
- GHashTable *conditions;
- McdStorage *storage = _mcd_account_get_storage (account);
- const gchar *account_name = mcd_account_get_unique_name (account);
-
- conditions = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
-
- keys = mcd_storage_dup_attributes (storage, account_name, NULL);
-
- for (key = keys; *key != NULL; key++)
- {
- if (strncmp (*key, "condition-", 10) != 0)
- continue;
-
- condition = mcd_storage_dup_string (storage, account_name, *key);
- DEBUG ("Condition: %s = %s", *key, condition);
- g_hash_table_insert (conditions, g_strdup (*key + 10), condition);
- }
-
- g_strfreev (keys);
-
- return conditions;
-}
-
diff --git a/src/mcd-account-conditions.h b/src/mcd-account-conditions.h
deleted file mode 100644
index cd8f75b6..00000000
--- a/src/mcd-account-conditions.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/* vi: set et sw=4 ts=8 cino=t0,(0: */
-/* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4; tab-width: 8 -*- */
-/*
- * mcd-account.h - the Telepathy Account D-Bus interface (service side)
- *
- * Copyright (C) 2008 Collabora Ltd. <http://www.collabora.co.uk/>
- * Copyright (C) 2008 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 __MCD_ACCOUNT_CONDITIONS_H__
-#define __MCD_ACCOUNT_CONDITIONS_H__
-
-#include "mcd-account.h"
-
-G_BEGIN_DECLS
-
-GHashTable *mcd_account_get_conditions (McdAccount *account);
-
-G_END_DECLS
-#endif
diff --git a/src/mcd-account-config.h b/src/mcd-account-config.h
index fc7a9eae..8abfbb87 100644
--- a/src/mcd-account-config.h
+++ b/src/mcd-account-config.h
@@ -46,7 +46,6 @@
#define MC_ACCOUNTS_KEY_ICON "Icon"
#define MC_ACCOUNTS_KEY_NICKNAME "Nickname"
#define MC_ACCOUNTS_KEY_SERVICE "Service"
-/* ... also "condition-*" reserved by mcd-account-conditions.c */
/* unsigned 32-bit integer, 'u' */
/* obsoleted by MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE */
@@ -57,7 +56,6 @@
#define MC_ACCOUNTS_KEY_CONNECT_AUTOMATICALLY "ConnectAutomatically"
#define MC_ACCOUNTS_KEY_ENABLED "Enabled"
#define MC_ACCOUNTS_KEY_HAS_BEEN_ONLINE "HasBeenOnline"
-#define MC_ACCOUNTS_KEY_HIDDEN "Hidden"
/* string array, 'as' */
#define MC_ACCOUNTS_KEY_URI_SCHEMES \
@@ -74,9 +72,11 @@
#define MC_OLD_ACCOUNTS_KEY_DATA_DIR "data_dir"
#define MC_OLD_ACCOUNTS_KEY_DELETED "deleted"
#define MC_OLD_ACCOUNTS_KEY_GROUPS "groups"
+#define MC_OLD_ACCOUNTS_KEY_HIDDEN "Hidden"
#define MC_OLD_ACCOUNTS_KEY_ICON_NAME "icon_name"
#define MC_OLD_ACCOUNTS_KEY_PRESETS "presets"
#define MC_OLD_ACCOUNTS_KEY_PROFILE "profile"
#define MC_OLD_ACCOUNTS_KEY_SECONDARY_VCARD_FIELDS "secondary_vcard_fields"
+/* ... also "condition-*" formerly reserved by Nokia Conditions interface */
#endif /* __MCD_ACCOUNT_CONFIG_H__ */
diff --git a/src/mcd-account-connection.c b/src/mcd-account-connection.c
index 327514de..a532f351 100644
--- a/src/mcd-account-connection.c
+++ b/src/mcd-account-connection.c
@@ -36,118 +36,3 @@
#include "mcd-account-priv.h"
#include "mcd-account-manager.h"
#include "mcd-connection-priv.h"
-
-struct _McdAccountConnectionContext {
- GHashTable *params;
- gboolean user_initiated;
-};
-
-void
-_mcd_account_connection_context_free (McdAccountConnectionContext *c)
-{
- g_hash_table_unref (c->params);
- g_free (c);
-}
-
-void
-_mcd_account_connection_begin (McdAccount *account,
- gboolean user_initiated)
-{
- McdAccountConnectionContext *ctx;
-
- /* check whether a connection process is already ongoing */
- if (_mcd_account_get_connection_context (account) != NULL)
- {
- DEBUG ("already trying to connect");
- return;
- }
-
- /* get account params */
- /* create dynamic params HT */
- /* run the handlers */
- ctx = g_malloc (sizeof (McdAccountConnectionContext));
- ctx->user_initiated = user_initiated;
-
- /* If we get this far, the account should be valid, so getting the
- * parameters should succeed.
- */
- ctx->params = _mcd_account_dup_parameters (account);
- g_assert (ctx->params != NULL);
-
- _mcd_account_set_connection_status (account,
- TP_CONNECTION_STATUS_CONNECTING,
- TP_CONNECTION_STATUS_REASON_REQUESTED,
- NULL, NULL, NULL);
- _mcd_account_set_connection_context (account, ctx);
- mcd_account_connection_proceed (account, TRUE);
-}
-
-void
-mcd_account_connection_proceed_with_reason (McdAccount *account,
- gboolean success,
- TpConnectionStatusReason reason)
-{
- McdAccountConnectionContext *ctx;
- gboolean delayed;
-
- /* call next handler, or terminate the chain (emitting proper signal).
- * if everything is fine, call mcd_manager_create_connection() and
- * _mcd_connection_connect () with the dynamic parameters. Remove that call
- * from mcd_manager_create_connection() */
- ctx = _mcd_account_get_connection_context (account);
- g_return_if_fail (ctx != NULL);
- g_return_if_fail (ctx->params != NULL);
-
- if (success)
- {
- if (mcd_connectivity_monitor_is_online (
- mcd_account_get_connectivity_monitor (account)) || _mcd_account_needs_dispatch (account))
- {
- DEBUG ("%s wants to connect and we're online - go for it",
- mcd_account_get_unique_name (account));
- delayed = FALSE;
- }
- else if (!mcd_account_get_waiting_for_connectivity (account))
- {
- DEBUG ("%s wants to connect, but we're offline; queuing it up",
- mcd_account_get_unique_name (account));
- delayed = TRUE;
- mcd_account_set_waiting_for_connectivity (account, TRUE);
- }
- else
- {
- DEBUG ("%s wants to connect, but is already waiting for "
- "connectivity?", mcd_account_get_unique_name (account));
- delayed = TRUE;
- }
- }
- else
- {
- DEBUG ("%s failed to connect: reason code %d",
- mcd_account_get_unique_name (account), reason);
- delayed = FALSE;
- }
-
- if (!delayed)
- {
- /* end of the chain */
- if (success)
- {
- _mcd_account_connect (account, ctx->params);
- }
- else
- {
- _mcd_account_set_connection_status
- (account, TP_CONNECTION_STATUS_DISCONNECTED, reason, NULL,
- TP_ERROR_STR_DISCONNECTED, NULL);
- }
- _mcd_account_set_connection_context (account, NULL);
- }
-}
-
-void
-mcd_account_connection_proceed (McdAccount *account, gboolean success)
-{
- mcd_account_connection_proceed_with_reason
- (account, success, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED);
-}
diff --git a/src/mcd-account-manager-default.c b/src/mcd-account-manager-default.c
index 1403f843..e6fc14fc 100644
--- a/src/mcd-account-manager-default.c
+++ b/src/mcd-account-manager-default.c
@@ -1,8 +1,8 @@
/*
- * The default account manager keyfile storage pseudo-plugin
+ * The default account manager storage pseudo-plugin
*
* Copyright © 2010 Nokia Corporation
- * Copyright © 2010 Collabora Ltd.
+ * Copyright © 2010-2012 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -30,12 +30,75 @@
#include "mcd-account-manager-default.h"
#include "mcd-debug.h"
+#include "mcd-storage.h"
#include "mcd-misc.h"
-#define PLUGIN_NAME "default-gkeyfile"
+#define PLUGIN_NAME "default"
#define PLUGIN_PRIORITY MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_DEFAULT
-#define PLUGIN_DESCRIPTION "GKeyFile (default) account storage backend"
-#define INITIAL_CONFIG "# Telepathy accounts\n"
+#define PLUGIN_DESCRIPTION "Default account storage backend"
+
+typedef struct {
+ /* owned string, attribute => owned GVariant, value
+ * attributes to be stored in the variant-file */
+ GHashTable *attributes;
+ /* owned string, parameter (without "param-") => owned GVariant, value
+ * parameters of known type to be stored in the variant-file */
+ GHashTable *parameters;
+ /* owned string, parameter (without "param-") => owned string, value
+ * parameters of unknwn type to be stored in the variant-file */
+ GHashTable *untyped_parameters;
+ /* TRUE if the account doesn't really exist, but is here to stop us
+ * loading it from a lower-priority file */
+ gboolean absent;
+ /* TRUE if this account needs saving */
+ gboolean dirty;
+} McdDefaultStoredAccount;
+
+static GVariant *
+variant_ref0 (GVariant *v)
+{
+ return (v == NULL ? NULL : g_variant_ref (v));
+}
+
+static McdDefaultStoredAccount *
+lookup_stored_account (McdAccountManagerDefault *self,
+ const gchar *account)
+{
+ return g_hash_table_lookup (self->accounts, account);
+}
+
+static McdDefaultStoredAccount *
+ensure_stored_account (McdAccountManagerDefault *self,
+ const gchar *account)
+{
+ McdDefaultStoredAccount *sa = lookup_stored_account (self, account);
+
+ if (sa == NULL)
+ {
+ sa = g_slice_new0 (McdDefaultStoredAccount);
+ sa->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_variant_unref);
+ sa->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) g_variant_unref);
+ sa->untyped_parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, g_free);
+ g_hash_table_insert (self->accounts, g_strdup (account), sa);
+ }
+
+ sa->absent = FALSE;
+ return sa;
+}
+
+static void
+stored_account_free (gpointer p)
+{
+ McdDefaultStoredAccount *sa = p;
+
+ g_hash_table_unref (sa->attributes);
+ g_hash_table_unref (sa->parameters);
+ g_hash_table_unref (sa->untyped_parameters);
+ g_slice_free (McdDefaultStoredAccount, sa);
+}
static void account_storage_iface_init (McpAccountStorageIface *,
gpointer);
@@ -65,22 +128,39 @@ get_old_filename (void)
}
static gchar *
-account_filename_in (const gchar *dir)
+accounts_cfg_in (const gchar *dir)
{
return g_build_filename (dir, "telepathy", "mission-control", "accounts.cfg",
NULL);
}
+static gchar *
+account_directory_in (const gchar *dir)
+{
+ return g_build_filename (dir, "telepathy", "mission-control", NULL);
+}
+
+static gchar *
+account_file_in (const gchar *dir,
+ const gchar *account)
+{
+ gchar *basename = g_strdup_printf ("%s.account", account);
+ gchar *ret;
+
+ g_strdelimit (basename, "/", '-');
+ ret = g_build_filename (dir, "telepathy", "mission-control",
+ basename, NULL);
+ g_free (basename);
+ return ret;
+}
+
static void
mcd_account_manager_default_init (McdAccountManagerDefault *self)
{
DEBUG ("mcd_account_manager_default_init");
- self->filename = account_filename_in (g_get_user_data_dir ());
- self->keyfile = g_key_file_new ();
- self->removed = g_key_file_new ();
- self->removed_accounts =
- g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
- self->save = FALSE;
+ self->directory = account_directory_in (g_get_user_data_dir ());
+ self->accounts = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
+ stored_account_free);
self->loaded = FALSE;
}
@@ -90,184 +170,433 @@ mcd_account_manager_default_class_init (McdAccountManagerDefaultClass *cls)
DEBUG ("mcd_account_manager_default_class_init");
}
-/* We happen to know that the string MC gave us is "sufficiently escaped" to
- * put it in the keyfile as-is. */
-static gboolean
-_set (const McpAccountStorage *self,
- const McpAccountManager *am,
+static McpAccountStorageSetResult
+set_parameter (McpAccountStorage *self,
+ McpAccountManager *am,
const gchar *account,
- const gchar *key,
- const gchar *val)
+ const gchar *parameter,
+ GVariant *val,
+ McpParameterFlags flags)
{
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa;
- amd->save = TRUE;
+ sa = lookup_stored_account (amd, account);
+ g_return_val_if_fail (sa != NULL, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+ g_return_val_if_fail (!sa->absent, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
- if (val != NULL)
- g_key_file_set_value (amd->keyfile, account, key, val);
+ if (val == NULL)
+ {
+ gboolean changed = FALSE;
+
+ changed = g_hash_table_remove (sa->parameters, parameter);
+ /* deliberately not ||= - if we removed it from parameters, we
+ * still want to remove it from untyped_parameters if it was there */
+ changed |= g_hash_table_remove (sa->untyped_parameters, parameter);
+
+ if (!changed)
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
+ }
else
- g_key_file_remove_key (amd->keyfile, account, key, NULL);
+ {
+ GVariant *old;
+
+ old = g_hash_table_lookup (sa->parameters, parameter);
+
+ if (old != NULL && g_variant_equal (old, val))
+ {
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
+ }
+
+ /* We haven't checked whether it's in untyped_parameters with the
+ * same value - but if it is, we want to migrate it to parameters
+ * anyway (in order to record its type), so treat it as having
+ * actually changed. */
- return TRUE;
+ g_hash_table_remove (sa->untyped_parameters, parameter);
+ g_hash_table_insert (sa->parameters, g_strdup (parameter),
+ g_variant_ref (val));
+ }
+
+ sa->dirty = TRUE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED;
}
-static gboolean
-_get (const McpAccountStorage *self,
- const McpAccountManager *am,
+static McpAccountStorageSetResult
+set_attribute (McpAccountStorage *self,
+ McpAccountManager *am,
const gchar *account,
- const gchar *key)
+ const gchar *attribute,
+ GVariant *val,
+ McpAttributeFlags flags)
{
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa;
- if (key != NULL)
+ sa = lookup_stored_account (amd, account);
+ g_return_val_if_fail (sa != NULL, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+ g_return_val_if_fail (!sa->absent, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+
+ if (val == NULL)
+ {
+ if (!g_hash_table_remove (sa->attributes, attribute))
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
+ }
+ else
{
- gchar *v = NULL;
+ GVariant *old;
- v = g_key_file_get_value (amd->keyfile, account, key, NULL);
+ old = g_hash_table_lookup (sa->attributes, attribute);
- if (v == NULL)
- return FALSE;
+ if (old != NULL && g_variant_equal (old, val))
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
- mcp_account_manager_set_value (am, account, key, v);
- g_free (v);
+ g_hash_table_insert (sa->attributes, g_strdup (attribute),
+ g_variant_ref (val));
}
- else
- {
- gsize i;
- gsize n;
- GStrv keys = g_key_file_get_keys (amd->keyfile, account, &n, NULL);
- if (keys == NULL)
- n = 0;
+ sa->dirty = TRUE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED;
+}
- for (i = 0; i < n; i++)
- {
- gchar *v = g_key_file_get_value (amd->keyfile, account, keys[i], NULL);
+static GVariant *
+get_attribute (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *attribute,
+ const GVariantType *type,
+ McpAttributeFlags *flags)
+{
+ McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
- if (v != NULL)
- mcp_account_manager_set_value (am, account, keys[i], v);
+ if (flags != NULL)
+ *flags = 0;
- g_free (v);
- }
+ g_return_val_if_fail (sa != NULL, NULL);
+ g_return_val_if_fail (!sa->absent, NULL);
- g_strfreev (keys);
- }
+ /* ignore @type, we store every attribute with its type anyway; MC will
+ * coerce values to an appropriate type if needed */
+ return variant_ref0 (g_hash_table_lookup (sa->attributes, attribute));
+}
- return TRUE;
+static GVariant *
+get_parameter (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *parameter,
+ const GVariantType *type,
+ McpParameterFlags *flags)
+{
+ McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+ GVariant *variant;
+ gchar *str;
+
+ if (flags != NULL)
+ *flags = 0;
+
+ g_return_val_if_fail (sa != NULL, NULL);
+ g_return_val_if_fail (!sa->absent, NULL);
+
+ variant = g_hash_table_lookup (sa->parameters, parameter);
+
+ if (variant != NULL)
+ return g_variant_ref (variant);
+
+ if (type == NULL)
+ return NULL;
+
+ str = g_hash_table_lookup (sa->untyped_parameters, parameter);
+
+ if (str == NULL)
+ return NULL;
+
+ return mcp_account_manager_unescape_variant_from_keyfile (am,
+ str, type, NULL);
+}
+
+static gchar **
+list_typed_parameters (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account)
+{
+ McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+ GPtrArray *arr;
+ GHashTableIter iter;
+ gpointer k;
+
+ g_return_val_if_fail (sa != NULL, NULL);
+ g_return_val_if_fail (!sa->absent, NULL);
+
+ arr = g_ptr_array_sized_new (g_hash_table_size (sa->parameters) + 1);
+
+ g_hash_table_iter_init (&iter, sa->parameters);
+
+ while (g_hash_table_iter_next (&iter, &k, NULL))
+ g_ptr_array_add (arr, g_strdup (k));
+
+ g_ptr_array_add (arr, NULL);
+
+ return (gchar **) g_ptr_array_free (arr, FALSE);
+}
+
+static gchar **
+list_untyped_parameters (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account)
+{
+ McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+ GPtrArray *arr;
+ GHashTableIter iter;
+ gpointer k;
+
+ g_return_val_if_fail (sa != NULL, NULL);
+ g_return_val_if_fail (!sa->absent, NULL);
+
+ arr = g_ptr_array_sized_new (g_hash_table_size (sa->untyped_parameters) + 1);
+
+ g_hash_table_iter_init (&iter, sa->untyped_parameters);
+
+ while (g_hash_table_iter_next (&iter, &k, NULL))
+ g_ptr_array_add (arr, g_strdup (k));
+
+ g_ptr_array_add (arr, NULL);
+
+ return (gchar **) g_ptr_array_free (arr, FALSE);
}
static gchar *
-_create (const McpAccountStorage *self,
- const McpAccountManager *am,
+_create (McpAccountStorage *self,
+ McpAccountManager *am,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identification,
GError **error)
{
+ McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
gchar *unique_name;
- /* See comment in plugin-account.c::_storage_create_account() before changing
- * this implementation, it's more subtle than it looks */
unique_name = mcp_account_manager_get_unique_name (MCP_ACCOUNT_MANAGER (am),
- manager, protocol, params);
+ manager, protocol,
+ identification);
g_return_val_if_fail (unique_name != NULL, NULL);
+ ensure_stored_account (amd, unique_name);
return unique_name;
}
-static gboolean
-_delete (const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key)
+static void
+delete_async (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+ GTask *task;
+ gchar *filename = NULL;
+ const gchar * const *iter;
+
+ task = g_task_new (amd, cancellable, callback, user_data);
+
+ g_return_if_fail (sa != NULL);
+ g_return_if_fail (!sa->absent);
- if (key == NULL)
+ filename = account_file_in (g_get_user_data_dir (), account);
+
+ DEBUG ("Deleting account %s from %s", account, filename);
+
+ if (g_unlink (filename) != 0)
{
- if (g_key_file_remove_group (amd->keyfile, account, NULL))
- amd->save = TRUE;
+ int e = errno;
+
+ /* ENOENT is OK, anything else is more upsetting */
+ if (e != ENOENT)
+ {
+ WARNING ("Unable to delete %s: %s", filename,
+ g_strerror (e));
+ g_task_return_new_error (task, G_IO_ERROR, g_io_error_from_errno (e),
+ "Unable to delete %s: %s", filename, g_strerror (e));
+ goto finally;
+ }
}
- else
+
+ for (iter = g_get_system_data_dirs ();
+ iter != NULL && *iter != NULL;
+ iter++)
{
- gsize n;
- GStrv keys;
- gboolean save = FALSE;
+ gchar *other = account_file_in (*iter, account);
+ gboolean other_exists = g_file_test (other, G_FILE_TEST_EXISTS);
- save = g_key_file_remove_key (amd->keyfile, account, key, NULL);
+ g_free (other);
- if (save)
- amd->save = TRUE;
+ if (other_exists)
+ {
+ GError *error = NULL;
- keys = g_key_file_get_keys (amd->keyfile, account, &n, NULL);
+ /* There is a lower-priority file that would provide this
+ * account. We can't delete a file from XDG_DATA_DIRS which
+ * are conceptually read-only, but we can mask it with an
+ * empty file (prior art: systemd) */
+ if (!g_file_set_contents (filename, "", 0, &error))
+ {
+ g_prefix_error (&error,
+ "Unable to save empty account file to %s: ", filename);
+ WARNING ("%s", error->message);
+ g_task_return_error (task, error);
+ g_free (filename);
+ goto finally;
+ }
- /* if that was the last parameter, the account is gone too */
- if (keys == NULL || n == 0)
- {
- g_key_file_remove_group (amd->keyfile, account, NULL);
+ break;
}
-
- g_strfreev (keys);
}
- return TRUE;
+ /* clean up the mess */
+ g_hash_table_remove (amd->accounts, account);
+ mcp_account_storage_emit_deleted (self, account);
+
+ g_task_return_boolean (task, TRUE);
+
+finally:
+ g_free (filename);
+ g_object_unref (task);
}
+static gboolean
+delete_finish (McpAccountStorage *storage,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
static gboolean
-_commit (const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account)
+am_default_commit_one (McdAccountManagerDefault *self,
+ const gchar *account_name,
+ McdDefaultStoredAccount *sa)
{
- gsize n;
- gchar *data;
- McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
- gboolean rval = FALSE;
- gchar *dir;
+ gchar *filename;
+ GHashTableIter inner;
+ gpointer k, v;
+ GVariantBuilder params_builder;
+ GVariantBuilder attrs_builder;
+ GVariant *content;
+ gchar *content_text;
+ gboolean ret;
GError *error = NULL;
- if (!amd->save)
+ g_return_val_if_fail (sa != NULL, FALSE);
+ g_return_val_if_fail (!sa->absent, FALSE);
+
+ if (!sa->dirty)
return TRUE;
- dir = g_path_get_dirname (amd->filename);
+ if (!mcd_ensure_directory (self->directory, &error))
+ {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ filename = account_file_in (g_get_user_data_dir (), account_name);
+
+ DEBUG ("Saving account %s to %s", account_name, filename);
+
+ g_variant_builder_init (&attrs_builder, G_VARIANT_TYPE_VARDICT);
- DEBUG ("Saving accounts to %s", amd->filename);
+ g_hash_table_iter_init (&inner, sa->attributes);
- if (!mcd_ensure_directory (dir, &error))
+ while (g_hash_table_iter_next (&inner, &k, &v))
{
- g_warning ("%s", error->message);
- g_clear_error (&error);
- /* fall through anyway: writing to the file will fail, but it does
- * give us a chance to commit to the keyring too */
+ g_variant_builder_add (&attrs_builder, "{sv}", k, v);
+ }
+
+ g_variant_builder_init (&params_builder, G_VARIANT_TYPE ("a{sv}"));
+ g_hash_table_iter_init (&inner, sa->parameters);
+
+ while (g_hash_table_iter_next (&inner, &k, &v))
+ {
+ g_variant_builder_add (&params_builder, "{sv}", k, v);
+ }
+
+ g_variant_builder_add (&attrs_builder, "{sv}",
+ "Parameters", g_variant_builder_end (&params_builder));
+
+ g_variant_builder_init (&params_builder, G_VARIANT_TYPE ("a{ss}"));
+ g_hash_table_iter_init (&inner, sa->untyped_parameters);
+
+ while (g_hash_table_iter_next (&inner, &k, &v))
+ {
+ g_variant_builder_add (&params_builder, "{ss}", k, v);
}
- g_free (dir);
+ g_variant_builder_add (&attrs_builder, "{sv}",
+ "KeyFileParameters", g_variant_builder_end (&params_builder));
- data = g_key_file_to_data (amd->keyfile, &n, NULL);
- rval = g_file_set_contents (amd->filename, data, n, &error);
+ content = g_variant_ref_sink (g_variant_builder_end (&attrs_builder));
+ content_text = g_variant_print (content, TRUE);
+ DEBUG ("%s", content_text);
+ g_variant_unref (content);
- if (rval)
+ if (g_file_set_contents (filename, content_text, -1, &error))
{
- amd->save = FALSE;
+ sa->dirty = FALSE;
+ ret = TRUE;
}
else
{
- g_warning ("%s", error->message);
- g_error_free (error);
+ WARNING ("Unable to save account to %s: %s", filename,
+ error->message);
+ g_clear_error (&error);
+ ret = FALSE;
}
- g_free (data);
+ g_free (filename);
+ g_free (content_text);
+ return ret;
+}
- return rval;
+static gboolean
+_commit (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account)
+{
+ McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ McdDefaultStoredAccount *sa = lookup_stored_account (amd, account);
+
+ g_return_val_if_fail (sa != NULL, FALSE);
+ g_return_val_if_fail (!sa->absent, FALSE);
+
+ DEBUG ("Saving account %s to %s", account, amd->directory);
+
+ return am_default_commit_one (amd, account, sa);
}
-static void
+static gboolean
am_default_load_keyfile (McdAccountManagerDefault *self,
const gchar *filename)
{
GError *error = NULL;
+ GKeyFile *keyfile = g_key_file_new ();
+ gsize i;
+ gsize n = 0;
+ GStrv account_tails;
+ gboolean all_ok = TRUE;
- if (g_key_file_load_from_file (self->keyfile, filename,
+ /* We shouldn't call this function without modification if we think we've
+ * migrated to a newer storage format, because it doesn't check whether
+ * each account has already been loaded. */
+ g_assert (!self->loaded);
+ g_assert (g_hash_table_size (self->accounts) == 0);
+
+ if (g_key_file_load_from_file (keyfile, filename,
G_KEY_FILE_KEEP_COMMENTS, &error))
{
DEBUG ("Loaded accounts from %s", filename);
@@ -277,33 +606,311 @@ am_default_load_keyfile (McdAccountManagerDefault *self,
DEBUG ("Failed to load accounts from %s: %s", filename, error->message);
g_error_free (error);
- /* Start with a blank configuration, but do not save straight away;
- * we don't want to overwrite a corrupt-but-maybe-recoverable
- * configuration file with an empty one until given a reason to
- * do so. */
- g_key_file_load_from_data (self->keyfile, INITIAL_CONFIG, -1,
- G_KEY_FILE_KEEP_COMMENTS, NULL);
+ /* Start with a blank configuration. */
+ g_key_file_load_from_data (keyfile, "", -1, 0, NULL);
+ /* Don't delete the old file, which might be recoverable. */
+ all_ok = FALSE;
+ }
+
+ account_tails = g_key_file_get_groups (keyfile, &n);
+
+ for (i = 0; i < n; i++)
+ {
+ const gchar *account = account_tails[i];
+ McdDefaultStoredAccount *sa = ensure_stored_account (self, account);
+ gsize j;
+ gsize m = 0;
+ GStrv keys = g_key_file_get_keys (keyfile, account, &m, NULL);
+
+ /* We're going to need to migrate this account. */
+ sa->dirty = TRUE;
+
+ for (j = 0; j < m; j++)
+ {
+ gchar *key = keys[j];
+
+ if (g_str_has_prefix (key, "param-"))
+ {
+ gchar *raw = g_key_file_get_value (keyfile, account, key, NULL);
+
+ /* steals ownership of raw */
+ g_hash_table_insert (sa->untyped_parameters, g_strdup (key + 6),
+ raw);
+ }
+ else
+ {
+ const GVariantType *type = mcd_storage_get_attribute_type (key);
+ GVariant *variant = NULL;
+
+ if (type == NULL)
+ {
+ /* go to the error code path */
+ g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "unknown attribute");
+ }
+ else
+ {
+ variant = mcd_keyfile_get_variant (keyfile,
+ account, key, type, &error);
+ }
+
+ if (variant == NULL)
+ {
+ WARNING ("Unable to migrate %s.%s from keyfile: %s",
+ account, key, error->message);
+ g_clear_error (&error);
+ /* Don't delete the old file, which might be recoverable. */
+ all_ok = FALSE;
+ }
+ else
+ {
+ g_hash_table_insert (sa->attributes, g_strdup (key),
+ g_variant_ref_sink (variant));
+ }
+ }
+ }
+
+ g_strfreev (keys);
+ }
+
+ g_strfreev (account_tails);
+ g_key_file_unref (keyfile);
+ return all_ok;
+}
+
+static void
+am_default_load_variant_file (McdAccountManagerDefault *self,
+ const gchar *account_tail,
+ const gchar *full_name)
+{
+ McdDefaultStoredAccount *sa;
+ gchar *text = NULL;
+ gsize len;
+ GVariant *contents = NULL;
+ GVariantIter iter;
+ const gchar *k;
+ GVariant *v;
+ GError *error = NULL;
+
+ DEBUG ("%s from %s", account_tail, full_name);
+
+ sa = lookup_stored_account (self, account_tail);
+
+ if (sa != NULL)
+ {
+ DEBUG ("Ignoring %s: account %s already %s",
+ full_name, account_tail, sa->absent ? "masked" : "loaded");
+ goto finally;
+ }
+
+ if (!g_file_get_contents (full_name, &text, &len, &error))
+ {
+ WARNING ("Unable to read account %s from %s: %s",
+ account_tail, full_name, error->message);
+ g_error_free (error);
+ goto finally;
+ }
+
+ if (len == 0)
+ {
+ DEBUG ("Empty file %s masks account %s", full_name, account_tail);
+ ensure_stored_account (self, account_tail)->absent = TRUE;
+ goto finally;
+ }
+
+ contents = g_variant_parse (G_VARIANT_TYPE_VARDICT,
+ text, text + len, NULL, &error);
+
+ if (contents == NULL)
+ {
+ WARNING ("Unable to parse account %s from %s: %s",
+ account_tail, full_name, error->message);
+ g_error_free (error);
+ goto finally;
+ }
+
+ sa = ensure_stored_account (self, account_tail);
+
+ g_variant_iter_init (&iter, contents);
+
+ while (g_variant_iter_loop (&iter, "{sv}", &k, &v))
+ {
+ if (!tp_strdiff (k, "KeyFileParameters"))
+ {
+ GVariantIter param_iter;
+ gchar *parameter;
+ gchar *param_value;
+
+ if (!g_variant_is_of_type (v, G_VARIANT_TYPE ("a{ss}")))
+ {
+ gchar *repr = g_variant_print (v, TRUE);
+
+ WARNING ("invalid KeyFileParameters found in %s, "
+ "ignoring: %s", full_name, repr);
+ g_free (repr);
+ continue;
+ }
+
+ g_variant_iter_init (&param_iter, v);
+
+ while (g_variant_iter_next (&param_iter, "{ss}", &parameter,
+ &param_value))
+ {
+ /* steals parameter, param_value */
+ g_hash_table_insert (sa->untyped_parameters, parameter,
+ param_value);
+ }
+ }
+ else if (!tp_strdiff (k, "Parameters"))
+ {
+ GVariantIter param_iter;
+ gchar *parameter;
+ GVariant *param_value;
+
+ if (!g_variant_is_of_type (v, G_VARIANT_TYPE ("a{sv}")))
+ {
+ gchar *repr = g_variant_print (v, TRUE);
+
+ WARNING ("invalid Parameters found in %s, "
+ "ignoring: %s", full_name, repr);
+ g_free (repr);
+ continue;
+ }
+
+ g_variant_iter_init (&param_iter, v);
+
+ while (g_variant_iter_next (&param_iter, "{sv}", &parameter,
+ &param_value))
+ {
+ /* steals parameter, param_value */
+ g_hash_table_insert (sa->parameters, parameter, param_value);
+ }
+ }
+ else
+ {
+ /* an ordinary attribute */
+ g_hash_table_insert (sa->attributes,
+ g_strdup (k), g_variant_ref (v));
+ }
+ }
+
+finally:
+ tp_clear_pointer (&contents, g_variant_unref);
+ g_free (text);
+}
+
+static void
+am_default_load_directory (McdAccountManagerDefault *self,
+ const gchar *directory)
+{
+ GDir *dir_handle;
+ const gchar *basename;
+ GRegex *regex;
+ GError *error = NULL;
+
+ dir_handle = g_dir_open (directory, 0, &error);
+
+ if (dir_handle == NULL)
+ {
+ /* We expect ENOENT. Anything else is a cause for (minor) concern. */
+ if (g_error_matches (error, G_FILE_ERROR, G_FILE_ERROR_NOENT))
+ DEBUG ("%s", error->message);
+ else
+ WARNING ("%s", error->message);
+
+ g_error_free (error);
+ return;
+ }
+
+ DEBUG ("Looking for accounts in %s", directory);
+
+ regex = g_regex_new ("^[A-Za-z][A-Za-z0-9_]*-" /* CM name */
+ "[A-Za-z][A-Za-z0-9_]*-" /* protocol with s/-/_/ */
+ "[A-Za-z_][A-Za-z0-9_]*\\.account$", /* account-specific part */
+ G_REGEX_DOLLAR_ENDONLY, 0, &error);
+ g_assert_no_error (error);
+
+ while ((basename = g_dir_read_name (dir_handle)) != NULL)
+ {
+ gchar *full_name;
+ gchar *account_tail;
+
+ /* skip it silently if it's obviously not an account */
+ if (!g_str_has_suffix (basename, ".account"))
+ continue;
+
+ /* We consider ourselves to have migrated to the new storage format
+ * as soon as we find something that looks as though it ought to be an
+ * account. */
+ self->loaded = TRUE;
+
+ if (!g_regex_match (regex, basename, 0, NULL))
+ {
+ WARNING ("Ignoring %s/%s: not a syntactically valid account",
+ directory, basename);
+ }
+
+ full_name = g_build_filename (directory, basename, NULL);
+ account_tail = g_strdup (basename);
+ g_strdelimit (account_tail, "-", '/');
+ g_strdelimit (account_tail, ".", '\0');
+
+ am_default_load_variant_file (self, account_tail, full_name);
+
+ g_free (account_tail);
+ g_free (full_name);
}
}
static GList *
-_list (const McpAccountStorage *self,
- const McpAccountManager *am)
+_list (McpAccountStorage *self,
+ McpAccountManager *am)
{
- gsize i;
- gsize n;
- GStrv accounts;
GList *rval = NULL;
McdAccountManagerDefault *amd = MCD_ACCOUNT_MANAGER_DEFAULT (self);
+ GHashTableIter hash_iter;
+ gchar *migrate_from = NULL;
+ gpointer k, v;
+ gboolean save = FALSE;
- if (!amd->loaded && g_file_test (amd->filename, G_FILE_TEST_EXISTS))
+ if (!amd->loaded)
{
- /* If the file exists, but loading it fails, we deliberately
- * do not fall through to the "initial configuration" case,
- * because we don't want to overwrite a corrupted file
- * with an empty one until an actual write takes place. */
- am_default_load_keyfile (amd, amd->filename);
- amd->loaded = TRUE;
+ const gchar * const *iter;
+
+ am_default_load_directory (amd, amd->directory);
+
+ /* We do this even if am_default_load_directory() succeeded, and
+ * do not stop when amd->loaded becomes true. If XDG_DATA_HOME
+ * contains gabble-jabber-example_2eexample_40com.account, that doesn't
+ * mean a directory in XDG_DATA_DIRS doesn't also contain
+ * haze-msn-example_2ehotmail_40com.account or something, which
+ * should also be loaded. */
+ for (iter = g_get_system_data_dirs ();
+ iter != NULL && *iter != NULL;
+ iter++)
+ {
+ gchar *dir = account_directory_in (*iter);
+
+ am_default_load_directory (amd, dir);
+ g_free (dir);
+ }
+ }
+
+ if (!amd->loaded)
+ {
+ migrate_from = accounts_cfg_in (g_get_user_data_dir ());
+
+ if (g_file_test (migrate_from, G_FILE_TEST_EXISTS))
+ {
+ if (!am_default_load_keyfile (amd, migrate_from))
+ tp_clear_pointer (&migrate_from, g_free);
+
+ amd->loaded = TRUE;
+ }
+ else
+ {
+ tp_clear_pointer (&migrate_from, g_free);
+ }
}
if (!amd->loaded)
@@ -314,14 +921,14 @@ _list (const McpAccountStorage *self,
iter != NULL && *iter != NULL;
iter++)
{
- gchar *filename = account_filename_in (*iter);
+ /* not setting migrate_from here - XDG_DATA_DIRS are conceptually
+ * read-only, so we don't want to delete these files */
+ gchar *filename = accounts_cfg_in (*iter);
if (g_file_test (filename, G_FILE_TEST_EXISTS))
{
am_default_load_keyfile (amd, filename);
amd->loaded = TRUE;
- /* Do not set amd->save: we don't need to write it to a
- * higher-priority directory until it actually changes. */
}
g_free (filename);
@@ -333,49 +940,99 @@ _list (const McpAccountStorage *self,
if (!amd->loaded)
{
- gchar *old_filename = get_old_filename ();
+ migrate_from = get_old_filename ();
- if (g_file_test (old_filename, G_FILE_TEST_EXISTS))
+ if (g_file_test (migrate_from, G_FILE_TEST_EXISTS))
{
- am_default_load_keyfile (amd, old_filename);
+ if (!am_default_load_keyfile (amd, migrate_from))
+ tp_clear_pointer (&migrate_from, g_free);
amd->loaded = TRUE;
- amd->save = TRUE;
-
- if (_commit (self, am, NULL))
- {
- DEBUG ("Migrated %s to new location: deleting old copy",
- old_filename);
- if (g_unlink (old_filename) != 0)
- g_warning ("Unable to delete %s: %s", old_filename,
- g_strerror (errno));
- }
+ save = TRUE;
+ }
+ else
+ {
+ tp_clear_pointer (&migrate_from, g_free);
}
-
- g_free (old_filename);
}
if (!amd->loaded)
{
DEBUG ("Creating initial account data");
- g_key_file_load_from_data (amd->keyfile, INITIAL_CONFIG, -1,
- G_KEY_FILE_KEEP_COMMENTS, NULL);
amd->loaded = TRUE;
- amd->save = TRUE;
- _commit (self, am, NULL);
+ save = TRUE;
}
- accounts = g_key_file_get_groups (amd->keyfile, &n);
+ if (!save)
+ {
+ g_hash_table_iter_init (&hash_iter, amd->accounts);
- for (i = 0; i < n; i++)
+ while (g_hash_table_iter_next (&hash_iter, NULL, &v))
+ {
+ McdDefaultStoredAccount *sa = v;
+
+ if (sa->dirty)
+ {
+ save = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (save)
{
- rval = g_list_prepend (rval, g_strdup (accounts[i]));
+ gboolean all_succeeded = TRUE;
+
+ DEBUG ("Saving initial or migrated account data");
+
+ g_hash_table_iter_init (&hash_iter, amd->accounts);
+
+ while (g_hash_table_iter_next (&hash_iter, &k, &v))
+ {
+ McdDefaultStoredAccount *sa = v;
+
+ if (sa->absent)
+ continue;
+
+ if (!am_default_commit_one (amd, k, v))
+ all_succeeded = FALSE;
+ }
+
+ if (all_succeeded)
+ {
+ if (migrate_from != NULL)
+ {
+ DEBUG ("Migrated %s to new location: deleting old copy",
+ migrate_from);
+
+ if (g_unlink (migrate_from) != 0)
+ WARNING ("Unable to delete %s: %s", migrate_from,
+ g_strerror (errno));
+ }
+ }
}
- g_strfreev (accounts);
+ tp_clear_pointer (&migrate_from, g_free);
+
+ g_hash_table_iter_init (&hash_iter, amd->accounts);
+
+ while (g_hash_table_iter_next (&hash_iter, &k, &v))
+ {
+ McdDefaultStoredAccount *sa = v;
+
+ if (!sa->absent)
+ rval = g_list_prepend (rval, g_strdup (k));
+ }
return rval;
}
+static McpAccountStorageFlags
+get_flags (McpAccountStorage *storage,
+ const gchar *account)
+{
+ return MCP_ACCOUNT_STORAGE_FLAG_STORES_TYPES;
+}
+
static void
account_storage_iface_init (McpAccountStorageIface *iface,
gpointer unused G_GNUC_UNUSED)
@@ -384,11 +1041,17 @@ account_storage_iface_init (McpAccountStorageIface *iface,
iface->desc = PLUGIN_DESCRIPTION;
iface->priority = PLUGIN_PRIORITY;
- iface->get = _get;
- iface->set = _set;
+ iface->get_flags = get_flags;
+ iface->get_attribute = get_attribute;
+ iface->get_parameter = get_parameter;
+ iface->list_typed_parameters = list_typed_parameters;
+ iface->list_untyped_parameters = list_untyped_parameters;
+ iface->set_attribute = set_attribute;
+ iface->set_parameter = set_parameter;
iface->create = _create;
- iface->delete = _delete;
- iface->commit_one = _commit;
+ iface->delete_async = delete_async;
+ iface->delete_finish = delete_finish;
+ iface->commit = _commit;
iface->list = _list;
}
diff --git a/src/mcd-account-manager-default.h b/src/mcd-account-manager-default.h
index b16bc4f9..fb2cb75e 100644
--- a/src/mcd-account-manager-default.h
+++ b/src/mcd-account-manager-default.h
@@ -49,11 +49,8 @@ G_BEGIN_DECLS
typedef struct {
GObject parent;
- GKeyFile *keyfile;
- GKeyFile *removed;
- GHashTable *removed_accounts;
- gchar *filename;
- gboolean save;
+ GHashTable *accounts;
+ gchar *directory;
gboolean loaded;
} _McdAccountManagerDefault;
diff --git a/src/mcd-account-manager-priv.h b/src/mcd-account-manager-priv.h
index 80a1e0fa..e89b1d33 100644
--- a/src/mcd-account-manager-priv.h
+++ b/src/mcd-account-manager-priv.h
@@ -28,9 +28,6 @@
#include "mcd-dbusprop.h"
-/* auto-generated stubs */
-#include "_gen/svc-Account_Manager_Interface_Hidden.h"
-
G_BEGIN_DECLS
G_GNUC_INTERNAL void _mcd_account_manager_setup
diff --git a/src/mcd-account-manager-sso.c b/src/mcd-account-manager-sso.c
deleted file mode 100644
index 186c6368..00000000
--- a/src/mcd-account-manager-sso.c
+++ /dev/null
@@ -1,1745 +0,0 @@
-/*
- * A pseudo-plugin that stores/fetches accounts in/from the SSO via libaccounts
- *
- * Copyright © 2010-2011 Nokia Corporation
- * Copyright © 2010-2011 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
- */
-
-#include "config.h"
-#include "mcd-account-manager-sso.h"
-#include "mcd-debug.h"
-
-#include <telepathy-glib/telepathy-glib.h>
-
-#include <libaccounts-glib/ag-account.h>
-#include <libaccounts-glib/ag-service.h>
-
-#include <string.h>
-#include <ctype.h>
-
-#define PLUGIN_PRIORITY (MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_KEYRING + 10)
-#define PLUGIN_NAME "maemo-libaccounts"
-#define PLUGIN_DESCRIPTION \
- "Account storage in the Maemo SSO store via libaccounts-glib API"
-#define PLUGIN_PROVIDER "org.maemo.Telepathy.Account.Storage.LibAccounts"
-
-#define MCPP "param-"
-#define AGPP "parameters/"
-#define LIBACCT_ID_KEY "libacct-uid"
-
-#define MC_ENABLED_KEY "Enabled"
-#define AG_ENABLED_KEY "enabled"
-
-#define AG_LABEL_KEY "name"
-#define MC_LABEL_KEY "DisplayName"
-
-#define AG_ACCOUNT_KEY "username"
-#define MC_ACCOUNT_KEY "account"
-#define PASSWORD_KEY "password"
-#define AG_ACCOUNT_ALT_KEY AGPP "account"
-
-#define MC_CMANAGER_KEY "manager"
-#define MC_PROTOCOL_KEY "protocol"
-#define MC_IDENTITY_KEY "tmc-uid"
-
-#define SERVICES_KEY "sso-services"
-
-#define MC_SERVICE_KEY "Service"
-
-#define AG_ACCOUNT_WRITE_INTERVAL 5
-
-static const gchar *exported_settings[] = { "CredentialsId", NULL };
-
-typedef enum {
- DELAYED_CREATE,
- DELAYED_DELETE,
-} DelayedSignal;
-
-typedef struct {
- gchar *mc_name;
- gchar *ag_name;
- gboolean global; /* global ag setting or service specific? */
- gboolean readable; /* does the _standard_ read method copy this into MC? */
- gboolean writable; /* does the _standard_ write method copy this into AG? */
- gboolean freeable; /* should clear_setting_data deallocate the names? */
-} Setting;
-
-#define GLOBAL TRUE
-#define SERVICE FALSE
-#define READABLE TRUE
-#define UNREADABLE FALSE
-#define WRITABLE TRUE
-#define UNWRITABLE FALSE
-
-typedef enum {
- SETTING_MC,
- SETTING_AG,
-} SettingType;
-
-/* IMPORTANT IMPLEMENTATION NOTE:
- *
- * The mapping between telepathy settings and parameter names
- * and ag account (libaccounts) settings, and whether those settings
- * are stored in the global or service specific ag section is a
- * finicky beast - the mapping below has been arrived at empirically
- * Take care when altering it.
- *
- * Settings not mentioned explicitly are:
- * • given the same name on both MC and AG sides
- * • assigned to the service specific section
- * • automatically prefixed (param- vs parameters/) for each side if necessary
- *
- * So if your setting fits these criteria, you do not need to add it at all.
- */
-Setting setting_map[] = {
- { MC_ENABLED_KEY , AG_ENABLED_KEY , GLOBAL , UNREADABLE, UNWRITABLE },
- { MCPP MC_ACCOUNT_KEY, AG_ACCOUNT_KEY , GLOBAL , READABLE , UNWRITABLE },
- { MCPP PASSWORD_KEY , PASSWORD_KEY , GLOBAL , READABLE , WRITABLE },
- { MC_LABEL_KEY , AG_LABEL_KEY , GLOBAL , READABLE , WRITABLE },
- { LIBACCT_ID_KEY , LIBACCT_ID_KEY , GLOBAL , UNREADABLE, UNWRITABLE },
- { MC_IDENTITY_KEY , MC_IDENTITY_KEY, SERVICE, READABLE , WRITABLE },
- { MC_CMANAGER_KEY , MC_CMANAGER_KEY, SERVICE, READABLE , UNWRITABLE },
- { MC_PROTOCOL_KEY , MC_PROTOCOL_KEY, SERVICE, READABLE , UNWRITABLE },
- { MC_SERVICE_KEY , MC_SERVICE_KEY , SERVICE, UNREADABLE, UNWRITABLE },
- { SERVICES_KEY , SERVICES_KEY , GLOBAL , UNREADABLE, UNWRITABLE },
- { NULL }
-};
-
-typedef struct {
- DelayedSignal signal;
- AgAccountId account_id;
-} DelayedSignalData;
-
-typedef struct {
- McdAccountManagerSso *sso;
- struct {
- AgAccountWatch service;
- AgAccountWatch global;
- } watch;
-} WatchData;
-
-static Setting *
-setting_data (const gchar *name, SettingType type)
-{
- guint i = 0;
- static Setting parameter = { NULL, NULL, SERVICE, READABLE, WRITABLE, TRUE };
- const gchar *prefix;
-
- for (; setting_map[i].mc_name != NULL; i++)
- {
- const gchar *setting_name = NULL;
-
- if (type == SETTING_MC)
- setting_name = setting_map[i].mc_name;
- else
- setting_name = setting_map[i].ag_name;
-
- if (g_strcmp0 (name, setting_name) == 0)
- return &setting_map[i];
- }
-
- prefix = (type == SETTING_MC) ? MCPP : AGPP;
-
- if (!g_str_has_prefix (name, prefix))
- { /* a non-parameter setting */
- parameter.mc_name = g_strdup (name);
- parameter.ag_name = g_strdup (name);
- }
- else
- { /* a setting that is a parameter on both sides (AG & MC) */
- const guint plength = strlen (prefix);
-
- parameter.mc_name = g_strdup_printf ("%s%s", MCPP, name + plength);
- parameter.ag_name = g_strdup_printf ("%s%s", AGPP, name + plength);
- }
-
- return &parameter;
-}
-
-static void
-clear_setting_data (Setting *setting)
-{
- if (setting == NULL)
- return;
-
- if (!setting->freeable)
- return;
-
- g_free (setting->mc_name);
- g_free (setting->ag_name);
- setting->mc_name = NULL;
- setting->ag_name = NULL;
-}
-
-static gboolean _sso_account_enabled (
- McdAccountManagerSso *self,
- AgAccount *account,
- AgService *service);
-
-static void account_storage_iface_init (McpAccountStorageIface *,
- gpointer);
-
-static gchar *
-_ag_accountid_to_mc_key (McdAccountManagerSso *sso,
- AgAccountId id,
- gboolean create);
-
-static void _ag_account_stored_cb (AgAccount *acct,
- const GError *err,
- gpointer ignore);
-
-static void _sso_created (GObject *object,
- AgAccountId id,
- gpointer user_data);
-
-static void _sso_toggled (GObject *object,
- AgAccountId id,
- gpointer data);
-
-static gboolean save_setting (
- McdAccountManagerSso *self,
- AgAccount *account,
- const Setting *setting,
- const gchar *val);
-
-G_DEFINE_TYPE_WITH_CODE (McdAccountManagerSso, mcd_account_manager_sso,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (MCP_TYPE_ACCOUNT_STORAGE,
- account_storage_iface_init));
-
-static gchar *
-_gvalue_to_string (const GValue *val)
-{
- switch (G_VALUE_TYPE (val))
- {
- case G_TYPE_STRING:
- return g_value_dup_string (val);
- case G_TYPE_BOOLEAN:
- return g_strdup (g_value_get_boolean (val) ? "true" : "false");
- case G_TYPE_CHAR:
- return g_strdup_printf ("%c", g_value_get_uchar (val));
- case G_TYPE_UCHAR:
- return g_strdup_printf ("%c", g_value_get_char (val));
- case G_TYPE_INT:
- return g_strdup_printf ("%i", g_value_get_int (val));
- case G_TYPE_UINT:
- return g_strdup_printf ("%u", g_value_get_uint (val));
- case G_TYPE_LONG:
- return g_strdup_printf ("%ld", g_value_get_long (val));
- case G_TYPE_ULONG:
- return g_strdup_printf ("%lu", g_value_get_ulong (val));
- case G_TYPE_INT64:
- return g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (val));
- case G_TYPE_UINT64:
- return g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (val));
- case G_TYPE_ENUM:
- return g_strdup_printf ("%d" , g_value_get_enum (val));
- case G_TYPE_FLAGS:
- return g_strdup_printf ("%u", g_value_get_flags (val));
- case G_TYPE_FLOAT:
- return g_strdup_printf ("%f", g_value_get_float (val));
- case G_TYPE_DOUBLE:
- return g_strdup_printf ("%g", g_value_get_double (val));
- default:
- DEBUG ("Unsupported type %s", G_VALUE_TYPE_NAME (val));
- return NULL;
- }
-}
-
-static const gchar *
-account_manager_sso_get_service_type (McdAccountManagerSso *self)
-{
- McdAccountManagerSsoClass *klass = MCD_ACCOUNT_MANAGER_SSO_GET_CLASS (self);
-
- g_assert (klass->service_type != NULL);
-
- return klass->service_type;
-}
-
-static gboolean
-_ag_account_select_default_im_service (
- McdAccountManagerSso *self,
- AgAccount *account)
-{
- const gchar *service_type = account_manager_sso_get_service_type (self);
- gboolean have_service = FALSE;
- GList *first = ag_account_list_services_by_type (account, service_type);
-
- if (first != NULL && first->data != NULL)
- {
- have_service = TRUE;
- DEBUG ("default %s service %s", service_type,
- ag_service_get_name (first->data));
- ag_account_select_service (account, first->data);
- }
-
- ag_service_list_free (first);
-
- return have_service;
-}
-
-static AgSettingSource
-_ag_account_global_value (AgAccount *account,
- const gchar *key,
- GValue *value)
-{
- AgSettingSource src = AG_SETTING_SOURCE_NONE;
- AgService *service = ag_account_get_selected_service (account);
-
- if (service != NULL)
- {
- ag_account_select_service (account, NULL);
- src = ag_account_get_value (account, key, value);
- ag_account_select_service (account, service);
- }
- else
- {
- src = ag_account_get_value (account, key, value);
- }
-
- return src;
-}
-
-static AgSettingSource
-_ag_account_local_value (
- McdAccountManagerSso *self,
- AgAccount *account,
- const gchar *key,
- GValue *value)
-{
- AgSettingSource src = AG_SETTING_SOURCE_NONE;
- AgService *service = ag_account_get_selected_service (account);
-
- if (service != NULL)
- {
- src = ag_account_get_value (account, key, value);
- }
- else
- {
- _ag_account_select_default_im_service (self, account);
- src = ag_account_get_value (account, key, value);
- ag_account_select_service (account, NULL);
- }
-
- return src;
-}
-
-/* AG_ACCOUNT_ALT_KEY from service overrides global AG_ACCOUNT_KEY if set */
-static void
-_maybe_set_account_param_from_service (
- McdAccountManagerSso *self,
- const McpAccountManager *am,
- AgAccount *ag_account,
- const gchar *mc_account)
-{
- Setting *setting = setting_data (AG_ACCOUNT_KEY, SETTING_AG);
- AgSettingSource source = AG_SETTING_SOURCE_NONE;
- GValue ag_value = G_VALUE_INIT;
-
- g_return_if_fail (setting != NULL);
- g_return_if_fail (ag_account != NULL);
-
- g_value_init (&ag_value, G_TYPE_STRING);
-
- source = _ag_account_local_value (self, ag_account, AG_ACCOUNT_ALT_KEY,
- &ag_value);
-
- if (source != AG_SETTING_SOURCE_NONE)
- {
- gchar *value = _gvalue_to_string (&ag_value);
-
- DEBUG ("overriding global %s param with %s: %s",
- AG_ACCOUNT_KEY, AG_ACCOUNT_ALT_KEY, value);
- mcp_account_manager_set_value (am, mc_account, setting->mc_name, value);
- g_free (value);
- }
-
- g_value_unset (&ag_value);
- clear_setting_data (setting);
-}
-
-static WatchData *
-make_watch_data (McdAccountManagerSso *sso)
-{
- WatchData *data = g_slice_new0 (WatchData);
-
- data->sso = g_object_ref (sso);
-
- return data;
-}
-
-static void
-free_watch_data (gpointer data)
-{
- WatchData *wd = data;
-
- if (wd == NULL)
- return;
-
- tp_clear_object (&wd->sso);
- g_slice_free (WatchData, wd);
-}
-
-static void unwatch_account_keys (McdAccountManagerSso *sso,
- AgAccountId id)
-{
- gpointer watch_key = GUINT_TO_POINTER (id);
- WatchData *wd = g_hash_table_lookup (sso->watches, watch_key);
- AgAccount *account = ag_manager_get_account (sso->ag_manager, id);
-
- if (wd != NULL && account != NULL)
- {
- ag_account_remove_watch (account, wd->watch.global);
- ag_account_remove_watch (account, wd->watch.service);
- }
-
- g_hash_table_remove (sso->watches, watch_key);
-}
-
-/* There are two types of ag watch: ag_account_watch_key and *
- * ag_account_watch_dir. _key passees us the watched key when invoking this *
- * callback, dir watches only a prefix, and passes the watched prefix *
- * (not the actual updated setting) - we now watch with _dir since _key *
- * doesn't allow us to watch for keys-that-are-not-set at creation time *
- * (since those cannot be known in advance): This means that in this *
- * callback we must compare what we have in MC with what's in AG and issue *
- * update notices accordingly (and remember to handle deleted keys). *
- * It also means the const gchar *what-was-updated parameter is not useful */
-static void _sso_updated (AgAccount *account,
- const gchar *unused,
- gpointer data)
-{
- WatchData *wd = data;
- McdAccountManagerSso *sso = wd->sso;
- McpAccountManager *am = sso->manager_interface;
- McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
- gpointer id = GUINT_TO_POINTER (account->id);
- const gchar *name = g_hash_table_lookup (sso->id_name_map, id);
- AgService *service = ag_account_get_selected_service (account);
- GStrv keys = NULL;
- GHashTable *unseen = NULL;
- GHashTableIter deleted_iter = { 0 };
- const gchar *deleted_key;
- guint i;
- gboolean params_updated = FALSE;
- const gchar *immutables[] = { MC_SERVICE_KEY, SERVICES_KEY, NULL };
-
- /* account has no name yet: might be time to create it */
- if (name == NULL)
- return _sso_created (G_OBJECT (sso->ag_manager), account->id, sso);
-
- DEBUG ("update for account %s", name);
-
- /* list the keys we know about so we can tell if one has been deleted */
- keys = mcp_account_manager_list_keys (am, name);
- unseen = g_hash_table_new (g_str_hash, g_str_equal);
-
- for (i = 0; keys != NULL && keys[i] != NULL; i++)
- g_hash_table_insert (unseen, keys[i], GUINT_TO_POINTER (TRUE));
-
- /* now iterate over ag settings, global then service specific: */
- ag_account_select_service (account, NULL);
-
- for (i = 0; i < 2; i++)
- {
- AgAccountSettingIter iter = { 0 };
- const gchar *ag_key = NULL;
- const GValue *ag_val = NULL;
-
- if (i == 1)
- _ag_account_select_default_im_service (sso, account);
-
- ag_account_settings_iter_init (account, &iter, NULL);
-
- while (ag_account_settings_iter_next (&iter, &ag_key, &ag_val))
- {
- Setting *setting = setting_data (ag_key, SETTING_AG);
- const gchar *mc_key;
- gchar *ag_str;
- gchar *mc_str;
-
- if (setting == NULL)
- continue;
-
- mc_key = setting->mc_name;
- mc_str = mcp_account_manager_get_value (am, name, mc_key);
- ag_str = _gvalue_to_string (ag_val);
- g_hash_table_remove (unseen, mc_key);
-
- if (tp_strdiff (ag_str, mc_str))
- {
- mcp_account_manager_set_value (am, name, mc_key, ag_str);
-
- if (sso->ready)
- {
- if (g_str_has_prefix (mc_key, MCPP))
- params_updated = TRUE;
- else
- mcp_account_storage_emit_altered_one (mcpa, name, mc_key);
- }
- }
-
- g_free (mc_str);
- g_free (ag_str);
- clear_setting_data (setting);
- }
- }
-
- /* special case values always exist and therefore cannot be deleted */
- for (i = 0; immutables[i] != NULL; i++)
- {
- Setting *immutable = setting_data (immutables[i], SETTING_AG);
-
- g_hash_table_remove (unseen, immutable->ag_name);
- clear_setting_data (immutable);
- }
-
- /* signal (and update) deleted settings: */
- g_hash_table_iter_init (&deleted_iter, unseen);
-
- while (g_hash_table_iter_next (&deleted_iter, (gpointer *)&deleted_key, NULL))
- {
- mcp_account_manager_set_value (am, name, deleted_key, NULL);
-
- if (g_str_has_prefix (deleted_key, MCPP))
- params_updated = TRUE;
- else
- mcp_account_storage_emit_altered_one (mcpa, name, deleted_key);
- }
-
- g_hash_table_unref (unseen);
- g_strfreev (keys);
-
- if (params_updated)
- mcp_account_storage_emit_altered_one (mcpa, name, "Parameters");
-
- /* put the selected service back the way it was when we found it */
- ag_account_select_service (account, service);
-}
-
-static void watch_for_updates (McdAccountManagerSso *sso,
- AgAccount *account)
-{
- WatchData *data;
- gpointer id = GUINT_TO_POINTER (account->id);
- AgService *service;
-
- /* already watching account? let's be idempotent */
- if (g_hash_table_lookup (sso->watches, id) != NULL)
- return;
-
- DEBUG ("watching AG ID %u for updates", account->id);
-
- service = ag_account_get_selected_service (account);
-
- data = make_watch_data (sso);
-
- ag_account_select_service (account, NULL);
- data->watch.global = ag_account_watch_dir (account, "", _sso_updated, data);
-
- _ag_account_select_default_im_service (sso, account);
- data->watch.service = ag_account_watch_dir (account, "", _sso_updated, data);
-
- g_hash_table_insert (sso->watches, id, data);
- ag_account_select_service (account, service);
-}
-
-static void _sso_toggled (GObject *object,
- AgAccountId id,
- gpointer data)
-{
- AgManager *manager = AG_MANAGER (object);
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (data);
- McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
- AgAccount *account = NULL;
- gboolean on = FALSE;
- const gchar *name = NULL;
-
- /* If the account manager isn't ready, account state changes are of no *
- * interest to us: it will pick up the then-current state of the account *
- * when it does become ready, and anything that happens between now and *
- * then is not important: */
- if (!sso->ready)
- return;
-
- account = ag_manager_get_account (manager, id);
-
- if (account != NULL)
- {
- on = _sso_account_enabled (sso, account, NULL);
- name = g_hash_table_lookup (sso->id_name_map, GUINT_TO_POINTER (id));
- }
-
- if (name != NULL)
- {
- const gchar *value = on ? "true" : "false";
- McpAccountManager *am = sso->manager_interface;
-
- mcp_account_manager_set_value (am, name, "Enabled", value);
- mcp_account_storage_emit_toggled (mcpa, name, on);
- }
- else
- {
- DEBUG ("received enabled=%u signal for unknown SSO account %u", on, id);
- }
-}
-
-static void _sso_deleted (GObject *object,
- AgAccountId id,
- gpointer user_data)
-{
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (user_data);
-
- if (sso->ready)
- {
- const gchar *name =
- g_hash_table_lookup (sso->id_name_map, GUINT_TO_POINTER (id));
-
- /* if the account was in our cache, then this was a 3rd party delete *
- * op that someone did behind our back: fire the signal and clean up */
- if (name != NULL)
- {
- McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
- gchar *signalled_name = g_strdup (name);
-
- /* forget id->name map first, so the signal can't start a loop */
- g_hash_table_remove (sso->id_name_map, GUINT_TO_POINTER (id));
- g_hash_table_remove (sso->accounts, signalled_name);
-
- /* stop watching for updates */
- unwatch_account_keys (sso, id);
-
- mcp_account_storage_emit_deleted (mcpa, signalled_name);
-
- g_free (signalled_name);
- }
- }
- else
- {
- DelayedSignalData *sig_data = g_slice_new0 (DelayedSignalData);
-
- sig_data->signal = DELAYED_DELETE;
- sig_data->account_id = id;
- g_queue_push_tail (sso->pending_signals, sig_data);
- }
-}
-
-/* return TRUE if we actually changed any state, FALSE otherwise */
-static gboolean _sso_account_enable (
- McdAccountManagerSso *self,
- AgAccount *account,
- AgService *service,
- gboolean on)
-{
- AgService *original = ag_account_get_selected_service (account);
-
- /* the setting account is already in one of the global+service
- configurations that corresponds to our current state: don't touch it */
- if (_sso_account_enabled (self, account, service) == on)
- return FALSE;
-
- /* turn the local enabled flag on/off as required */
- if (service != NULL)
- ag_account_select_service (account, service);
- else
- _ag_account_select_default_im_service (self, account);
-
- ag_account_set_enabled (account, on);
-
- /* if we are turning the account on, the global flag must also be set *
- * NOTE: this isn't needed when turning the account off */
- if (on)
- {
- ag_account_select_service (account, NULL);
- ag_account_set_enabled (account, on);
- }
-
- ag_account_select_service (account, original);
-
- return TRUE;
-}
-
-static gboolean _sso_account_enabled (
- McdAccountManagerSso *self,
- AgAccount *account,
- AgService *service)
-{
- gboolean local = FALSE;
- gboolean global = FALSE;
- AgService *original = ag_account_get_selected_service (account);
-
- if (service == NULL)
- {
- _ag_account_select_default_im_service (self, account);
- local = ag_account_get_enabled (account);
- }
- else
- {
- if (original != service)
- ag_account_select_service (account, service);
-
- local = ag_account_get_enabled (account);
- }
-
- ag_account_select_service (account, NULL);
- global = ag_account_get_enabled (account);
-
- ag_account_select_service (account, original);
-
- DEBUG ("_sso_account_enabled: global:%d && local:%d", global, local);
-
- return local && global;
-}
-
-static void _sso_created (GObject *object,
- AgAccountId id,
- gpointer user_data)
-{
- AgManager *ag_manager = AG_MANAGER (object);
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (user_data);
- gchar *name =
- g_hash_table_lookup (sso->id_name_map, GUINT_TO_POINTER (id));
-
- if (sso->ready)
- {
- /* if we already know the account's name, we shouldn't fire the new *
- * account signal as it is one we (and our superiors) already have *
- * This could happen as a result of multiple updates being set off *
- * before we are ready, for example */
- if (name == NULL)
- {
- McpAccountStorage *mcpa = MCP_ACCOUNT_STORAGE (sso);
- AgAccount *account = ag_manager_get_account (ag_manager, id);
-
- if (account != NULL)
- {
- /* this will be owned by the ag account hash, do not free it */
- name = _ag_accountid_to_mc_key (sso, id, TRUE);
-
- if (name != NULL)
- {
- Setting *setting = setting_data (MC_IDENTITY_KEY, SETTING_MC);
-
- g_hash_table_insert (sso->accounts, name, account);
- g_hash_table_insert (sso->id_name_map, GUINT_TO_POINTER (id),
- g_strdup (name));
-
- save_setting (sso, account, setting, name);
-
- ag_account_store (account, _ag_account_stored_cb, sso);
-
- mcp_account_storage_emit_created (mcpa, name);
-
- clear_setting_data (setting);
- }
- else
- {
- /* not enough data to name the account: wait for an update */
- DEBUG ("SSO account #%u is currently unnameable", id);
- }
-
- /* in either case, add the account to the watched list */
- watch_for_updates (sso, account);
- }
- }
- }
- else
- {
- DelayedSignalData *sig_data = g_slice_new0 (DelayedSignalData);
-
- sig_data->signal = DELAYED_CREATE;
- sig_data->account_id = id;
- g_queue_push_tail (sso->pending_signals, sig_data);
- }
-}
-
-static void
-mcd_account_manager_sso_init (McdAccountManagerSso *self)
-{
- self->accounts =
- g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
- self->id_name_map =
- g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, g_free);
- self->watches =
- g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL,
- (GDestroyNotify) free_watch_data);
- self->pending_signals = g_queue_new ();
-
-}
-
-static void
-mcd_account_manager_sso_constructed (GObject *object)
-{
- McdAccountManagerSso *self = MCD_ACCOUNT_MANAGER_SSO (object);
- GObjectClass *parent_class =
- G_OBJECT_CLASS (mcd_account_manager_sso_parent_class);
- const gchar *service_type = account_manager_sso_get_service_type (self);
-
- if (parent_class->constructed != NULL)
- parent_class->constructed (object);
-
- DEBUG ("Watching for services of type '%s'", service_type);
- self->ag_manager = ag_manager_new_for_service_type (service_type);
-
- g_signal_connect(self->ag_manager, "enabled-event",
- G_CALLBACK (_sso_toggled), self);
- g_signal_connect(self->ag_manager, "account-deleted",
- G_CALLBACK (_sso_deleted), self);
- g_signal_connect(self->ag_manager, "account-created",
- G_CALLBACK (_sso_created), self);
-}
-
-static void
-mcd_account_manager_sso_class_init (McdAccountManagerSsoClass *klass)
-{
- GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
- object_class->constructed = mcd_account_manager_sso_constructed;
-
- klass->service_type = "IM";
-}
-
-static void
-_ag_account_stored_cb (
- AgAccount *account,
- const GError *err,
- gpointer user_data)
-{
- McdAccountManagerSso *self = MCD_ACCOUNT_MANAGER_SSO (user_data);
- GValue uid = G_VALUE_INIT;
- const gchar *name = NULL;
- AgSettingSource src = AG_SETTING_SOURCE_NONE;
-
- g_value_init (&uid, G_TYPE_STRING);
-
- src = _ag_account_local_value (self, account, MC_IDENTITY_KEY, &uid);
-
- if (src != AG_SETTING_SOURCE_NONE && G_VALUE_HOLDS_STRING (&uid))
- {
- name = g_value_get_string (&uid);
- DEBUG ("%p:%s stored: %s", account, name, err ? err->message : "-");
- g_value_unset (&uid);
- }
- else
- {
- DEBUG ("%p:%s not stored? %s", acct,
- ag_account_get_display_name (account), err ? err->message : "-");
- }
-}
-
-static gchar *
-_ag_accountid_to_mc_key (McdAccountManagerSso *sso,
- AgAccountId id,
- gboolean create)
-{
- AgAccount *account = ag_manager_get_account (sso->ag_manager, id);
- AgSettingSource src = AG_SETTING_SOURCE_NONE;
- AgService *service = NULL;
- GValue value = G_VALUE_INIT;
-
- if (account == NULL)
- {
- DEBUG ("AG Account ID %u invalid", id);
- return NULL;
- }
-
- service = ag_account_get_selected_service (account);
-
- DEBUG ("AG Account ID: %u", id);
-
- g_value_init (&value, G_TYPE_STRING);
-
- /* first look for the stored TMC uid */
- src = _ag_account_local_value (sso, account, MC_IDENTITY_KEY, &value);
-
- /* if we found something, our work here is done: */
- if (src != AG_SETTING_SOURCE_NONE)
- {
- gchar *uid = g_value_dup_string (&value);
- g_value_unset (&value);
- return uid;
- }
-
- if (!create)
- {
- g_value_unset (&value);
- return NULL;
- }
-
- DEBUG ("no " MC_IDENTITY_KEY " found, synthesising one:");
-
- src = _ag_account_global_value (account, AG_ACCOUNT_KEY, &value);
-
- /* fall back to the alernative account-naming setting if necessary: */
- if (src == AG_SETTING_SOURCE_NONE)
- {
- _ag_account_select_default_im_service (sso, account);
- src = _ag_account_local_value (sso, account, AG_ACCOUNT_ALT_KEY, &value);
- }
-
- if (src != AG_SETTING_SOURCE_NONE && G_VALUE_HOLDS_STRING (&value))
- {
- AgAccountSettingIter iter;
- const gchar *k;
- const GValue *v;
- GValue cmanager = G_VALUE_INIT;
- GValue protocol = G_VALUE_INIT;
- const gchar *cman, *proto;
- McpAccountManager *am = sso->manager_interface;
- GHashTable *params = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
- gchar *name = NULL;
-
- g_value_init (&cmanager, G_TYPE_STRING);
- g_value_init (&protocol, G_TYPE_STRING);
-
- /* if we weren't on a service when got here, pick the most likely one: */
- if (service == NULL)
- _ag_account_select_default_im_service (sso, account);
-
- ag_account_get_value (account, MC_CMANAGER_KEY, &cmanager);
- cman = g_value_get_string (&cmanager);
-
- if (cman == NULL)
- goto cleanup;
-
- ag_account_get_value (account, MC_PROTOCOL_KEY, &protocol);
- proto = g_value_get_string (&protocol);
-
- if (proto == NULL)
- goto cleanup;
-
- /* prepare the hash of MC param keys -> GValue */
- /* NOTE: some AG bare settings map to MC parameters, *
- * so we must iterate over all AG settings, parameters *
- * and bare settings included */
-
- /* first any matching global values: */
- ag_account_select_service (account, NULL);
- ag_account_settings_iter_init (account, &iter, NULL);
-
- while (ag_account_settings_iter_next (&iter, &k, &v))
- {
- Setting *setting = setting_data (k, SETTING_AG);
-
- if (setting != NULL && g_str_has_prefix (setting->mc_name, MCPP))
- {
- gchar *param_key = g_strdup (setting->mc_name + strlen (MCPP));
-
- g_hash_table_insert (params, param_key, (gpointer) v);
- }
-
- clear_setting_data (setting);
- }
-
- /* then any service specific settings */
- if (service != NULL)
- ag_account_select_service (account, service);
- else
- _ag_account_select_default_im_service (sso, account);
-
- ag_account_settings_iter_init (account, &iter, NULL);
- while (ag_account_settings_iter_next (&iter, &k, &v))
- {
- Setting *setting = setting_data (k, SETTING_AG);
-
- if (setting != NULL && g_str_has_prefix (setting->mc_name, MCPP))
- {
- gchar *param_key = g_strdup (setting->mc_name + strlen (MCPP));
-
- g_hash_table_insert (params, param_key, (gpointer) v);
- }
-
- clear_setting_data (setting);
- }
-
- /* we want this to override any other settings for uid generation */
- g_hash_table_insert (params, g_strdup (MC_ACCOUNT_KEY), &value);
-
- name = mcp_account_manager_get_unique_name (am, cman, proto, params);
-
- cleanup:
- ag_account_select_service (account, service);
- g_hash_table_unref (params);
- g_value_unset (&value);
- g_value_unset (&cmanager);
- g_value_unset (&protocol);
-
- DEBUG (MC_IDENTITY_KEY " value %p:%s synthesised", name, name);
- return name;
- }
- else
- {
- g_value_unset (&value);
- }
-
- DEBUG (MC_IDENTITY_KEY " not synthesised, returning NULL");
- return NULL;
-}
-
-static AgAccount *
-get_ag_account (const McdAccountManagerSso *sso,
- const McpAccountManager *am,
- const gchar *name,
- AgAccountId *id)
-{
- AgAccount *account;
-
- g_return_val_if_fail (id != NULL, NULL);
-
- /* we have a cached account, just return that */
- account = g_hash_table_lookup (sso->accounts, name);
- if (account != NULL)
- {
- *id = account->id;
- return account;
- }
-
- *id = 0;
-
- return NULL;
-}
-
-/* returns true if it actually changed an account's state */
-static gboolean
-save_setting (
- McdAccountManagerSso *self,
- AgAccount *account,
- const Setting *setting,
- const gchar *val)
-{
- gboolean changed = FALSE;
- AgService *service = ag_account_get_selected_service (account);
-
- if (!setting->writable)
- return FALSE;
-
- if (setting->global)
- ag_account_select_service (account, NULL);
- else if (service == NULL)
- _ag_account_select_default_im_service (self, account);
-
- if (setting->readable)
- {
- GValue old = G_VALUE_INIT;
- AgSettingSource src = AG_SETTING_SOURCE_NONE;
-
- g_value_init (&old, G_TYPE_STRING);
-
- if (setting->global)
- src = _ag_account_global_value (account, setting->ag_name, &old);
- else
- src = _ag_account_local_value (self, account, setting->ag_name, &old);
-
- /* unsetting an already unset value, bail out */
- if (val == NULL && src == AG_SETTING_SOURCE_NONE)
- goto done;
-
- /* assigning a value to one which _is_ set: check it actually changed */
- if (val != NULL && src != AG_SETTING_SOURCE_NONE)
- {
- gchar *str = _gvalue_to_string (&old);
- gboolean noop = g_strcmp0 (str, val) == 0;
-
- g_value_unset (&old);
- g_free (str);
-
- if (noop)
- goto done;
- }
- }
-
- /* if we got this far, we're changing the stored state: */
- changed = TRUE;
-
- if (val != NULL)
- {
- GValue value = G_VALUE_INIT;
-
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, val);
- ag_account_set_value (account, setting->ag_name, &value);
- g_value_unset (&value);
- }
- else
- {
- ag_account_set_value (account, setting->ag_name, NULL);
- }
-
- /* leave the selected service as we found it: */
- done:
- ag_account_select_service (account, service);
-
- return changed;
-}
-
-static gboolean
-_set (const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account_suffix,
- const gchar *key,
- const gchar *val)
-{
- AgAccountId id;
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
- AgAccount *account = get_ag_account (sso, am, account_suffix, &id);
- Setting *setting = NULL;
- gboolean updated = FALSE;
-
- /* can't store a setting with no name */
- g_return_val_if_fail (key != NULL, FALSE);
-
- /* we no longer create accounts in libaccount: either an account exists *
- * in libaccount as a result of some 3rd party intervention, or it is *
- * not an account that this plugin should ever concern itself with */
-
- if (account != NULL)
- setting = setting_data (key, SETTING_MC);
- else
- return FALSE;
-
- if (setting != NULL)
- {
- /* Enabled is both a global and a local value, for extra fun: */
- if (g_str_equal (setting->mc_name, MC_ENABLED_KEY))
- {
- gboolean on = g_str_equal (val, "true");
-
- DEBUG ("setting enabled flag: '%d'", on);
- updated = _sso_account_enable (sso, account, NULL, on);
- }
- else
- {
- updated = save_setting (sso, account, setting, val);
- }
-
- if (updated)
- sso->save = TRUE;
-
- clear_setting_data (setting);
- }
-
- /* whether or not we stored this value, if we got this far it's our *
- * setting and no-one else is allowed to claim it: so return TRUE */
- return TRUE;
-}
-
-/* Implements the half of the _get method where key is not NULL. */
-static void
-account_manager_sso_get_one (
- McdAccountManagerSso *sso,
- const McpAccountManager *am,
- const gchar *account_suffix,
- const gchar *key,
- AgAccount *account,
- AgService *service)
-{
- if (g_str_equal (key, MC_ENABLED_KEY))
- {
- const gchar *v = NULL;
-
- v = _sso_account_enabled (sso, account, service) ? "true" : "false";
- mcp_account_manager_set_value (am, account_suffix, key, v);
- }
- else if (g_str_equal (key, SERVICES_KEY))
- {
- GString *result = g_string_new ("");
- AgManager * agm = ag_account_get_manager (account);
- GList *services = ag_manager_list_services (agm);
- GList *item = NULL;
-
- for (item = services; item != NULL; item = g_list_next (item))
- {
- const gchar *name = ag_service_get_name (item->data);
-
- g_string_append_printf (result, "%s;", name);
- }
-
- mcp_account_manager_set_value (am, account_suffix, key, result->str);
-
- ag_service_list_free (services);
- g_string_free (result, TRUE);
- }
- else if (g_str_equal (key, MC_SERVICE_KEY))
- {
- const gchar *service_name = NULL;
- AgService *im_service = NULL;
-
- _ag_account_select_default_im_service (sso, account);
- im_service = ag_account_get_selected_service (account);
- service_name = ag_service_get_name (im_service);
- mcp_account_manager_set_value (am, account_suffix, key, service_name);
- }
- else
- {
- GValue v = G_VALUE_INIT;
- AgSettingSource src = AG_SETTING_SOURCE_NONE;
- Setting *setting = setting_data (key, SETTING_MC);
-
- if (setting == NULL)
- return;
-
- g_value_init (&v, G_TYPE_STRING);
-
- if (setting->global)
- src = _ag_account_global_value (account, setting->ag_name, &v);
- else
- src = _ag_account_local_value (sso, account, setting->ag_name, &v);
-
- if (src != AG_SETTING_SOURCE_NONE)
- {
- gchar *val = _gvalue_to_string (&v);
-
- mcp_account_manager_set_value (am, account_suffix, key, val);
-
- g_free (val);
- }
-
- if (g_str_equal (key, MCPP MC_ACCOUNT_KEY))
- _maybe_set_account_param_from_service (sso, am, account,
- account_suffix);
-
- g_value_unset (&v);
- clear_setting_data (setting);
- }
-}
-
-/* Implements the half of the _get method where key == NULL, which is an
- * instruction from MC that we should look up all of this account's properties
- * and stash them with mcp_account_manager_set_value().
- */
-static void
-account_manager_sso_get_all (
- McdAccountManagerSso *sso,
- const McpAccountManager *am,
- const gchar *account_suffix,
- AgAccount *account,
- AgService *service)
-{
- AgAccountSettingIter ag_setting;
- const gchar *k;
- const GValue *v;
- const gchar *on = NULL;
- AgService *im_service = NULL;
-
- /* pick the IM service if we haven't got one set */
- if (service == NULL)
- _ag_account_select_default_im_service (sso, account);
-
- /* special case, not stored as a normal setting */
- im_service = ag_account_get_selected_service (account);
- mcp_account_manager_set_value (am, account_suffix, MC_SERVICE_KEY,
- ag_service_get_name (im_service));
-
- ag_account_settings_iter_init (account, &ag_setting, NULL);
- while (ag_account_settings_iter_next (&ag_setting, &k, &v))
- {
- Setting *setting = setting_data (k, SETTING_AG);
-
- if (setting != NULL && setting->readable && !setting->global)
- {
- gchar *value = _gvalue_to_string (v);
-
- mcp_account_manager_set_value (am, account_suffix,
- setting->mc_name, value);
-
- g_free (value);
- }
-
- clear_setting_data (setting);
- }
-
- /* deselect any service we may have to get global settings */
- ag_account_select_service (account, NULL);
- ag_account_settings_iter_init (account, &ag_setting, NULL);
-
- while (ag_account_settings_iter_next (&ag_setting, &k, &v))
- {
- Setting *setting = setting_data (k, SETTING_AG);
-
- if (setting != NULL && setting->readable && setting->global)
- {
- gchar *value = _gvalue_to_string (v);
-
- mcp_account_manager_set_value (am, account_suffix,
- setting->mc_name, value);
-
- g_free (value);
- }
-
- clear_setting_data (setting);
- }
-
- /* special case, actually two separate but related flags in SSO */
- on = _sso_account_enabled (sso, account, NULL) ? "true" : "false";
- mcp_account_manager_set_value (am, account_suffix, MC_ENABLED_KEY, on);
-
- _maybe_set_account_param_from_service (sso, am, account, account_suffix);
-}
-
-gboolean
-_mcd_account_manager_sso_get (
- const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account_suffix,
- const gchar *key)
-{
- AgAccountId id;
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
- AgAccount *account = get_ag_account (sso, am, account_suffix, &id);
- AgService *service = ag_account_get_selected_service (account);
-
- if (account == NULL)
- return FALSE;
-
- /* Delegate to one of the two relatively-orthogonal meanings of this
- * method... */
- if (key != NULL)
- account_manager_sso_get_one (sso, am, account_suffix, key, account,
- service);
- else
- account_manager_sso_get_all (sso, am, account_suffix, account, service);
-
- /* leave the selected service as we found it */
- ag_account_select_service (account, service);
- return TRUE;
-}
-
-static gboolean
-_delete (const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account_suffix,
- const gchar *key)
-{
- AgAccountId id;
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
- AgAccount *account = get_ag_account (sso, am, account_suffix, &id);
- gboolean updated = FALSE;
-
- /* have no values for this account, nothing to do here: */
- if (account == NULL)
- return TRUE;
-
- if (key == NULL)
- {
- ag_account_delete (account);
- g_hash_table_remove (sso->accounts, account_suffix);
- g_hash_table_remove (sso->id_name_map, GUINT_TO_POINTER (id));
-
- /* stop watching for updates */
- unwatch_account_keys (sso, id);
- updated = TRUE;
- }
- else
- {
- Setting *setting = setting_data (key, SETTING_MC);
-
- if (setting != NULL)
- updated = save_setting (sso, account, setting, NULL);
-
- clear_setting_data (setting);
- }
-
- if (updated)
- sso->save = TRUE;
-
- return TRUE;
-}
-
-static gboolean
-_commit_real (gpointer user_data)
-{
- McpAccountStorage *self = MCP_ACCOUNT_STORAGE (user_data);
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
- GHashTableIter iter;
- gchar *key;
- AgAccount *account;
-
- g_hash_table_iter_init (&iter, sso->accounts);
-
- /* for each account, set its telepathy uid MC_IDENTITY_KEY in the *
- * AgAccount structure, and then flush any changes to said account *
- * to long term storage with ag_account_store() *
- * The actual changes are those pushed into the AgAccount in _set *
- * and _delete */
- while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &account))
- {
- Setting *setting = setting_data (MC_IDENTITY_KEY, SETTING_MC);
- /* this value ties MC accounts to SSO accounts */
- save_setting (sso, account, setting, key);
- ag_account_store (account, _ag_account_stored_cb, sso);
- }
-
- sso->commit_source = 0;
-
- /* any pending changes should now have been pushed, clear the save-me flag */
- sso->save = FALSE;
-
- return FALSE;
-}
-
-static gboolean
-_commit (const McpAccountStorage *self,
- const McpAccountManager *am)
-{
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
-
- if (!sso->save)
- return TRUE;
-
- if (sso->commit_source == 0)
- {
- DEBUG ("Deferring commit for %d seconds", AG_ACCOUNT_WRITE_INTERVAL);
- sso->commit_source = g_timeout_add_seconds_full (G_PRIORITY_DEFAULT,
- AG_ACCOUNT_WRITE_INTERVAL,
- _commit_real, g_object_ref (sso), g_object_unref);
- }
- else
- {
- DEBUG ("Already deferred commit");
- }
-
- return TRUE;
-}
-
-static void
-_load_from_libaccounts (McdAccountManagerSso *sso,
- const McpAccountManager *am)
-{
- GList *ag_ids = ag_manager_list_by_service_type (sso->ag_manager,
- account_manager_sso_get_service_type (sso));
- GList *ag_id;
-
- for (ag_id = ag_ids; ag_id != NULL; ag_id = g_list_next (ag_id))
- {
- const gchar *key;
- const GValue *val;
- AgAccountSettingIter iter;
- AgAccountId id = GPOINTER_TO_UINT (ag_id->data);
- AgAccount *account = ag_manager_get_account (sso->ag_manager, id);
-
- if (account != NULL)
- {
- AgService *service = ag_account_get_selected_service (account);
- gchar *name = _ag_accountid_to_mc_key (sso, id, FALSE);
-
- if (name != NULL)
- {
- AgService *im_service = NULL;
- gchar *ident = g_strdup_printf ("%u", id);
- GStrv mc_id = g_strsplit (name, "/", 3);
- gboolean enabled;
-
- /* cache the account object, and the ID->name maping: the *
- * latter is required because we might receive an async *
- * delete signal with the ID after libaccounts-glib has *
- * purged all its account data, so we couldn't rely on the *
- * MC_IDENTITY_KEY setting. */
- g_hash_table_insert (sso->accounts, name, account);
- g_hash_table_insert (sso->id_name_map, GUINT_TO_POINTER (id),
- g_strdup (name));
-
- if (service == NULL)
- _ag_account_select_default_im_service (sso, account);
-
- /* special case, not stored as a normal setting */
- im_service = ag_account_get_selected_service (account);
- mcp_account_manager_set_value (am, name, MC_SERVICE_KEY,
- ag_service_get_name (im_service));
-
- ag_account_settings_iter_init (account, &iter, NULL);
-
- while (ag_account_settings_iter_next (&iter, &key, &val))
- {
- Setting *setting = setting_data (key, SETTING_AG);
-
- if (setting != NULL && !setting->global && setting->readable)
- {
- gchar *value = _gvalue_to_string (val);
-
- mcp_account_manager_set_value (am, name, setting->mc_name,
- value);
-
- g_free (value);
- }
-
- clear_setting_data (setting);
- }
-
- ag_account_select_service (account, NULL);
- ag_account_settings_iter_init (account, &iter, NULL);
-
- while (ag_account_settings_iter_next (&iter, &key, &val))
- {
- Setting *setting = setting_data (key, SETTING_AG);
-
- if (setting != NULL && setting->global && setting->readable)
- {
- gchar *value = _gvalue_to_string (val);
-
- mcp_account_manager_set_value (am, name, setting->mc_name,
- value);
-
- g_free (value);
- }
-
- clear_setting_data (setting);
- }
-
- /* special case, actually two separate but related flags in SSO */
- enabled = _sso_account_enabled (sso, account, NULL);
-
- mcp_account_manager_set_value (am, name, MC_ENABLED_KEY,
- enabled ? "true" : "false");
- mcp_account_manager_set_value (am, name, LIBACCT_ID_KEY, ident);
- mcp_account_manager_set_value (am, name, MC_CMANAGER_KEY, mc_id[0]);
- mcp_account_manager_set_value (am, name, MC_PROTOCOL_KEY, mc_id[1]);
- mcp_account_manager_set_value (am, name, MC_IDENTITY_KEY, name);
- _maybe_set_account_param_from_service (sso, am, account, name);
-
- /* force the services value to be synthesised + cached */
- _mcd_account_manager_sso_get (MCP_ACCOUNT_STORAGE (sso), am,
- name, SERVICES_KEY);
-
- ag_account_select_service (account, service);
-
- watch_for_updates (sso, account);
-
- g_strfreev (mc_id);
- g_free (ident);
- }
- }
- }
-
- sso->loaded = TRUE;
- ag_manager_list_free (ag_ids);
-}
-
-static GList *
-_list (const McpAccountStorage *self,
- const McpAccountManager *am)
-{
- GList *rval = NULL;
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
- GList *ag_ids = NULL;
- GList *ag_id;
-
- if (!sso->loaded)
- _load_from_libaccounts (sso, am);
-
- ag_ids = ag_manager_list_by_service_type (sso->ag_manager,
- account_manager_sso_get_service_type (sso));
-
- for (ag_id = ag_ids; ag_id != NULL; ag_id = g_list_next (ag_id))
- {
- AgAccountId id = GPOINTER_TO_UINT (ag_id->data);
- gchar *name = NULL;
-
- name = _ag_accountid_to_mc_key (sso, id, FALSE);
-
- if (name != NULL)
- {
- DEBUG ("account %s listed", name);
- rval = g_list_prepend (rval, name);
- }
- else
- {
- DelayedSignalData *data = g_slice_new0 (DelayedSignalData);
-
- DEBUG ("account %u delayed", id);
- data->signal = DELAYED_CREATE;
- data->account_id = id;
- g_queue_push_tail (sso->pending_signals, data);
- }
- }
-
- ag_manager_list_free (ag_ids);
-
- return rval;
-}
-
-static void
-_ready (const McpAccountStorage *self,
- const McpAccountManager *am)
-{
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
-
- if (sso->ready)
- return;
-
- g_assert (sso->manager_interface == NULL);
- sso->manager_interface = g_object_ref (G_OBJECT (am));
- sso->ready = TRUE;
-
- while (g_queue_get_length (sso->pending_signals) > 0)
- {
- DelayedSignalData *data = g_queue_pop_head (sso->pending_signals);
- GObject *signal_source = G_OBJECT (sso->ag_manager);
-
- switch (data->signal)
- {
- case DELAYED_CREATE:
- _sso_created (signal_source, data->account_id, sso);
- break;
- case DELAYED_DELETE:
- _sso_deleted (signal_source, data->account_id, sso);
- break;
- default:
- g_assert_not_reached ();
- }
-
- g_slice_free (DelayedSignalData, data);
- }
-
- g_queue_free (sso->pending_signals);
- sso->pending_signals = NULL;
-}
-
-static gboolean
-_find_account (McdAccountManagerSso *sso,
- const gchar *account_name,
- AgAccountId *account_id)
-{
- GList *ag_ids = NULL;
- GList *ag_id;
- gboolean found = FALSE;
-
- g_return_val_if_fail (account_id != NULL, found);
-
- ag_ids = ag_manager_list_by_service_type (sso->ag_manager,
- account_manager_sso_get_service_type (sso));
-
- for (ag_id = ag_ids; ag_id != NULL; ag_id = g_list_next (ag_id))
- {
- AgAccountId id = GPOINTER_TO_UINT (ag_id->data);
- gchar *name = NULL;
-
- name = _ag_accountid_to_mc_key (sso, id, FALSE);
-
- if (g_strcmp0 (name, account_name) == 0)
- {
- found = TRUE;
- *account_id = id;
- }
-
- g_free (name);
-
- if (found)
- break;
- }
-
- ag_manager_list_free (ag_ids);
-
- return found;
-}
-
-static void
-_get_identifier (const McpAccountStorage *self,
- const gchar *account,
- GValue *identifier)
-{
- AgAccountId account_id = 0;
-
- if (!_find_account (MCD_ACCOUNT_MANAGER_SSO (self), account, &account_id))
- g_warning ("Didn't find account %s in %s", account, PLUGIN_NAME);
-
- g_value_init (identifier, G_TYPE_UINT);
-
- g_value_set_uint (identifier, account_id);
-}
-
-static GHashTable *
-_get_additional_info (const McpAccountStorage *self,
- const gchar *account_suffix)
-{
- AgAccountId account_id = 0;
- McdAccountManagerSso *sso = MCD_ACCOUNT_MANAGER_SSO (self);
- GHashTable *additional_info = NULL;
- AgAccount *account;
- AgService *service;
- AgAccountSettingIter iter;
- const GValue *val;
- const gchar *key;
-
- if (!_find_account (sso, account_suffix, &account_id))
- {
- g_warning ("Didn't find account %s in %s", account_suffix, PLUGIN_NAME);
- return NULL;
- }
-
- account = ag_manager_get_account (sso->ag_manager, account_id);
-
- g_return_val_if_fail (account != NULL, NULL);
-
- service = ag_account_get_selected_service (account);
-
- additional_info = g_hash_table_new_full (g_str_hash, g_str_equal,
- (GDestroyNotify) g_free, (GDestroyNotify) tp_g_value_slice_free);
-
- if (service == NULL)
- _ag_account_select_default_im_service (sso, account);
-
- ag_account_settings_iter_init (account, &iter, NULL);
-
- while (ag_account_settings_iter_next (&iter, &key, &val))
- {
- if (tp_strv_contains (exported_settings, key))
- g_hash_table_insert (additional_info, g_strdup (key),
- tp_g_value_slice_dup (val));
- }
-
- ag_account_select_service (account, NULL);
- ag_account_settings_iter_init (account, &iter, NULL);
-
- while (ag_account_settings_iter_next (&iter, &key, &val))
- {
- if (tp_strv_contains (exported_settings, key))
- g_hash_table_insert (additional_info, g_strdup (key),
- tp_g_value_slice_dup (val));
- }
-
- ag_account_select_service (account, service);
-
- g_object_unref (account);
-
- return additional_info;
-}
-
-static void
-account_storage_iface_init (McpAccountStorageIface *iface,
- gpointer unused G_GNUC_UNUSED)
-{
- iface->name = PLUGIN_NAME;
- iface->desc = PLUGIN_DESCRIPTION;
- iface->priority = PLUGIN_PRIORITY;
- iface->provider = PLUGIN_PROVIDER;
-
- iface->get = _mcd_account_manager_sso_get;
- iface->set = _set;
- iface->delete = _delete;
- iface->commit = _commit;
- iface->list = _list;
- iface->ready = _ready;
- iface->get_identifier = _get_identifier;
- iface->get_additional_info = _get_additional_info;
-}
-
-McdAccountManagerSso *
-mcd_account_manager_sso_new (void)
-{
- return g_object_new (MCD_TYPE_ACCOUNT_MANAGER_SSO, NULL);
-}
diff --git a/src/mcd-account-manager-sso.h b/src/mcd-account-manager-sso.h
deleted file mode 100644
index 12e616f8..00000000
--- a/src/mcd-account-manager-sso.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * The SSO/libaccounts-glib manager keyfile storage pseudo-plugin
- *
- * Copyright © 2010 Nokia Corporation
- * 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
- */
-
-#include <mission-control-plugins/mission-control-plugins.h>
-#include <libaccounts-glib/ag-manager.h>
-
-#ifndef __MCD_ACCOUNT_MANAGER_SSO_H__
-#define __MCD_ACCOUNT_MANAGER_SSO_H__
-
-G_BEGIN_DECLS
-
-#define MCD_TYPE_ACCOUNT_MANAGER_SSO \
- (mcd_account_manager_sso_get_type ())
-
-#define MCD_ACCOUNT_MANAGER_SSO(o) \
- (G_TYPE_CHECK_INSTANCE_CAST ((o), MCD_TYPE_ACCOUNT_MANAGER_SSO, \
- McdAccountManagerSso))
-
-#define MCD_ACCOUNT_MANAGER_SSO_CLASS(k) \
- (G_TYPE_CHECK_CLASS_CAST((k), MCD_TYPE_ACCOUNT_MANAGER_SSO, \
- McdAccountManagerSsoClass))
-
-#define MCD_IS_ACCOUNT_MANAGER_SSO(o) \
- (G_TYPE_CHECK_INSTANCE_TYPE ((o), MCD_TYPE_ACCOUNT_MANAGER_SSO))
-
-#define MCD_IS_ACCOUNT_MANAGER_SSO_CLASS(k) \
- (G_TYPE_CHECK_CLASS_TYPE ((k), MCD_TYPE_ACCOUNT_MANAGER_SSO))
-
-#define MCD_ACCOUNT_MANAGER_SSO_GET_CLASS(o) \
- (G_TYPE_INSTANCE_GET_CLASS ((o), MCD_TYPE_ACCOUNT_MANAGER_SSO, \
- McdAccountManagerSsoClass))
-
-typedef struct {
- GObject parent;
- GHashTable *accounts;
- GHashTable *id_name_map;
- GHashTable *watches;
- GQueue *pending_signals;
- AgManager *ag_manager;
- McpAccountManager *manager_interface;
- gboolean ready;
- gboolean save;
- gboolean loaded;
- guint commit_source;
-} _McdAccountManagerSso;
-
-typedef struct {
- GObjectClass parent_class;
-
- /* In the libaccounts model, each account has a number of associated
- * 'services'; for example, you might have a Google account with Google Talk,
- * Google Mail, Google Calendar, etc. services. Each service is of a
- * particular service type; for instance, the service named "google-talk" is
- * of type "IM".
- *
- * Typically we care about the "IM" service type for Telepathy purposes; but
- * we allow for the possibility of a subclass which cares about some other
- * service type.
- */
- const gchar *service_type;
-} _McdAccountManagerSsoClass;
-
-typedef _McdAccountManagerSso McdAccountManagerSso;
-typedef _McdAccountManagerSsoClass McdAccountManagerSsoClass;
-
-GType mcd_account_manager_sso_get_type (void) G_GNUC_CONST;
-
-McdAccountManagerSso *mcd_account_manager_sso_new (void);
-
-/* FIXME: we shouldn't need to expose this. Subclasses should be able to chain
- * up to the parent class's implementation of the interface method, but they
- * can't because McpAccountStorageIface isn't exposed. See
- * <https://bugs.freedesktop.org//show_bug.cgi?id=32914>.
- */
-gboolean _mcd_account_manager_sso_get (
- const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account_suffix,
- const gchar *key);
-
-G_END_DECLS
-
-#endif
diff --git a/src/mcd-account-manager.c b/src/mcd-account-manager.c
index 8584308d..ec06908d 100644
--- a/src/mcd-account-manager.c
+++ b/src/mcd-account-manager.c
@@ -49,8 +49,6 @@
#include "mission-control-plugins/implementation.h"
#include "plugin-loader.h"
-#include "_gen/interfaces.h"
-
#define PARAM_PREFIX "param-"
#define WRITE_CONF_DELAY 500
@@ -59,24 +57,17 @@
static void account_manager_iface_init (TpSvcAccountManagerClass *iface,
gpointer iface_data);
-static void account_manager_hidden_iface_init (
- McSvcAccountManagerInterfaceHiddenClass *iface,
- gpointer iface_data);
static void properties_iface_init (TpSvcDBusPropertiesClass *iface,
gpointer iface_data);
static void _mcd_account_manager_constructed (GObject *obj);
static const McdDBusProp account_manager_properties[];
-static const McdDBusProp account_manager_hidden_properties[];
static const McdInterfaceData account_manager_interfaces[] = {
MCD_IMPLEMENT_IFACE (tp_svc_account_manager_get_type,
account_manager,
TP_IFACE_ACCOUNT_MANAGER),
- MCD_IMPLEMENT_IFACE (mc_svc_account_manager_interface_hidden_get_type,
- account_manager_hidden,
- MC_IFACE_ACCOUNT_MANAGER_INTERFACE_HIDDEN),
{ NULL, }
};
@@ -99,6 +90,8 @@ struct _McdAccountManagerPrivate
gchar *account_connections_file; /* in account_connections_dir */
gboolean dbus_registered;
+ /* 1 per thing we need to do before we can take the AccountManager name */
+ gint setup_lock;
};
typedef struct
@@ -107,11 +100,16 @@ typedef struct
McpAccountStorage *storage_plugin;
McdAccount *account;
gint account_lock;
+ gboolean holds_setup_lock;
} McdLoadAccountsData;
typedef struct
{
McdAccountManager *account_manager;
+ gchar *cm_name;
+ gchar *protocol_name;
+ gchar *display_name;
+ gchar *provider;
GHashTable *parameters;
GHashTable *properties;
McdGetAccountCb callback;
@@ -135,80 +133,18 @@ enum
PROP_CLIENT_FACTORY
};
-static guint write_conf_id = 0;
-
static void register_dbus_service (McdAccountManager *account_manager);
+static void release_setup_lock (McdAccountManager *account_manager);
+static void setup_account_loaded (McdAccount *account,
+ const GError *error,
+ gpointer user_data);
static void release_load_accounts_lock (McdLoadAccountsData *lad);
static void add_account (McdAccountManager *manager, McdAccount *account,
const gchar *source);
-static void account_loaded (McdAccount *account,
- const GError *error,
- gpointer user_data);
-
-/* calback chain for asynchronously updates from backends: */
-static void
-async_altered_validity_cb (McdAccount *account, const GError *invalid_reason, gpointer data)
-{
- DEBUG ("asynchronously altered account %s is %svalid",
- mcd_account_get_unique_name (account), (invalid_reason == NULL) ? "" : "in");
-
- g_object_unref (account);
-}
-
-static void
-async_altered_manager_cb (McdManager *cm, const GError *error, gpointer data)
-{
- McdAccount *account = data;
- const gchar *name = NULL;
-
- if (cm != NULL)
- name = mcd_manager_get_name (cm);
-
- if (error != NULL)
- DEBUG ("manager %s not ready: %s", name, error->message);
- else
- DEBUG ("manager %s is ready", name);
-
- /* this triggers the final parameter check which results in dbus signals *
- * being fired and (potentially) the account going online automatically */
- mcd_account_check_validity (account, async_altered_validity_cb, NULL);
-
- g_object_unref (cm);
-}
-
-/* account has been updated by a third party, and the McpAccountStorage *
- * plugin has just informed us of this fact */
-static void
-altered_cb (GObject *storage, const gchar *name, gpointer data)
-{
- McdAccountManager *am = MCD_ACCOUNT_MANAGER (data);
- McdMaster *master = mcd_master_get_default ();
- McdAccount *account = NULL;
- McdManager *cm = NULL;
- const gchar *cm_name = NULL;
-
- account = mcd_account_manager_lookup_account (am, name);
-
- if (G_UNLIKELY (!account))
- {
- g_warning ("%s: account %s does not exist", G_STRFUNC, name);
- return;
- }
-
- /* in theory, the CM is already ready by this point, but make sure: */
- cm_name = mcd_account_get_manager_name (account);
-
- if (cm_name != NULL)
- cm = _mcd_master_lookup_manager (master, cm_name);
-
- if (cm != NULL)
- {
- g_object_ref (cm);
- g_object_ref (account);
- mcd_manager_call_when_ready (cm, async_altered_manager_cb, account);
- }
-}
+static void async_account_loaded (McdAccount *account,
+ const GError *error,
+ gpointer user_data);
static void
async_altered_one_manager_cb (McdManager *cm,
@@ -238,7 +174,8 @@ async_altered_one_manager_cb (McdManager *cm,
static void
-altered_one_cb (GObject *storage,
+altered_one_cb (McdStorage *storage,
+ McpAccountStorage *plugin,
const gchar *account_name,
const gchar *key,
gpointer data)
@@ -275,17 +212,6 @@ altered_one_cb (GObject *storage,
}
}
-/* callbacks for the various stages in an backend-driven account creation */
-static void
-async_created_validity_cb (McdAccount *account, const GError *invalid_reason, gpointer data)
-{
- DEBUG ("asynchronously created account %s is %svalid",
- mcd_account_get_unique_name (account), (invalid_reason == NULL) ? "" : "in");
-
- /* safely cached in the accounts hash by now */
- g_object_unref (account);
-}
-
static void
async_created_manager_cb (McdManager *cm, const GError *error, gpointer data)
{
@@ -294,6 +220,12 @@ async_created_manager_cb (McdManager *cm, const GError *error, gpointer data)
McdAccountManager *am = lad->account_manager;
McpAccountStorage *plugin = lad->storage_plugin;
const gchar *name = NULL;
+ gboolean ok;
+
+ g_assert (lad->account_lock > 0);
+ g_assert (MCD_IS_ACCOUNT (lad->account));
+ g_assert (MCD_IS_ACCOUNT_MANAGER (lad->account_manager));
+ g_assert (MCP_IS_ACCOUNT_STORAGE (lad->storage_plugin));
if (cm != NULL)
name = mcd_manager_get_name (cm);
@@ -307,13 +239,19 @@ async_created_manager_cb (McdManager *cm, const GError *error, gpointer data)
add_account (am, account, mcp_account_storage_name (plugin));
/* this will free the McdLoadAccountsData, don't use it after this */
- _mcd_account_load (account, account_loaded, lad);
+ _mcd_account_load (account, async_account_loaded, lad);
/* this triggers the final parameter check which results in dbus signals *
* being fired and (potentially) the account going online automatically */
- mcd_account_check_validity (account, async_created_validity_cb, NULL);
+ ok = mcd_account_check_validity (account, NULL);
+ DEBUG ("asynchronously created account %s is %svalid",
+ mcd_account_get_unique_name (account),
+ ok ? "" : "in");
g_object_unref (cm);
+
+ /* safely cached in the accounts hash by now */
+ g_object_unref (account);
}
/* account created by an McpAccountStorage plugin after the initial setup *
@@ -321,40 +259,35 @@ async_created_manager_cb (McdManager *cm, const GError *error, gpointer data)
* to fetch the named account explicitly at this point (ie it's a read, not *
* not a write, from the plugin's POV: */
static void
-created_cb (GObject *storage_plugin_obj,
+created_cb (McdStorage *storage,
+ GObject *storage_plugin_obj,
const gchar *name,
gpointer data)
{
McpAccountStorage *plugin = MCP_ACCOUNT_STORAGE (storage_plugin_obj);
McdAccountManager *am = MCD_ACCOUNT_MANAGER (data);
McdAccountManagerPrivate *priv = MCD_ACCOUNT_MANAGER_PRIV (am);
- McdLoadAccountsData *lad = g_slice_new (McdLoadAccountsData);
+ McdLoadAccountsData *lad = NULL;
McdAccount *account = NULL;
- McdStorage *storage = priv->storage;
McdMaster *master = mcd_master_get_default ();
McdManager *cm = NULL;
const gchar *cm_name = NULL;
- lad->account_manager = am;
- lad->storage_plugin = plugin;
- lad->account_lock = 1; /* will be released at the end of this function */
+ g_return_if_fail (storage == priv->storage);
- /* actually fetch the data into our cache from the plugin: */
- if (mcd_storage_add_account_from_plugin (storage, plugin, name))
- {
- account = mcd_account_new (am, name, priv->minotaur);
- lad->account = account;
- }
- else
- {
- /* that function already warned about it */
- goto finish;
- }
+ account = mcd_account_new (am, name, priv->minotaur, plugin);
+ g_assert (MCD_IS_ACCOUNT (account));
- if (G_UNLIKELY (!account))
+ lad = g_slice_new0 (McdLoadAccountsData);
+ lad->account_manager = g_object_ref (am);
+ lad->storage_plugin = g_object_ref (plugin);
+ lad->account_lock = 1; /* released at the end of this function */
+ lad->account = g_object_ref (account);
+
+ if (am->priv->setup_lock > 0)
{
- g_warning ("%s: account %s failed to instantiate", G_STRFUNC, name);
- goto finish;
+ lad->holds_setup_lock = TRUE;
+ am->priv->setup_lock++;
}
cm_name = mcd_account_get_manager_name (account);
@@ -376,12 +309,15 @@ created_cb (GObject *storage_plugin_obj,
g_object_unref (account);
}
-finish:
release_load_accounts_lock (lad);
}
static void
-toggled_cb (GObject *plugin, const gchar *name, gboolean on, gpointer data)
+toggled_cb (McdStorage *storage,
+ GObject *plugin,
+ const gchar *name,
+ gboolean on,
+ gpointer data)
{
McpAccountStorage *storage_plugin = MCP_ACCOUNT_STORAGE (plugin);
McdAccountManager *manager = MCD_ACCOUNT_MANAGER (data);
@@ -401,7 +337,7 @@ toggled_cb (GObject *plugin, const gchar *name, gboolean on, gpointer data)
}
_mcd_account_set_enabled (account, on, FALSE,
- MCD_DBUS_PROP_SET_FLAG_NONE, &error);
+ MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE, &error);
if (error != NULL)
{
@@ -411,7 +347,10 @@ toggled_cb (GObject *plugin, const gchar *name, gboolean on, gpointer data)
}
static void
-reconnect_cb (GObject *plugin, const gchar *name, gpointer data)
+reconnect_cb (McdStorage *storage,
+ GObject *plugin,
+ const gchar *name,
+ gpointer data)
{
McpAccountStorage *storage_plugin = MCP_ACCOUNT_STORAGE (plugin);
McdAccountManager *manager = MCD_ACCOUNT_MANAGER (data);
@@ -435,16 +374,35 @@ reconnect_cb (GObject *plugin, const gchar *name, gpointer data)
}
static void
-_mcd_account_delete_cb (McdAccount *account, const GError *error, gpointer data)
+mcd_account_delete_debug_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
{
- /* no need to do anything other than release the account ref, which *
- * should be the last ref we hold by the time this rolls arouns: */
- g_object_unref (account);
+ McdAccount *account = MCD_ACCOUNT (source);
+ GError *error = NULL;
+
+ if (mcd_account_delete_finish (account, res, &error))
+ {
+ DEBUG ("successfully deleted account %s (%s)",
+ mcd_account_get_unique_name (account),
+ (const gchar *) user_data);
+ }
+ else
+ {
+ WARNING ("could not delete account %s (%s): %s #%d: %s",
+ mcd_account_get_unique_name (account),
+ (const gchar *) user_data,
+ g_quark_to_string (error->domain), error->code, error->message);
+ g_clear_error (&error);
+ }
}
/* a backend plugin notified us that an account was vaporised: remove it */
static void
-deleted_cb (GObject *plugin, const gchar *name, gpointer data)
+deleted_cb (McdStorage *storage,
+ GObject *plugin,
+ const gchar *name,
+ gpointer data)
{
McpAccountStorage *storage_plugin = MCP_ACCOUNT_STORAGE (plugin);
McdAccountManager *manager = MCD_ACCOUNT_MANAGER (data);
@@ -463,7 +421,11 @@ deleted_cb (GObject *plugin, const gchar *name, gpointer data)
/* this unhooks the account's signal handlers */
g_hash_table_remove (manager->priv->accounts, name);
tp_svc_account_manager_emit_account_removed (manager, object_path);
- mcd_account_delete (account, _mcd_account_delete_cb, NULL);
+ mcd_account_delete_async (account,
+ MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE,
+ mcd_account_delete_debug_cb,
+ "in response to McpAccountStorage::deleted");
+ g_object_unref (account);
}
}
@@ -622,45 +584,24 @@ on_account_validity_changed (McdAccount *account, gboolean valid,
object_path = mcd_account_get_object_path (account);
- if (_mcd_account_is_hidden (account))
- {
- mc_svc_account_manager_interface_hidden_emit_hidden_account_validity_changed (
- account_manager, object_path, valid);
- }
- else
- {
- tp_svc_account_manager_emit_account_validity_changed (account_manager,
- object_path,
- valid);
- }
+ tp_svc_account_manager_emit_account_validity_changed (account_manager,
+ object_path,
+ valid);
}
static void
on_account_removed (McdAccount *account, McdAccountManager *account_manager)
{
McdAccountManagerPrivate *priv = account_manager->priv;
- McdStorage *storage = priv->storage;
const gchar *name, *object_path;
object_path = mcd_account_get_object_path (account);
- if (_mcd_account_is_hidden (account))
- {
- mc_svc_account_manager_interface_hidden_emit_hidden_account_removed (
- account_manager, object_path);
- }
- else
- {
- tp_svc_account_manager_emit_account_removed (account_manager,
- object_path);
- }
+ tp_svc_account_manager_emit_account_removed (account_manager,
+ object_path);
name = mcd_account_get_unique_name (account);
g_hash_table_remove (priv->accounts, name);
-
- mcd_storage_delete_account (storage, name);
- mcd_account_manager_write_conf_async (account_manager, account, NULL,
- NULL);
}
static inline void
@@ -737,6 +678,14 @@ mcd_create_account_data_free (McdCreateAccountData *cad)
if (G_UNLIKELY (cad->error))
g_error_free (cad->error);
+ if (cad->destroy != NULL)
+ cad->destroy (cad->user_data);
+
+ g_free (cad->provider);
+ g_free (cad->cm_name);
+ g_free (cad->protocol_name);
+ g_free (cad->display_name);
+
g_slice_free (McdCreateAccountData, cad);
}
@@ -783,12 +732,18 @@ complete_account_creation_finish (McdAccount *account,
if (!cad->ok)
{
- mcd_account_delete (account, NULL, NULL);
+ mcd_account_delete_async (account,
+ MCD_DBUS_PROP_SET_FLAG_NONE,
+ mcd_account_delete_debug_cb,
+ "while recovering from failure to create");
tp_clear_object (&account);
}
- mcd_account_manager_write_conf_async (account_manager, account, NULL,
- NULL);
+ if (account != NULL)
+ {
+ mcd_storage_commit (account_manager->priv->storage,
+ mcd_account_get_unique_name (account));
+ }
if (cad->callback != NULL)
cad->callback (account_manager, account, cad->error, cad->user_data);
@@ -798,23 +753,6 @@ complete_account_creation_finish (McdAccount *account,
}
static void
-complete_account_creation_check_validity_cb (McdAccount *account,
- const GError *invalid_reason,
- gpointer user_data)
-{
- McdCreateAccountData *cad = user_data;
-
- if (invalid_reason != NULL)
- {
- cad->ok = FALSE;
- g_set_error_literal (&cad->error, invalid_reason->domain,
- invalid_reason->code, invalid_reason->message);
- }
-
- complete_account_creation_finish (account, cad);
-}
-
-static void
complete_account_creation_set_cb (McdAccount *account, GPtrArray *not_yet,
const GError *set_error, gpointer user_data)
{
@@ -839,12 +777,12 @@ complete_account_creation_set_cb (McdAccount *account, GPtrArray *not_yet,
if (cad->ok)
{
add_account (account_manager, account, G_STRFUNC);
- mcd_account_check_validity (account, complete_account_creation_check_validity_cb, cad);
- }
- else
- {
- complete_account_creation_finish (account, cad);
+
+ if (!mcd_account_check_validity (account, &cad->error))
+ cad->ok = FALSE;
}
+
+ complete_account_creation_finish (account, cad);
}
static void
@@ -868,85 +806,134 @@ complete_account_creation (McdAccount *account,
cad);
}
-void
-_mcd_account_manager_create_account (McdAccountManager *account_manager,
- const gchar *manager,
- const gchar *protocol,
- const gchar *display_name,
- GHashTable *params,
- GHashTable *properties,
- McdGetAccountCb callback,
- gpointer user_data,
- GDestroyNotify destroy)
+static void
+identify_account_cb (GObject *source_object,
+ GAsyncResult *result,
+ gpointer user_data)
{
- McdAccountManagerPrivate *priv = account_manager->priv;
- McdStorage *storage = priv->storage;
- McdCreateAccountData *cad;
+ McdStorage *storage = MCD_STORAGE (source_object);
+ McdCreateAccountData *cad = user_data;
+ gchar *id;
+ gchar *unique_name;
McdAccount *account;
- gchar *unique_name = NULL;
- const gchar *provider;
- GError *e = NULL;
+ McpAccountStorage *plugin;
- DEBUG ("called");
- if (G_UNLIKELY (manager == NULL || manager[0] == 0 ||
- protocol == NULL || protocol[0] == 0))
+ id = mcp_account_manager_identify_account_finish (
+ MCP_ACCOUNT_MANAGER (storage), result, &cad->error);
+
+ if (id == NULL)
{
- GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Invalid parameters"};
- callback (account_manager, NULL, &error, user_data);
- if (destroy)
- destroy (user_data);
+ cad->callback (cad->account_manager, NULL, cad->error, cad->user_data);
+ mcd_create_account_data_free (cad);
return;
}
- provider = tp_asv_get_string (properties,
- TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER);
-
- unique_name = mcd_storage_create_account (storage, provider,
- manager, protocol, params,
- &e);
+ unique_name = mcd_storage_create_account (storage, cad->provider,
+ cad->cm_name, cad->protocol_name,
+ id, &plugin, &cad->error);
if (unique_name == NULL)
{
- callback (account_manager, NULL, e, user_data);
- g_clear_error (&e);
- if (destroy)
- destroy (user_data);
+ g_free (id);
+ cad->callback (cad->account_manager, NULL, cad->error, cad->user_data);
+ mcd_create_account_data_free (cad);
return;
}
/* create the basic account keys */
mcd_storage_set_string (storage, unique_name,
- MC_ACCOUNTS_KEY_MANAGER, manager);
+ MC_ACCOUNTS_KEY_MANAGER, cad->cm_name);
mcd_storage_set_string (storage, unique_name,
- MC_ACCOUNTS_KEY_PROTOCOL, protocol);
+ MC_ACCOUNTS_KEY_PROTOCOL, cad->protocol_name);
+ g_free (id);
- if (display_name != NULL)
+ if (cad->display_name != NULL)
mcd_storage_set_string (storage, unique_name,
- MC_ACCOUNTS_KEY_DISPLAY_NAME, display_name);
+ MC_ACCOUNTS_KEY_DISPLAY_NAME,
+ cad->display_name);
- account = mcd_account_new (account_manager, unique_name, priv->minotaur);
+ account = mcd_account_new (cad->account_manager, unique_name,
+ cad->account_manager->priv->minotaur,
+ plugin);
g_free (unique_name);
+ g_object_unref (plugin);
if (G_LIKELY (account))
{
- cad = g_slice_new (McdCreateAccountData);
- cad->account_manager = account_manager;
- cad->parameters = g_hash_table_ref (params);
- cad->properties = (properties ? g_hash_table_ref (properties) : NULL);
- cad->callback = callback;
- cad->user_data = user_data;
- cad->destroy = destroy;
- cad->error = NULL;
_mcd_account_load (account, complete_account_creation, cad);
}
else
{
GError error = { TP_ERROR, TP_ERROR_NOT_AVAILABLE, "" };
+ cad->callback (cad->account_manager, NULL, &error, cad->user_data);
+ mcd_create_account_data_free (cad);
+ }
+}
+
+void
+_mcd_account_manager_create_account (McdAccountManager *account_manager,
+ const gchar *manager,
+ const gchar *protocol,
+ const gchar *display_name,
+ GHashTable *params,
+ GHashTable *properties,
+ McdGetAccountCb callback,
+ gpointer user_data,
+ GDestroyNotify destroy)
+{
+ McdAccountManagerPrivate *priv = account_manager->priv;
+ McdStorage *storage = priv->storage;
+ McdCreateAccountData *cad;
+ GValue value = G_VALUE_INIT;
+ GVariant *variant_params;
+
+ DEBUG ("called");
+ if (G_UNLIKELY (manager == NULL || manager[0] == 0 ||
+ protocol == NULL || protocol[0] == 0))
+ {
+ GError error = { TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "Invalid parameters"};
callback (account_manager, NULL, &error, user_data);
if (destroy)
destroy (user_data);
+ return;
}
+
+ cad = g_slice_new0 (McdCreateAccountData);
+ cad->account_manager = account_manager;
+ cad->cm_name = g_strdup (manager);
+ cad->protocol_name = g_strdup (protocol);
+ cad->display_name = g_strdup (display_name);
+ cad->parameters = g_hash_table_ref (params);
+ cad->callback = callback;
+ cad->user_data = user_data;
+ cad->destroy = destroy;
+ cad->error = NULL;
+
+ if (properties != NULL)
+ {
+ cad->properties = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) tp_g_value_slice_free);
+
+ tp_g_hash_table_update (cad->properties, properties,
+ (GBoxedCopyFunc) g_strdup,
+ (GBoxedCopyFunc) tp_g_value_slice_dup);
+
+ /* special case: "construct-only" */
+ cad->provider = g_strdup (tp_asv_get_string (cad->properties,
+ TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER));
+ g_hash_table_remove (cad->properties,
+ TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER);
+ }
+
+ g_value_init (&value, TP_HASH_TYPE_STRING_VARIANT_MAP);
+ g_value_set_static_boxed (&value, params);
+ variant_params = dbus_g_value_build_g_variant (&value);
+ g_value_unset (&value);
+
+ mcp_account_manager_identify_account_async (MCP_ACCOUNT_MANAGER (storage),
+ manager, protocol, variant_params, NULL, identify_account_cb, cad);
+ g_variant_unref (variant_params);
}
static void
@@ -993,15 +980,7 @@ account_manager_iface_init (TpSvcAccountManagerClass *iface,
}
static void
-account_manager_hidden_iface_init (
- McSvcAccountManagerInterfaceHiddenClass *iface,
- gpointer iface_data)
-{
-}
-
-static void
-accounts_to_gvalue (GHashTable *accounts, gboolean valid, gboolean hidden,
- GValue *value)
+accounts_to_gvalue (GHashTable *accounts, gboolean valid, GValue *value)
{
static GType ao_type = G_TYPE_INVALID;
GPtrArray *account_array;
@@ -1019,8 +998,7 @@ accounts_to_gvalue (GHashTable *accounts, gboolean valid, gboolean hidden,
while (g_hash_table_iter_next (&iter, &k, (gpointer)&account))
{
- if (mcd_account_is_valid (account) == valid &&
- _mcd_account_is_hidden (account) == hidden)
+ if (mcd_account_is_valid (account) == valid)
{
g_ptr_array_add (account_array,
g_strdup (mcd_account_get_object_path (account)));
@@ -1039,7 +1017,7 @@ get_valid_accounts (TpSvcDBusProperties *self, const gchar *name,
McdAccountManagerPrivate *priv = account_manager->priv;
DEBUG ("called");
- accounts_to_gvalue (priv->accounts, TRUE, FALSE, value);
+ accounts_to_gvalue (priv->accounts, TRUE, value);
}
static void
@@ -1050,7 +1028,7 @@ get_invalid_accounts (TpSvcDBusProperties *self, const gchar *name,
McdAccountManagerPrivate *priv = account_manager->priv;
DEBUG ("called");
- accounts_to_gvalue (priv->accounts, FALSE, FALSE, value);
+ accounts_to_gvalue (priv->accounts, FALSE, value);
}
static void
@@ -1068,9 +1046,7 @@ get_supported_account_properties (TpSvcDBusProperties *svc,
TP_IFACE_ACCOUNT ".Supersedes",
TP_PROP_ACCOUNT_SERVICE,
TP_IFACE_ACCOUNT_INTERFACE_AVATAR ".Avatar",
- MC_IFACE_ACCOUNT_INTERFACE_CONDITIONS ".Condition",
TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER,
- MC_IFACE_ACCOUNT_INTERFACE_HIDDEN ".Hidden",
NULL
};
@@ -1087,32 +1063,6 @@ static const McdDBusProp account_manager_properties[] = {
};
static void
-get_valid_hidden_accounts (TpSvcDBusProperties *self, const gchar *name,
- GValue *value)
-{
- McdAccountManager *account_manager = MCD_ACCOUNT_MANAGER (self);
- McdAccountManagerPrivate *priv = account_manager->priv;
-
- accounts_to_gvalue (priv->accounts, TRUE, TRUE, value);
-}
-
-static void
-get_invalid_hidden_accounts (TpSvcDBusProperties *self, const gchar *name,
- GValue *value)
-{
- McdAccountManager *account_manager = MCD_ACCOUNT_MANAGER (self);
- McdAccountManagerPrivate *priv = account_manager->priv;
-
- accounts_to_gvalue (priv->accounts, FALSE, TRUE, value);
-}
-
-static const McdDBusProp account_manager_hidden_properties[] = {
- { "ValidHiddenAccounts", NULL, get_valid_hidden_accounts },
- { "InvalidHiddenAccounts", NULL, get_invalid_hidden_accounts },
- { 0 },
-};
-
-static void
properties_iface_init (TpSvcDBusPropertiesClass *iface, gpointer iface_data)
{
#define IMPLEMENT(x) tp_svc_dbus_properties_implement_##x (\
@@ -1123,18 +1073,17 @@ properties_iface_init (TpSvcDBusPropertiesClass *iface, gpointer iface_data)
#undef IMPLEMENT
}
-static gboolean
-write_conf (gpointer userdata)
+static void
+release_setup_lock (McdAccountManager *self)
{
- McdStorage *storage = MCD_STORAGE (userdata);
+ g_return_if_fail (self->priv->setup_lock > 0);
+ self->priv->setup_lock--;
+ DEBUG ("called, count is now %d", self->priv->setup_lock);
- DEBUG ("called");
- g_source_remove (write_conf_id);
- write_conf_id = 0;
-
- mcd_storage_commit (storage, NULL);
-
- return TRUE;
+ if (self->priv->setup_lock == 0)
+ {
+ register_dbus_service (self);
+ }
}
static void
@@ -1146,13 +1095,21 @@ release_load_accounts_lock (McdLoadAccountsData *lad)
if (lad->account_lock == 0)
{
- register_dbus_service (lad->account_manager);
+ if (lad->holds_setup_lock)
+ release_setup_lock (lad->account_manager);
+
+ g_object_unref (lad->account_manager);
+ g_object_unref (lad->storage_plugin);
+ g_object_unref (lad->account);
+
g_slice_free (McdLoadAccountsData, lad);
}
}
static void
-account_loaded (McdAccount *account, const GError *error, gpointer user_data)
+async_account_loaded (McdAccount *account,
+ const GError *error,
+ gpointer user_data)
{
McdLoadAccountsData *lad = user_data;
@@ -1167,54 +1124,61 @@ account_loaded (McdAccount *account, const GError *error, gpointer user_data)
}
static void
-uncork_storage_plugins (McdAccountManager *account_manager)
+setup_account_loaded (McdAccount *account,
+ const GError *error,
+ gpointer user_data)
{
- McdAccountManagerPrivate *priv = MCD_ACCOUNT_MANAGER_PRIV (account_manager);
+ McdAccountManager *self = MCD_ACCOUNT_MANAGER (user_data);
- mcd_account_manager_write_conf_async (account_manager, NULL, NULL, NULL);
- mcd_storage_ready (priv->storage);
+ if (error)
+ {
+ g_warning ("%s: got error: %s", G_STRFUNC, error->message);
+ g_hash_table_remove (self->priv->accounts,
+ mcd_account_get_unique_name (account));
+ }
+
+ release_setup_lock (self);
+ g_object_unref (self);
}
typedef struct
{
McdAccountManager *self;
McdAccount *account;
- McdLoadAccountsData *lad;
} MigrateCtx;
static MigrateCtx *
migrate_ctx_new (McdAccountManager *self,
- McdAccount *account,
- McdLoadAccountsData *lad)
+ McdAccount *account)
{
MigrateCtx *ctx = g_slice_new (MigrateCtx);
ctx->self = g_object_ref (self);
ctx->account = g_object_ref (account);
- ctx->lad = lad;
/* Lock attempting to migrate the account */
- lad->account_lock++;
+ self->priv->setup_lock++;
return ctx;
}
static void
migrate_ctx_free (MigrateCtx *ctx)
{
+ release_setup_lock (ctx->self);
g_object_unref (ctx->self);
g_object_unref (ctx->account);
- release_load_accounts_lock (ctx->lad);
g_slice_free (MigrateCtx, ctx);
}
static void
-migrate_delete_account_cb (McdAccount *account,
- const GError *error,
- gpointer user_data)
+migrate_delete_account_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
{
MigrateCtx *ctx = user_data;
+ mcd_account_delete_debug_cb (source, res, "after migrating it");
migrate_ctx_free (ctx);
}
@@ -1238,7 +1202,8 @@ migrate_create_account_cb (McdAccountManager *account_manager,
DEBUG ("Account %s migrated, removing it",
mcd_account_get_unique_name (ctx->account));
- mcd_account_delete (ctx->account, migrate_delete_account_cb, ctx);
+ mcd_account_delete_async (ctx->account, MCD_DBUS_PROP_SET_FLAG_NONE,
+ migrate_delete_account_cb, ctx);
}
static void
@@ -1265,7 +1230,9 @@ migrate_butterfly_haze_ready (McdManager *manager,
/* Parameters; the only mandatory one is 'account' */
if (!mcd_account_get_parameter_of_known_type (ctx->account,
- "account", G_TYPE_STRING,
+ "account",
+ G_VARIANT_TYPE_STRING,
+ G_TYPE_STRING,
&v, NULL))
{
_mcd_account_set_enabled (ctx->account, FALSE, TRUE,
@@ -1279,7 +1246,9 @@ migrate_butterfly_haze_ready (McdManager *manager,
/* If MC is storing the password, let's copy that too, so Empathy
* can migrate it somewhere better. */
if (mcd_account_get_parameter_of_known_type (ctx->account,
- "password", G_TYPE_STRING,
+ "password",
+ G_VARIANT_TYPE_STRING,
+ G_TYPE_STRING,
&password_v, NULL))
{
g_hash_table_insert (parameters, "password", &password_v);
@@ -1370,12 +1339,11 @@ error:
static void
migrate_butterfly_account (McdAccountManager *self,
- McdAccount *account,
- McdLoadAccountsData *lad)
+ McdAccount *account)
{
MigrateCtx *ctx;
- ctx = migrate_ctx_new (self, account, lad);
+ ctx = migrate_ctx_new (self, account);
_mcd_account_load (account, butterfly_account_loaded, ctx);
}
@@ -1383,8 +1351,7 @@ migrate_butterfly_account (McdAccountManager *self,
/* Migrate some specific type of account. If something went wrong during the
* migration we disable it. */
static void
-migrate_accounts (McdAccountManager *self,
- McdLoadAccountsData *lad)
+migrate_accounts (McdAccountManager *self)
{
McdAccountManagerPrivate *priv = self->priv;
GHashTableIter iter;
@@ -1402,7 +1369,7 @@ migrate_accounts (McdAccountManager *self,
continue;
if (!tp_strdiff (tp_connection_manager_get_name (cm), "butterfly"))
- migrate_butterfly_account (self, account, lad);
+ migrate_butterfly_account (self, account);
}
}
@@ -1418,42 +1385,62 @@ _mcd_account_manager_setup (McdAccountManager *account_manager)
{
McdAccountManagerPrivate *priv = account_manager->priv;
McdStorage *storage = priv->storage;
- McdLoadAccountsData *lad;
- gchar **accounts, **name;
+ GHashTable *accounts;
GHashTableIter iter;
- gpointer v;
+ gpointer k, v;
+
+ /* for simplicity we don't support re-entrant setup */
+ g_return_if_fail (priv->setup_lock == 0);
+
+ priv->setup_lock = 1; /* will be released at the end of this function */
tp_list_connection_names (priv->dbus_daemon,
list_connection_names_cb, NULL, NULL,
(GObject *)account_manager);
- lad = g_slice_new (McdLoadAccountsData);
- lad->account_manager = account_manager;
- lad->account_lock = 1; /* will be released at the end of this function */
+ accounts = mcd_storage_get_accounts (storage);
+
+ /* as soon as we've listed the initial set, connect to signals
+ * for any subsequently-added accounts */
+ g_signal_connect_object (priv->storage, "altered-one",
+ G_CALLBACK (altered_one_cb), account_manager, 0);
+ g_signal_connect_object (priv->storage, "created",
+ G_CALLBACK (created_cb), account_manager, 0);
+ g_signal_connect_object (priv->storage, "toggled",
+ G_CALLBACK (toggled_cb), account_manager, 0);
+ g_signal_connect_object (priv->storage, "deleted",
+ G_CALLBACK (deleted_cb), account_manager, 0);
+ g_signal_connect_object (priv->storage, "reconnect",
+ G_CALLBACK (reconnect_cb), account_manager, 0);
- accounts = mcd_storage_dup_accounts (storage, NULL);
+ g_hash_table_iter_init (&iter, accounts);
- for (name = accounts; *name != NULL; name++)
+ while (g_hash_table_iter_next (&iter, &k, &v))
{
gboolean plausible = FALSE;
const gchar *manager = NULL;
const gchar *protocol = NULL;
+ const gchar *account_name = k;
+ McpAccountStorage *plugin = v;
McdAccount *account = mcd_account_manager_lookup_account (
- account_manager, *name);
+ account_manager, account_name);
if (account != NULL)
{
- /* FIXME: this shouldn't really happen */
- DEBUG ("already have account %p called '%s'; skipping", account, *name);
+ /* FIXME: can't happen? We shouldn't create any accounts before
+ * we got here, and there can't be any duplicates in @accounts */
+ DEBUG ("already have account %p called '%s'; skipping",
+ account, account_name);
continue;
}
- account = mcd_account_new (account_manager, *name, priv->minotaur);
+ account = mcd_account_new (account_manager, account_name,
+ priv->minotaur, plugin);
if (G_UNLIKELY (!account))
{
g_warning ("%s: account %s failed to instantiate", G_STRFUNC,
- *name);
+ account_name);
continue;
}
@@ -1468,23 +1455,30 @@ _mcd_account_manager_setup (McdAccountManager *account_manager)
const gchar *dbg_protocol = (protocol == NULL) ? "(nil)" : protocol;
g_warning ("%s: account %s has implausible manager/protocol: %s/%s",
- G_STRFUNC, *name, dbg_manager, dbg_protocol);
+ G_STRFUNC, account_name, dbg_manager, dbg_protocol);
g_object_unref (account);
continue;
}
- lad->account_lock++;
- add_account (lad->account_manager, account, "keyfile");
- _mcd_account_load (account, account_loaded, lad);
+ priv->setup_lock++;
+ add_account (account_manager, account, "keyfile");
+ _mcd_account_load (account, setup_account_loaded,
+ g_object_ref (account_manager));
g_object_unref (account);
}
- g_strfreev (accounts);
- uncork_storage_plugins (account_manager);
+ /* FIXME: why do we need to commit the accounts at this point?
+ * It was added to uncork_storage_plugins() in 3d5b5e7a248d
+ * without explanation */
+ g_hash_table_iter_init (&iter, account_manager->priv->accounts);
+ while (g_hash_table_iter_next (&iter, &k, NULL))
+ {
+ mcd_storage_commit (storage, k);
+ }
- migrate_accounts (account_manager, lad);
+ migrate_accounts (account_manager);
- release_load_accounts_lock (lad);
+ release_setup_lock (account_manager);
g_hash_table_iter_init (&iter, account_manager->priv->accounts);
@@ -1566,12 +1560,6 @@ _mcd_account_manager_finalize (GObject *object)
{
McdAccountManagerPrivate *priv = MCD_ACCOUNT_MANAGER_PRIV (object);
- if (write_conf_id)
- {
- write_conf (priv->storage);
- g_assert (write_conf_id == 0);
- }
-
tp_clear_object (&priv->storage);
g_free (priv->account_connections_dir);
remove (priv->account_connections_file);
@@ -1655,15 +1643,6 @@ _mcd_account_manager_constructed (GObject *obj)
{
McdAccountManager *account_manager = MCD_ACCOUNT_MANAGER (obj);
McdAccountManagerPrivate *priv = account_manager->priv;
- guint i = 0;
- static struct { const gchar *name; GCallback handler; } sig[] =
- { { "created", G_CALLBACK (created_cb) },
- { "altered", G_CALLBACK (altered_cb) },
- { "toggled", G_CALLBACK (toggled_cb) },
- { "deleted", G_CALLBACK (deleted_cb) },
- { "altered-one", G_CALLBACK (altered_one_cb) },
- { "reconnect", G_CALLBACK (reconnect_cb) },
- { NULL, NULL } };
DEBUG ("");
@@ -1681,13 +1660,6 @@ _mcd_account_manager_constructed (GObject *obj)
DEBUG ("loading plugins");
mcd_storage_load (priv->storage);
- /* hook up all the storage plugin signals to their handlers: */
- for (i = 0; sig[i].name != NULL; i++)
- {
- mcd_storage_connect_signal (sig[i].name, sig[i].handler,
- account_manager);
- }
-
/* initializes the interfaces */
mcd_dbus_init_interfaces_instances (account_manager);
}
@@ -1724,63 +1696,6 @@ mcd_account_manager_get_connectivity_monitor (McdAccountManager *self)
return self->priv->minotaur;
}
-/**
- * McdAccountManagerWriteConfCb:
- * @account_manager: the #McdAccountManager
- * @error: a set #GError on failure or %NULL if there was no error
- * @user_data: user data
- *
- * The callback from mcd_account_manager_write_conf_async(). If the config
- * writing was successful, @error will be %NULL, otherwise it will be set
- * with the appropriate error.
- */
-
-/**
- * mcd_account_manager_write_conf_async:
- * @account_manager: the #McdAccountManager
- * @account: the account to be written, or %NULL to flush all accounts
- * @callback: a callback to be called on write success or failure
- * @user_data: data to be passed to @callback
- *
- * Write the account manager configuration to disk.
- */
-void
-mcd_account_manager_write_conf_async (McdAccountManager *account_manager,
- McdAccount *account,
- McdAccountManagerWriteConfCb callback,
- gpointer user_data)
-{
- McdStorage *storage = NULL;
- const gchar *account_name = NULL;
-
- g_return_if_fail (MCD_IS_ACCOUNT_MANAGER (account_manager));
-
- storage = account_manager->priv->storage;
-
- if (account != NULL)
- {
- account_name = mcd_account_get_unique_name (account);
-
- DEBUG ("updating %s", account_name);
- mcd_storage_commit (storage, account_name);
- }
- else
- {
- GStrv groups;
- gsize n_accounts = 0;
-
- groups = mcd_storage_dup_accounts (storage, &n_accounts);
- DEBUG ("updating all %" G_GSIZE_FORMAT " accounts", n_accounts);
-
- mcd_storage_commit (storage, NULL);
-
- g_strfreev (groups);
- }
-
- if (callback != NULL)
- callback (account_manager, NULL, user_data);
-}
-
GHashTable *
_mcd_account_manager_get_accounts (McdAccountManager *account_manager)
{
diff --git a/src/mcd-account-manager.h b/src/mcd-account-manager.h
index 922f4896..f33c2949 100644
--- a/src/mcd-account-manager.h
+++ b/src/mcd-account-manager.h
@@ -66,15 +66,6 @@ McdAccountManager *mcd_account_manager_new (
TpDBusDaemon *mcd_account_manager_get_dbus_daemon
(McdAccountManager *account_manager);
-typedef void (McdAccountManagerWriteConfCb) (McdAccountManager *account_manager,
- const GError *error,
- gpointer user_data);
-
-void mcd_account_manager_write_conf_async (McdAccountManager *account_manager,
- McdAccount *account,
- McdAccountManagerWriteConfCb callback,
- gpointer user_data);
-
McdAccount *mcd_account_manager_lookup_account (McdAccountManager *account_manager,
const gchar *name);
McdAccount *mcd_account_manager_lookup_account_by_path (McdAccountManager *account_manager,
diff --git a/src/mcd-account-priv.h b/src/mcd-account-priv.h
index 7225d3e5..c4991325 100644
--- a/src/mcd-account-priv.h
+++ b/src/mcd-account-priv.h
@@ -35,13 +35,6 @@
#include <telepathy-glib/proxy-subclass.h>
-/* auto-generated stubs */
-#include "_gen/svc-Account_Interface_Conditions.h"
-#include "_gen/svc-Account_Interface_External_Password_Storage.h"
-#include "_gen/svc-Account_Interface_Hidden.h"
-
-#include "_gen/cli-Connection_Manager_Interface_Account_Storage.h"
-
G_GNUC_INTERNAL void _mcd_account_maybe_autoconnect (McdAccount *account);
G_GNUC_INTERNAL void _mcd_account_connect (McdAccount *account,
GHashTable *params);
@@ -130,19 +123,6 @@ G_GNUC_INTERNAL McdChannel *_mcd_account_create_request (
gboolean use_existing,
McdRequest **request_out, GError **error);
-typedef struct _McdAccountConnectionContext McdAccountConnectionContext;
-
-G_GNUC_INTERNAL
-McdAccountConnectionContext *_mcd_account_get_connection_context
- (McdAccount *self);
-
-G_GNUC_INTERNAL
-void _mcd_account_set_connection_context (McdAccount *self,
- McdAccountConnectionContext *c);
-
-G_GNUC_INTERNAL void _mcd_account_connection_context_free
- (McdAccountConnectionContext *c);
-
typedef void (*McdAccountDupParametersCb) (McdAccount *account,
GHashTable *params,
gpointer user_data);
@@ -150,17 +130,10 @@ typedef void (*McdAccountDupParametersCb) (McdAccount *account,
G_GNUC_INTERNAL G_GNUC_WARN_UNUSED_RESULT
GHashTable *_mcd_account_dup_parameters (McdAccount *account);
-extern const McdDBusProp account_conditions_properties[];
-
-void account_conditions_iface_init (McSvcAccountInterfaceConditionsClass *iface,
- gpointer iface_data);
-
G_GNUC_INTERNAL gboolean _mcd_account_check_request_real (McdAccount *account,
GHashTable *request,
GError **error);
-G_GNUC_INTERNAL gboolean _mcd_account_get_always_on (McdAccount *self);
-
G_GNUC_INTERNAL void _mcd_account_set_changing_presence (McdAccount *self,
gboolean value);
G_GNUC_INTERNAL gboolean _mcd_account_set_enabled (McdAccount *account,
@@ -172,8 +145,6 @@ G_GNUC_INTERNAL gboolean _mcd_account_set_enabled (McdAccount *account,
G_GNUC_INTERNAL gboolean _mcd_account_presence_type_is_settable (
TpConnectionPresenceType type);
-gboolean _mcd_account_is_hidden (McdAccount *account);
-
G_GNUC_INTERNAL gboolean _mcd_account_needs_dispatch (McdAccount *account);
G_GNUC_INTERNAL void _mcd_account_reconnect (McdAccount *self,
diff --git a/src/mcd-account.c b/src/mcd-account.c
index f02c80d2..8009110e 100644
--- a/src/mcd-account.c
+++ b/src/mcd-account.c
@@ -34,7 +34,6 @@
#include <telepathy-glib/telepathy-glib-dbus.h>
#include "mcd-account-priv.h"
-#include "mcd-account-conditions.h"
#include "mcd-account-manager-priv.h"
#include "mcd-account-addressing.h"
#include "mcd-connection-priv.h"
@@ -45,11 +44,6 @@
#include "mcd-master-priv.h"
#include "mcd-dbusprop.h"
-#include "_gen/interfaces.h"
-#include "_gen/enums.h"
-#include "_gen/gtypes.h"
-#include "_gen/cli-Connection_Manager_Interface_Account_Storage-body.h"
-
#define MC_OLD_AVATAR_FILENAME "avatar.bin"
#define MCD_ACCOUNT_PRIV(account) (MCD_ACCOUNT (account)->priv)
@@ -63,40 +57,22 @@ static void account_avatar_iface_init (TpSvcAccountInterfaceAvatarClass *iface,
static void account_storage_iface_init (
TpSvcAccountInterfaceStorageClass *iface,
gpointer iface_data);
-static void account_hidden_iface_init (
- McSvcAccountInterfaceHiddenClass *iface,
- gpointer iface_data);
-static void account_external_password_storage_iface_init (
- McSvcAccountInterfaceExternalPasswordStorageClass *iface,
- gpointer iface_data);
static const McdDBusProp account_properties[];
static const McdDBusProp account_avatar_properties[];
static const McdDBusProp account_storage_properties[];
-static const McdDBusProp account_hidden_properties[];
-static const McdDBusProp account_external_password_storage_properties[];
static const McdInterfaceData account_interfaces[] = {
MCD_IMPLEMENT_IFACE (tp_svc_account_get_type, account, TP_IFACE_ACCOUNT),
MCD_IMPLEMENT_IFACE (tp_svc_account_interface_avatar_get_type,
account_avatar,
TP_IFACE_ACCOUNT_INTERFACE_AVATAR),
- MCD_IMPLEMENT_IFACE (mc_svc_account_interface_conditions_get_type,
- account_conditions,
- MC_IFACE_ACCOUNT_INTERFACE_CONDITIONS),
MCD_IMPLEMENT_IFACE (tp_svc_account_interface_storage_get_type,
account_storage,
TP_IFACE_ACCOUNT_INTERFACE_STORAGE),
MCD_IMPLEMENT_IFACE (tp_svc_account_interface_addressing_get_type,
account_addressing,
TP_IFACE_ACCOUNT_INTERFACE_ADDRESSING),
- MCD_IMPLEMENT_IFACE (mc_svc_account_interface_hidden_get_type,
- account_hidden,
- MC_IFACE_ACCOUNT_INTERFACE_HIDDEN),
- MCD_IMPLEMENT_OPTIONAL_IFACE (
- mc_svc_account_interface_external_password_storage_get_type,
- account_external_password_storage,
- MC_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE),
{ NULL, }
};
@@ -112,6 +88,11 @@ typedef struct {
gpointer user_data;
} McdOnlineRequestData;
+typedef struct {
+ GHashTable *params;
+ gboolean user_initiated;
+} McdAccountConnectionContext;
+
struct _McdAccountPrivate
{
gchar *unique_name;
@@ -170,13 +151,11 @@ struct _McdAccountPrivate
gboolean loaded;
gboolean has_been_online;
gboolean removed;
- gboolean always_on;
gboolean changing_presence;
gboolean setting_avatar;
gboolean waiting_for_initial_avatar;
gboolean waiting_for_connectivity;
- gboolean hidden;
/* In addition to affecting dispatching, this flag also makes this
* account bypass connectivity checks. */
gboolean always_dispatch;
@@ -195,9 +174,8 @@ enum
PROP_DBUS_DAEMON,
PROP_CONNECTIVITY_MONITOR,
PROP_STORAGE,
+ PROP_STORAGE_PLUGIN,
PROP_NAME,
- PROP_ALWAYS_ON,
- PROP_HIDDEN,
};
enum
@@ -207,9 +185,19 @@ enum
LAST_SIGNAL
};
+static void
+_mcd_account_connection_context_free (McdAccountConnectionContext *c)
+{
+ g_hash_table_unref (c->params);
+ g_free (c);
+}
+
static guint _mcd_account_signals[LAST_SIGNAL] = { 0 };
static GQuark account_ready_quark = 0;
+static void mcd_account_changed_property (McdAccount *account,
+ const gchar *key, const GValue *value);
+
GQuark
mcd_account_error_quark (void)
{
@@ -330,6 +318,20 @@ mcd_account_loaded (McdAccount *account)
g_return_if_fail (!account->priv->loaded);
account->priv->loaded = TRUE;
+ if (account->priv->invalid_reason == NULL)
+ {
+ DEBUG ("account %s is now loaded and valid",
+ account->priv->unique_name);
+ }
+ else
+ {
+ DEBUG ("account %s is now loaded, but not valid: %s #%d: %s",
+ account->priv->unique_name,
+ g_quark_to_string (account->priv->invalid_reason->domain),
+ account->priv->invalid_reason->code,
+ account->priv->invalid_reason->message);
+ }
+
/* invoke all the callbacks */
g_object_ref (account);
@@ -394,17 +396,17 @@ _mcd_account_set_parameter (McdAccount *account, const gchar *name,
McdAccountPrivate *priv = account->priv;
McdStorage *storage = priv->storage;
const gchar *account_name = mcd_account_get_unique_name (account);
- gboolean secret = mcd_account_parameter_is_secret (account, name);
- mcd_storage_set_parameter (storage, account_name, name, value, secret);
+ mcd_storage_set_parameter (storage, account_name, name, value);
}
-static GType mc_param_type (const TpConnectionManagerParam *param);
+static GType mc_param_type (const TpConnectionManagerParam *param,
+ const GVariantType **variant_type_out);
/**
* mcd_account_get_parameter:
* @account: the #McdAccount.
- * @name: the parameter name.
+ * @param: a connection manager parameter
* @parameter: location at which to store the parameter's current value, or
* %NULL if you don't actually care about the parameter's value.
* @error: location at which to store an error if the parameter cannot be
@@ -414,26 +416,28 @@ static GType mc_param_type (const TpConnectionManagerParam *param);
*
* Returns: %TRUE if the parameter could be retrieved; %FALSE otherwise
*/
-gboolean
-mcd_account_get_parameter (McdAccount *account, const gchar *name,
+static gboolean
+mcd_account_get_parameter (McdAccount *account,
+ const TpConnectionManagerParam *param,
GValue *parameter,
GError **error)
{
- McdAccountPrivate *priv = account->priv;
- const TpConnectionManagerParam *param;
GType type;
+ const GVariantType *variant_type;
+ gboolean ret;
+ const gchar *name = tp_connection_manager_param_get_name (param);
- param = mcd_manager_get_protocol_param (priv->manager,
- priv->protocol_name, name);
- type = mc_param_type (param);
+ type = mc_param_type (param, &variant_type);
- return mcd_account_get_parameter_of_known_type (account, name,
- type, parameter, error);
+ ret = mcd_account_get_parameter_of_known_type (account, name,
+ variant_type, type, parameter, error);
+ return ret;
}
gboolean
mcd_account_get_parameter_of_known_type (McdAccount *account,
const gchar *name,
+ const GVariantType *variant_type,
GType type,
GValue *parameter,
GError **error)
@@ -444,7 +448,8 @@ mcd_account_get_parameter_of_known_type (McdAccount *account,
g_value_init (&tmp, type);
- if (mcd_storage_get_parameter (storage, account_name, name, &tmp, error))
+ if (mcd_storage_get_parameter (storage, account_name, name, variant_type,
+ &tmp, error))
{
if (parameter != NULL)
{
@@ -462,169 +467,63 @@ mcd_account_get_parameter_of_known_type (McdAccount *account,
return FALSE;
}
-typedef void (*CheckParametersCb) (
- McdAccount *account,
- const GError *invalid_reason,
- gpointer user_data);
-static void mcd_account_check_parameters (McdAccount *account,
- CheckParametersCb callback, gpointer user_data);
-
-static void
-manager_ready_check_params_cb (McdAccount *account,
- const GError *invalid_reason,
- gpointer user_data)
-{
- McdAccountPrivate *priv = account->priv;
-
- g_clear_error (&priv->invalid_reason);
- if (invalid_reason != NULL)
- {
- priv->invalid_reason = g_error_copy (invalid_reason);
- }
-
- mcd_account_loaded (account);
-}
-
-static void
-account_external_password_storage_get_accounts_cb (TpProxy *cm,
- const GValue *value,
- const GError *in_error,
- gpointer user_data,
- GObject *self)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- const char *account_id = user_data;
- GHashTable *map, *props;
-
- if (in_error != NULL)
- {
- DEBUG ("Failed to get Account property: %s", in_error->message);
- return;
- }
-
- g_return_if_fail (G_VALUE_HOLDS (value, MC_HASH_TYPE_ACCOUNT_FLAGS_MAP));
-
- map = g_value_get_boxed (value);
-
- account->priv->password_saved =
- GPOINTER_TO_UINT (g_hash_table_lookup (map, account_id)) &
- MC_ACCOUNT_FLAG_CREDENTIALS_STORED;
-
- DEBUG ("PasswordSaved = %u", account->priv->password_saved);
-
- /* emit the changed signal */
- props = tp_asv_new (
- "PasswordSaved", G_TYPE_BOOLEAN, account->priv->password_saved,
- NULL);
-
- tp_svc_dbus_properties_emit_properties_changed (account,
- MC_IFACE_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE,
- props,
- NULL);
-
- g_hash_table_unref (props);
-}
-
-static void
-account_setup_identify_account_cb (TpProxy *protocol,
- const char *account_id,
- const GError *in_error,
- gpointer user_data,
- GObject *self)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- TpConnectionManager *cm = mcd_account_get_cm (account);
-
- if (in_error != NULL)
- {
- DEBUG ("Error identifying account: %s", in_error->message);
- return;
- }
-
- DEBUG ("Identified account as %s", account_id);
-
- /* look up the current value of the CM.I.AS.Accounts property
- * and monitor future changes */
- tp_cli_dbus_properties_call_get (cm, -1,
- MC_IFACE_CONNECTION_MANAGER_INTERFACE_ACCOUNT_STORAGE,
- "Accounts",
- account_external_password_storage_get_accounts_cb,
- g_strdup (account_id), g_free, G_OBJECT (account));
-}
-
-static void
-account_external_password_storage_properties_changed_cb (TpProxy *cm,
- const char *iface,
- GHashTable *changed_properties,
- const char **invalidated_properties,
- gpointer user_data,
- GObject *self)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- TpProtocol *protocol = tp_connection_manager_get_protocol_object (
- TP_CONNECTION_MANAGER (cm), account->priv->protocol_name);
- GHashTable *params;
-
- if (tp_strdiff (iface,
- MC_IFACE_CONNECTION_MANAGER_INTERFACE_ACCOUNT_STORAGE))
- return;
-
- /* look up account identity so we can look up our value in
- * the Accounts map */
- params = _mcd_account_dup_parameters (account);
- tp_cli_protocol_call_identify_account (protocol, -1, params,
- account_setup_identify_account_cb,
- NULL, NULL, G_OBJECT (account));
-
- g_hash_table_unref (params);
-}
+static gboolean mcd_account_check_parameters (McdAccount *account,
+ GError **invalid_reason);
static void on_manager_ready (McdManager *manager, const GError *error,
gpointer user_data)
{
McdAccount *account = MCD_ACCOUNT (user_data);
+ GError *invalid_reason = NULL;
+ TpProtocol *protocol;
if (error)
{
DEBUG ("got error: %s", error->message);
- mcd_account_loaded (account);
+ }
+ else if (!mcd_account_check_parameters (account, &invalid_reason))
+ {
+ g_clear_error (&account->priv->invalid_reason);
+ account->priv->invalid_reason = invalid_reason;
}
else
{
- TpConnectionManager *cm = mcd_manager_get_tp_proxy (manager);
+ g_clear_error (&account->priv->invalid_reason);
+ }
- mcd_account_check_parameters (account, manager_ready_check_params_cb,
- NULL);
+ protocol = _mcd_manager_dup_protocol (account->priv->manager,
+ account->priv->protocol_name);
- /* determine if we support Acct.I.ExternalPasswordStorage */
- if (tp_proxy_has_interface_by_id (cm,
- MC_IFACE_QUARK_CONNECTION_MANAGER_INTERFACE_ACCOUNT_STORAGE))
+ if (protocol != NULL)
+ {
+ if (mcd_storage_maybe_migrate_parameters (
+ account->priv->storage,
+ account->priv->unique_name,
+ protocol))
{
- TpProtocol *protocol = tp_connection_manager_get_protocol_object (
- cm, account->priv->protocol_name);
- GHashTable *params;
-
- DEBUG ("CM %s has CM.I.AccountStorage iface",
- mcd_manager_get_name (manager));
+ GHashTable *params = _mcd_account_dup_parameters (account);
- mcd_dbus_activate_optional_interface (
- TP_SVC_DBUS_PROPERTIES (account),
- MC_TYPE_SVC_ACCOUNT_INTERFACE_EXTERNAL_PASSWORD_STORAGE);
+ if (params != NULL)
+ {
+ GValue value = G_VALUE_INIT;
- /* look up account identity so we can look up our value in
- * the Accounts map */
- params = _mcd_account_dup_parameters (account);
- tp_cli_protocol_call_identify_account (protocol, -1, params,
- account_setup_identify_account_cb,
- NULL, NULL, G_OBJECT (account));
+ g_value_init (&value, TP_HASH_TYPE_STRING_VARIANT_MAP);
+ g_value_take_boxed (&value, params);
+ mcd_account_changed_property (account, "Parameters", &value);
+ g_value_unset (&value);
+ }
+ else
+ {
+ WARNING ("somehow managed to migrate parameters without "
+ "being able to emit change notification");
+ }
+ }
- tp_cli_dbus_properties_connect_to_properties_changed (cm,
- account_external_password_storage_properties_changed_cb,
- NULL, NULL, G_OBJECT (account), NULL);
- g_hash_table_unref (params);
- }
+ g_object_unref (protocol);
}
+
+ mcd_account_loaded (account);
}
static gboolean
@@ -666,31 +565,8 @@ get_old_account_data_path (McdAccountPrivate *priv)
return g_build_filename (base, priv->unique_name, NULL);
}
-static void
-account_delete_identify_account_cb (TpProxy *protocol,
- const char *account_id,
- const GError *in_error,
- gpointer user_data,
- GObject *self)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- TpConnectionManager *cm = mcd_account_get_cm (account);
-
- if (in_error != NULL)
- {
- DEBUG ("Error identifying account: %s", in_error->message);
- }
- else
- {
- DEBUG ("Identified account as %s", account_id);
-
- mc_cli_connection_manager_interface_account_storage_call_remove_account (
- cm, -1, account_id,
- NULL, NULL, NULL, NULL);
- }
-
- g_object_unref (account);
-}
+static TpStorageRestrictionFlags mcd_account_get_storage_restrictions (
+ McdAccount *account);
static void
unregister_dbus_service (McdAccount *self)
@@ -709,48 +585,48 @@ unregister_dbus_service (McdAccount *self)
}
void
-mcd_account_delete (McdAccount *account,
- McdAccountDeleteCb callback,
- gpointer user_data)
+mcd_account_delete_async (McdAccount *account,
+ McdDBusPropSetFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
McdAccountPrivate *priv = account->priv;
gchar *data_dir_str;
GError *error = NULL;
const gchar *name = mcd_account_get_unique_name (account);
- TpConnectionManager *cm = mcd_account_get_cm (account);
-
- /* if the CM implements CM.I.AccountStorage, we need to tell the CM
- * to forget any account credentials it knows */
- if (tp_proxy_has_interface_by_id (cm,
- MC_IFACE_QUARK_CONNECTION_MANAGER_INTERFACE_ACCOUNT_STORAGE))
- {
- TpProtocol *protocol;
- GHashTable *params;
-
- /* identify the account */
- protocol = tp_connection_manager_get_protocol_object (cm,
- account->priv->protocol_name);
- params = _mcd_account_dup_parameters (account);
-
- tp_cli_protocol_call_identify_account (protocol, -1, params,
- account_delete_identify_account_cb,
- NULL, NULL, g_object_ref (account));
-
- g_hash_table_unref (params);
+ GTask *task;
+
+ task = g_task_new (account, NULL, callback, user_data);
+
+ /* We don't really have a flag for "cannot delete accounts" yet, but
+ * it seems reasonable that if you can't disable it or put it
+ * offline, you shouldn't be able to delete it. Also, we're going
+ * to try to disable it in a moment anyway. */
+ if ((flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE) == 0 &&
+ (mcd_account_get_storage_restrictions (account) &
+ (TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED |
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PRESENCE)) != 0)
+ {
+ g_task_return_new_error (task, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
+ "Storage plugin for %s does not allow deleting it",
+ name);
+ g_object_unref (task);
+ return;
}
/* got to turn the account off before removing it, otherwise we can *
* end up with an orphaned CM holding the account online */
if (!_mcd_account_set_enabled (account, FALSE, FALSE,
- MCD_DBUS_PROP_SET_FLAG_NONE, &error))
+ flags, &error))
{
g_warning ("could not disable account %s (%s)", name, error->message);
- callback (account, error, user_data);
- g_error_free (error);
+ g_task_return_error (task, error);
+ g_object_unref (task);
return;
}
- mcd_storage_delete_account (priv->storage, name);
+ if ((flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE) == 0)
+ mcd_storage_delete_account (priv->storage, name);
data_dir_str = get_old_account_data_path (priv);
@@ -777,27 +653,27 @@ mcd_account_delete (McdAccount *account,
g_free (data_dir_str);
}
- mcd_storage_commit (priv->storage, name);
-
- /* The callback may drop the latest ref on @account so make sure it stays
- * alive while we still need it. */
- g_object_ref (account);
-
- if (callback != NULL)
- callback (account, NULL, user_data);
-
- /* If the account was not removed via the DBus Account interface code *
- * path and something is holding a ref to it so it does not get disposed, *
- * then this signal may not get fired, so we make sure it _does_ here */
if (!priv->removed)
{
- DEBUG ("Forcing Account.Removed for %s", name);
+ DEBUG ("emitting Account.Removed for %s", name);
priv->removed = TRUE;
tp_svc_account_emit_removed (account);
}
unregister_dbus_service (account);
- g_object_unref (account);
+
+ g_task_return_boolean (task, TRUE);
+ g_object_unref (task);
+}
+
+gboolean
+mcd_account_delete_finish (McdAccount *self,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, self), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
}
void
@@ -805,10 +681,29 @@ _mcd_account_load (McdAccount *account, McdAccountLoadCb callback,
gpointer user_data)
{
if (account->priv->loaded)
+ {
+ if (account->priv->invalid_reason == NULL)
+ {
+ DEBUG ("account %s already loaded and valid",
+ account->priv->unique_name);
+ }
+ else
+ {
+ DEBUG ("account %s already loaded, but not valid: %s #%d: %s",
+ account->priv->unique_name,
+ g_quark_to_string (account->priv->invalid_reason->domain),
+ account->priv->invalid_reason->code,
+ account->priv->invalid_reason->message);
+ }
+
callback (account, NULL, user_data);
+ }
else
+ {
+ DEBUG ("account %s not yet loaded", account->priv->unique_name);
_mcd_object_call_when_ready (account, account_ready_quark,
(McdReadyCb)callback, user_data);
+ }
}
static void
@@ -820,9 +715,6 @@ on_connection_abort (McdConnection *connection, McdAccount *account)
_mcd_account_set_connection (account, NULL);
}
-static void mcd_account_changed_property (McdAccount *account,
- const gchar *key, const GValue *value);
-
static void
mcd_account_request_presence_int (McdAccount *account,
TpConnectionPresenceType type,
@@ -1104,7 +996,8 @@ mcd_account_get_string_val (McdAccount *account, const gchar *key,
g_value_init (value, G_TYPE_STRING);
- if (!mcd_storage_get_attribute (priv->storage, name, key, value, NULL))
+ if (!mcd_storage_get_attribute (priv->storage, name, key,
+ G_VARIANT_TYPE_STRING, value, NULL))
{
g_value_set_static_string (value, NULL);
}
@@ -1195,19 +1088,21 @@ _mcd_account_set_enabled (McdAccount *account,
{
McdAccountPrivate *priv = account->priv;
- if (priv->always_on && !enabled)
- {
- g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
- "Account %s cannot be disabled",
- priv->unique_name);
- return FALSE;
- }
-
if (priv->enabled != enabled)
{
GValue value = G_VALUE_INIT;
const gchar *name = mcd_account_get_unique_name (account);
+ if ((flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE) == 0 &&
+ (mcd_account_get_storage_restrictions (account) &
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_ENABLED) != 0)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
+ "Storage plugin for %s does not allow changing "
+ "its Enabled property", name);
+ return FALSE;
+ }
+
if (!enabled && priv->connection != NULL)
_mcd_connection_request_presence (priv->connection,
TP_CONNECTION_PRESENCE_TYPE_OFFLINE,
@@ -1735,6 +1630,16 @@ set_automatic_presence (TpSvcDBusProperties *self,
return FALSE;
}
+ if ((flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE) == 0 &&
+ (mcd_account_get_storage_restrictions (account) &
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PRESENCE) != 0)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
+ "Storage plugin for %s does not allow changing "
+ "its presence", priv->unique_name);
+ return FALSE;
+ }
+
DEBUG ("setting automatic presence: %d, %s, %s", type, status, message);
if (priv->auto_presence_type != type)
@@ -1816,18 +1721,24 @@ set_connect_automatically (TpSvcDBusProperties *self,
connect_automatically = g_value_get_boolean (value);
- if (priv->always_on && !connect_automatically)
- {
- g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
- "Account %s always connects automatically",
- priv->unique_name);
- return FALSE;
- }
-
if (priv->connect_automatically != connect_automatically)
{
const gchar *account_name = mcd_account_get_unique_name (account);
+ /* We use CANNOT_SET_PRESENCE to control access to
+ * ConnectAutomatically, because RequestedPresence is not stored,
+ * but it can be derived from ConnectAutomatically and
+ * AutomaticPresence */
+ if ((flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE) == 0 &&
+ (mcd_account_get_storage_restrictions (account) &
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PRESENCE) != 0)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
+ "Storage plugin for %s does not allow changing "
+ "its ConnectAutomatically property", account_name);
+ return FALSE;
+ }
+
if (!(flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE))
{
mcd_storage_set_attribute (priv->storage, account_name,
@@ -1969,10 +1880,13 @@ set_requested_presence (TpSvcDBusProperties *self,
status = g_value_get_string (va->values + 1);
message = g_value_get_string (va->values + 2);
- if (priv->always_on && !_presence_type_is_online (type))
+ if ((flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE) == 0 &&
+ (mcd_account_get_storage_restrictions (account) &
+ TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_PRESENCE) != 0)
{
g_set_error (error, TP_ERROR, TP_ERROR_PERMISSION_DENIED,
- "Account %s cannot be taken offline", priv->unique_name);
+ "Storage plugin for %s does not allow changing "
+ "its presence", priv->unique_name);
return FALSE;
}
@@ -2078,58 +1992,16 @@ get_supersedes (TpSvcDBusProperties *svc,
g_value_set_boxed (value, self->priv->supersedes);
}
-static McpAccountStorage *
-get_storage_plugin (McdAccount *account)
-{
- McdAccountPrivate *priv = account->priv;
- const gchar *account_name = mcd_account_get_unique_name (account);
-
- if (priv->storage_plugin != NULL)
- return priv->storage_plugin;
-
- priv->storage_plugin = mcd_storage_get_plugin (priv->storage, account_name);
-
- if (priv->storage_plugin != NULL)
- g_object_ref (priv->storage_plugin);
-
- return priv->storage_plugin;
-}
-
static void
get_storage_provider (TpSvcDBusProperties *self,
const gchar *name, GValue *value)
{
McdAccount *account = MCD_ACCOUNT (self);
- McpAccountStorage *storage_plugin = get_storage_plugin (account);
g_value_init (value, G_TYPE_STRING);
- if (storage_plugin != NULL)
- g_value_set_string (value, mcp_account_storage_provider (storage_plugin));
- else
- g_value_set_static_string (value, "");
-}
-
-static gboolean
-set_storage_provider (TpSvcDBusProperties *self,
- const gchar *name,
- const GValue *value,
- McdDBusPropSetFlags flags,
- GError **error)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- McpAccountStorage *storage_plugin = get_storage_plugin (account);
- const gchar *current_provider = mcp_account_storage_provider (storage_plugin);
-
- if (!G_VALUE_HOLDS_STRING (value) ||
- tp_strdiff (g_value_get_string (value), current_provider))
- {
- g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Cannot change provider, it is defined at account creation only");
- return FALSE;
- }
-
- return TRUE;
+ g_value_set_string (value,
+ mcp_account_storage_provider (account->priv->storage_plugin));
}
static void
@@ -2138,22 +2010,13 @@ get_storage_identifier (TpSvcDBusProperties *self,
{
McdAccount *account = MCD_ACCOUNT (self);
- McpAccountStorage *storage_plugin = get_storage_plugin (account);
GValue identifier = G_VALUE_INIT;
g_value_init (value, G_TYPE_VALUE);
- if (storage_plugin != NULL)
- {
- mcp_account_storage_get_identifier (
- storage_plugin, account->priv->unique_name, &identifier);
- }
- else
- {
- g_value_init (&identifier, G_TYPE_UINT);
-
- g_value_set_uint (&identifier, 0);
- }
+ mcp_account_storage_get_identifier (
+ account->priv->storage_plugin, account->priv->unique_name,
+ &identifier);
g_value_set_boxed (value, &identifier);
@@ -2166,35 +2029,29 @@ get_storage_specific_info (TpSvcDBusProperties *self,
{
GHashTable *storage_specific_info;
McdAccount *account = MCD_ACCOUNT (self);
- McpAccountStorage *storage_plugin = get_storage_plugin (account);
g_value_init (value, TP_HASH_TYPE_STRING_VARIANT_MAP);
- if (storage_plugin != NULL)
- storage_specific_info = mcp_account_storage_get_additional_info (
- storage_plugin, account->priv->unique_name);
- else
- storage_specific_info = g_hash_table_new (g_str_hash, g_str_equal);
+ storage_specific_info = mcp_account_storage_get_additional_info (
+ account->priv->storage_plugin, account->priv->unique_name);
g_value_take_boxed (value, storage_specific_info);
}
+static TpStorageRestrictionFlags
+mcd_account_get_storage_restrictions (McdAccount *self)
+{
+ return mcp_account_storage_get_restrictions (self->priv->storage_plugin,
+ self->priv->unique_name);
+}
+
static void
get_storage_restrictions (TpSvcDBusProperties *self,
const gchar *name, GValue *value)
{
- TpStorageRestrictionFlags flags;
- McdAccount *account = MCD_ACCOUNT (self);
- McpAccountStorage *storage_plugin = get_storage_plugin (account);
-
g_value_init (value, G_TYPE_UINT);
-
- g_return_if_fail (storage_plugin != NULL);
-
- flags = mcp_account_storage_get_restrictions (storage_plugin,
- account->priv->unique_name);
-
- g_value_set_uint (value, flags);
+ g_value_set_uint (value,
+ mcd_account_get_storage_restrictions (MCD_ACCOUNT (self)));
}
static const McdDBusProp account_properties[] = {
@@ -2228,7 +2085,7 @@ static const McdDBusProp account_avatar_properties[] = {
};
static const McdDBusProp account_storage_properties[] = {
- { "StorageProvider", set_storage_provider, get_storage_provider },
+ { "StorageProvider", NULL, get_storage_provider },
{ "StorageIdentifier", NULL, get_storage_identifier },
{ "StorageSpecificInformation", NULL, get_storage_specific_info },
{ "StorageRestrictions", NULL, get_storage_restrictions },
@@ -2248,173 +2105,6 @@ account_storage_iface_init (TpSvcAccountInterfaceStorageClass *iface,
}
static void
-get_hidden (TpSvcDBusProperties *self,
- const gchar *name, GValue *value)
-{
- g_value_init (value, G_TYPE_BOOLEAN);
- g_object_get_property (G_OBJECT (self), "hidden", value);
-}
-
-static gboolean
-set_hidden (TpSvcDBusProperties *self,
- const gchar *name,
- const GValue *value,
- McdDBusPropSetFlags flags,
- GError **error)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- McdAccountPrivate *priv = account->priv;
- const gchar *account_name = mcd_account_get_unique_name (account);
-
- if (!G_VALUE_HOLDS_BOOLEAN (value))
- {
- g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "Hidden must be set to a boolean, not a %s",
- G_VALUE_TYPE_NAME (value));
- return FALSE;
- }
-
- /* Technically this property is immutable after the account's been created,
- * but currently it's not easy for this code to tell whether or not this is
- * a create-time property. It would probably be better if the create-time
- * properties were passed into us as a construct-time GObject property. But
- * that's a job for another month.
- *
- * So for now we check whether the value has changed, and violate the spec
- * by making this property mutable (at least with the keyfile backend).
- */
- if (mcd_storage_set_attribute (priv->storage, account_name,
- MC_ACCOUNTS_KEY_HIDDEN, value))
- {
- mcd_storage_commit (priv->storage, account_name);
- mcd_account_changed_property (account, MC_ACCOUNTS_KEY_HIDDEN, value);
- g_object_set_property (G_OBJECT (self), "hidden", value);
- }
-
- return TRUE;
-}
-
-static const McdDBusProp account_hidden_properties[] = {
- { "Hidden", set_hidden, get_hidden },
- { 0 },
-};
-
-static void
-account_hidden_iface_init (
- McSvcAccountInterfaceHiddenClass *iface,
- gpointer iface_data)
-{
- /* wow, it's pretty crap that I need this. */
-}
-
-static void
-get_password_saved (TpSvcDBusProperties *self,
- const gchar *name,
- GValue *value)
-{
- McdAccount *account = MCD_ACCOUNT (self);
-
- g_assert_cmpstr (name, ==, "PasswordSaved");
-
- g_value_init (value, G_TYPE_BOOLEAN);
- g_value_set_boolean (value, account->priv->password_saved);
-}
-
-static const McdDBusProp account_external_password_storage_properties[] = {
- { "PasswordSaved", NULL, get_password_saved },
- { 0 },
-};
-
-static void
-account_external_password_storage_forget_credentials_cb (TpProxy *cm,
- const GError *in_error,
- gpointer user_data,
- GObject *self)
-{
- DBusGMethodInvocation *context = user_data;
-
- if (in_error != NULL)
- {
- dbus_g_method_return_error (context, in_error);
- return;
- }
-
- mc_svc_account_interface_external_password_storage_return_from_forget_password (context);
-}
-
-static void
-account_external_password_storage_identify_account_cb (TpProxy *protocol,
- const char *account_id,
- const GError *in_error,
- gpointer user_data,
- GObject *self)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- DBusGMethodInvocation *context = user_data;
- TpConnectionManager *cm = mcd_account_get_cm (account);
-
- if (in_error != NULL)
- {
- dbus_g_method_return_error (context, in_error);
- return;
- }
-
- DEBUG ("Identified account as %s", account_id);
-
- mc_cli_connection_manager_interface_account_storage_call_forget_credentials (
- cm, -1, account_id,
- account_external_password_storage_forget_credentials_cb,
- context, NULL, self);
-}
-
-static void
-account_external_password_storage_forget_password (
- McSvcAccountInterfaceExternalPasswordStorage *self,
- DBusGMethodInvocation *context)
-{
- McdAccount *account = MCD_ACCOUNT (self);
- TpConnectionManager *cm = mcd_account_get_cm (account);
- TpProtocol *protocol;
- GHashTable *params;
-
- /* do we support the interface */
- if (!tp_proxy_has_interface_by_id (cm,
- MC_IFACE_QUARK_CONNECTION_MANAGER_INTERFACE_ACCOUNT_STORAGE))
- {
- GError *error = g_error_new (TP_ERROR, TP_ERROR_NOT_IMPLEMENTED,
- "CM for this Account does not implement AccountStorage iface");
-
- dbus_g_method_return_error (context, error);
- g_error_free (error);
-
- return;
- }
-
- /* identify the account */
- protocol = tp_connection_manager_get_protocol_object (cm,
- account->priv->protocol_name);
- params = _mcd_account_dup_parameters (account);
-
- tp_cli_protocol_call_identify_account (protocol, -1, params,
- account_external_password_storage_identify_account_cb,
- context, NULL, G_OBJECT (self));
-
- g_hash_table_unref (params);
-}
-
-static void
-account_external_password_storage_iface_init (
- McSvcAccountInterfaceExternalPasswordStorageClass *iface,
- gpointer iface_data)
-{
-#define IMPLEMENT(x) \
- mc_svc_account_interface_external_password_storage_implement_##x (\
- iface, account_external_password_storage_##x)
- IMPLEMENT (forget_password);
-#undef IMPLEMENT
-}
-
-static void
properties_iface_init (TpSvcDBusPropertiesClass *iface, gpointer iface_data)
{
#define IMPLEMENT(x) tp_svc_dbus_properties_implement_##x (\
@@ -2426,10 +2116,13 @@ properties_iface_init (TpSvcDBusPropertiesClass *iface, gpointer iface_data)
}
static GType
-mc_param_type (const TpConnectionManagerParam *param)
+mc_param_type (const TpConnectionManagerParam *param,
+ const GVariantType **variant_type_out)
{
const gchar *dbus_signature;
+ *variant_type_out = NULL;
+
if (G_UNLIKELY (param == NULL))
return G_TYPE_INVALID;
@@ -2441,37 +2134,49 @@ mc_param_type (const TpConnectionManagerParam *param)
switch (dbus_signature[0])
{
case DBUS_TYPE_STRING:
+ *variant_type_out = G_VARIANT_TYPE_STRING;
return G_TYPE_STRING;
case DBUS_TYPE_BYTE:
+ *variant_type_out = G_VARIANT_TYPE_BYTE;
return G_TYPE_UCHAR;
case DBUS_TYPE_INT16:
case DBUS_TYPE_INT32:
+ *variant_type_out = G_VARIANT_TYPE_INT32;
return G_TYPE_INT;
case DBUS_TYPE_UINT16:
case DBUS_TYPE_UINT32:
+ *variant_type_out = G_VARIANT_TYPE_UINT32;
return G_TYPE_UINT;
case DBUS_TYPE_BOOLEAN:
+ *variant_type_out = G_VARIANT_TYPE_BOOLEAN;
return G_TYPE_BOOLEAN;
case DBUS_TYPE_DOUBLE:
+ *variant_type_out = G_VARIANT_TYPE_DOUBLE;
return G_TYPE_DOUBLE;
case DBUS_TYPE_OBJECT_PATH:
+ *variant_type_out = G_VARIANT_TYPE_OBJECT_PATH;
return DBUS_TYPE_G_OBJECT_PATH;
case DBUS_TYPE_INT64:
+ *variant_type_out = G_VARIANT_TYPE_INT64;
return G_TYPE_INT64;
case DBUS_TYPE_UINT64:
+ *variant_type_out = G_VARIANT_TYPE_UINT64;
return G_TYPE_UINT64;
case DBUS_TYPE_ARRAY:
if (dbus_signature[1] == DBUS_TYPE_STRING)
+ {
+ *variant_type_out = G_VARIANT_TYPE_STRING_ARRAY;
return G_TYPE_STRV;
+ }
/* other array types are not supported:
* fall through the default case */
default:
@@ -2488,25 +2193,24 @@ typedef struct
} RemoveMethodData;
static void
-account_remove_delete_cb (McdAccount *account, const GError *error,
+account_remove_delete_cb (GObject *source,
+ GAsyncResult *res,
gpointer user_data)
{
RemoveMethodData *data = (RemoveMethodData *) user_data;
+ GError *error = NULL;
- if (error != NULL)
+ if (!mcd_account_delete_finish (MCD_ACCOUNT (source), res, &error))
{
dbus_g_method_return_error (data->context, (GError *) error);
+ g_error_free (error);
return;
}
- if (!data->self->priv->removed)
- {
- data->self->priv->removed = TRUE;
- tp_svc_account_emit_removed (data->self);
- }
+ /* mcd_account_delete() is meant to have deleted it */
+ g_warn_if_fail (data->self->priv->removed);
tp_svc_account_return_from_remove (data->context);
-
g_slice_free (RemoveMethodData, data);
}
@@ -2521,7 +2225,8 @@ account_remove (TpSvcAccount *svc, DBusGMethodInvocation *context)
data->context = context;
DEBUG ("called");
- mcd_account_delete (self, account_remove_delete_cb, data);
+ mcd_account_delete_async (self, MCD_DBUS_PROP_SET_FLAG_NONE,
+ account_remove_delete_cb, data);
}
/*
@@ -2548,11 +2253,13 @@ mcd_account_altered_by_plugin (McdAccount *account,
const McdDBusProp *prop = NULL;
GValue value = G_VALUE_INIT;
GError *error = NULL;
+ const GVariantType *variant_type = NULL;
DEBUG ("%s", name);
if (tp_strdiff (name, "Parameters") &&
- !mcd_storage_init_value_for_attribute (&value, name))
+ !mcd_storage_init_value_for_attribute (&value, name,
+ &variant_type))
{
WARNING ("plugin wants to alter %s but I don't know what "
"type that ought to be", name);
@@ -2565,7 +2272,8 @@ mcd_account_altered_by_plugin (McdAccount *account,
}
else if (!mcd_storage_get_attribute (account->priv->storage,
account->priv->unique_name,
- name, &value, &error))
+ name, variant_type, &value,
+ &error))
{
WARNING ("cannot get new value of %s: %s", name, error->message);
g_error_free (error);
@@ -2615,25 +2323,22 @@ mcd_account_altered_by_plugin (McdAccount *account,
}
-static void
+static gboolean
mcd_account_check_parameters (McdAccount *account,
- CheckParametersCb callback,
- gpointer user_data)
+ GError **error)
{
McdAccountPrivate *priv = account->priv;
TpProtocol *protocol;
GList *params = NULL;
GList *iter;
- GError *error = NULL;
-
- g_return_if_fail (callback != NULL);
+ GError *inner_error = NULL;
DEBUG ("called for %s", priv->unique_name);
protocol = _mcd_manager_dup_protocol (priv->manager, priv->protocol_name);
if (protocol == NULL)
{
- g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ g_set_error (&inner_error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
"CM '%s' doesn't implement protocol '%s'", priv->manager_name,
priv->protocol_name);
goto out;
@@ -2644,40 +2349,36 @@ mcd_account_check_parameters (McdAccount *account,
for (iter = params; iter != NULL; iter = iter->next)
{
TpConnectionManagerParam *param = iter->data;
- const gchar *param_name = tp_connection_manager_param_get_name (param);
if (!tp_connection_manager_param_is_required ((param)))
continue;
- if (!mcd_account_get_parameter (account, param_name, NULL, NULL))
+ if (!mcd_account_get_parameter (account, param, NULL, NULL))
{
- g_set_error (&error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "missing required parameter '%s'", param_name);
+ g_set_error (&inner_error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "missing required parameter '%s'",
+ tp_connection_manager_param_get_name (param));
goto out;
}
}
out:
- if (error != NULL)
+ if (inner_error != NULL)
{
- DEBUG ("%s", error->message);
+ DEBUG ("%s", inner_error->message);
}
- callback (account, error, user_data);
- g_clear_error (&error);
g_list_free_full (params,
(GDestroyNotify) tp_connection_manager_param_free);
g_clear_object (&protocol);
-}
-static void
-set_parameters_maybe_autoconnect_cb (McdAccount *account,
- const GError *invalid_reason,
- gpointer user_data G_GNUC_UNUSED)
-{
- /* Strictly speaking this doesn't need to be called unless invalid_reason
- * is NULL, but calling it in all cases gives us clearer debug output */
- _mcd_account_maybe_autoconnect (account);
+ if (inner_error != NULL)
+ {
+ g_propagate_error (error, inner_error);
+ return FALSE;
+ }
+
+ return TRUE;
}
static void
@@ -2715,8 +2416,11 @@ apply_parameter_updates (McdAccount *account,
}
}
- mcd_account_check_validity (account,
- set_parameters_maybe_autoconnect_cb, NULL);
+ mcd_account_check_validity (account, NULL);
+
+ /* Strictly speaking this doesn't need to be called if not valid,
+ * but calling it in all cases gives us clearer debug output */
+ _mcd_account_maybe_autoconnect (account);
}
static void
@@ -2754,6 +2458,7 @@ check_one_parameter_update (McdAccount *account,
const TpConnectionManagerParam *param =
tp_protocol_get_param (protocol, name);
GType type;
+ const GVariantType *variant_type;
if (param == NULL)
{
@@ -2763,15 +2468,18 @@ check_one_parameter_update (McdAccount *account,
return FALSE;
}
- type = mc_param_type (param);
+ type = mc_param_type (param, &variant_type);
if (G_VALUE_TYPE (new_value) != type)
{
/* FIXME: use D-Bus type names, not GType names. */
g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
- "parameter '%s' must be of type %s, not %s",
+ "parameter '%s' must be of type %s ('%.*s'), not %s",
tp_connection_manager_param_get_name (param),
- g_type_name (type), G_VALUE_TYPE_NAME (new_value));
+ g_type_name (type),
+ (int) g_variant_type_get_string_length (variant_type),
+ g_variant_type_peek_string (variant_type),
+ G_VALUE_TYPE_NAME (new_value));
return FALSE;
}
@@ -2783,7 +2491,7 @@ check_one_parameter_update (McdAccount *account,
/* Check if the parameter's current value (or its default, if it has
* one and it's not set to anything) matches the new value.
*/
- if (mcd_account_get_parameter (account, tp_connection_manager_param_get_name (param),
+ if (mcd_account_get_parameter (account, param,
&current_value, NULL) ||
tp_connection_manager_param_get_default (param, &current_value))
{
@@ -2826,7 +2534,7 @@ check_one_parameter_unset (McdAccount *account,
{
GValue current_value = G_VALUE_INIT;
- if (mcd_account_get_parameter (account, tp_connection_manager_param_get_name (param),
+ if (mcd_account_get_parameter (account, param,
&current_value, NULL))
{
/* There's an existing value; let's see if it's the same as the
@@ -3013,6 +2721,11 @@ void
_mcd_account_reconnect (McdAccount *self,
gboolean user_initiated)
{
+ DEBUG ("%s", mcd_account_get_unique_name (self));
+
+ /* If the account is disabled, invalid or has offline requested presence,
+ * disconnecting should be a no-op, so we keep this before checking
+ * whether we want to. */
/* FIXME: this isn't quite right. If we've just called RequestConnection
* (possibly with out of date parameters) but we haven't got a Connection
* back from the CM yet, the old parameters will still be used, I think
@@ -3020,32 +2733,28 @@ _mcd_account_reconnect (McdAccount *self,
if (self->priv->connection)
mcd_connection_close (self->priv->connection, NULL);
- _mcd_account_connection_begin (self, user_initiated);
-}
-
-static void
-account_reconnect (TpSvcAccount *service,
- DBusGMethodInvocation *context)
-{
- McdAccount *self = MCD_ACCOUNT (service);
- McdAccountPrivate *priv = self->priv;
-
- DEBUG ("%s", mcd_account_get_unique_name (self));
-
/* if we can't, or don't want to, connect this method is a no-op */
- if (!priv->enabled ||
+ if (!self->priv->enabled ||
!mcd_account_is_valid (self) ||
- priv->req_presence_type == TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
+ self->priv->req_presence_type == TP_CONNECTION_PRESENCE_TYPE_OFFLINE)
{
DEBUG ("doing nothing (enabled=%c, valid=%c and "
"combined presence=%i)",
self->priv->enabled ? 'T' : 'F',
mcd_account_is_valid (self) ? 'T' : 'F',
self->priv->req_presence_type);
- tp_svc_account_return_from_reconnect (context);
return;
}
+ _mcd_account_connection_begin (self, user_initiated);
+}
+
+static void
+account_reconnect (TpSvcAccount *service,
+ DBusGMethodInvocation *context)
+{
+ McdAccount *self = MCD_ACCOUNT (service);
+
/* Reconnect() counts as user-initiated */
_mcd_account_reconnect (self, TRUE);
@@ -3341,20 +3050,14 @@ mcd_account_setup (McdAccount *account)
priv->object_path = g_strconcat (TP_ACCOUNT_OBJECT_PATH_BASE, name, NULL);
- if (!priv->always_on)
- {
- priv->enabled =
- mcd_storage_get_boolean (storage, name, MC_ACCOUNTS_KEY_ENABLED);
+ priv->enabled = mcd_storage_get_boolean (storage, name,
+ MC_ACCOUNTS_KEY_ENABLED);
- priv->connect_automatically =
- mcd_storage_get_boolean (storage, name,
- MC_ACCOUNTS_KEY_CONNECT_AUTOMATICALLY);
- }
+ priv->connect_automatically = mcd_storage_get_boolean (storage, name,
+ MC_ACCOUNTS_KEY_CONNECT_AUTOMATICALLY);
priv->has_been_online =
mcd_storage_get_boolean (storage, name, MC_ACCOUNTS_KEY_HAS_BEEN_ONLINE);
- priv->hidden =
- mcd_storage_get_boolean (storage, name, MC_ACCOUNTS_KEY_HIDDEN);
/* special case flag (for ring accounts, so far) */
priv->always_dispatch =
@@ -3366,7 +3069,8 @@ mcd_account_setup (McdAccount *account)
g_free (priv->auto_presence_message);
if (mcd_storage_get_attribute (storage, name,
- MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE, &value,
+ MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE,
+ G_VARIANT_TYPE ("(uss)"), &value,
NULL))
{
GValueArray *va = g_value_get_boxed (&value);
@@ -3438,7 +3142,9 @@ mcd_account_setup (McdAccount *account)
g_ptr_array_unref (priv->supersedes);
if (mcd_storage_get_attribute (storage, name,
- MC_ACCOUNTS_KEY_SUPERSEDES, &value, NULL))
+ MC_ACCOUNTS_KEY_SUPERSEDES,
+ G_VARIANT_TYPE_OBJECT_PATH_ARRAY,
+ &value, NULL))
{
priv->supersedes = g_value_dup_boxed (&value);
}
@@ -3486,6 +3192,11 @@ set_property (GObject *obj, guint prop_id,
priv->storage = g_value_dup_object (val);
break;
+ case PROP_STORAGE_PLUGIN:
+ g_assert (priv->storage_plugin == NULL);
+ priv->storage_plugin = g_value_dup_object (val);
+ break;
+
case PROP_DBUS_DAEMON:
g_assert (priv->dbus_daemon == NULL);
priv->dbus_daemon = g_value_dup_object (val);
@@ -3501,22 +3212,6 @@ set_property (GObject *obj, guint prop_id,
priv->unique_name = g_value_dup_string (val);
break;
- case PROP_ALWAYS_ON:
- priv->always_on = g_value_get_boolean (val);
-
- if (priv->always_on)
- {
- priv->enabled = TRUE;
- priv->connect_automatically = TRUE;
- priv->req_presence_type = priv->auto_presence_type;
- priv->req_presence_status = g_strdup (priv->auto_presence_status);
- priv->req_presence_message = g_strdup (priv->auto_presence_message);
- }
-
- break;
- case PROP_HIDDEN:
- priv->hidden = g_value_get_boolean (val);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -3542,9 +3237,6 @@ get_property (GObject *obj, guint prop_id,
case PROP_NAME:
g_value_set_string (val, priv->unique_name);
break;
- case PROP_HIDDEN:
- g_value_set_boolean (val, priv->hidden);
- break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec);
break;
@@ -3591,6 +3283,9 @@ _mcd_account_dispose (GObject *object)
if (!self->priv->removed)
{
+ /* this can happen in certain account-creation error paths,
+ * as far as I can see */
+ DEBUG ("Account never emitted Removed, emitting it now");
self->priv->removed = TRUE;
tp_svc_account_emit_removed (self);
}
@@ -3621,7 +3316,8 @@ _mcd_account_dispose (GObject *object)
tp_clear_object (&priv->self_contact);
tp_clear_object (&priv->connectivity);
- _mcd_account_set_connection_context (self, NULL);
+ tp_clear_pointer (&self->priv->connection_context,
+ _mcd_account_connection_context_free);
_mcd_account_set_connection (self, NULL);
G_OBJECT_CLASS (mcd_account_parent_class)->dispose (object);
@@ -3649,6 +3345,9 @@ _mcd_account_constructor (GType type, guint n_params,
return (GObject *) account;
}
+static void mcd_account_connection_proceed_with_reason
+ (McdAccount *account, gboolean success, TpConnectionStatusReason reason);
+
static void
monitor_state_changed_cb (
McdConnectivityMonitor *monitor,
@@ -3721,16 +3420,6 @@ _mcd_account_constructed (GObject *object)
}
static void
-mcd_account_add_signals (TpProxy *self,
- guint quark,
- DBusGProxy *proxy,
- gpointer data)
-{
- mc_cli_Connection_Manager_Interface_Account_Storage_add_signals (self,
- quark, proxy, data);
-}
-
-static void
mcd_account_class_init (McdAccountClass * klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
@@ -3766,23 +3455,17 @@ mcd_account_class_init (McdAccountClass * klass)
G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property
+ (object_class, PROP_STORAGE_PLUGIN,
+ g_param_spec_object ("storage-plugin", "storage-plugin",
+ "Storage plugin", MCP_TYPE_ACCOUNT_STORAGE,
+ G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property
(object_class, PROP_NAME,
g_param_spec_string ("name", "Unique name", "Unique name",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
- g_object_class_install_property
- (object_class, PROP_ALWAYS_ON,
- g_param_spec_boolean ("always-on", "Always on?", "Always on?",
- FALSE,
- G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS));
-
- g_object_class_install_property
- (object_class, PROP_HIDDEN,
- g_param_spec_boolean ("hidden", "Hidden?", "Is this account hidden?",
- FALSE,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
/* Signals */
_mcd_account_signals[VALIDITY_CHANGED] =
g_signal_new ("validity-changed",
@@ -3801,9 +3484,6 @@ mcd_account_class_init (McdAccountClass * klass)
G_TYPE_NONE, 1, G_TYPE_STRING);
account_ready_quark = g_quark_from_static_string ("mcd_account_load");
-
- tp_proxy_or_subclass_hook_on_interface_add (TP_TYPE_CONNECTION_MANAGER,
- mcd_account_add_signals);
}
static void
@@ -3824,7 +3504,6 @@ mcd_account_init (McdAccount *account)
priv->curr_presence_status = g_strdup ("offline");
priv->curr_presence_message = g_strdup ("");
- priv->always_on = FALSE;
priv->always_dispatch = FALSE;
priv->enabled = FALSE;
priv->connect_automatically = FALSE;
@@ -3854,7 +3533,8 @@ mcd_account_init (McdAccount *account)
McdAccount *
mcd_account_new (McdAccountManager *account_manager,
const gchar *name,
- McdConnectivityMonitor *connectivity)
+ McdConnectivityMonitor *connectivity,
+ McpAccountStorage *storage_plugin)
{
gpointer *obj;
McdStorage *storage = mcd_account_manager_get_storage (account_manager);
@@ -3862,6 +3542,7 @@ mcd_account_new (McdAccountManager *account_manager,
obj = g_object_new (MCD_TYPE_ACCOUNT,
"storage", storage,
+ "storage-plugin", storage_plugin,
"dbus-daemon", dbus,
"connectivity-monitor", connectivity,
"name", name,
@@ -3875,6 +3556,12 @@ _mcd_account_get_storage (McdAccount *account)
return account->priv->storage;
}
+McpAccountStorage *
+mcd_account_get_storage_plugin (McdAccount *account)
+{
+ return account->priv->storage_plugin;
+}
+
/*
* mcd_account_is_valid:
* @account: the #McdAccount.
@@ -3892,6 +3579,39 @@ mcd_account_is_valid (McdAccount *account)
return priv->invalid_reason == NULL;
}
+/*
+ * mcd_account_dup_protocol:
+ * @self: the account
+ *
+ * Returns: (transfer full): the account's connection manager's protocol,
+ * possibly %NULL if "not valid"
+ */
+static TpProtocol *
+mcd_account_dup_protocol (McdAccount *self)
+{
+ TpProtocol *protocol;
+
+ if (!self->priv->manager && !load_manager (self))
+ {
+ DEBUG ("unable to load manager for account %s",
+ self->priv->unique_name);
+ return NULL;
+ }
+
+ protocol = _mcd_manager_dup_protocol (self->priv->manager,
+ self->priv->protocol_name);
+
+ if (G_UNLIKELY (protocol == NULL))
+ {
+ DEBUG ("unable to get protocol for %s account %s",
+ self->priv->protocol_name,
+ self->priv->unique_name);
+ return NULL;
+ }
+
+ return protocol;
+}
+
/**
* mcd_account_is_enabled:
* @account: the #McdAccount.
@@ -3907,14 +3627,6 @@ mcd_account_is_enabled (McdAccount *account)
return priv->enabled;
}
-gboolean
-_mcd_account_is_hidden (McdAccount *account)
-{
- g_return_val_if_fail (MCD_IS_ACCOUNT (account), FALSE);
-
- return account->priv->hidden;
-}
-
const gchar *
mcd_account_get_unique_name (McdAccount *account)
{
@@ -3927,54 +3639,25 @@ mcd_account_get_object_path (McdAccount *account)
return account->priv->object_path;
}
-/**
- * _mcd_account_dup_parameters:
- * @account: the #McdAccount.
- *
- * Get the parameters set for this account. The resulting #GHashTable will be
- * newly allocated and must be g_hash_table_unref()'d after use.
+/*
+ * Like _mcd_account_dup_parameters(), but return the parameters as they
+ * would be passed to RequestConnection for the given protocol.
*
- * Returns: @account's current parameters, or %NULL if they could not be
- * retrieved.
+ * Returns: A GHashTable with g_strdup'ed keys and tp_g_value_slice_dup'ed
+ * values. Be careful: callers rely on that memory allocation model.
*/
-GHashTable *
-_mcd_account_dup_parameters (McdAccount *account)
+static GHashTable *
+mcd_account_coerce_parameters (McdAccount *account,
+ TpProtocol *protocol)
{
- McdAccountPrivate *priv;
- TpProtocol *protocol;
GList *protocol_params;
GList *iter;
GHashTable *params;
g_return_val_if_fail (MCD_IS_ACCOUNT (account), NULL);
- priv = account->priv;
-
DEBUG ("called");
- /* FIXME: this is ridiculous. MC stores the parameters for the account, so
- * it should be able to expose them on D-Bus even if the CM is uninstalled.
- * It shouldn't need to iterate across the parameters supported by the CM.
- * But it does, because MC doesn't store the types of parameters. So it
- * needs the CM (or .manager file) to be around to tell it whether "true"
- * is a string or a boolean…
- */
- if (!priv->manager && !load_manager (account))
- {
- DEBUG ("unable to load manager for account %s", priv->unique_name);
- return NULL;
- }
-
- protocol = _mcd_manager_dup_protocol (priv->manager,
- priv->protocol_name);
-
- if (G_UNLIKELY (protocol == NULL))
- {
- DEBUG ("unable to get protocol for %s account %s", priv->protocol_name,
- priv->unique_name);
- return NULL;
- }
-
params = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free,
(GDestroyNotify) tp_g_value_slice_free);
@@ -3984,11 +3667,11 @@ _mcd_account_dup_parameters (McdAccount *account)
for (iter = protocol_params; iter != NULL; iter = iter->next)
{
TpConnectionManagerParam *param = iter->data;
- const gchar *name = tp_connection_manager_param_get_name (param);
GValue v = G_VALUE_INIT;
- if (mcd_account_get_parameter (account, name, &v, NULL))
+ if (mcd_account_get_parameter (account, param, &v, NULL))
{
+ const gchar *name = tp_connection_manager_param_get_name (param);
g_hash_table_insert (params, g_strdup (name),
tp_g_value_slice_dup (&v));
g_value_unset (&v);
@@ -3997,11 +3680,67 @@ _mcd_account_dup_parameters (McdAccount *account)
g_list_free_full (protocol_params,
(GDestroyNotify) tp_connection_manager_param_free);
- g_object_unref (protocol);
return params;
}
/**
+ * _mcd_account_dup_parameters:
+ * @account: the #McdAccount.
+ *
+ * Get the parameters set for this account. The resulting #GHashTable will be
+ * newly allocated and must be g_hash_table_unref()'d after use.
+ *
+ * Returns: @account's current parameters, or %NULL if they could not be
+ * retrieved.
+ */
+GHashTable *
+_mcd_account_dup_parameters (McdAccount *self)
+{
+ McpAccountManager *api;
+ gchar **untyped_parameters;
+ GHashTable *params = NULL;
+ TpProtocol *protocol;
+
+ g_return_val_if_fail (MCD_IS_ACCOUNT (self), NULL);
+
+ DEBUG ("called");
+
+ /* Maybe our storage plugin knows the types of the parameters? */
+
+ api = MCP_ACCOUNT_MANAGER (self->priv->storage);
+ untyped_parameters = mcp_account_storage_list_untyped_parameters (
+ self->priv->storage_plugin, api, self->priv->unique_name);
+
+ if (untyped_parameters == NULL || *untyped_parameters == NULL)
+ {
+ /* Happy path: there are no parameters that lack types. */
+ params = mcd_storage_dup_typed_parameters (self->priv->storage,
+ self->priv->unique_name);
+ goto finally;
+ }
+
+ /* MC didn't always know parameters' types, so it might need the CM
+ * (or .manager file) to be around to tell it whether "true"
+ * is a string or a boolean… this is ridiculous, but backwards-compatible.
+ */
+ protocol = mcd_account_dup_protocol (self);
+
+ if (protocol != NULL)
+ {
+ params = mcd_account_coerce_parameters (self, protocol);
+ g_object_unref (protocol);
+
+ if (params != NULL)
+ goto finally;
+ }
+
+finally:
+ g_strfreev (untyped_parameters);
+
+ return params;
+}
+
+/**
* mcd_account_request_presence:
* @account: the #McdAccount.
* @presence: a #TpConnectionPresenceType.
@@ -4675,23 +4414,22 @@ mcd_account_get_connection (McdAccount *account)
return priv->connection;
}
-typedef struct
-{
- McdAccountCheckValidityCb callback;
- gpointer user_data;
-} CheckValidityData;
-
-static void
-check_validity_check_parameters_cb (McdAccount *account,
- const GError *invalid_reason,
- gpointer user_data)
+gboolean
+mcd_account_check_validity (McdAccount *account,
+ GError **error)
{
- CheckValidityData *data = (CheckValidityData *) user_data;
McdAccountPrivate *priv = account->priv;
- gboolean now_valid = (invalid_reason == NULL);
- gboolean was_valid = (priv->invalid_reason == NULL);
+ GError *invalid_reason = NULL;
+ gboolean now_valid;
+ gboolean was_valid;
+
+ g_return_val_if_fail (MCD_IS_ACCOUNT (account), FALSE);
+
+ was_valid = (priv->invalid_reason == NULL);
+ now_valid = mcd_account_check_parameters (account, &invalid_reason);
g_clear_error (&priv->invalid_reason);
+
if (invalid_reason != NULL)
{
priv->invalid_reason = g_error_copy (invalid_reason);
@@ -4717,27 +4455,13 @@ check_validity_check_parameters_cb (McdAccount *account,
}
}
- if (data->callback != NULL)
- data->callback (account, invalid_reason, data->user_data);
-
- g_slice_free (CheckValidityData, data);
-}
-
-void
-mcd_account_check_validity (McdAccount *account,
- McdAccountCheckValidityCb callback,
- gpointer user_data)
-{
- CheckValidityData *data;
-
- g_return_if_fail (MCD_IS_ACCOUNT (account));
-
- data = g_slice_new0 (CheckValidityData);
- data->callback = callback;
- data->user_data = user_data;
+ if (invalid_reason != NULL)
+ {
+ g_propagate_error (error, invalid_reason);
+ return FALSE;
+ }
- mcd_account_check_parameters (account, check_validity_check_parameters_cb,
- data);
+ return TRUE;
}
/*
@@ -5235,36 +4959,6 @@ _mcd_account_set_has_been_online (McdAccount *account)
}
}
-McdAccountConnectionContext *
-_mcd_account_get_connection_context (McdAccount *self)
-{
- g_return_val_if_fail (MCD_IS_ACCOUNT (self), NULL);
-
- return self->priv->connection_context;
-}
-
-void
-_mcd_account_set_connection_context (McdAccount *self,
- McdAccountConnectionContext *c)
-{
- g_return_if_fail (MCD_IS_ACCOUNT (self));
-
- if (self->priv->connection_context != NULL)
- {
- _mcd_account_connection_context_free (self->priv->connection_context);
- }
-
- self->priv->connection_context = c;
-}
-
-gboolean
-_mcd_account_get_always_on (McdAccount *self)
-{
- g_return_val_if_fail (MCD_IS_ACCOUNT (self), FALSE);
-
- return self->priv->always_on;
-}
-
gboolean
_mcd_account_needs_dispatch (McdAccount *self)
{
@@ -5273,19 +4967,6 @@ _mcd_account_needs_dispatch (McdAccount *self)
return self->priv->always_dispatch;
}
-gboolean
-mcd_account_parameter_is_secret (McdAccount *self, const gchar *name)
-{
- McdAccountPrivate *priv = self->priv;
- const TpConnectionManagerParam *param;
-
- param = mcd_manager_get_protocol_param (priv->manager,
- priv->protocol_name, name);
-
- return (param != NULL &&
- tp_connection_manager_param_is_secret (param));
-}
-
void
_mcd_account_set_changing_presence (McdAccount *self, gboolean value)
{
@@ -5345,3 +5026,114 @@ mcd_account_set_waiting_for_connectivity (McdAccount *self,
{
self->priv->waiting_for_connectivity = waiting;
}
+
+void
+_mcd_account_connection_begin (McdAccount *account,
+ gboolean user_initiated)
+{
+ McdAccountConnectionContext *ctx;
+ TpProtocol *protocol;
+
+ /* check whether a connection process is already ongoing */
+ if (account->priv->connection_context != NULL)
+ {
+ DEBUG ("already trying to connect");
+ return;
+ }
+
+ /* get account params */
+ /* create dynamic params HT */
+ /* run the handlers */
+ ctx = g_malloc (sizeof (McdAccountConnectionContext));
+ ctx->user_initiated = user_initiated;
+
+ /* If we get this far, the account should be valid, so getting the
+ * protocol should succeed.
+ */
+ protocol = mcd_account_dup_protocol (account);
+ g_assert (protocol != NULL);
+
+ ctx->params = mcd_account_coerce_parameters (account, protocol);
+ g_assert (ctx->params != NULL);
+
+ /* Inject "account-path-suffix" parameter if supported by the protocol */
+ if (tp_protocol_has_param (protocol, "account-path-suffix"))
+ {
+ g_hash_table_insert (ctx->params, g_strdup ("account-path-suffix"),
+ tp_g_value_slice_new_string (account->priv->unique_name));
+ }
+ g_object_unref (protocol);
+
+ _mcd_account_set_connection_status (account,
+ TP_CONNECTION_STATUS_CONNECTING,
+ TP_CONNECTION_STATUS_REASON_REQUESTED,
+ NULL, NULL, NULL);
+ account->priv->connection_context = ctx;
+
+ mcd_account_connection_proceed_with_reason
+ (account, TRUE, TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED);
+}
+
+void
+mcd_account_connection_proceed_with_reason (McdAccount *account,
+ gboolean success,
+ TpConnectionStatusReason reason)
+{
+ McdAccountConnectionContext *ctx;
+ gboolean delayed;
+
+ /* call next handler, or terminate the chain (emitting proper signal).
+ * if everything is fine, call mcd_manager_create_connection() and
+ * _mcd_connection_connect () with the dynamic parameters. Remove that call
+ * from mcd_manager_create_connection() */
+ ctx = account->priv->connection_context;
+ g_return_if_fail (ctx != NULL);
+ g_return_if_fail (ctx->params != NULL);
+
+ if (success)
+ {
+ if (mcd_connectivity_monitor_is_online (
+ mcd_account_get_connectivity_monitor (account)) || _mcd_account_needs_dispatch (account))
+ {
+ DEBUG ("%s wants to connect and we're online - go for it",
+ mcd_account_get_unique_name (account));
+ delayed = FALSE;
+ }
+ else if (!mcd_account_get_waiting_for_connectivity (account))
+ {
+ DEBUG ("%s wants to connect, but we're offline; queuing it up",
+ mcd_account_get_unique_name (account));
+ delayed = TRUE;
+ mcd_account_set_waiting_for_connectivity (account, TRUE);
+ }
+ else
+ {
+ DEBUG ("%s wants to connect, but is already waiting for "
+ "connectivity?", mcd_account_get_unique_name (account));
+ delayed = TRUE;
+ }
+ }
+ else
+ {
+ DEBUG ("%s failed to connect: reason code %d",
+ mcd_account_get_unique_name (account), reason);
+ delayed = FALSE;
+ }
+
+ if (!delayed)
+ {
+ /* end of the chain */
+ if (success)
+ {
+ _mcd_account_connect (account, ctx->params);
+ }
+ else
+ {
+ _mcd_account_set_connection_status
+ (account, TP_CONNECTION_STATUS_DISCONNECTED, reason, NULL,
+ TP_ERROR_STR_DISCONNECTED, NULL);
+ }
+ tp_clear_pointer (&account->priv->connection_context,
+ _mcd_account_connection_context_free);
+ }
+}
diff --git a/src/mcd-account.h b/src/mcd-account.h
index 7843c279..85a56cce 100644
--- a/src/mcd-account.h
+++ b/src/mcd-account.h
@@ -40,6 +40,7 @@ typedef struct _McdAccountClass McdAccountClass;
#include "mcd-connection.h"
#include "mcd-account-manager.h"
+#include "mcd-dbusprop.h"
struct _McdAccount
{
@@ -60,9 +61,6 @@ GQuark mcd_account_error_quark (void);
typedef void (*McdAccountLoadCb) (McdAccount *account,
const GError *error,
gpointer user_data);
-typedef void (*McdAccountDeleteCb) (McdAccount *account,
- const GError *error,
- gpointer user_data);
struct _McdAccountClass
{
@@ -82,22 +80,24 @@ GType mcd_account_get_type (void);
McdAccount *mcd_account_new (McdAccountManager *account_manager,
const gchar *name,
- McdConnectivityMonitor *minotaur);
+ McdConnectivityMonitor *minotaur,
+ McpAccountStorage *storage_plugin);
-void mcd_account_delete (McdAccount *account, McdAccountDeleteCb callback,
- gpointer user_data);
+void mcd_account_delete_async (McdAccount *account,
+ McdDBusPropSetFlags flags,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean mcd_account_delete_finish (McdAccount *account,
+ GAsyncResult *result,
+ GError **error);
const gchar *mcd_account_get_unique_name (McdAccount *account);
const gchar *mcd_account_get_object_path (McdAccount *account);
gboolean mcd_account_is_valid (McdAccount *account);
-typedef void (*McdAccountCheckValidityCb) (McdAccount *account,
- const GError *invalid_reason,
- gpointer user_data);
-void mcd_account_check_validity (McdAccount *account,
- McdAccountCheckValidityCb callback,
- gpointer user_data);
+gboolean mcd_account_check_validity (McdAccount *account,
+ GError **error);
gboolean mcd_account_is_enabled (McdAccount *account);
@@ -126,19 +126,13 @@ McdConnection *mcd_account_get_connection (McdAccount *account);
gboolean mcd_account_check_request (McdAccount *account, GHashTable *request,
GError **error);
-gboolean mcd_account_parameter_is_secret (McdAccount *self,
- const gchar *name);
-
void mcd_account_altered_by_plugin (McdAccount *account, const gchar *name);
gchar * mcd_account_dup_display_name (McdAccount *self);
-gboolean mcd_account_get_parameter (McdAccount *account, const gchar *name,
- GValue *parameter,
- GError **error);
-
gboolean mcd_account_get_parameter_of_known_type (McdAccount *account,
const gchar *name,
+ const GVariantType *variant_type,
GType type,
GValue *parameter,
GError **error);
@@ -154,9 +148,7 @@ gboolean mcd_account_get_waiting_for_connectivity (McdAccount *self);
void mcd_account_set_waiting_for_connectivity (McdAccount *self,
gboolean waiting);
-void mcd_account_connection_proceed (McdAccount *account, gboolean success);
-void mcd_account_connection_proceed_with_reason
- (McdAccount *account, gboolean success, TpConnectionStatusReason reason);
+McpAccountStorage *mcd_account_get_storage_plugin (McdAccount *account);
G_END_DECLS
diff --git a/src/mcd-channel-priv.h b/src/mcd-channel-priv.h
index b45ad313..9e045837 100644
--- a/src/mcd-channel-priv.h
+++ b/src/mcd-channel-priv.h
@@ -67,10 +67,6 @@ void _mcd_channel_set_request_proxy (McdChannel *channel, McdChannel *source);
void _mcd_channel_close (McdChannel *channel);
-G_GNUC_INTERNAL void _mcd_channel_depart (McdChannel *channel,
- TpChannelGroupChangeReason reason,
- const gchar *message);
-
G_GNUC_INTERNAL gboolean _mcd_channel_is_primary_for_path (McdChannel *self,
const gchar *channel_path);
diff --git a/src/mcd-channel.c b/src/mcd-channel.c
index fe2b0323..a0d0a95c 100644
--- a/src/mcd-channel.c
+++ b/src/mcd-channel.c
@@ -48,8 +48,6 @@
#include "mcd-enum-types.h"
#include "request.h"
-#include "_gen/interfaces.h"
-
#define MCD_CHANNEL_PRIV(channel) (MCD_CHANNEL (channel)->priv)
G_DEFINE_TYPE (McdChannel, mcd_channel, MCD_TYPE_MISSION)
@@ -1123,95 +1121,6 @@ mcd_channel_get_tp_channel (McdChannel *channel)
return channel->priv->tp_chan;
}
-static void
-mcd_channel_depart_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer data G_GNUC_UNUSED)
-{
- GError *error = NULL;
-
- /* By this point, TpChannel has already called Close() for us;
- * we only get an error if that failed. If Close() fails, there's
- * not a whole lot we can do about it. */
-
- if (!tp_channel_leave_finish (TP_CHANNEL (source_object), result, &error))
- {
- WARNING ("failed to depart, even via Close(): %s %d: %s",
- g_quark_to_string (error->domain), error->code, error->message);
- g_error_free (error);
- }
-}
-
-typedef struct {
- TpChannelGroupChangeReason reason;
- gchar *message;
-} DepartData;
-
-static void
-mcd_channel_ready_to_depart_cb (GObject *source_object,
- GAsyncResult *result,
- gpointer data)
-{
- TpChannel *channel = TP_CHANNEL (source_object);
- DepartData *d = data;
- GError *error = NULL;
-
- if (!tp_proxy_prepare_finish (channel, result, &error))
- {
- DEBUG ("%s %d: %s", g_quark_to_string (error->domain), error->code,
- error->message);
- g_free (d->message);
- g_slice_free (DepartData, d);
- g_clear_error (&error);
- return;
- }
-
- /* If it's a Group, this will leave gracefully.
- * If not, it will just close it. Either's good. */
- tp_channel_leave_async (channel, d->reason, d->message,
- mcd_channel_depart_cb, NULL);
-}
-
-void
-_mcd_channel_depart (McdChannel *channel,
- TpChannelGroupChangeReason reason,
- const gchar *message)
-{
- DepartData *d;
- const GError *invalidated;
- GQuark just_group_feature[] = { TP_CHANNEL_FEATURE_GROUP, 0 };
-
- g_return_if_fail (MCD_IS_CHANNEL (channel));
-
- g_return_if_fail (channel->priv->tp_chan != NULL);
- g_return_if_fail (message != NULL);
-
- invalidated = tp_proxy_get_invalidated (channel->priv->tp_chan);
-
- if (invalidated != NULL)
- {
- DEBUG ("%s %d: %s", g_quark_to_string (invalidated->domain),
- invalidated->code, invalidated->message);
- return;
- }
-
- if (message[0] == '\0' && reason == TP_CHANNEL_GROUP_CHANGE_REASON_NONE)
- {
- /* exactly equivalent to Close(), so skip the Group interface */
- tp_channel_close_async (channel->priv->tp_chan, NULL, NULL);
- return;
- }
-
- d = g_slice_new (DepartData);
- d->reason = reason;
- d->message = g_strdup (message);
-
- /* tp_channel_leave_async documents calling it without first preparing
- * GROUP as deprecated. */
- tp_proxy_prepare_async (channel->priv->tp_chan, just_group_feature,
- mcd_channel_ready_to_depart_cb, d);
-}
-
/*
* _mcd_channel_is_primary_for_path:
* @self: an McdChannel
diff --git a/src/mcd-client-priv.h b/src/mcd-client-priv.h
index c00ce13a..069d2a67 100644
--- a/src/mcd-client-priv.h
+++ b/src/mcd-client-priv.h
@@ -97,8 +97,6 @@ G_GNUC_INTERNAL const GList *_mcd_client_proxy_get_handler_filters
(McdClientProxy *self);
G_GNUC_INTERNAL gboolean _mcd_client_proxy_get_bypass_approval
(McdClientProxy *self);
-G_GNUC_INTERNAL gboolean _mcd_client_proxy_get_bypass_observers
- (McdClientProxy *self);
G_GNUC_INTERNAL gboolean _mcd_client_proxy_get_delay_approvers
(McdClientProxy *self);
diff --git a/src/mcd-client.c b/src/mcd-client.c
index 455cfd77..ec5c504b 100644
--- a/src/mcd-client.c
+++ b/src/mcd-client.c
@@ -68,7 +68,6 @@ struct _McdClientProxyPrivate
gboolean introspect_started;
gboolean ready;
gboolean bypass_approval;
- gboolean bypass_observers;
gboolean delay_approvers;
gboolean recover;
@@ -400,10 +399,6 @@ parse_client_file (McdClientProxy *client,
g_key_file_get_boolean (file, TP_IFACE_CLIENT_HANDLER,
"BypassApproval", NULL);
- client->priv->bypass_observers =
- g_key_file_get_boolean (file, TP_IFACE_CLIENT_HANDLER,
- "BypassObservers", NULL);
-
client->priv->delay_approvers =
g_key_file_get_boolean (file, TP_IFACE_CLIENT_OBSERVER,
"DelayApprovers", NULL);
@@ -664,10 +659,6 @@ _mcd_client_proxy_handler_get_all_cb (TpProxy *proxy,
self->priv->bypass_approval = bypass;
DEBUG ("%s has BypassApproval=%c", bus_name, bypass ? 'T' : 'F');
- bypass = tp_asv_get_boolean (properties, "BypassObservers", NULL);
- self->priv->bypass_observers = bypass;
- DEBUG ("%s has BypassObservers=%c", bus_name, bypass ? 'T' : 'F');
-
/* don't emit handler-capabilities-changed if we're not actually available
* any more - if that's the case, then we already signalled our loss of
* any capabilities */
@@ -1369,14 +1360,6 @@ _mcd_client_proxy_get_bypass_approval (McdClientProxy *self)
}
gboolean
-_mcd_client_proxy_get_bypass_observers (McdClientProxy *self)
-{
- g_return_val_if_fail (MCD_IS_CLIENT_PROXY (self), FALSE);
-
- return self->priv->bypass_observers;
-}
-
-gboolean
_mcd_client_proxy_get_delay_approvers (McdClientProxy *self)
{
g_return_val_if_fail (MCD_IS_CLIENT_PROXY (self), FALSE);
diff --git a/src/mcd-connection-service-points.c b/src/mcd-connection-service-points.c
index 58b65f19..b52abe30 100644
--- a/src/mcd-connection-service-points.c
+++ b/src/mcd-connection-service-points.c
@@ -31,25 +31,6 @@
#include <telepathy-glib/telepathy-glib-dbus.h>
static void
-service_point_contact_cb (GObject *source,
- GAsyncResult *result,
- gpointer user_data)
-{
- McdConnection *connection = MCD_CONNECTION (user_data);
- TpContact *contact = tp_connection_dup_contact_by_id_finish (
- TP_CONNECTION (source), result, NULL);
-
- if (contact != NULL)
- {
- mcd_connection_add_emergency_handle (connection,
- tp_contact_get_handle (contact));
- g_object_unref (contact);
- }
-
- g_object_unref (connection);
-}
-
-static void
parse_services_list (McdConnection *connection,
const GPtrArray *services)
{
@@ -76,22 +57,6 @@ parse_services_list (McdConnection *connection,
if (e_numbers != NULL)
{
- GSList *service;
- TpConnection *tp_conn = mcd_connection_get_tp_connection (connection);
-
- /* FIXME: in 1.0, drop this and spec that when calling a service point,
- * you should use TargetID. See
- * https://bugs.freedesktop.org/show_bug.cgi?id=59162#c3 */
- for (service = e_numbers; service != NULL; service =g_slist_next (service))
- {
- const gchar * const *iter;
-
- for (iter = service->data; iter != NULL && *iter != NULL; iter++)
- tp_connection_dup_contact_by_id_async (tp_conn,
- *iter, 0, NULL, service_point_contact_cb,
- g_object_ref (connection));
- }
-
_mcd_connection_take_emergency_numbers (connection, e_numbers);
}
}
@@ -125,31 +90,16 @@ service_points_fetched_cb (TpProxy *proxy,
parse_services_list (connection, g_value_get_boxed (value));
}
-static void
-service_point_interface_check (TpConnection *tp_conn,
- const gchar **interfaces,
- const GError *error,
- gpointer data,
- GObject *connection)
+void
+mcd_connection_service_point_setup (McdConnection *connection,
+ gboolean watch)
{
- const gchar *interface;
- gboolean found = FALSE;
- gboolean watch = GPOINTER_TO_UINT (data);
- guint i = 0;
-
- if (interfaces == NULL)
- return;
-
- for (interface = interfaces[0];
- !found && !tp_str_empty (interface);
- interface = interfaces[++i])
- {
- if (!tp_strdiff (interface, TP_IFACE_CONNECTION_INTERFACE_SERVICE_POINT))
- found = TRUE;
- }
+ TpConnection *tp_conn = mcd_connection_get_tp_connection (connection);
- if (!found)
- return;
+ g_return_if_fail (MCD_IS_CONNECTION (connection));
+ g_return_if_fail (TP_IS_PROXY (tp_conn));
+ g_return_if_fail (tp_proxy_is_prepared (tp_conn,
+ TP_CONNECTION_FEATURE_CONNECTED));
/* so we know if/when the service points change (eg the SIM might not be
* accessible yet, in which case the call below won't return any entries)
@@ -157,25 +107,12 @@ service_point_interface_check (TpConnection *tp_conn,
*/
if (watch)
tp_cli_connection_interface_service_point_connect_to_service_points_changed
- (tp_conn, service_points_changed_cb, NULL, NULL, connection, NULL);
+ (tp_conn, service_points_changed_cb, NULL, NULL,
+ (GObject *) connection, NULL);
/* fetch the current list to initialise our state */
tp_cli_dbus_properties_call_get (tp_conn, -1,
TP_IFACE_CONNECTION_INTERFACE_SERVICE_POINT,
"KnownServicePoints", service_points_fetched_cb,
- NULL, NULL, connection);
-}
-
-void
-mcd_connection_service_point_setup (McdConnection *connection, gboolean watch)
-{
- TpConnection *tp_conn = mcd_connection_get_tp_connection (connection);
-
- if (G_UNLIKELY (!tp_conn))
- return;
-
- /* see if the connection supports the service point interface */
- tp_cli_connection_call_get_interfaces (tp_conn, -1,
- service_point_interface_check,
- GUINT_TO_POINTER (watch), NULL, G_OBJECT (connection));
+ NULL, NULL, (GObject *) connection);
}
diff --git a/src/mcd-connection.c b/src/mcd-connection.c
index fe7029fd..066deba2 100644
--- a/src/mcd-connection.c
+++ b/src/mcd-connection.c
@@ -50,6 +50,7 @@
#include <stdlib.h>
#include <dlfcn.h>
+#include <dbus/dbus.h>
#include <telepathy-glib/telepathy-glib.h>
#include <telepathy-glib/telepathy-glib-dbus.h>
@@ -104,7 +105,6 @@ struct _McdConnectionPrivate
TpConnectionStatusReason abort_reason;
guint got_contact_capabilities : 1;
guint has_presence_if : 1;
- guint has_capabilities_if : 1;
guint has_contact_capabilities_if : 1;
guint has_power_saving_if : 1;
@@ -173,7 +173,8 @@ static const gchar * const *presence_fallbacks[] = {
};
static void _mcd_connection_release_tp_connection (McdConnection *connection,
- McdInhibit *inhibit);
+ McdInhibit *inhibit,
+ gboolean already_signalled);
static gboolean request_channel_new_iface (McdConnection *connection,
McdChannel *channel);
@@ -487,40 +488,6 @@ _mcd_connection_request_presence (McdConnection *self,
}
static void
-on_new_channel (TpConnection *proxy, const gchar *chan_obj_path,
- const gchar *chan_type, guint handle_type, guint handle,
- gboolean suppress_handler, gpointer user_data,
- GObject *weak_object)
-{
- McdConnection *connection = MCD_CONNECTION (weak_object);
- McdConnectionPrivate *priv = user_data;
- McdChannel *channel;
-
- DEBUG ("%s (t=%s, ht=%u, h=%u, suppress=%c)",
- chan_obj_path, chan_type, handle_type, handle,
- suppress_handler ? 'T' : 'F');
-
- if (priv->dispatched_initial_channels)
- {
- channel = mcd_channel_new_from_path (proxy,
- chan_obj_path,
- chan_type, handle, handle_type);
- if (G_UNLIKELY (!channel)) return;
- mcd_operation_take_mission (MCD_OPERATION (connection),
- MCD_MISSION (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_add_channel (priv->dispatcher, channel,
- suppress_handler, suppress_handler);
- }
-}
-
-static void
_foreach_channel_remove (McdMission * mission, McdOperation * operation)
{
g_assert (MCD_IS_MISSION (mission));
@@ -624,10 +591,6 @@ on_connection_status_changed (TpConnection *tp_conn, GParamSpec *pspec,
priv->probation_drop_count = 0;
}
- mcd_connection_service_point_setup (connection,
- !priv->service_points_watched);
- priv->service_points_watched = TRUE;
-
priv->connected = TRUE;
}
break;
@@ -738,7 +701,7 @@ mcd_connection_invalidated_cb (TpConnection *tp_conn,
DEBUG ("Proxy destroyed (%s)!", message);
- _mcd_connection_release_tp_connection (connection, NULL);
+ _mcd_connection_release_tp_connection (connection, NULL, FALSE);
if (priv->connected &&
priv->abort_reason != TP_CONNECTION_STATUS_REASON_REQUESTED &&
@@ -1083,65 +1046,6 @@ mcd_connection_setup_requests (McdConnection *connection)
}
static void
-list_channels_cb (TpConnection *connection,
- const GPtrArray *structs,
- const GError *error,
- gpointer user_data,
- GObject *weak_object)
-{
- McdConnection *self = MCD_CONNECTION (weak_object);
- guint i;
-
- if (error)
- {
- g_warning ("ListChannels got error: %s", error->message);
- return;
- }
-
- for (i = 0; i < structs->len; i++)
- {
- GValueArray *va = g_ptr_array_index (structs, i);
- const gchar *object_path;
- GHashTable *channel_props;
-
- object_path = g_value_get_boxed (va->values + 0);
-
- DEBUG ("%s (t=%s, ht=%u, h=%u)",
- object_path,
- g_value_get_string (va->values + 1),
- g_value_get_uint (va->values + 2),
- g_value_get_uint (va->values + 3));
-
- /* this is not the most efficient thing we could possibly do, but
- * we're on a fallback path so it's OK to be a bit slow */
- channel_props = g_hash_table_new (g_str_hash, g_str_equal);
- g_hash_table_insert (channel_props, TP_IFACE_CHANNEL ".ChannelType",
- va->values + 1);
- g_hash_table_insert (channel_props, TP_IFACE_CHANNEL ".TargetHandleType",
- va->values + 2);
- g_hash_table_insert (channel_props, TP_IFACE_CHANNEL ".TargetHandle",
- va->values + 3);
- mcd_connection_found_channel (self, object_path, channel_props);
- g_hash_table_unref (channel_props);
- }
-
- self->priv->dispatched_initial_channels = TRUE;
-}
-
-static void
-mcd_connection_setup_pre_requests (McdConnection *connection)
-{
- McdConnectionPrivate *priv = connection->priv;
-
- tp_cli_connection_connect_to_new_channel
- (priv->tp_conn, on_new_channel, priv, NULL,
- (GObject *)connection, NULL);
-
- tp_cli_connection_call_list_channels (priv->tp_conn, -1,
- list_channels_cb, priv, NULL, (GObject *) connection);
-}
-
-static void
on_connection_ready (GObject *source_object, GAsyncResult *result,
gpointer user_data)
{
@@ -1161,13 +1065,41 @@ on_connection_ready (GObject *source_object, GAsyncResult *result,
if (!connection)
goto finally;
+ if (!tp_proxy_has_interface_by_id (tp_conn,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS))
+ {
+ GHashTable *asv;
+
+ DEBUG ("%s: connection manager is too old",
+ tp_proxy_get_object_path (tp_conn));
+ connection->priv->abort_reason =
+ TP_CONNECTION_STATUS_REASON_NONE_SPECIFIED;
+ asv = tp_asv_new (
+ "debug-message", G_TYPE_STRING,
+ "Connection manager does not implement Requests interface",
+ NULL);
+ g_signal_emit (connection, signals[CONNECTION_STATUS_CHANGED], 0,
+ TP_CONNECTION_STATUS_DISCONNECTED,
+ connection->priv->abort_reason,
+ tp_conn, TP_ERROR_STR_SOFTWARE_UPGRADE_REQUIRED, asv);
+ g_hash_table_unref (asv);
+ _mcd_connection_release_tp_connection (connection, NULL, TRUE);
+ goto finally;
+ }
+
DEBUG ("connection is ready");
priv = MCD_CONNECTION_PRIV (connection);
+ if (tp_proxy_has_interface_by_id (tp_conn,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_SERVICE_POINT))
+ {
+ mcd_connection_service_point_setup (connection,
+ !priv->service_points_watched);
+ priv->service_points_watched = TRUE;
+ }
+
priv->has_presence_if = tp_proxy_has_interface_by_id
(tp_conn, TP_IFACE_QUARK_CONNECTION_INTERFACE_SIMPLE_PRESENCE);
- priv->has_capabilities_if = tp_proxy_has_interface_by_id (tp_conn,
- TP_IFACE_QUARK_CONNECTION_INTERFACE_CAPABILITIES);
priv->has_contact_capabilities_if = tp_proxy_has_interface_by_id (tp_conn,
TP_IFACE_QUARK_CONNECTION_INTERFACE_CONTACT_CAPABILITIES);
priv->has_power_saving_if = tp_proxy_has_interface_by_id (tp_conn,
@@ -1202,11 +1134,9 @@ _mcd_connection_start_dispatching (McdConnection *self,
self->priv->dispatching_started = TRUE;
- if (tp_proxy_has_interface_by_id (self->priv->tp_conn,
- TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS))
- mcd_connection_setup_requests (self);
- else
- mcd_connection_setup_pre_requests (self);
+ g_return_if_fail (tp_proxy_has_interface_by_id (self->priv->tp_conn,
+ TP_IFACE_QUARK_CONNECTION_INTERFACE_REQUESTS));
+ mcd_connection_setup_requests (self);
/* FIXME: why is this here? if we need to update caps before and after *
* connected, it should be in the call_when_ready callback. */
@@ -1294,12 +1224,13 @@ mcd_connection_early_get_statuses_cb (TpProxy *proxy,
}
static void
-mcd_connection_early_get_interfaces_cb (TpConnection *tp_conn,
- const gchar **interfaces,
+mcd_connection_early_get_interfaces_cb (TpProxy *proxy,
+ const GValue *value,
const GError *error,
gpointer user_data,
GObject *weak_object)
{
+ TpConnection *tp_conn = TP_CONNECTION (proxy);
McdConnection *self = MCD_CONNECTION (weak_object);
const gchar **iter;
@@ -1317,9 +1248,11 @@ mcd_connection_early_get_interfaces_cb (TpConnection *tp_conn,
tp_proxy_get_object_path (tp_conn),
g_quark_to_string (error->domain), error->code, error->message);
}
- else
+ else if (G_VALUE_HOLDS (value, G_TYPE_STRV))
{
- for (iter = interfaces; *iter != NULL; iter++)
+ for (iter = g_value_get_boxed (value);
+ iter != NULL && *iter != NULL;
+ iter++)
{
GQuark q = g_quark_try_string (*iter);
@@ -1373,6 +1306,12 @@ mcd_connection_early_get_interfaces_cb (TpConnection *tp_conn,
}
}
}
+ else
+ {
+ DEBUG ("%s: Early GetInterfaces returned unexpected type %s",
+ tp_proxy_get_object_path (tp_conn),
+ G_VALUE_TYPE_NAME (value));
+ }
mcd_connection_done_task_before_connect (self);
}
@@ -1501,7 +1440,8 @@ request_connection_cb (TpConnectionManager *proxy, const gchar *bus_name,
/* TpConnection doesn't yet know how to get this information before
* the Connection goes to CONNECTED, so we'll have to do it ourselves */
- tp_cli_connection_call_get_interfaces (priv->tp_conn, -1,
+ tp_cli_dbus_properties_call_get (priv->tp_conn, -1,
+ TP_IFACE_CONNECTION, "Interfaces",
mcd_connection_early_get_interfaces_cb, NULL, NULL,
(GObject *) connection);
@@ -1556,13 +1496,18 @@ _mcd_connection_finalize (GObject * object)
static void
_mcd_connection_release_tp_connection (McdConnection *connection,
- McdInhibit *inhibit)
+ McdInhibit *inhibit,
+ gboolean already_signalled)
{
McdConnectionPrivate *priv = MCD_CONNECTION_PRIV (connection);
DEBUG ("%p", connection);
- if (priv->abort_reason == TP_CONNECTION_STATUS_REASON_REQUESTED)
+ if (already_signalled)
+ {
+ DEBUG ("already emitted connection-status-changed");
+ }
+ else if (priv->abort_reason == TP_CONNECTION_STATUS_REASON_REQUESTED)
{
g_signal_emit (connection, signals[CONNECTION_STATUS_CHANGED], 0,
TP_CONNECTION_STATUS_DISCONNECTED,
@@ -1675,7 +1620,7 @@ _mcd_connection_dispose (GObject * object)
mcd_operation_foreach (MCD_OPERATION (connection),
(GFunc) _foreach_channel_remove, connection);
- _mcd_connection_release_tp_connection (connection, NULL);
+ _mcd_connection_release_tp_connection (connection, NULL, FALSE);
g_assert (priv->tp_conn == NULL);
if (priv->account)
@@ -1892,8 +1837,6 @@ mcd_connection_class_init (McdConnectionClass * klass)
object_class->set_property = _mcd_connection_set_property;
object_class->get_property = _mcd_connection_get_property;
- _mcd_ext_register_dbus_glib_marshallers ();
-
tp_connection_init_known_interfaces ();
/* Properties */
@@ -1934,7 +1877,7 @@ mcd_connection_class_init (McdConnectionClass * klass)
g_object_class_install_property
(object_class, PROP_SLACKER,
g_param_spec_object ("slacker",
- "MCE slacker",
+ "Slacker",
"Slacker object notifies us of user inactivity",
MCD_TYPE_SLACKER,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
@@ -2123,7 +2066,7 @@ mcd_connection_close (McdConnection *connection,
connection->priv->closed = TRUE;
connection->priv->abort_reason = TP_CONNECTION_STATUS_REASON_REQUESTED;
- _mcd_connection_release_tp_connection (connection, inhibit);
+ _mcd_connection_release_tp_connection (connection, inhibit, FALSE);
mcd_mission_abort (MCD_MISSION (connection));
}
@@ -2257,7 +2200,7 @@ _mcd_connection_set_tp_connection (McdConnection *connection,
}
DEBUG ("releasing old connection first");
- _mcd_connection_release_tp_connection (connection, NULL);
+ _mcd_connection_release_tp_connection (connection, NULL, FALSE);
}
g_assert (priv->tp_conn == NULL);
diff --git a/src/mcd-dispatch-operation-priv.h b/src/mcd-dispatch-operation-priv.h
index ce168fc3..a61bb7be 100644
--- a/src/mcd-dispatch-operation-priv.h
+++ b/src/mcd-dispatch-operation-priv.h
@@ -108,9 +108,6 @@ G_GNUC_INTERNAL void _mcd_dispatch_operation_start_plugin_delay (
G_GNUC_INTERNAL void _mcd_dispatch_operation_end_plugin_delay (
McdDispatchOperation *self);
-G_GNUC_INTERNAL void _mcd_dispatch_operation_leave_channels (
- McdDispatchOperation *self, TpChannelGroupChangeReason reason,
- const gchar *message);
G_GNUC_INTERNAL void _mcd_dispatch_operation_close_channels (
McdDispatchOperation *self);
G_GNUC_INTERNAL void _mcd_dispatch_operation_destroy_channels (
diff --git a/src/mcd-dispatch-operation.c b/src/mcd-dispatch-operation.c
index 4948b6be..4abaf078 100644
--- a/src/mcd-dispatch-operation.c
+++ b/src/mcd-dispatch-operation.c
@@ -388,8 +388,6 @@ static void mcd_dispatch_operation_set_channel_handled_by (
const gchar *well_known_name);
static gboolean _mcd_dispatch_operation_handlers_can_bypass_approval (
McdDispatchOperation *self);
-static gboolean _mcd_dispatch_operation_handlers_can_bypass_observers (
- McdDispatchOperation *self);
static void
_mcd_dispatch_operation_check_client_locks (McdDispatchOperation *self)
@@ -1828,34 +1826,6 @@ _mcd_dispatch_operation_handlers_can_bypass_approval (
return FALSE;
}
-/* this is analogous to *_can_bypass_handlers() method above */
-static gboolean
-_mcd_dispatch_operation_handlers_can_bypass_observers (
- McdDispatchOperation *self)
-{
- gchar **iter;
-
- for (iter = self->priv->possible_handlers;
- iter != NULL && *iter != NULL;
- iter++)
- {
- McdClientProxy *handler = _mcd_client_registry_lookup (
- self->priv->client_registry, *iter);
-
- if (handler != NULL)
- {
- gboolean bypass = _mcd_client_proxy_get_bypass_observers (
- handler);
-
- DEBUG ("%s has BypassObservers=%c", *iter, bypass ? 'T' : 'F');
- return bypass;
- }
- }
-
- return FALSE;
-}
-
-
gboolean
_mcd_dispatch_operation_has_channel (McdDispatchOperation *self,
McdChannel *channel)
@@ -2240,15 +2210,8 @@ _mcd_dispatch_operation_run_clients (McdDispatchOperation *self)
{
const GList *mini_plugins;
- if (_mcd_dispatch_operation_handlers_can_bypass_observers (self))
- {
- DEBUG ("Bypassing observers");
- }
- else
- {
- DEBUG ("Running observers");
- _mcd_dispatch_operation_run_observers (self);
- }
+ DEBUG ("Running observers");
+ _mcd_dispatch_operation_run_observers (self);
for (mini_plugins = mcp_list_objects ();
mini_plugins != NULL;
@@ -2544,29 +2507,6 @@ _mcd_dispatch_operation_forget_channels (McdDispatchOperation *self)
}
void
-_mcd_dispatch_operation_leave_channels (McdDispatchOperation *self,
- TpChannelGroupChangeReason reason,
- const gchar *message)
-{
- if (message == NULL)
- {
- message = "";
- }
-
- if (self->priv->channel != NULL)
- {
- /* Take a temporary copy, because self->priv->channels could
- * be modified as a result */
- McdChannel *channel = g_object_ref (self->priv->channel);
-
- _mcd_channel_depart (channel, reason, message);
- g_object_unref (channel);
- }
-
- _mcd_dispatch_operation_forget_channels (self);
-}
-
-void
_mcd_dispatch_operation_close_channels (McdDispatchOperation *self)
{
if (self->priv->channel != NULL)
diff --git a/src/mcd-dispatcher.c b/src/mcd-dispatcher.c
index b004b096..3e6e1c16 100644
--- a/src/mcd-dispatcher.c
+++ b/src/mcd-dispatcher.c
@@ -59,8 +59,6 @@
#include "mcd-misc.h"
#include "plugin-loader.h"
-#include "_gen/svc-dispatcher.h"
-
#include <telepathy-glib/telepathy-glib.h>
#include <telepathy-glib/telepathy-glib-dbus.h>
@@ -70,11 +68,6 @@
#include <string.h>
#include "sp_timestamp.h"
-#define CREATE_CHANNEL TP_IFACE_CONNECTION_INTERFACE_REQUESTS ".CreateChannel"
-#define ENSURE_CHANNEL TP_IFACE_CONNECTION_INTERFACE_REQUESTS ".EnsureChannel"
-#define SEND_MESSAGE \
- TP_IFACE_CHANNEL_DISPATCHER ".Interface.Messages.DRAFT.SendMessage"
-
#define MCD_DISPATCHER_PRIV(dispatcher) (MCD_DISPATCHER (dispatcher)->priv)
static void dispatcher_iface_init (gpointer, gpointer);
@@ -84,7 +77,7 @@ static void messages_iface_init (gpointer, gpointer);
G_DEFINE_TYPE_WITH_CODE (McdDispatcher, mcd_dispatcher, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_DISPATCHER,
dispatcher_iface_init);
- G_IMPLEMENT_INTERFACE (MC_TYPE_SVC_CHANNEL_DISPATCHER_INTERFACE_MESSAGES_DRAFT,
+ G_IMPLEMENT_INTERFACE (TP_TYPE_SVC_CHANNEL_DISPATCHER_INTERFACE_MESSAGES1,
messages_iface_init);
G_IMPLEMENT_INTERFACE (
TP_TYPE_SVC_CHANNEL_DISPATCHER_INTERFACE_OPERATION_LIST,
@@ -357,6 +350,7 @@ _mcd_dispatcher_set_property (GObject * obj, guint prop_id,
static const char * const interfaces[] = {
TP_IFACE_CHANNEL_DISPATCHER_INTERFACE_OPERATION_LIST,
+ TP_IFACE_CHANNEL_DISPATCHER_INTERFACE_MESSAGES1,
NULL
};
@@ -595,17 +589,7 @@ mcd_dispatcher_client_needs_recovery_cb (McdClientProxy *client,
for (list = channels; list; list = list->next)
{
TpChannel *channel = list->data;
- const gchar *object_path = tp_proxy_get_object_path (channel);
GVariant *properties;
- McdClientProxy *handler;
-
- /* FIXME: This is not exactly the right behaviour, see fd.o#40305 */
- handler = _mcd_dispatcher_lookup_handler (self, channel, NULL);
- if (handler && _mcd_client_proxy_get_bypass_observers (handler))
- {
- DEBUG ("skipping unobservable channel %s", object_path);
- continue;
- }
properties = tp_channel_dup_immutable_properties (channel);
@@ -1317,92 +1301,6 @@ finally:
}
static void
-dispatcher_channel_request_acl_cleanup (gpointer data)
-{
- McdChannelRequestACL *crd = data;
-
- DEBUG ("cleanup acl (%p)", data);
-
- g_free (crd->account_path);
- g_free (crd->preferred_handler);
- g_hash_table_unref (crd->properties);
- g_object_unref (crd->dispatcher);
- tp_clear_pointer (&crd->request_metadata, g_hash_table_unref);
-
- g_slice_free (McdChannelRequestACL, crd);
-}
-
-static void
-dispatcher_channel_request_acl_success (DBusGMethodInvocation *context,
- gpointer data)
-{
- McdChannelRequestACL *crd = data;
-
- DEBUG ("complete acl (%p)", crd);
-
- dispatcher_request_channel (MCD_DISPATCHER (crd->dispatcher),
- crd->account_path,
- crd->properties,
- crd->user_action_time,
- crd->preferred_handler,
- crd->request_metadata,
- context,
- crd->ensure);
-}
-
-static void
-free_gvalue (gpointer gvalue)
-{
- GValue *gv = gvalue;
-
- g_value_unset (gv);
- g_slice_free (GValue, gv);
-}
-
-static void
-dispatcher_channel_request_acl_start (McdDispatcher *dispatcher,
- const gchar *method,
- const gchar *account_path,
- GHashTable *requested_properties,
- gint64 user_action_time,
- const gchar *preferred_handler,
- GHashTable *request_metadata,
- DBusGMethodInvocation *context,
- gboolean ensure)
-{
- McdChannelRequestACL *crd = g_slice_new0 (McdChannelRequestACL);
- GValue *account = g_slice_new0 (GValue);
- GHashTable *params =
- g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_gvalue);
-
- g_value_init (account, G_TYPE_STRING);
- g_value_set_string (account, account_path);
- g_hash_table_insert (params, "account-path", account);
-
- crd->dispatcher = g_object_ref (dispatcher);
- crd->account_path = g_strdup (account_path);
- crd->preferred_handler = g_strdup (preferred_handler);
- crd->properties = g_hash_table_ref (requested_properties);
- crd->user_action_time = user_action_time;
- crd->ensure = ensure;
- crd->request_metadata = request_metadata != NULL ?
- g_hash_table_ref (request_metadata) : NULL;
-
- DEBUG ("start %s.%s acl (%p)", account_path, method, crd);
-
- mcp_dbus_acl_authorised_async (dispatcher->priv->dbus_daemon,
- context,
- DBUS_ACL_TYPE_METHOD,
- method,
- params,
- dispatcher_channel_request_acl_success,
- crd,
- dispatcher_channel_request_acl_cleanup);
-
- g_hash_table_unref (params);
-}
-
-static void
dispatcher_create_channel (TpSvcChannelDispatcher *iface,
const gchar *account_path,
GHashTable *requested_properties,
@@ -1410,15 +1308,14 @@ dispatcher_create_channel (TpSvcChannelDispatcher *iface,
const gchar *preferred_handler,
DBusGMethodInvocation *context)
{
- dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface),
- CREATE_CHANNEL,
- account_path,
- requested_properties,
- user_action_time,
- preferred_handler,
- NULL,
- context,
- FALSE);
+ dispatcher_request_channel (MCD_DISPATCHER (iface),
+ account_path,
+ requested_properties,
+ user_action_time,
+ preferred_handler,
+ NULL,
+ context,
+ FALSE);
}
static void
@@ -1429,15 +1326,14 @@ dispatcher_ensure_channel (TpSvcChannelDispatcher *iface,
const gchar *preferred_handler,
DBusGMethodInvocation *context)
{
- dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface),
- ENSURE_CHANNEL,
- account_path,
- requested_properties,
- user_action_time,
- preferred_handler,
- NULL,
- context,
- TRUE);
+ dispatcher_request_channel (MCD_DISPATCHER (iface),
+ account_path,
+ requested_properties,
+ user_action_time,
+ preferred_handler,
+ NULL,
+ context,
+ TRUE);
}
static void
@@ -1449,15 +1345,14 @@ dispatcher_create_channel_with_hints (TpSvcChannelDispatcher *iface,
GHashTable *hints,
DBusGMethodInvocation *context)
{
- dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface),
- CREATE_CHANNEL,
- account_path,
- requested_properties,
- user_action_time,
- preferred_handler,
- hints,
- context,
- FALSE);
+ dispatcher_request_channel (MCD_DISPATCHER (iface),
+ account_path,
+ requested_properties,
+ user_action_time,
+ preferred_handler,
+ hints,
+ context,
+ FALSE);
}
static void
@@ -1469,15 +1364,14 @@ dispatcher_ensure_channel_with_hints (TpSvcChannelDispatcher *iface,
GHashTable *hints,
DBusGMethodInvocation *context)
{
- dispatcher_channel_request_acl_start (MCD_DISPATCHER (iface),
- ENSURE_CHANNEL,
- account_path,
- requested_properties,
- user_action_time,
- preferred_handler,
- hints,
- context,
- TRUE);
+ dispatcher_request_channel (MCD_DISPATCHER (iface),
+ account_path,
+ requested_properties,
+ user_action_time,
+ preferred_handler,
+ hints,
+ context,
+ TRUE);
}
@@ -1552,17 +1446,6 @@ typedef struct
} MessageContext;
static MessageContext *
-message_context_steal (MessageContext *from)
-{
- MessageContext *stolen = g_slice_new0 (MessageContext);
-
- g_memmove (stolen, from, sizeof (MessageContext));
- memset (from, 0, sizeof (MessageContext));
-
- return stolen;
-}
-
-static MessageContext *
message_context_new (McdDispatcher *dispatcher,
const gchar *account_path,
const gchar *target_id,
@@ -1650,7 +1533,7 @@ send_message_submitted (TpChannel *proxy,
/* this frees the dbus context, so clear it from our cache afterwards */
if (error == NULL)
{
- mc_svc_channel_dispatcher_interface_messages_draft_return_from_send_message (context, token);
+ tp_svc_channel_dispatcher_interface_messages1_return_from_send_message (context, token);
message_context_set_return_context (message, NULL);
}
else
@@ -1717,16 +1600,6 @@ send_message_got_channel (McdRequest *request,
}
static void
-messages_send_message_acl_success (DBusGMethodInvocation *dbus_context,
- gpointer data)
-{
- /* steal the contents of the message context from the ACL framework: *
- * this avoids a nasty double-free (and means we don't have to dup *
- * the message payload memory twice) */
- messages_send_message_start (dbus_context, message_context_steal (data));
-}
-
-static void
messages_send_message_start (DBusGMethodInvocation *dbus_context,
MessageContext *message)
{
@@ -1820,18 +1693,7 @@ finished:
}
static void
-messages_send_message_acl_cleanup (gpointer data)
-{
- MessageContext *message = data;
-
- /* At this point either the messages framework or the ACL framework *
- * is expected to have handled the DBus return, so we must not try to */
- message_context_set_return_context (message, NULL);
- message_context_free (message);
-}
-
-static void
-messages_send_message (McSvcChannelDispatcherInterfaceMessagesDraft *iface,
+messages_send_message (TpSvcChannelDispatcherInterfaceMessages1 *iface,
const gchar *account_path,
const gchar *target_id,
const GPtrArray *payload,
@@ -1842,30 +1704,14 @@ messages_send_message (McSvcChannelDispatcherInterfaceMessagesDraft *iface,
MessageContext *message =
message_context_new (self, account_path, target_id, payload, flags);
- /* these are for the ACL itself */
- GValue *account = g_slice_new0 (GValue);
- GHashTable *params =
- g_hash_table_new_full (g_str_hash, g_str_equal, NULL, free_gvalue);
-
- g_value_init (account, G_TYPE_STRING);
- g_value_set_string (account, account_path);
- g_hash_table_insert (params, "account-path", account);
-
- mcp_dbus_acl_authorised_async (self->priv->dbus_daemon,
- context,
- DBUS_ACL_TYPE_METHOD,
- SEND_MESSAGE,
- params,
- messages_send_message_acl_success,
- message,
- messages_send_message_acl_cleanup);
+ messages_send_message_start (context, message);
}
static void
messages_iface_init (gpointer iface, gpointer data G_GNUC_UNUSED)
{
#define IMPLEMENT(x) \
- mc_svc_channel_dispatcher_interface_messages_draft_implement_##x (iface, messages_##x)
+ tp_svc_channel_dispatcher_interface_messages1_implement_##x (iface, messages_##x)
IMPLEMENT (send_message);
#undef IMPLEMENT
}
diff --git a/src/mcd-master.c b/src/mcd-master.c
index 37c127bd..d4b53cfc 100644
--- a/src/mcd-master.c
+++ b/src/mcd-master.c
@@ -71,7 +71,6 @@
#include "mcd-dispatcher.h"
#include "mcd-account-manager.h"
#include "mcd-account-manager-priv.h"
-#include "mcd-account-conditions.h"
#include "mcd-account-priv.h"
#include "plugin-loader.h"
diff --git a/src/mcd-misc.c b/src/mcd-misc.c
index 3a3f1541..14fb905b 100644
--- a/src/mcd-misc.c
+++ b/src/mcd-misc.c
@@ -37,8 +37,6 @@
#include "mcd-debug.h"
-#include "_gen/register-dbus-glib-marshallers-body.h"
-
#include <dbus/dbus.h>
#include <dbus/dbus-glib-lowlevel.h>
diff --git a/src/mcd-service.c b/src/mcd-service.c
index 17c94b04..cf3d05e7 100644
--- a/src/mcd-service.c
+++ b/src/mcd-service.c
@@ -133,6 +133,10 @@ mcd_service_constructed (GObject *obj)
{
DEBUG ("called");
+ /* It's actually quite important that we request *a* bus name here,
+ * so we can use it as a mutex for loading and migrating accounts,
+ * all of which we want to have finished before we open up our main
+ * D-Bus API for business. (See also fd.o #24000) */
mcd_service_obtain_bus_name (MCD_OBJECT (obj));
mcd_debug_print_tree (obj);
diff --git a/src/mcd-storage-ag-hidden.c b/src/mcd-storage-ag-hidden.c
deleted file mode 100644
index ee857a74..00000000
--- a/src/mcd-storage-ag-hidden.c
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * storage-ag-hidden.c - account backend for "magic" hidden accounts using
- * accounts-glib
- * Copyright ©2011 Collabora Ltd.
- * Copyright ©2011 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 "config.h"
-
-#include "mcd-storage-ag-hidden.h"
-
-#include <telepathy-glib/telepathy-glib.h>
-
-#include "mcd-debug.h"
-/* FIXME: if we weren't in-tree, we wouldn't be able to include this header and
- * we'd have to re-hardcode magic strings like "Hidden".
- */
-#include "mcd-account-config.h"
-
-static void account_storage_iface_init (
- McpAccountStorageIface *iface,
- gpointer unused G_GNUC_UNUSED);
-
-G_DEFINE_TYPE_WITH_CODE (McdStorageAgHidden, mcd_storage_ag_hidden,
- MCD_TYPE_ACCOUNT_MANAGER_SSO,
- G_IMPLEMENT_INTERFACE (MCP_TYPE_ACCOUNT_STORAGE,
- account_storage_iface_init);
- );
-
-static void
-mcd_storage_ag_hidden_init (McdStorageAgHidden *self)
-{
-}
-
-static void
-mcd_storage_ag_hidden_class_init (McdStorageAgHiddenClass *klass)
-{
- McdAccountManagerSsoClass *super = MCD_ACCOUNT_MANAGER_SSO_CLASS (klass);
-
- super->service_type = ACCOUNTS_GLIB_HIDDEN_SERVICE_TYPE;
-}
-
-static gboolean
-_mcd_storage_ag_hidden_get (
- const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account_suffix,
- const gchar *key)
-{
- /* Chain up to the real implementation, checking whether this is an account
- * we care about in the process.
- */
- if (!_mcd_account_manager_sso_get (self, am, account_suffix, key))
- return FALSE;
-
- /* If the caller is looking for the "Hidden" key (or NULL, which means
- * everything), let's fill it in. (Every account this plugin cares about
- * should be hidden.)
- */
- if (key == NULL || !tp_strdiff (key, MC_ACCOUNTS_KEY_HIDDEN))
- mcp_account_manager_set_value (am, account_suffix, MC_ACCOUNTS_KEY_HIDDEN,
- "true");
-
- return TRUE;
-}
-
-static void
-account_storage_iface_init (
- McpAccountStorageIface *iface,
- gpointer unused G_GNUC_UNUSED)
-{
- mcp_account_storage_iface_set_name (iface,
- "maemo-libaccounts-hidden");
- mcp_account_storage_iface_set_desc (iface,
- "Loads accounts with service type '" ACCOUNTS_GLIB_HIDDEN_SERVICE_TYPE
- "' from accounts-glib, and marks them as Hidden");
- mcp_account_storage_iface_implement_get (iface,
- _mcd_storage_ag_hidden_get);
-}
-
-McdStorageAgHidden *
-mcd_storage_ag_hidden_new ()
-{
- return g_object_new (MCD_TYPE_STORAGE_AG_HIDDEN, NULL);
-}
diff --git a/src/mcd-storage-ag-hidden.h b/src/mcd-storage-ag-hidden.h
deleted file mode 100644
index 2d9311f4..00000000
--- a/src/mcd-storage-ag-hidden.h
+++ /dev/null
@@ -1,59 +0,0 @@
-/*
- * storage-ag-hidden.h - account backend for "magic" hidden accounts using
- * accounts-glib
- * Copyright ©2011 Collabora Ltd.
- * Copyright ©2011 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 MCD_STORAGE_AG_HIDDEN_H
-#define MCD_STORAGE_AG_HIDDEN_H
-
-#include <glib-object.h>
-#include "mcd-account-manager-sso.h"
-
-typedef struct _McdStorageAgHidden McdStorageAgHidden;
-typedef struct _McdStorageAgHiddenClass McdStorageAgHiddenClass;
-
-struct _McdStorageAgHiddenClass {
- McdAccountManagerSsoClass parent_class;
-};
-
-struct _McdStorageAgHidden {
- McdAccountManagerSso parent;
-};
-
-GType mcd_storage_ag_hidden_get_type (void);
-
-McdStorageAgHidden *mcd_storage_ag_hidden_new (void);
-
-/* TYPE MACROS */
-#define MCD_TYPE_STORAGE_AG_HIDDEN \
- (mcd_storage_ag_hidden_get_type ())
-#define MCD_STORAGE_AG_HIDDEN(obj) \
- (G_TYPE_CHECK_INSTANCE_CAST((obj), MCD_TYPE_STORAGE_AG_HIDDEN, McdStorageAgHidden))
-#define MCD_STORAGE_AG_HIDDEN_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_CAST((klass), MCD_TYPE_STORAGE_AG_HIDDEN,\
- McdStorageAgHiddenClass))
-#define MCD_IS_STORAGE_AG_HIDDEN(obj) \
- (G_TYPE_CHECK_INSTANCE_TYPE((obj), MCD_TYPE_STORAGE_AG_HIDDEN))
-#define MCD_IS_STORAGE_AG_HIDDEN_CLASS(klass) \
- (G_TYPE_CHECK_CLASS_TYPE((klass), MCD_TYPE_STORAGE_AG_HIDDEN))
-#define MCD_STORAGE_AG_HIDDEN_GET_CLASS(obj) \
- (G_TYPE_INSTANCE_GET_CLASS ((obj), MCD_TYPE_STORAGE_AG_HIDDEN, \
- McdStorageAgHiddenClass))
-
-#endif /* MCD_STORAGE_AG_HIDDEN_H */
diff --git a/src/mcd-storage.c b/src/mcd-storage.c
index 1a0ebbf5..fea76c2a 100644
--- a/src/mcd-storage.c
+++ b/src/mcd-storage.c
@@ -32,6 +32,7 @@
#include <errno.h>
#include <string.h>
+#include <dbus/dbus.h>
#include <telepathy-glib/telepathy-glib.h>
#include <telepathy-glib/telepathy-glib-dbus.h>
@@ -40,13 +41,6 @@
/* these pseudo-plugins take care of the actual account storage/retrieval */
#include "mcd-account-manager-default.h"
-#if ENABLE_LIBACCOUNTS_SSO
-#include "mcd-account-manager-sso.h"
-# ifdef ACCOUNTS_GLIB_HIDDEN_SERVICE_TYPE
-# include "mcd-storage-ag-hidden.h"
-# endif
-#endif
-
#define MAX_KEY_LENGTH (DBUS_MAXIMUM_NAME_LENGTH + 6)
static GList *stores = NULL;
@@ -56,6 +50,17 @@ enum {
PROP_DBUS_DAEMON = 1,
};
+enum {
+ SIGNAL_CREATED,
+ SIGNAL_TOGGLED,
+ SIGNAL_DELETED,
+ SIGNAL_ALTERED_ONE,
+ SIGNAL_RECONNECT,
+ N_SIGNALS
+};
+
+static guint signals[N_SIGNALS] = { 0 };
+
struct _McdStorageClass {
GObjectClass parent;
};
@@ -67,39 +72,11 @@ G_DEFINE_TYPE_WITH_CODE (McdStorage, mcd_storage,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (MCP_TYPE_ACCOUNT_MANAGER, plugin_iface_init))
-typedef struct {
- /* owned string => GVariant
- * e.g. { 'DisplayName': <'Frederick Bloggs'> } */
- GHashTable *attributes;
- /* owned string => owned GVariant
- * e.g. { 'account': <'fred@example.com'>, 'password': <'foo'> } */
- GHashTable *parameters;
- /* owned string => owned string escaped as if for a keyfile
- * e.g. { 'account': 'fred@example.com', 'password': 'foo' }
- * keys of @parameters and @escaped_parameters are disjoint */
- GHashTable *escaped_parameters;
- /* set of owned strings
- * e.g. { 'password': 'password' } */
- GHashTable *secrets;
-} McdStorageAccount;
-
-static void
-mcd_storage_account_free (gpointer p)
-{
- McdStorageAccount *sa = p;
-
- g_hash_table_unref (sa->attributes);
- g_hash_table_unref (sa->parameters);
- g_hash_table_unref (sa->escaped_parameters);
- g_hash_table_unref (sa->secrets);
- g_slice_free (McdStorageAccount, sa);
-}
-
static void
mcd_storage_init (McdStorage *self)
{
self->accounts = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, mcd_storage_account_free);
+ g_free, g_object_unref);
}
static void
@@ -181,6 +158,31 @@ mcd_storage_class_init (McdStorageClass *cls)
object_class->finalize = storage_finalize;
g_object_class_install_property (object_class, PROP_DBUS_DAEMON, spec);
+
+ signals[SIGNAL_CREATED] = g_signal_new ("created",
+ MCD_TYPE_STORAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ NULL, G_TYPE_NONE,
+ 2, MCP_TYPE_ACCOUNT_STORAGE, G_TYPE_STRING);
+
+ signals[SIGNAL_ALTERED_ONE] = g_signal_new ("altered-one",
+ MCD_TYPE_STORAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ NULL, G_TYPE_NONE,
+ 3, MCP_TYPE_ACCOUNT_STORAGE, G_TYPE_STRING, G_TYPE_STRING);
+
+ signals[SIGNAL_DELETED] = g_signal_new ("deleted",
+ MCD_TYPE_STORAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ NULL, G_TYPE_NONE,
+ 2, MCP_TYPE_ACCOUNT_STORAGE, G_TYPE_STRING);
+
+ signals[SIGNAL_TOGGLED] = g_signal_new ("toggled",
+ MCD_TYPE_STORAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ NULL, G_TYPE_NONE,
+ 3, MCP_TYPE_ACCOUNT_STORAGE, G_TYPE_STRING, G_TYPE_BOOLEAN);
+
+ signals[SIGNAL_RECONNECT] = g_signal_new ("reconnect",
+ MCD_TYPE_STORAGE, G_SIGNAL_RUN_LAST, 0, NULL, NULL,
+ NULL, G_TYPE_NONE,
+ 2, MCP_TYPE_ACCOUNT_STORAGE, G_TYPE_STRING);
}
McdStorage *
@@ -194,106 +196,18 @@ mcd_storage_new (TpDBusDaemon *dbus_daemon)
static gchar *
mcd_keyfile_escape_variant (GVariant *variant)
{
- GValue value = G_VALUE_INIT;
+ GKeyFile *keyfile;
gchar *ret;
- dbus_g_value_parse_g_variant (variant, &value);
-
- if (G_IS_VALUE (&value))
- {
- ret = mcd_keyfile_escape_value (&value);
- g_value_unset (&value);
- }
- else
- {
- gchar *printed = g_variant_print (variant, TRUE);
-
- ret = NULL;
- g_warning ("Unable to translate variant %s", printed);
- g_free (printed);
- }
+ g_return_val_if_fail (variant != NULL, NULL);
+ keyfile = g_key_file_new ();
+ mcd_keyfile_set_variant (keyfile, "g", "k", variant);
+ ret = g_key_file_get_value (keyfile, "g", "k", NULL);
+ g_key_file_free (keyfile);
return ret;
}
-static McdStorageAccount *
-lookup_account (McdStorage *self,
- const gchar *account)
-{
- return g_hash_table_lookup (self->accounts, account);
-}
-
-static McdStorageAccount *
-ensure_account (McdStorage *self,
- const gchar *account)
-{
- McdStorageAccount *sa = lookup_account (self, account);
-
- if (sa == NULL)
- {
- sa = g_slice_new (McdStorageAccount);
- sa->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_variant_unref);
- sa->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, (GDestroyNotify) g_variant_unref);
- sa->escaped_parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, g_free);
- sa->secrets = g_hash_table_new_full (g_str_hash, g_str_equal,
- g_free, NULL);
- g_hash_table_insert (self->accounts, g_strdup (account), sa);
- }
-
- return sa;
-}
-
-static gchar *
-get_value (const McpAccountManager *ma,
- const gchar *account,
- const gchar *key)
-{
- McdStorage *self = MCD_STORAGE (ma);
- McdStorageAccount *sa = lookup_account (self, account);
- GVariant *variant;
- gchar *ret;
-
- if (sa == NULL)
- return NULL;
-
- if (g_str_has_prefix (key, "param-"))
- {
- variant = g_hash_table_lookup (sa->parameters, key + 6);
-
- if (variant != NULL)
- {
- ret = mcd_keyfile_escape_variant (variant);
- g_variant_unref (variant);
- return ret;
- }
- else
- {
- /* OK, we don't have it as a variant. How about the keyfile-escaped
- * version? */
- return g_strdup (g_hash_table_lookup (sa->escaped_parameters,
- key + 6));
- }
- }
- else
- {
- variant = g_hash_table_lookup (sa->attributes, key);
-
- if (variant != NULL)
- {
- ret = mcd_keyfile_escape_variant (variant);
- g_variant_unref (variant);
- return ret;
- }
- else
- {
- return NULL;
- }
- }
-}
-
static struct {
const gchar *type;
const gchar *name;
@@ -314,7 +228,6 @@ static struct {
{ "b", MC_ACCOUNTS_KEY_CONNECT_AUTOMATICALLY },
{ "b", MC_ACCOUNTS_KEY_ENABLED },
{ "b", MC_ACCOUNTS_KEY_HAS_BEEN_ONLINE },
- { "b", MC_ACCOUNTS_KEY_HIDDEN },
/* Strings */
{ "s", MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE },
@@ -335,7 +248,7 @@ static struct {
{ NULL, NULL }
};
-const gchar *
+const GVariantType *
mcd_storage_get_attribute_type (const gchar *attribute)
{
guint i;
@@ -343,26 +256,26 @@ mcd_storage_get_attribute_type (const gchar *attribute)
for (i = 0; known_attributes[i].type != NULL; i++)
{
if (!tp_strdiff (attribute, known_attributes[i].name))
- return known_attributes[i].type;
+ return G_VARIANT_TYPE (known_attributes[i].type);
}
- /* special case for mcd-account-conditions.c */
- if (g_str_has_prefix (attribute, "condition-"))
- return "s";
-
return NULL;
}
gboolean
mcd_storage_init_value_for_attribute (GValue *value,
- const gchar *attribute)
+ const gchar *attribute,
+ const GVariantType **variant_type)
{
- const gchar *s = mcd_storage_get_attribute_type (attribute);
+ const GVariantType *s = mcd_storage_get_attribute_type (attribute);
if (s == NULL)
return FALSE;
- switch (s[0])
+ if (variant_type != NULL)
+ *variant_type = s;
+
+ switch (g_variant_type_peek_string (s)[0])
{
case 's':
g_value_init (value, G_TYPE_STRING);
@@ -379,7 +292,7 @@ mcd_storage_init_value_for_attribute (GValue *value,
case 'a':
{
- switch (s[1])
+ switch (g_variant_type_peek_string (s)[1])
{
case 'o':
g_value_init (value, TP_ARRAY_TYPE_OBJECT_PATH_LIST);
@@ -394,7 +307,7 @@ mcd_storage_init_value_for_attribute (GValue *value,
case '(':
{
- if (!tp_strdiff (s, "(uss)"))
+ if (g_variant_type_equal (s, G_VARIANT_TYPE ("(uss)")))
{
g_value_init (value, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
return TRUE;
@@ -406,230 +319,134 @@ mcd_storage_init_value_for_attribute (GValue *value,
return FALSE;
}
-static gboolean
-mcpa_init_value_for_attribute (const McpAccountManager *mcpa,
- GValue *value,
- const gchar *attribute)
-{
- return mcd_storage_init_value_for_attribute (value, attribute);
-}
-
-static void
-mcpa_set_attribute (const McpAccountManager *ma,
- const gchar *account,
- const gchar *attribute,
- GVariant *value,
- McpAttributeFlags flags)
+static gchar *
+unique_name (const McpAccountManager *ma,
+ const gchar *manager,
+ const gchar *protocol,
+ const gchar *identification)
{
McdStorage *self = MCD_STORAGE (ma);
- McdStorageAccount *sa = ensure_account (self, account);
+ gchar *esc_manager, *esc_protocol, *esc_base;
+ guint i;
+ gsize base_len = strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
+ DBusGConnection *connection = tp_proxy_get_dbus_connection (self->dbusd);
- if (value != NULL)
- {
- g_hash_table_insert (sa->attributes, g_strdup (attribute),
- g_variant_ref_sink (value));
- }
- else
- {
- g_hash_table_remove (sa->attributes, attribute);
- }
-}
+ esc_manager = tp_escape_as_identifier (manager);
+ esc_protocol = g_strdelimit (g_strdup (protocol), "-", '_');
+ esc_base = tp_escape_as_identifier (identification);
-static void
-mcpa_set_parameter (const McpAccountManager *ma,
- const gchar *account,
- const gchar *parameter,
- GVariant *value,
- McpParameterFlags flags)
-{
- McdStorage *self = MCD_STORAGE (ma);
- McdStorageAccount *sa = ensure_account (self, account);
+ for (i = 0; i < G_MAXUINT; i++)
+ {
+ gchar *path = g_strdup_printf (
+ TP_ACCOUNT_OBJECT_PATH_BASE "%s/%s/%s%u",
+ esc_manager, esc_protocol, esc_base, i);
- g_hash_table_remove (sa->parameters, parameter);
- g_hash_table_remove (sa->escaped_parameters, parameter);
+ if (!g_hash_table_contains (self->accounts, path + base_len) &&
+ dbus_g_connection_lookup_g_object (connection, path) == NULL)
+ {
+ gchar *ret = g_strdup (path + base_len);
- if (value != NULL)
- g_hash_table_insert (sa->parameters, g_strdup (parameter),
- g_variant_ref_sink (value));
+ g_free (path);
+ return ret;
+ }
- if (flags & MCP_PARAMETER_FLAG_SECRET)
- {
- DEBUG ("flagging %s parameter %s as secret", account, parameter);
- g_hash_table_add (sa->secrets, g_strdup (parameter));
+ g_free (path);
}
+
+ return NULL;
}
static void
-set_value (const McpAccountManager *ma,
- const gchar *account,
- const gchar *key,
- const gchar *value)
+identify_account_cb (TpProxy *proxy,
+ const gchar *identification,
+ const GError *error,
+ gpointer task,
+ GObject *weak_object G_GNUC_UNUSED)
{
- McdStorage *self = MCD_STORAGE (ma);
- McdStorageAccount *sa = ensure_account (self, account);
-
- if (g_str_has_prefix (key, "param-"))
+ if (error == NULL)
{
- g_hash_table_remove (sa->parameters, key + 6);
- g_hash_table_remove (sa->escaped_parameters, key + 6);
-
- if (value != NULL)
- g_hash_table_insert (sa->escaped_parameters, g_strdup (key + 6),
- g_strdup (value));
+ DEBUG ("identified account: %s", identification);
+ g_task_return_pointer (task, g_strdup (identification), g_free);
}
- else
+ else if (g_error_matches (error, TP_ERROR, TP_ERROR_INVALID_HANDLE) ||
+ g_error_matches (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT))
{
- if (value != NULL)
- {
- GValue tmp = G_VALUE_INIT;
- GError *error = NULL;
-
- if (!mcd_storage_init_value_for_attribute (&tmp, key))
- {
- g_warning ("Not sure what the type of '%s' is, assuming string",
- key);
- g_value_init (&tmp, G_TYPE_STRING);
- }
-
- if (mcd_keyfile_unescape_value (value, &tmp, &error))
- {
- g_hash_table_insert (sa->attributes, g_strdup (key),
- g_variant_ref_sink (dbus_g_value_build_g_variant (&tmp)));
- g_value_unset (&tmp);
- }
- else
- {
- g_warning ("Could not decode attribute '%s':'%s' from plugin: %s",
- key, value, error->message);
- g_error_free (error);
- g_hash_table_remove (sa->attributes, key);
- }
- }
- else
- {
- g_hash_table_remove (sa->attributes, key);
- }
+ /* The connection manager didn't like our account parameters.
+ * Give up now. */
+ DEBUG ("failed to identify account: %s #%d: %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+ g_task_return_error (task, g_error_copy (error));
}
-}
-
-static GStrv
-list_keys (const McpAccountManager *ma,
- const gchar * account)
-{
- McdStorage *self = MCD_STORAGE (ma);
- GPtrArray *ret = g_ptr_array_new ();
- McdStorageAccount *sa = lookup_account (self, account);
-
- if (sa != NULL)
+ else
{
- GHashTableIter iter;
- gpointer k;
-
- g_hash_table_iter_init (&iter, sa->attributes);
-
- while (g_hash_table_iter_next (&iter, &k, NULL))
- g_ptr_array_add (ret, g_strdup (k));
-
- g_hash_table_iter_init (&iter, sa->parameters);
-
- while (g_hash_table_iter_next (&iter, &k, NULL))
- g_ptr_array_add (ret, g_strdup_printf ("param-%s", (gchar *) k));
+ /* We weren't able to identify the account, but carry on and hope
+ * for the best... */
+ DEBUG ("ignoring failure to identify account: %s #%d: %s",
+ g_quark_to_string (error->domain), error->code, error->message);
+ g_task_return_pointer (task, g_strdup (g_task_get_task_data (task)),
+ g_free);
}
-
- g_ptr_array_add (ret, NULL);
- return (GStrv) g_ptr_array_free (ret, FALSE);
-}
-
-static gboolean
-is_secret (const McpAccountManager *ma,
- const gchar *account,
- const gchar *key)
-{
- McdStorage *self = MCD_STORAGE (ma);
- McdStorageAccount *sa = lookup_account (self, account);
-
- if (sa == NULL || !g_str_has_prefix (key, "param-"))
- return FALSE;
-
- return g_hash_table_contains (sa->secrets, key + 6);
}
-static void
-mcd_storage_make_secret (McdStorage *self,
- const gchar *account,
- const gchar *key)
+static gchar *
+identify_account_finish (McpAccountManager *mcpa,
+ GAsyncResult *result,
+ GError **error)
{
- McdStorageAccount *sa;
+ g_return_val_if_fail (g_task_is_valid (result, mcpa), NULL);
- g_return_if_fail (MCD_IS_STORAGE (self));
- g_return_if_fail (account != NULL);
- g_return_if_fail (key != NULL);
-
- if (!g_str_has_prefix (key, "param-"))
- return;
-
- DEBUG ("flagging %s parameter %s as secret", account, key + 6);
- sa = ensure_account (self, account);
- g_hash_table_add (sa->secrets, g_strdup (key + 6));
+ return g_task_propagate_pointer (G_TASK (result), error);
}
static void
-make_secret (const McpAccountManager *ma,
- const gchar *account,
- const gchar *key)
-{
- mcd_storage_make_secret (MCD_STORAGE (ma), account, key);
-}
-
-static gchar *
-unique_name (const McpAccountManager *ma,
+identify_account_async (McpAccountManager *mcpa,
const gchar *manager,
- const gchar *protocol,
- const GHashTable *params)
+ const gchar *protocol_name,
+ GVariant *parameters,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
- McdStorage *self = MCD_STORAGE (ma);
- const gchar *base = NULL;
- gchar *esc_manager, *esc_protocol, *esc_base;
- guint i;
- gsize base_len = strlen (TP_ACCOUNT_OBJECT_PATH_BASE);
- DBusGConnection *connection = tp_proxy_get_dbus_connection (self->dbusd);
+ McdStorage *self = MCD_STORAGE (mcpa);
+ GError *error = NULL;
+ TpProtocol *protocol;
+ GTask *task;
+ GValue value = G_VALUE_INIT;
+ const gchar *base;
- base = tp_asv_get_string (params, "account");
+ task = g_task_new (self, cancellable, callback, user_data);
- if (base == NULL)
+ /* in case IdentifyAccount fails and we need to make something up */
+ if (!g_variant_lookup (parameters, "account", "&s", &base))
base = "account";
- esc_manager = tp_escape_as_identifier (manager);
- esc_protocol = g_strdelimit (g_strdup (protocol), "-", '_');
- esc_base = tp_escape_as_identifier (base);
-
- for (i = 0; i < G_MAXUINT; i++)
- {
- gchar *path = g_strdup_printf (
- TP_ACCOUNT_OBJECT_PATH_BASE "%s/%s/%s%u",
- esc_manager, esc_protocol, esc_base, i);
+ g_task_set_task_data (task, g_strdup (base), g_free);
- if (!g_hash_table_contains (self->accounts, path + base_len) &&
- dbus_g_connection_lookup_g_object (connection, path) == NULL)
- {
- gchar *ret = g_strdup (path + base_len);
+ protocol = tp_protocol_new (self->dbusd, manager, protocol_name,
+ NULL, &error);
- g_free (path);
- return ret;
- }
-
- g_free (path);
+ if (protocol == NULL)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
}
- return NULL;
+ dbus_g_value_parse_g_variant (parameters, &value);
+
+ tp_cli_protocol_call_identify_account (protocol, -1,
+ g_value_get_boxed (&value), identify_account_cb, task, g_object_unref,
+ NULL);
+ g_object_unref (protocol);
+ g_value_unset (&value);
}
/* sort in descending order of priority (ie higher prio => earlier in list) */
static gint
account_storage_cmp (gconstpointer a, gconstpointer b)
{
- gint pa = mcp_account_storage_priority (a);
- gint pb = mcp_account_storage_priority (b);
+ gint pa = mcp_account_storage_priority ((McpAccountStorage *) a);
+ gint pb = mcp_account_storage_priority ((McpAccountStorage *) b);
if (pa > pb) return -1;
if (pa < pb) return 1;
@@ -644,17 +461,6 @@ add_storage_plugin (McpAccountStorage *plugin)
}
static void
-add_libaccounts_plugins_if_enabled (void)
-{
-#if ENABLE_LIBACCOUNTS_SSO
- add_storage_plugin (MCP_ACCOUNT_STORAGE (mcd_account_manager_sso_new ()));
-# ifdef ACCOUNTS_GLIB_HIDDEN_SERVICE_TYPE
- add_storage_plugin (MCP_ACCOUNT_STORAGE (mcd_storage_ag_hidden_new ()));
-# endif
-#endif
-}
-
-static void
sort_and_cache_plugins ()
{
const GList *p;
@@ -668,7 +474,6 @@ sort_and_cache_plugins ()
/* Add compiled-in plugins */
add_storage_plugin (MCP_ACCOUNT_STORAGE (mcd_account_manager_default_new ()));
- add_libaccounts_plugins_if_enabled ();
for (p = mcp_list_objects(); p != NULL; p = g_list_next (p))
{
@@ -694,23 +499,125 @@ sort_and_cache_plugins ()
plugins_cached = TRUE;
}
-void
-mcd_storage_connect_signal (const gchar *signame,
- GCallback func,
- gpointer user_data)
+static void
+created_cb (McpAccountStorage *plugin,
+ const gchar *account_name,
+ McdStorage *self)
{
- GList *p;
+ GError *error = NULL;
- for (p = stores; p != NULL; p = g_list_next (p))
+ g_return_if_fail (MCP_IS_ACCOUNT_STORAGE (plugin));
+ g_return_if_fail (MCD_IS_STORAGE (self));
+
+ if (mcd_storage_add_account_from_plugin (self, plugin, account_name, &error))
{
- McpAccountStorage *plugin = p->data;
+ DEBUG ("%s", account_name);
+ g_signal_emit (self, signals[SIGNAL_CREATED], 0, plugin, account_name);
+ }
+ else
+ {
+ WARNING ("%s", error->message);
+ g_error_free (error);
+ }
+}
+
+static gboolean
+check_is_responsible (McdStorage *self,
+ McpAccountStorage *plugin,
+ const gchar *account_name,
+ const gchar *changing,
+ GError **error)
+{
+ McpAccountStorage *other = g_hash_table_lookup (self->accounts,
+ account_name);
+
+ if (other == NULL)
+ {
+ WARNING ("account %s does not exist, preventing plugin '%s' from "
+ "%s it", account_name, mcp_account_storage_name (plugin), changing);
+ return FALSE;
+ }
+
+ if (other != plugin)
+ {
+ WARNING ("account %s is in plugin '%s', preventing plugin '%s' from "
+ "%s it", account_name, mcp_account_storage_name (other),
+ mcp_account_storage_name (plugin), changing);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+static void
+toggled_cb (McpAccountStorage *plugin,
+ const gchar *account_name,
+ gboolean on,
+ McdStorage *self)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (MCP_IS_ACCOUNT_STORAGE (plugin));
+ g_return_if_fail (MCD_IS_STORAGE (self));
- DEBUG ("connecting handler to %s plugin signal %s ",
- mcp_account_storage_name (plugin), signame);
- g_signal_connect (plugin, signame, func, user_data);
+ if (check_is_responsible (self, plugin, account_name, "toggling", &error))
+ g_signal_emit (self, signals[SIGNAL_TOGGLED], 0, plugin,
+ account_name, on);
+}
+
+static void
+deleted_cb (McpAccountStorage *plugin,
+ const gchar *account_name,
+ McdStorage *self)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (MCP_IS_ACCOUNT_STORAGE (plugin));
+ g_return_if_fail (MCD_IS_STORAGE (self));
+
+ if (check_is_responsible (self, plugin, account_name, "deleting",
+ &error))
+ {
+ g_hash_table_remove (self->accounts, account_name);
+
+ g_signal_emit (self, signals[SIGNAL_DELETED], 0, plugin,
+ account_name);
}
}
+static void
+altered_one_cb (McpAccountStorage *plugin,
+ const gchar *account_name,
+ const gchar *key,
+ McdStorage *self)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (MCP_IS_ACCOUNT_STORAGE (plugin));
+ g_return_if_fail (MCD_IS_STORAGE (self));
+
+ if (check_is_responsible (self, plugin, account_name, "altering",
+ &error))
+ g_signal_emit (self, signals[SIGNAL_ALTERED_ONE], 0, plugin,
+ account_name, key);
+}
+
+static void
+reconnect_cb (McpAccountStorage *plugin,
+ const gchar *account_name,
+ McdStorage *self)
+{
+ GError *error = NULL;
+
+ g_return_if_fail (MCP_IS_ACCOUNT_STORAGE (plugin));
+ g_return_if_fail (MCD_IS_STORAGE (self));
+
+ if (check_is_responsible (self, plugin, account_name, "reconnecting",
+ &error))
+ g_signal_emit (self, signals[SIGNAL_RECONNECT], 0, plugin,
+ account_name);
+}
+
/*
* mcd_storage_load:
* @storage: An object implementing the #McdStorage interface
@@ -729,95 +636,68 @@ mcd_storage_load (McdStorage *self)
sort_and_cache_plugins ();
- store = g_list_last (stores);
-
- /* fetch accounts stored in plugins, in reverse priority so higher prio *
- * plugins can overwrite lower prio ones' account data */
- while (store != NULL)
+ /* fetch accounts stored in plugins, highest priority first, so that
+ * low priority plugins can be overidden by high priority */
+ for (store = stores; store != NULL; store = store->next)
{
GList *account;
McpAccountStorage *plugin = store->data;
- GList *stored = mcp_account_storage_list (plugin, ma);
+ GList *stored;
const gchar *pname = mcp_account_storage_name (plugin);
const gint prio = mcp_account_storage_priority (plugin);
- DEBUG ("listing from plugin %s [prio: %d]", pname, prio);
+ DEBUG ("listing initial accounts from plugin %s [prio: %d]", pname, prio);
+ stored = mcp_account_storage_list (plugin, ma);
+
+ /* Connect to signals for non-initial accounts. We only do this
+ * after we have called list(), to make sure the plugins don't need
+ * to queue up change-notification signals until after we've
+ * called the old "ready" vfunc. */
+ g_signal_connect_object (plugin, "created", G_CALLBACK (created_cb),
+ self, 0);
+ g_signal_connect_object (plugin, "toggled", G_CALLBACK (toggled_cb),
+ self, 0);
+ g_signal_connect_object (plugin, "deleted", G_CALLBACK (deleted_cb),
+ self, 0);
+ g_signal_connect_object (plugin, "altered-one",
+ G_CALLBACK (altered_one_cb), self, 0);
+ g_signal_connect_object (plugin, "reconnect", G_CALLBACK (reconnect_cb),
+ self, 0);
+
for (account = stored; account != NULL; account = g_list_next (account))
{
+ GError *error = NULL;
gchar *name = account->data;
DEBUG ("fetching %s from plugin %s [prio: %d]", name, pname, prio);
- mcd_storage_add_account_from_plugin (self, plugin, name);
+
+ if (!mcd_storage_add_account_from_plugin (self, plugin, name,
+ &error))
+ {
+ DEBUG ("%s", error->message);
+ g_clear_error (&error);
+ }
+
g_free (name);
}
/* already freed the contents, just need to free the list itself */
g_list_free (stored);
- store = g_list_previous (store);
}
}
/*
- * mcd_storage_dup_accounts:
+ * mcd_storage_get_accounts:
* @storage: An object implementing the #McdStorage interface
* @n: place for the number of accounts to be written to (or %NULL)
*
- * Returns: a newly allocated GStrv containing the unique account names,
- * which must be freed by the caller with g_strfreev().
+ * Returns: (transfer none) (element-type utf8 Mcp.AccountStorage): a
+ * map from account object path tail to plugin
*/
-GStrv
-mcd_storage_dup_accounts (McdStorage *self,
- gsize *n)
+GHashTable *
+mcd_storage_get_accounts (McdStorage *self)
{
- GPtrArray *ret = g_ptr_array_new ();
- GHashTableIter iter;
- gpointer k, v;
-
- g_hash_table_iter_init (&iter, self->accounts);
-
- while (g_hash_table_iter_next (&iter, &k, &v))
- {
- McdStorageAccount *sa = v;
-
- if (g_hash_table_size (sa->attributes) > 0)
- g_ptr_array_add (ret, g_strdup (k));
- }
-
- g_ptr_array_add (ret, NULL);
- return (GStrv) g_ptr_array_free (ret, FALSE);
-}
-
-/*
- * mcd_storage_dup_attributes:
- * @storage: An object implementing the #McdStorage interface
- * @account: unique name of the account
- * @n: place for the number of attributes to be written to (or %NULL)
- *
- * Returns: a newly allocated GStrv containing the names of all the
- * attributes or parameters currently stored for @account. Must be
- * freed by the caller with g_strfreev().
- */
-GStrv
-mcd_storage_dup_attributes (McdStorage *self,
- const gchar *account,
- gsize *n)
-{
- GPtrArray *ret = g_ptr_array_new ();
- McdStorageAccount *sa = lookup_account (self, account);
-
- if (sa != NULL)
- {
- GHashTableIter iter;
- gpointer k;
-
- g_hash_table_iter_init (&iter, sa->attributes);
-
- while (g_hash_table_iter_next (&iter, &k, NULL))
- g_ptr_array_add (ret, g_strdup (k));
- }
-
- g_ptr_array_add (ret, NULL);
- return (GStrv) g_ptr_array_free (ret, FALSE);
+ return self->accounts;
}
/*
@@ -837,22 +717,15 @@ McpAccountStorage *
mcd_storage_get_plugin (McdStorage *self,
const gchar *account)
{
- GList *store = stores;
- McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
- McpAccountStorage *owner = NULL;
+ McpAccountStorage *plugin;
g_return_val_if_fail (MCD_IS_STORAGE (self), NULL);
g_return_val_if_fail (account != NULL, NULL);
- for (; store != NULL && owner == NULL; store = g_list_next (store))
- {
- McpAccountStorage *plugin = store->data;
-
- if (mcp_account_storage_owns (plugin, ma, account))
- owner = plugin;
- }
+ plugin = g_hash_table_lookup (self->accounts, account);
+ g_return_val_if_fail (plugin != NULL, NULL);
- return owner;
+ return plugin;
}
/*
@@ -879,7 +752,8 @@ mcd_storage_dup_string (McdStorage *self,
g_value_init (&tmp, G_TYPE_STRING);
- if (!mcd_storage_get_attribute (self, account, attribute, &tmp, NULL))
+ if (!mcd_storage_get_attribute (self, account, attribute,
+ G_VARIANT_TYPE_STRING, &tmp, NULL))
return NULL;
ret = g_value_dup_string (&tmp);
@@ -907,10 +781,10 @@ mcd_storage_coerce_variant_to_value (GVariant *variant,
/* This is really pretty stupid but it'll do for now.
* FIXME: implement a better similar-type-coercion mechanism than
* round-tripping through a GKeyFile. */
- escaped = mcd_keyfile_escape_value (&tmp);
+ g_value_unset (&tmp);
+ escaped = mcd_keyfile_escape_variant (variant);
ret = mcd_keyfile_unescape_value (escaped, value, error);
g_free (escaped);
- g_value_unset (&tmp);
return ret;
}
@@ -926,36 +800,42 @@ gboolean
mcd_storage_get_attribute (McdStorage *self,
const gchar *account,
const gchar *attribute,
+ const GVariantType *type,
GValue *value,
GError **error)
{
- McdStorageAccount *sa;
+ McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ McpAccountStorage *plugin;
GVariant *variant;
+ gboolean ret;
g_return_val_if_fail (MCD_IS_STORAGE (self), FALSE);
g_return_val_if_fail (account != NULL, FALSE);
g_return_val_if_fail (attribute != NULL, FALSE);
g_return_val_if_fail (!g_str_has_prefix (attribute, "param-"), FALSE);
- sa = lookup_account (self, account);
+ plugin = g_hash_table_lookup (self->accounts, account);
- if (sa == NULL)
+ if (plugin == NULL)
{
g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Account %s does not exist", account);
return FALSE;
}
- variant = g_hash_table_lookup (sa->attributes, attribute);
+ variant = mcp_account_storage_get_attribute (plugin, ma, account,
+ attribute, type, NULL);
if (variant == NULL)
{
g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Setting '%s' not stored by account %s", attribute, account);
+ "Account %s has no attribute '%s'", account, attribute);
return FALSE;
}
- return mcd_storage_coerce_variant_to_value (variant, value, error);
+ ret = mcd_storage_coerce_variant_to_value (variant, value, error);
+ g_variant_unref (variant);
+ return ret;
}
/*
@@ -970,52 +850,42 @@ gboolean
mcd_storage_get_parameter (McdStorage *self,
const gchar *account,
const gchar *parameter,
+ const GVariantType *type,
GValue *value,
GError **error)
{
- McdStorageAccount *sa;
- const gchar *escaped;
+ McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ McpAccountStorage *plugin;
GVariant *variant;
+ gboolean ret;
g_return_val_if_fail (MCD_IS_STORAGE (self), FALSE);
g_return_val_if_fail (account != NULL, FALSE);
g_return_val_if_fail (parameter != NULL, FALSE);
+ g_return_val_if_fail (!g_str_has_prefix (parameter, "param-"), FALSE);
- sa = lookup_account (self, account);
+ plugin = g_hash_table_lookup (self->accounts, account);
- if (sa == NULL)
+ if (plugin == NULL)
{
g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
"Account %s does not exist", account);
return FALSE;
}
- variant = g_hash_table_lookup (sa->parameters, parameter);
+ variant = mcp_account_storage_get_parameter (plugin, ma, account,
+ parameter, type, NULL);
- if (variant != NULL)
- return mcd_storage_coerce_variant_to_value (variant, value, error);
-
- /* OK, we don't have it as a variant. How about the keyfile-escaped
- * version? */
- escaped = g_hash_table_lookup (sa->escaped_parameters, parameter);
-
- if (escaped == NULL)
+ if (variant == NULL)
{
g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
- "Parameter '%s' not stored by account %s", parameter, account);
+ "Account %s has no parameter '%s'", account, parameter);
return FALSE;
}
- return mcd_keyfile_unescape_value (escaped, value, error);
-}
-
-static gboolean
-mcpa_unescape_value_from_keyfile (const McpAccountManager *unused G_GNUC_UNUSED,
- const gchar *escaped,
- GValue *value,
- GError **error)
-{
- return mcd_keyfile_unescape_value (escaped, value, error);
+ ret = mcd_storage_coerce_variant_to_value (variant, value, error);
+ g_variant_unref (variant);
+ return ret;
}
/*
@@ -1061,8 +931,8 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
GValue *value,
GError **error)
{
- gboolean ret = FALSE;
GType type;
+ GVariant *variant = NULL;
g_return_val_if_fail (keyfile != NULL, FALSE);
g_return_val_if_fail (group != NULL, FALSE);
@@ -1074,20 +944,155 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
switch (type)
{
case G_TYPE_STRING:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_STRING, error);
+ break;
+
+ case G_TYPE_INT:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_INT32, error);
+ break;
+
+ case G_TYPE_INT64:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_INT64, error);
+ break;
+
+ case G_TYPE_UINT:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_UINT32, error);
+ break;
+
+ case G_TYPE_UCHAR:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_BYTE, error);
+ break;
+
+ case G_TYPE_UINT64:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_UINT64, error);
+ break;
+
+ case G_TYPE_BOOLEAN:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_BOOLEAN, error);
+ break;
+
+ case G_TYPE_DOUBLE:
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_DOUBLE, error);
+ break;
+
+ default:
+ if (type == G_TYPE_STRV)
+ {
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_STRING_ARRAY, error);
+ }
+ else if (type == DBUS_TYPE_G_OBJECT_PATH)
+ {
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_OBJECT_PATH, error);
+ }
+ else if (type == TP_ARRAY_TYPE_OBJECT_PATH_LIST)
+ {
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE_OBJECT_PATH_ARRAY, error);
+ }
+ else if (type == TP_STRUCT_TYPE_SIMPLE_PRESENCE)
+ {
+ variant = mcd_keyfile_get_variant (keyfile, group, key,
+ G_VARIANT_TYPE ("(uss)"), error);
+ }
+ else
+ {
+ gchar *message =
+ g_strdup_printf ("cannot get key %s from group %s: "
+ "unknown type %s",
+ key, group, g_type_name (type));
+
+ g_warning ("%s: %s", G_STRFUNC, message);
+ g_set_error (error, MCD_ACCOUNT_ERROR,
+ MCD_ACCOUNT_ERROR_GET_PARAMETER,
+ "%s", message);
+ g_free (message);
+ }
+ }
+
+ if (variant == NULL)
+ return FALSE;
+
+ g_variant_ref_sink (variant);
+ g_value_unset (value);
+ dbus_g_value_parse_g_variant (variant, value);
+ g_assert (G_VALUE_TYPE (value) == type);
+ g_variant_unref (variant);
+ return TRUE;
+}
+
+/*
+ * mcd_keyfile_get_variant:
+ * @keyfile: A #GKeyFile
+ * @group: name of a group
+ * @key: name of a key
+ * @type: the desired type
+ * @error: a place to store any #GError<!-- -->s that occur
+ *
+ * Returns: a new floating #GVariant
+ */
+GVariant *
+mcd_keyfile_get_variant (GKeyFile *keyfile,
+ const gchar *group,
+ const gchar *key,
+ const GVariantType *type,
+ GError **error)
+{
+ const gchar *type_str = g_variant_type_peek_string (type);
+ GVariant *ret = NULL;
+
+ g_return_val_if_fail (keyfile != NULL, NULL);
+ g_return_val_if_fail (group != NULL, NULL);
+ g_return_val_if_fail (key != NULL, NULL);
+ g_return_val_if_fail (g_variant_type_string_scan (type_str, NULL, NULL),
+ NULL);
+
+ switch (type_str[0])
+ {
+ case G_VARIANT_CLASS_STRING:
{
gchar *v_string = g_key_file_get_string (keyfile, group,
key, error);
if (v_string != NULL)
+ ret = g_variant_new_string (v_string);
+ /* else error is already set */
+ }
+ break;
+
+ case G_VARIANT_CLASS_INT16:
+ {
+ GError *e = NULL;
+ gint v_int = g_key_file_get_integer (keyfile, group,
+ key, &e);
+
+ if (e != NULL)
{
- g_value_take_string (value, v_string);
- ret = TRUE;
+ g_propagate_error (error, e);
+ }
+ else if (v_int < G_MININT16 || v_int > G_MAXINT16)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "integer %d out of range [%d,%d]",
+ v_int, G_MININT16, G_MAXINT16);
+ }
+ else
+ {
+ ret = g_variant_new_int16 (v_int);
}
- /* else error is already set */
}
break;
- case G_TYPE_INT:
+ case G_VARIANT_CLASS_INT32:
{
GError *e = NULL;
gint v_int = g_key_file_get_integer (keyfile, group,
@@ -1099,13 +1104,12 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_int (value, v_int);
- ret = TRUE;
+ ret = g_variant_new_int32 (v_int);
}
}
break;
- case G_TYPE_INT64:
+ case G_VARIANT_CLASS_INT64:
{
GError *e = NULL;
gint64 v_int = g_key_file_get_int64 (keyfile, group,
@@ -1117,13 +1121,34 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_int64 (value, v_int);
- ret = TRUE;
+ ret = g_variant_new_int64 (v_int);
}
}
break;
- case G_TYPE_UINT:
+ case G_VARIANT_CLASS_UINT16:
+ {
+ GError *e = NULL;
+ gint v_int = g_key_file_get_integer (keyfile, group,
+ key, &e);
+
+ if (e != NULL)
+ {
+ g_propagate_error (error, e);
+ }
+ else if (v_int < 0 || (unsigned) v_int > G_MAXUINT16)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_INVALID_ARGUMENT,
+ "integer %d out of range [0,%d]", v_int, G_MAXUINT16);
+ }
+ else
+ {
+ ret = g_variant_new_uint16 (v_int);
+ }
+ }
+ break;
+
+ case G_VARIANT_CLASS_UINT32:
{
GError *e = NULL;
guint64 v_uint = g_key_file_get_uint64 (keyfile, group,
@@ -1142,13 +1167,12 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_uint (value, v_uint);
- ret = TRUE;
+ ret = g_variant_new_uint32 (v_uint);
}
}
break;
- case G_TYPE_UCHAR:
+ case G_VARIANT_CLASS_BYTE:
{
GError *e = NULL;
gint v_int = g_key_file_get_integer (keyfile, group,
@@ -1167,13 +1191,12 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_uchar (value, v_int);
- ret = TRUE;
+ ret = g_variant_new_byte (v_int);
}
}
break;
- case G_TYPE_UINT64:
+ case G_VARIANT_CLASS_UINT64:
{
GError *e = NULL;
guint64 v_uint = g_key_file_get_uint64 (keyfile, group,
@@ -1185,13 +1208,12 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_uint64 (value, v_uint);
- ret = TRUE;
+ ret = g_variant_new_uint64 (v_uint);
}
}
break;
- case G_TYPE_BOOLEAN:
+ case G_VARIANT_CLASS_BOOLEAN:
{
GError *e = NULL;
gboolean v_bool = g_key_file_get_boolean (keyfile, group,
@@ -1203,13 +1225,12 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_boolean (value, v_bool);
- ret = TRUE;
+ ret = g_variant_new_boolean (v_bool);
}
}
break;
- case G_TYPE_DOUBLE:
+ case G_VARIANT_CLASS_DOUBLE:
{
GError *e = NULL;
gdouble v_double = g_key_file_get_double (keyfile, group,
@@ -1221,25 +1242,24 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
else
{
- g_value_set_double (value, v_double);
- ret = TRUE;
+ ret = g_variant_new_double (v_double);
}
}
break;
default:
- if (type == G_TYPE_STRV)
+ if (g_variant_type_equal (type, G_VARIANT_TYPE_STRING_ARRAY))
{
gchar **v = g_key_file_get_string_list (keyfile, group,
key, NULL, error);
if (v != NULL)
{
- g_value_take_boxed (value, v);
- ret = TRUE;
+ ret = g_variant_new_strv ((const gchar **) v, -1);
+ g_strfreev (v);
}
}
- else if (type == DBUS_TYPE_G_OBJECT_PATH)
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH))
{
gchar *v_string = g_key_file_get_string (keyfile, group,
key, error);
@@ -1253,15 +1273,15 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
g_set_error (error, MCD_ACCOUNT_ERROR,
MCD_ACCOUNT_ERROR_GET_PARAMETER,
"Invalid object path %s", v_string);
- g_free (v_string);
}
else
{
- g_value_take_boxed (value, v_string);
- ret = TRUE;
+ ret = g_variant_new_object_path (v_string);
}
+
+ g_free (v_string);
}
- else if (type == TP_ARRAY_TYPE_OBJECT_PATH_LIST)
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE_OBJECT_PATH_ARRAY))
{
gchar **v = g_key_file_get_string_list (keyfile, group,
key, NULL, error);
@@ -1269,7 +1289,6 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
if (v != NULL)
{
gchar **iter;
- GPtrArray *arr = g_ptr_array_new ();
for (iter = v; iter != NULL && *iter != NULL; iter++)
{
@@ -1284,21 +1303,11 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
}
- for (iter = v; iter != NULL && *iter != NULL; iter++)
- {
- /* transfer ownership from v to arr */
- g_ptr_array_add (arr, *iter);
- }
-
- /* not g_strfreev - the strings' ownership has been
- * transferred */
- g_free (v);
-
- g_value_take_boxed (value, arr);
- ret = TRUE;
+ ret = g_variant_new_objv ((const gchar **) v, -1);
+ g_strfreev (v);
}
}
- else if (type == TP_STRUCT_TYPE_SIMPLE_PRESENCE)
+ else if (g_variant_type_equal (type, G_VARIANT_TYPE ("(uss)")))
{
gchar **v = g_key_file_get_string_list (keyfile, group,
key, NULL, error);
@@ -1328,13 +1337,8 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
else
{
/* a syntactically valid simple presence */
- g_value_take_boxed (value,
- tp_value_array_build (3,
- G_TYPE_UINT, (guint) u,
- G_TYPE_STRING, v[1],
- G_TYPE_STRING, v[2],
- G_TYPE_INVALID));
- ret = TRUE;
+ ret = g_variant_new_parsed ("(%u, %s, %s)",
+ (guint32) u, v[1], v[2]);
}
}
@@ -1344,8 +1348,9 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
{
gchar *message =
g_strdup_printf ("cannot get key %s from group %s: "
- "unknown type %s",
- key, group, g_type_name (type));
+ "unknown type %.*s", key, group,
+ (int) g_variant_type_get_string_length (type),
+ type_str);
g_warning ("%s: %s", G_STRFUNC, message);
g_set_error (error, MCD_ACCOUNT_ERROR,
@@ -1355,6 +1360,7 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
}
}
+ g_assert (ret == NULL || g_variant_is_of_type (ret, type));
return ret;
}
@@ -1380,7 +1386,8 @@ mcd_storage_get_boolean (McdStorage *self,
g_value_init (&tmp, G_TYPE_BOOLEAN);
- if (!mcd_storage_get_attribute (self, account, attribute, &tmp, NULL))
+ if (!mcd_storage_get_attribute (self, account, attribute,
+ G_VARIANT_TYPE_BOOLEAN, &tmp, NULL))
return FALSE;
return g_value_get_boolean (&tmp);
@@ -1408,65 +1415,60 @@ mcd_storage_get_integer (McdStorage *self,
g_value_init (&tmp, G_TYPE_INT);
- if (!mcd_storage_get_attribute (self, account, attribute, &tmp, NULL))
+ if (!mcd_storage_get_attribute (self, account, attribute,
+ G_VARIANT_TYPE_INT32, &tmp, NULL))
return FALSE;
return g_value_get_int (&tmp);
}
-static void
+static gboolean
update_storage (McdStorage *self,
const gchar *account,
+ gboolean parameter,
const gchar *key,
- GVariant *variant,
- const gchar *escaped,
- gboolean secret)
+ GVariant *variant)
{
- GList *store;
- gboolean done = FALSE;
- gboolean parameter = g_str_has_prefix (key, "param-");
McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ gboolean updated = FALSE;
+ McpAccountStorage *plugin;
+ const gchar *pn;
+ McpAccountStorageSetResult res;
- if (secret)
- mcd_storage_make_secret (self, account, key);
+ plugin = g_hash_table_lookup (self->accounts, account);
+ g_return_val_if_fail (plugin != NULL, FALSE);
+ pn = mcp_account_storage_name (plugin);
- /* we're deleting, which is unconditional, no need to check if anyone *
- * claims this setting for themselves */
- if (escaped == NULL)
- done = TRUE;
+ if (parameter)
+ res = mcp_account_storage_set_parameter (plugin, ma, account,
+ key, variant, MCP_PARAMETER_FLAG_NONE);
+ else
+ res = mcp_account_storage_set_attribute (plugin, ma, account,
+ key, variant, MCP_ATTRIBUTE_FLAG_NONE);
- for (store = stores; store != NULL; store = g_list_next (store))
+ switch (res)
{
- McpAccountStorage *plugin = store->data;
- const gchar *pn = mcp_account_storage_name (plugin);
+ case MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED:
+ DEBUG ("MCP:%s -> store %s %s.%s", pn,
+ parameter ? "parameter" : "attribute", account, key);
+ updated = TRUE;
+ break;
- if (done)
- {
- DEBUG ("MCP:%s -> delete %s.%s", pn, account, key);
- mcp_account_storage_delete (plugin, ma, account, key);
- }
- else if (variant != NULL && !parameter &&
- mcp_account_storage_set_attribute (plugin, ma, account, key, variant,
- MCP_ATTRIBUTE_FLAG_NONE))
- {
- done = TRUE;
- DEBUG ("MCP:%s -> store attribute %s.%s", pn, account, key);
- }
- else if (variant != NULL && parameter &&
- mcp_account_storage_set_parameter (plugin, ma, account, key + 6,
- variant,
- secret ? MCP_PARAMETER_FLAG_SECRET : MCP_PARAMETER_FLAG_NONE))
- {
- done = TRUE;
- DEBUG ("MCP:%s -> store parameter %s.%s", pn, account, key);
- }
- else
- {
- done = mcp_account_storage_set (plugin, ma, account, key, escaped);
- DEBUG ("MCP:%s -> %s %s.%s",
- pn, done ? "store" : "ignore", account, key);
- }
+ case MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED:
+ DEBUG ("MCP:%s -> failed to store %s %s.%s",
+ pn, parameter ? "parameter" : "attribute", account, key);
+ break;
+
+ case MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED:
+ DEBUG ("MCP:%s -> no change to %s %s.%s",
+ pn, parameter ? "parameter" : "attribute", account, key);
+ break;
+
+ default:
+ g_warn_if_reached ();
}
+
+ return updated;
}
/*
@@ -1537,45 +1539,24 @@ mcd_storage_set_attribute (McdStorage *self,
const gchar *attribute,
const GValue *value)
{
- McdStorageAccount *sa;
- GVariant *old_v;
GVariant *new_v;
gboolean updated = FALSE;
+ McpAccountStorage *plugin;
g_return_val_if_fail (MCD_IS_STORAGE (self), FALSE);
g_return_val_if_fail (account != NULL, FALSE);
g_return_val_if_fail (attribute != NULL, FALSE);
g_return_val_if_fail (!g_str_has_prefix (attribute, "param-"), FALSE);
- sa = ensure_account (self, account);
+ plugin = g_hash_table_lookup (self->accounts, account);
+ g_return_val_if_fail (plugin != NULL, FALSE);
if (value != NULL)
new_v = g_variant_ref_sink (dbus_g_value_build_g_variant (value));
else
new_v = NULL;
- old_v = g_hash_table_lookup (sa->attributes, attribute);
-
- if (!mcd_nullable_variant_equal (old_v, new_v))
- {
- gchar *escaped = NULL;
-
- /* First put it in the attributes hash table. (Watch out, this might
- * invalidate old_v.) */
- if (new_v == NULL)
- g_hash_table_remove (sa->attributes, attribute);
- else
- g_hash_table_insert (sa->attributes, g_strdup (attribute),
- g_variant_ref (new_v));
-
- /* OK now we have to escape it in a stupid way for plugins */
- if (value != NULL)
- escaped = mcd_keyfile_escape_value (value);
-
- update_storage (self, account, attribute, new_v, escaped, FALSE);
- g_free (escaped);
- updated = TRUE;
- }
+ updated = update_storage (self, account, FALSE, attribute, new_v);
tp_clear_pointer (&new_v, g_variant_unref);
return updated;
@@ -1587,8 +1568,6 @@ mcd_storage_set_attribute (McdStorage *self,
* @account: the unique name of an account
* @parameter: the name of the parameter, e.g. "account"
* @value: the value to be stored (or %NULL to erase it)
- * @secret: whether the value is confidential (might get stored in the
- * keyring, for example)
*
* Copies and stores the supplied @value (or removes it if %NULL) in the
* internal cache.
@@ -1603,66 +1582,30 @@ gboolean
mcd_storage_set_parameter (McdStorage *self,
const gchar *account,
const gchar *parameter,
- const GValue *value,
- gboolean secret)
+ const GValue *value)
{
- GVariant *old_v;
GVariant *new_v = NULL;
- const gchar *old_escaped;
- gchar *new_escaped = NULL;
- McdStorageAccount *sa;
gboolean updated = FALSE;
+ McpAccountStorage *plugin;
g_return_val_if_fail (MCD_IS_STORAGE (self), FALSE);
g_return_val_if_fail (account != NULL, FALSE);
g_return_val_if_fail (parameter != NULL, FALSE);
- sa = ensure_account (self, account);
+ plugin = g_hash_table_lookup (self->accounts, account);
+ g_return_val_if_fail (plugin != NULL, FALSE);
if (value != NULL)
{
- new_escaped = mcd_keyfile_escape_value (value);
new_v = g_variant_ref_sink (dbus_g_value_build_g_variant (value));
}
- old_v = g_hash_table_lookup (sa->parameters, parameter);
- old_escaped = g_hash_table_lookup (sa->escaped_parameters, parameter);
-
- if (old_v != NULL)
- updated = !mcd_nullable_variant_equal (old_v, new_v);
- else if (old_escaped != NULL)
- updated = tp_strdiff (old_escaped, new_escaped);
- else
- updated = (value != NULL);
+ updated = update_storage (self, account, TRUE, parameter, new_v);
- if (updated)
- {
- gchar key[MAX_KEY_LENGTH];
-
- g_hash_table_remove (sa->parameters, parameter);
- g_hash_table_remove (sa->escaped_parameters, parameter);
-
- if (new_v != NULL)
- g_hash_table_insert (sa->parameters, g_strdup (parameter),
- g_variant_ref (new_v));
-
- g_snprintf (key, sizeof (key), "param-%s", parameter);
- update_storage (self, account, key, new_v, new_escaped, secret);
- return TRUE;
- }
-
- g_free (new_escaped);
tp_clear_pointer (&new_v, g_variant_unref);
return updated;
}
-static gchar *
-mcpa_escape_value_for_keyfile (const McpAccountManager *unused G_GNUC_UNUSED,
- const GValue *value)
-{
- return mcd_keyfile_escape_value (value);
-}
-
/*
* @value: a populated #GValue of a supported #GType
*
@@ -1675,15 +1618,23 @@ mcpa_escape_value_for_keyfile (const McpAccountManager *unused G_GNUC_UNUSED,
gchar *
mcd_keyfile_escape_value (const GValue *value)
{
- GKeyFile *keyfile;
+ GVariant *variant;
gchar *ret;
g_return_val_if_fail (G_IS_VALUE (value), NULL);
- keyfile = g_key_file_new ();
- mcd_keyfile_set_value (keyfile, "g", "k", value);
- ret = g_key_file_get_value (keyfile, "g", "k", NULL);
- g_key_file_free (keyfile);
+ variant = dbus_g_value_build_g_variant (value);
+
+ if (variant == NULL)
+ {
+ g_warning ("Unable to convert %s to GVariant",
+ G_VALUE_TYPE_NAME (value));
+ return NULL;
+ }
+
+ g_variant_ref_sink (variant);
+ ret = mcd_keyfile_escape_variant (variant);
+ g_variant_unref (variant);
return ret;
}
@@ -1721,6 +1672,53 @@ mcd_keyfile_set_value (GKeyFile *keyfile,
if (value == NULL)
{
+ return mcd_keyfile_set_variant (keyfile, name, key, NULL);
+ }
+ else
+ {
+ GVariant *variant;
+ gboolean ret;
+
+ variant = dbus_g_value_build_g_variant (value);
+
+ if (variant == NULL)
+ {
+ g_warning ("Unable to convert %s to GVariant",
+ G_VALUE_TYPE_NAME (value));
+ return FALSE;
+ }
+
+ g_variant_ref_sink (variant);
+ ret = mcd_keyfile_set_variant (keyfile, name, key, variant);
+ g_variant_unref (variant);
+ return ret;
+ }
+}
+
+/*
+ * mcd_keyfile_set_variant:
+ * @keyfile: a keyfile
+ * @name: the name of a group
+ * @key: the key in the group
+ * @value: the value to be stored (or %NULL to erase it)
+ *
+ * Escape @variant and store it in the keyfile.
+ *
+ * Returns: %TRUE if the keyfile actually changed,
+ * so that the caller can decide whether to request a commit to
+ * long term storage or not.
+ */
+gboolean
+mcd_keyfile_set_variant (GKeyFile *keyfile,
+ const gchar *name,
+ const gchar *key,
+ GVariant *value)
+{
+ g_return_val_if_fail (name != NULL, FALSE);
+ g_return_val_if_fail (key != NULL, FALSE);
+
+ if (value == NULL)
+ {
gchar *old = g_key_file_get_value (keyfile, name, key, NULL);
gboolean updated = (old != NULL);
@@ -1735,75 +1733,88 @@ mcd_keyfile_set_value (GKeyFile *keyfile,
gchar *new = NULL;
gchar *buf = NULL;
- switch (G_VALUE_TYPE (value))
+ switch (g_variant_classify (value))
{
- case G_TYPE_STRING:
+ case G_VARIANT_CLASS_STRING:
+ case G_VARIANT_CLASS_OBJECT_PATH:
+ case G_VARIANT_CLASS_SIGNATURE:
g_key_file_set_string (keyfile, name, key,
- g_value_get_string (value));
+ g_variant_get_string (value, NULL));
+ break;
+
+ case G_VARIANT_CLASS_UINT16:
+ buf = g_strdup_printf ("%u", g_variant_get_uint16 (value));
break;
- case G_TYPE_UINT:
- buf = g_strdup_printf ("%u", g_value_get_uint (value));
+ case G_VARIANT_CLASS_UINT32:
+ buf = g_strdup_printf ("%u", g_variant_get_uint32 (value));
break;
- case G_TYPE_INT:
- g_key_file_set_integer (keyfile, name, key,
- g_value_get_int (value));
+ case G_VARIANT_CLASS_INT16:
+ buf = g_strdup_printf ("%d", g_variant_get_int16 (value));
break;
- case G_TYPE_BOOLEAN:
+ case G_VARIANT_CLASS_INT32:
+ buf = g_strdup_printf ("%d", g_variant_get_int32 (value));
+ break;
+
+ case G_VARIANT_CLASS_BOOLEAN:
g_key_file_set_boolean (keyfile, name, key,
- g_value_get_boolean (value));
+ g_variant_get_boolean (value));
break;
- case G_TYPE_UCHAR:
- buf = g_strdup_printf ("%u", g_value_get_uchar (value));
+ case G_VARIANT_CLASS_BYTE:
+ buf = g_strdup_printf ("%u", g_variant_get_byte (value));
break;
- case G_TYPE_UINT64:
+ case G_VARIANT_CLASS_UINT64:
buf = g_strdup_printf ("%" G_GUINT64_FORMAT,
- g_value_get_uint64 (value));
+ g_variant_get_uint64 (value));
break;
- case G_TYPE_INT64:
+ case G_VARIANT_CLASS_INT64:
buf = g_strdup_printf ("%" G_GINT64_FORMAT,
- g_value_get_int64 (value));
+ g_variant_get_int64 (value));
break;
- case G_TYPE_DOUBLE:
+ case G_VARIANT_CLASS_DOUBLE:
g_key_file_set_double (keyfile, name, key,
- g_value_get_double (value));
+ g_variant_get_double (value));
break;
- default:
- if (G_VALUE_HOLDS (value, G_TYPE_STRV))
+ case G_VARIANT_CLASS_ARRAY:
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE_STRING_ARRAY))
{
- gchar **strings = g_value_get_boxed (value);
+ gsize len;
+ const gchar **strings = g_variant_get_strv (value, &len);
- g_key_file_set_string_list (keyfile, name, key,
- (const gchar **)strings,
- g_strv_length (strings));
+ g_key_file_set_string_list (keyfile, name, key, strings, len);
}
- else if (G_VALUE_HOLDS (value, DBUS_TYPE_G_OBJECT_PATH))
+ else if (g_variant_is_of_type (value,
+ G_VARIANT_TYPE_OBJECT_PATH_ARRAY))
{
- g_key_file_set_string (keyfile, name, key,
- g_value_get_boxed (value));
+ gsize len;
+ const gchar **strings = g_variant_get_objv (value, &len);
+
+ g_key_file_set_string_list (keyfile, name, key, strings, len);
}
- else if (G_VALUE_HOLDS (value, TP_ARRAY_TYPE_OBJECT_PATH_LIST))
+ else
{
- GPtrArray *arr = g_value_get_boxed (value);
-
- g_key_file_set_string_list (keyfile, name, key,
- (const gchar * const *) arr->pdata, arr->len);
+ g_warning ("Unexpected array type %s",
+ g_variant_get_type_string (value));
+ return FALSE;
}
- else if (G_VALUE_HOLDS (value, TP_STRUCT_TYPE_SIMPLE_PRESENCE))
+ break;
+
+ case G_VARIANT_CLASS_TUPLE:
+ if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(uss)")))
{
- guint type;
+ guint32 type;
/* enough for "4294967296" + \0 */
gchar printf_buf[11];
const gchar * strv[4] = { NULL, NULL, NULL, NULL };
- tp_value_array_unpack (g_value_get_boxed (value), 3,
+ g_variant_get (value, "(u&s&s)",
&type,
&(strv[1]),
&(strv[2]));
@@ -1814,8 +1825,16 @@ mcd_keyfile_set_value (GKeyFile *keyfile,
}
else
{
- g_warning ("Unexpected param type %s",
- G_VALUE_TYPE_NAME (value));
+ g_warning ("Unexpected struct type %s",
+ g_variant_get_type_string (value));
+ return FALSE;
+ }
+ break;
+
+ default:
+ {
+ g_warning ("Unexpected variant type %s",
+ g_variant_get_type_string (value));
return FALSE;
}
}
@@ -1842,7 +1861,8 @@ mcd_keyfile_set_value (GKeyFile *keyfile,
* @provider: the desired storage provider, or %NULL
* @manager: the name of the manager
* @protocol: the name of the protocol
- * @params: A gchar * / GValue * hash table of account parameters
+ * @identification: the result of IdentifyAccount
+ * @plugin_out: (out) (transfer full): the plugin we used
* @error: a #GError to fill when returning %NULL
*
* Create a new account in storage. This should not store any
@@ -1857,11 +1877,16 @@ mcd_storage_create_account (McdStorage *self,
const gchar *provider,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identification,
+ McpAccountStorage **plugin_out,
GError **error)
{
GList *store;
McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ gchar *ret;
+
+ if (plugin_out != NULL)
+ *plugin_out = NULL;
g_return_val_if_fail (MCD_IS_STORAGE (self), NULL);
g_return_val_if_fail (!tp_str_empty (manager), NULL);
@@ -1876,8 +1901,21 @@ mcd_storage_create_account (McdStorage *self,
if (!tp_strdiff (mcp_account_storage_provider (plugin), provider))
{
- return mcp_account_storage_create (plugin, ma, manager,
- protocol, params, error);
+ ret = mcp_account_storage_create (plugin, ma, manager,
+ protocol, identification, error);
+ if (mcd_storage_add_account_from_plugin (self, plugin, ret,
+ error))
+ {
+ if (plugin_out != NULL)
+ *plugin_out = g_object_ref (plugin);
+
+ return ret;
+ }
+ else
+ {
+ g_free (ret);
+ return NULL;
+ }
}
}
@@ -1889,50 +1927,30 @@ mcd_storage_create_account (McdStorage *self,
/* No provider specified, let's pick the first plugin able to create this
* account in priority order.
- *
- * FIXME: This is rather subtle, and relies on the fact that accounts
- * aren't always strongly tied to a single plugin.
- *
- * For plugins that only store their accounts set up specifically
- * through them (like the libaccounts/SSO pseudo-plugin,
- * McdAccountManagerSSO), create() will fail as unimplemented,
- * and we'll fall through to the next plugin. Eventually we'll
- * reach the default keyfile+gnome-keyring plugin, or another
- * plugin that accepts arbitrary accounts. When set() is called,
- * the libaccounts/SSO plugin will reject that too, and again,
- * we'll fall through to a plugin that accepts arbitrary
- * accounts.
- *
- * Plugins that will accept arbitrary accounts being created
- * via D-Bus (like the default keyfile+gnome-keyring plugin,
- * and the account-diversion plugin in tests/twisted)
- * should, in principle, implement create() to be successful.
- * If they do, their create() will succeed, and later, so will
- * their set().
- *
- * We can't necessarily rely on all such plugins implementing
- * create(), because it isn't a mandatory part of the plugin
- * API (it was added later). However, as it happens, the
- * default plugin returns successfully from create() without
- * really doing anything. When we iterate through the accounts again
- * to call set(), higher-priority plugins are given a second
- * chance to intercept that; so we end up with create() in
- * the default plugin being followed by set() from the
- * higher-priority plugin. In theory that's bad because it
- * splits the account across two plugins, but in practice
- * it isn't a problem because the default plugin's create()
- * doesn't really do anything anyway.
*/
for (store = stores; store != NULL; store = g_list_next (store))
{
McpAccountStorage *plugin = store->data;
- gchar *ret;
- ret = mcp_account_storage_create (plugin, ma, manager, protocol, params,
- error);
+ ret = mcp_account_storage_create (plugin, ma, manager, protocol,
+ identification, error);
if (ret != NULL)
- return ret;
+ {
+ if (mcd_storage_add_account_from_plugin (self, plugin, ret,
+ error))
+ {
+ if (plugin_out != NULL)
+ *plugin_out = g_object_ref (plugin);
+
+ return ret;
+ }
+ else
+ {
+ g_free (ret);
+ return NULL;
+ }
+ }
g_clear_error (error);
}
@@ -1946,6 +1964,29 @@ mcd_storage_create_account (McdStorage *self,
return NULL;
}
+static void
+delete_cb (GObject *source,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ GError *error = NULL;
+ const gchar *account_name = user_data;
+
+ if (mcp_account_storage_delete_finish (MCP_ACCOUNT_STORAGE (source),
+ res, &error))
+ {
+ DEBUG ("deleted account %s", account_name);
+ }
+ else
+ {
+ DEBUG ("could not delete account %s (but no way to signal that): "
+ "%s #%d: %s", account_name,
+ g_quark_to_string (error->domain), error->code, error->message);
+ g_error_free (error);
+ }
+
+ g_free (user_data);
+}
/*
* mcd_storage_delete_account:
@@ -1961,20 +2002,19 @@ void
mcd_storage_delete_account (McdStorage *self,
const gchar *account)
{
- GList *store;
McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ McpAccountStorage *plugin;
g_return_if_fail (MCD_IS_STORAGE (self));
g_return_if_fail (account != NULL);
- g_hash_table_remove (self->accounts, account);
+ plugin = g_hash_table_lookup (self->accounts, account);
+ g_return_if_fail (plugin != NULL);
- for (store = stores; store != NULL; store = g_list_next (store))
- {
- McpAccountStorage *plugin = store->data;
-
- mcp_account_storage_delete (plugin, ma, account, NULL);
- }
+ /* FIXME: stop ignoring the error (if any), and make this method async
+ * in order to pass the error up to McdAccount */
+ mcp_account_storage_delete_async (plugin, ma, account, NULL,
+ delete_cb, g_strdup (account));
}
/*
@@ -1988,27 +2028,21 @@ mcd_storage_delete_account (McdStorage *self,
void
mcd_storage_commit (McdStorage *self, const gchar *account)
{
- GList *store;
McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ McpAccountStorage *plugin;
+ const gchar *pname;
g_return_if_fail (MCD_IS_STORAGE (self));
+ g_return_if_fail (account != NULL);
- for (store = stores; store != NULL; store = g_list_next (store))
- {
- McpAccountStorage *plugin = store->data;
- const gchar *pname = mcp_account_storage_name (plugin);
+ plugin = g_hash_table_lookup (self->accounts, account);
+ g_return_if_fail (plugin != NULL);
- if (account != NULL)
- {
- DEBUG ("flushing plugin %s %s to long term storage", pname, account);
- mcp_account_storage_commit_one (plugin, ma, account);
- }
- else
- {
- DEBUG ("flushing plugin %s to long term storage", pname);
- mcp_account_storage_commit (plugin, ma);
- }
- }
+ pname = mcp_account_storage_name (plugin);
+
+ /* FIXME: fd.o #29563: this should be async, really */
+ DEBUG ("flushing plugin %s %s to long term storage", pname, account);
+ mcp_account_storage_commit (plugin, ma, account);
}
/*
@@ -2049,20 +2083,27 @@ mcd_storage_set_strv (McdStorage *storage,
return ret;
}
-void
-mcd_storage_ready (McdStorage *self)
+static GVariant *
+mcpa_unescape_variant_from_keyfile (const McpAccountManager *mcpa,
+ const gchar *escaped,
+ const GVariantType *type,
+ GError **error)
{
- GList *store;
- McpAccountManager *ma = MCP_ACCOUNT_MANAGER (self);
+ GKeyFile *keyfile;
+ GVariant *ret;
- for (store = stores; store != NULL; store = g_list_next (store))
- {
- McpAccountStorage *plugin = store->data;
- const gchar *plugin_name = mcp_account_storage_name (plugin);
+ g_return_val_if_fail (escaped != NULL, NULL);
+ g_return_val_if_fail (type != NULL, NULL);
- DEBUG ("Unblocking async account ops by %s", plugin_name);
- mcp_account_storage_ready (plugin, ma);
- }
+ keyfile = g_key_file_new ();
+ g_key_file_set_value (keyfile, "g", "k", escaped);
+ ret = mcd_keyfile_get_variant (keyfile, "g", "k", type, error);
+ g_key_file_free (keyfile);
+
+ if (ret != NULL)
+ g_variant_ref_sink (ret);
+
+ return ret;
}
static void
@@ -2071,32 +2112,252 @@ plugin_iface_init (McpAccountManagerIface *iface,
{
DEBUG ();
- iface->get_value = get_value;
- iface->set_value = set_value;
- iface->set_attribute = mcpa_set_attribute;
- iface->set_parameter = mcpa_set_parameter;
- iface->is_secret = is_secret;
- iface->make_secret = make_secret;
iface->unique_name = unique_name;
- iface->list_keys = list_keys;
- iface->escape_value_for_keyfile = mcpa_escape_value_for_keyfile;
+ iface->identify_account_async = identify_account_async;
+ iface->identify_account_finish = identify_account_finish;
iface->escape_variant_for_keyfile = mcpa_escape_variant_for_keyfile;
- iface->unescape_value_from_keyfile = mcpa_unescape_value_from_keyfile;
- iface->init_value_for_attribute = mcpa_init_value_for_attribute;
+ iface->unescape_variant_from_keyfile = mcpa_unescape_variant_from_keyfile;
}
gboolean
mcd_storage_add_account_from_plugin (McdStorage *self,
McpAccountStorage *plugin,
- const gchar *account)
+ const gchar *account,
+ GError **error)
{
- if (!mcp_account_storage_get (plugin, MCP_ACCOUNT_MANAGER (self),
- account, NULL))
+ McpAccountStorage *other = g_hash_table_lookup (self->accounts, account);
+ McpAccountManager *api = (McpAccountManager *) self;
+ gchar **typed_parameters;
+ gchar **untyped_parameters;
+
+ if (other != NULL)
{
- g_warning ("plugin %s disowned account %s",
- mcp_account_storage_name (plugin), account);
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "account %s already exists in plugin '%s', cannot create "
+ "for plugin '%s'",
+ account,
+ mcp_account_storage_name (other),
+ mcp_account_storage_name (plugin));
return FALSE;
}
+ g_hash_table_insert (self->accounts, g_strdup (account),
+ g_object_ref (plugin));
+
+ typed_parameters = mcp_account_storage_list_typed_parameters (plugin, api,
+ account);
+ untyped_parameters = mcp_account_storage_list_untyped_parameters (plugin,
+ api, account);
+
+ DEBUG ("Account parameters for %s", account);
+
+ if (typed_parameters != NULL)
+ {
+ gsize i;
+
+ for (i = 0; typed_parameters[i] != NULL; i++)
+ {
+ GVariant *v = mcp_account_storage_get_parameter (plugin, api, account,
+ typed_parameters[i], NULL, NULL);
+
+ if (v == NULL)
+ {
+ CRITICAL ("%s: could not be retrieved", typed_parameters[i]);
+ }
+ else
+ {
+ DEBUG ("%s: type '%s'", typed_parameters[i],
+ g_variant_get_type_string (v));
+ g_variant_unref (v);
+ }
+ }
+ }
+
+ if (untyped_parameters != NULL)
+ {
+ gsize i;
+
+ for (i = 0; untyped_parameters[i] != NULL; i++)
+ {
+ DEBUG ("%s: type not stored", untyped_parameters[i]);
+ }
+ }
+
+ DEBUG ("End of parameters");
+
+ g_strfreev (typed_parameters);
+ g_strfreev (untyped_parameters);
+
return TRUE;
}
+
+GHashTable *
+mcd_storage_dup_typed_parameters (McdStorage *self,
+ const gchar *account_name)
+{
+ McpAccountStorage *plugin;
+ McpAccountManager *api = (McpAccountManager *) self;
+ gsize i;
+ gchar **typed_parameters;
+ GHashTable *params;
+
+ g_return_val_if_fail (MCD_IS_STORAGE (self), NULL);
+
+ plugin = g_hash_table_lookup (self->accounts, account_name);
+ g_return_val_if_fail (plugin != NULL, NULL);
+
+ typed_parameters = mcp_account_storage_list_typed_parameters (plugin, api,
+ account_name);
+
+ params = g_hash_table_new_full (g_str_hash, g_str_equal,
+ g_free, (GDestroyNotify) tp_g_value_slice_free);
+
+ for (i = 0;
+ typed_parameters != NULL && typed_parameters[i] != NULL;
+ i++)
+ {
+ GVariant *v = mcp_account_storage_get_parameter (plugin, api,
+ account_name, typed_parameters[i], NULL, NULL);
+ GValue *value;
+
+ if (v == NULL)
+ {
+ CRITICAL ("%s was in list_typed_parameters() but could not be "
+ "retrieved", typed_parameters[i]);
+ continue;
+ }
+
+ value = g_slice_new0 (GValue);
+ dbus_g_value_parse_g_variant (v, value);
+
+ if (!G_IS_VALUE (value))
+ {
+ CRITICAL ("could not turn %s into a GValue", typed_parameters[i]);
+ g_slice_free (GValue, value);
+ continue;
+ }
+
+ g_hash_table_insert (params, g_strdup (typed_parameters[i]),
+ value);
+ g_variant_unref (v);
+ }
+
+ return params;
+}
+
+/* See whether we can migrate the parameters from being stored without
+ * their types, to being stored with their types.
+ * Commit changes and return TRUE if anything happened. */
+gboolean
+mcd_storage_maybe_migrate_parameters (McdStorage *self,
+ const gchar *account_name,
+ TpProtocol *protocol)
+{
+ McpAccountManager *api = MCP_ACCOUNT_MANAGER (self);
+ McpAccountStorage *plugin;
+ gchar **untyped_parameters = NULL;
+ gsize i;
+ gboolean ret = FALSE;
+
+ plugin = g_hash_table_lookup (self->accounts, account_name);
+ g_return_val_if_fail (plugin != NULL, FALSE);
+
+ /* If the storage backend can't store typed parameters, there's no point. */
+ if (!mcp_account_storage_has_any_flag (plugin, account_name,
+ MCP_ACCOUNT_STORAGE_FLAG_STORES_TYPES))
+ goto finally;
+
+ untyped_parameters = mcp_account_storage_list_untyped_parameters (
+ plugin, api, account_name);
+
+ /* If there's nothing to migrate, there's also no point. */
+ if (untyped_parameters == NULL || untyped_parameters[0] == NULL)
+ goto finally;
+
+ DEBUG ("trying to migrate %s", account_name);
+
+ for (i = 0; untyped_parameters[i] != NULL; i++)
+ {
+ const gchar *param_name = untyped_parameters[i];
+ const TpConnectionManagerParam *param = tp_protocol_get_param (protocol,
+ param_name);
+ GVariantType *type = NULL;
+ GVariant *value;
+ McpAccountStorageSetResult res;
+
+ if (param == NULL)
+ {
+ DEBUG ("cannot migrate parameter '%s': not supported by %s/%s",
+ param_name, tp_protocol_get_cm_name (protocol),
+ tp_protocol_get_name (protocol));
+ goto next_param;
+ }
+
+ type = tp_connection_manager_param_dup_variant_type (param);
+
+ DEBUG ("Migrating parameter '%s' of type '%.*s'",
+ param_name,
+ (gint) g_variant_type_get_string_length (type),
+ g_variant_type_peek_string (type));
+
+ value = mcp_account_storage_get_parameter (plugin, api,
+ account_name, param_name, type, NULL);
+
+ if (value == NULL)
+ {
+ DEBUG ("cannot migrate parameter '%s'", param_name);
+ goto next_param;
+ }
+
+ if (!g_variant_is_of_type (value, type))
+ {
+ DEBUG ("trying to convert parameter from type '%s'",
+ g_variant_get_type_string (value));
+
+ /* consumes parameter */
+ value = tp_variant_convert (value, type);
+
+ if (value == NULL)
+ {
+ DEBUG ("could not convert parameter to desired type");
+ goto next_param;
+ }
+ }
+
+ res = mcp_account_storage_set_parameter (plugin, api,
+ account_name, param_name, value, MCP_PARAMETER_FLAG_NONE);
+
+ switch (res)
+ {
+ case MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED:
+ /* it really ought to be CHANGED, surely? */
+ DEBUG ("Tried to upgrade parameter %s but the "
+ "storage backend claims not to have changed it? "
+ "Not sure I really believe that", param_name);
+ /* fall through to the CHANGED case */
+
+ case MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED:
+ ret = TRUE;
+ break;
+
+ case MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED:
+ WARNING ("Failed to set parameter %s", param_name);
+ break;
+
+ default:
+ WARNING ("set_parameter returned invalid result code %d "
+ "for parameter %s", res, param_name);
+ }
+
+next_param:
+ if (type != NULL)
+ g_variant_type_free (type);
+ }
+
+ if (ret)
+ mcp_account_storage_commit (plugin, api, account_name);
+
+finally:
+ g_strfreev (untyped_parameters);
+ return ret;
+}
diff --git a/src/mcd-storage.h b/src/mcd-storage.h
index 893a0af3..56732f11 100644
--- a/src/mcd-storage.h
+++ b/src/mcd-storage.h
@@ -30,7 +30,7 @@ G_BEGIN_DECLS
typedef struct {
GObject parent;
TpDBusDaemon *dbusd;
- /* owned string => owned McdStorageAccount */
+ /* owned string => owned McpAccountStorage */
GHashTable *accounts;
} McdStorage;
@@ -64,11 +64,7 @@ void mcd_storage_connect_signal (const gchar *signal,
void mcd_storage_load (McdStorage *storage);
-GStrv mcd_storage_dup_accounts (McdStorage *storage, gsize *n);
-
-GStrv mcd_storage_dup_attributes (McdStorage *storage,
- const gchar *account,
- gsize *n);
+GHashTable *mcd_storage_get_accounts (McdStorage *storage);
gboolean mcd_storage_set_string (McdStorage *storage,
const gchar *account,
@@ -88,14 +84,14 @@ gboolean mcd_storage_set_attribute (McdStorage *storage,
gboolean mcd_storage_set_parameter (McdStorage *storage,
const gchar *account,
const gchar *parameter,
- const GValue *value,
- gboolean secret);
+ const GValue *value);
gchar *mcd_storage_create_account (McdStorage *storage,
const gchar *provider,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identification,
+ McpAccountStorage **plugin_out,
GError **error);
void mcd_storage_delete_account (McdStorage *storage, const gchar *account);
@@ -109,12 +105,14 @@ gchar *mcd_storage_dup_string (McdStorage *storage,
gboolean mcd_storage_get_attribute (McdStorage *storage,
const gchar *account,
const gchar *attribute,
+ const GVariantType *type,
GValue *value,
GError **error);
gboolean mcd_storage_get_parameter (McdStorage *storage,
const gchar *account,
const gchar *parameter,
+ const GVariantType *type,
GValue *value,
GError **error);
@@ -133,13 +131,23 @@ G_GNUC_INTERNAL void _mcd_storage_store_connections (McdStorage *storage);
gboolean mcd_storage_add_account_from_plugin (McdStorage *storage,
McpAccountStorage *plugin,
- const gchar *account);
+ const gchar *account,
+ GError **error);
+GVariant *mcd_keyfile_get_variant (GKeyFile *keyfile,
+ const gchar *group,
+ const gchar *key,
+ const GVariantType *type,
+ GError **error);
gboolean mcd_keyfile_get_value (GKeyFile *keyfile,
const gchar *group,
const gchar *key,
GValue *value,
GError **error);
+gboolean mcd_keyfile_set_variant (GKeyFile *keyfile,
+ const gchar *name,
+ const gchar *key,
+ GVariant *value);
gboolean mcd_keyfile_set_value (GKeyFile *keyfile,
const gchar *name,
const gchar *key,
@@ -150,9 +158,17 @@ gboolean mcd_keyfile_unescape_value (const gchar *escaped,
GValue *value,
GError **error);
-const gchar *mcd_storage_get_attribute_type (const gchar *attribute);
+const GVariantType *mcd_storage_get_attribute_type (const gchar *attribute);
gboolean mcd_storage_init_value_for_attribute (GValue *value,
- const gchar *attribute);
+ const gchar *attribute,
+ const GVariantType **variant_type);
+
+GHashTable *mcd_storage_dup_typed_parameters (McdStorage *self,
+ const gchar *account);
+
+gboolean mcd_storage_maybe_migrate_parameters (McdStorage *self,
+ const gchar *account_name,
+ TpProtocol *protocol);
G_END_DECLS
diff --git a/src/mcd.xml b/src/mcd.xml
deleted file mode 100644
index 27ae8d62..00000000
--- a/src/mcd.xml
+++ /dev/null
@@ -1,17 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright>
-
-<xi:include href="../xml/Connection_Manager_Interface_Account_Storage.xml"/>
-
-<xi:include href="../xml/Account_Interface_Conditions.xml"/>
-<xi:include href="../xml/Account_Interface_External_Password_Storage.xml"/>
-<xi:include href="../xml/Account_Interface_Hidden.xml"/>
-
-<xi:include href="../xml/Account_Manager_Interface_Hidden.xml"/>
-
-<xi:include href="dispatcher.xml"/>
-
-</tp:spec>
diff --git a/src/plugin-dispatch-operation.c b/src/plugin-dispatch-operation.c
index cd9c279c..22d777cd 100644
--- a/src/plugin-dispatch-operation.c
+++ b/src/plugin-dispatch-operation.c
@@ -34,7 +34,6 @@
typedef enum {
PLUGIN_ACTION_NONE,
PLUGIN_ACTION_CLOSE,
- PLUGIN_ACTION_LEAVE,
PLUGIN_ACTION_DESTROY
} PluginAction;
@@ -279,38 +278,6 @@ plugin_do_end_delay (McpDispatchOperation *obj,
g_object_unref (self);
}
-
-/* Close */
-static void
-plugin_do_leave_channels (McpDispatchOperation *obj,
- gboolean wait_for_observers, TpChannelGroupChangeReason reason,
- const gchar *message)
-{
- McdPluginDispatchOperation *self = MCD_PLUGIN_DISPATCH_OPERATION (obj);
-
- DEBUG ("%p (wait=%c reason=%d message=%s)", self,
- wait_for_observers ? 'T' : 'F', reason, message);
-
- g_return_if_fail (self != NULL);
-
- if (wait_for_observers)
- {
- if (self->after_observers < PLUGIN_ACTION_LEAVE)
- {
- DEBUG ("Remembering for later");
- self->after_observers = PLUGIN_ACTION_LEAVE;
- self->reason = reason;
- g_free (self->message);
- self->message = g_strdup (message);
- }
- }
- else
- {
- DEBUG ("Leaving now");
- _mcd_dispatch_operation_leave_channels (self->real_cdo, reason, message);
- }
-}
-
static void
plugin_do_close_channels (McpDispatchOperation *obj,
gboolean wait_for_observers)
@@ -370,12 +337,6 @@ _mcd_plugin_dispatch_operation_observers_finished (
_mcd_dispatch_operation_destroy_channels (self->real_cdo);
break;
- case PLUGIN_ACTION_LEAVE:
- DEBUG ("leaving now: %d %s", self->reason, self->message);
- _mcd_dispatch_operation_leave_channels (self->real_cdo,
- self->reason, self->message);
- break;
-
case PLUGIN_ACTION_CLOSE:
DEBUG ("closing now");
_mcd_dispatch_operation_close_channels (self->real_cdo);
@@ -412,7 +373,6 @@ plugin_iface_init (McpDispatchOperationIface *iface,
iface->start_delay = plugin_do_start_delay;
iface->end_delay = plugin_do_end_delay;
- iface->leave_channels = plugin_do_leave_channels;
iface->close_channels = plugin_do_close_channels;
iface->destroy_channels = plugin_do_destroy_channels;
}
diff --git a/src/plugin-loader.c b/src/plugin-loader.c
index 7062c3a2..d6beefdc 100644
--- a/src/plugin-loader.c
+++ b/src/plugin-loader.c
@@ -27,10 +27,6 @@
#include "mcd-debug.h"
-#if ENABLE_AEGIS
-#include "plugins/mcp-dbus-aegis-acl.h"
-#endif
-
static gsize ready = 0;
void
@@ -38,9 +34,6 @@ _mcd_plugin_loader_init (void)
{
if (g_once_init_enter (&ready))
{
-#if ENABLE_AEGIS
- GObject *pseudo_plugin;
-#endif
const gchar *dir = g_getenv ("MC_FILTER_PLUGIN_DIR");
if (dir == NULL)
@@ -48,15 +41,6 @@ _mcd_plugin_loader_init (void)
mcp_read_dir (dir);
-#if ENABLE_AEGIS
- /* The last object added by mcp_add_object() will be treated as highest
- * priority, at least for the interfaces used here */
- DEBUG ("Initialising built-in Aegis ACL plugin");
- pseudo_plugin = G_OBJECT (aegis_acl_new ());
- mcp_add_object (pseudo_plugin);
- g_object_unref (pseudo_plugin);
-#endif
-
g_once_init_leave (&ready, 1);
}
}
diff --git a/src/request.c b/src/request.c
index ce91440f..e59ec4c1 100644
--- a/src/request.c
+++ b/src/request.c
@@ -34,7 +34,6 @@
#include "mcd-misc.h"
#include "plugin-loader.h"
#include "plugin-request.h"
-#include "_gen/interfaces.h"
enum {
PROP_0,
diff --git a/tests/Makefile.am b/tests/Makefile.am
index cf7edc9c..a808ac7a 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -1,4 +1,4 @@
-INCLUDES = \
+AM_CPPFLAGS = \
$(DBUS_CFLAGS) \
$(TELEPATHY_CFLAGS) \
-I$(top_srcdir) \
@@ -37,11 +37,8 @@ tease_the_minotaur_LDADD = $(top_builddir)/src/libmcd-convenience.la
account_store_LDADD = $(GLIB_LIBS)
account_store_SOURCES = \
account-store.c \
- account-store-default.c \
- account-store-default.h
-
-if ENABLE_LIBACCOUNTS_SSO
-account_store_SOURCES += account-store-libaccounts.c account-store-libaccounts.h
-account_store_LDADD += $(LIBACCOUNTS_SSO_LIBS)
-INCLUDES += $(LIBACCOUNTS_SSO_CFLAGS)
-endif
+ account-store-keyfile.c \
+ account-store-keyfile.h \
+ account-store-variant-file.c \
+ account-store-variant-file.h \
+ $(NULL)
diff --git a/tests/account-store-default.c b/tests/account-store-keyfile.c
index 7f4c8c3b..efa96b0a 100644
--- a/tests/account-store-default.c
+++ b/tests/account-store-keyfile.c
@@ -1,5 +1,5 @@
/*
- * MC account storage backend inspector, default backend
+ * MC account storage inspector: MC 5.0-compatible single keyfile backend
*
* Copyright © 2010 Nokia Corporation
* Copyright © 2010 Collabora Ltd.
@@ -23,7 +23,7 @@
#include <glib.h>
#include <string.h>
-#include "account-store-default.h"
+#include "account-store-keyfile.h"
static const gchar *default_config (void)
{
@@ -76,14 +76,14 @@ static gboolean commit_changes (void)
}
gchar *
-default_get (const gchar *account,
+keyfile_get (const gchar *account,
const gchar *key)
{
return g_key_file_get_string (default_keyfile (), account, key, NULL);
}
gboolean
-default_set (const gchar *account,
+keyfile_set (const gchar *account,
const gchar *key,
const gchar *value)
{
@@ -100,7 +100,7 @@ default_set (const gchar *account,
}
gboolean
-default_delete (const gchar *account)
+keyfile_delete (const gchar *account)
{
GKeyFile *keyfile = default_keyfile ();
@@ -110,13 +110,13 @@ default_delete (const gchar *account)
}
gboolean
-default_exists (const gchar *account)
+keyfile_exists (const gchar *account)
{
return g_key_file_has_group (default_keyfile (), account);
}
GStrv
-default_list (void)
+keyfile_list (void)
{
return g_key_file_get_groups (default_keyfile (), NULL);
}
diff --git a/tests/account-store-default.h b/tests/account-store-keyfile.h
index 739f95cc..a6ce2179 100644
--- a/tests/account-store-default.h
+++ b/tests/account-store-keyfile.h
@@ -1,5 +1,5 @@
/*
- * MC account storage backend inspector, default backend
+ * MC account storage inspector: MC 5.0-compatible single keyfile backend
*
* Copyright © 2010 Nokia Corporation
* Copyright © 2010 Collabora Ltd.
@@ -19,23 +19,23 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef _ACCOUNT_STORE_DEFAULT_H_
-#define _ACCOUNT_STORE_DEFAULT_H_
+#ifndef _ACCOUNT_STORE_KEYFILE_H_
+#define _ACCOUNT_STORE_KEYFILE_H_
#include <glib.h>
#include <glib-object.h>
-gchar * default_get (const gchar *account,
+gchar * keyfile_get (const gchar *account,
const gchar *key);
-gboolean default_set (const gchar *account,
+gboolean keyfile_set (const gchar *account,
const gchar *key,
const gchar *value);
-gboolean default_delete (const gchar *account);
+gboolean keyfile_delete (const gchar *account);
-gboolean default_exists (const gchar *account);
+gboolean keyfile_exists (const gchar *account);
-GStrv default_list (void);
+GStrv keyfile_list (void);
#endif
diff --git a/tests/account-store-libaccounts.c b/tests/account-store-libaccounts.c
deleted file mode 100644
index e2756969..00000000
--- a/tests/account-store-libaccounts.c
+++ /dev/null
@@ -1,629 +0,0 @@
-/*
- * MC account storage backend inspector, libaccounts backend
- *
- * Copyright © 2010 Nokia Corporation
- * 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
- */
-
-#include "account-store-libaccounts.h"
-
-#include <libaccounts-glib/ag-manager.h>
-#include <libaccounts-glib/ag-account.h>
-#include <libaccounts-glib/ag-service.h>
-
-#include <string.h>
-
-#undef G_LOG_DOMAIN
-#define G_LOG_DOMAIN "account-store-libaccounts"
-
-/* MC <-> AG global/local setting meta data */
-#define MCPP "param-"
-#define AGPP "parameters/"
-#define LIBACCT_ID_KEY "libacct-uid"
-
-#define MC_ENABLED_KEY "Enabled"
-#define AG_ENABLED_KEY "enabled"
-
-#define AG_LABEL_KEY "name"
-#define MC_LABEL_KEY "DisplayName"
-
-#define AG_ACCOUNT_KEY "username"
-#define MC_ACCOUNT_KEY "account"
-#define PASSWORD_KEY "password"
-#define AG_ACCOUNT_ALT_KEY AGPP "account"
-
-#define MC_CMANAGER_KEY "manager"
-#define MC_PROTOCOL_KEY "protocol"
-#define MC_IDENTITY_KEY "tmc-uid"
-
-#define SERVICES_KEY "sso-services"
-
-#define MC_SERVICE_KEY "Service"
-
-typedef struct {
- gchar *mc_name;
- gchar *ag_name;
- gboolean global; /* global ag setting or service specific? */
- gboolean readable; /* does the _standard_ read method copy this into MC? */
- gboolean writable; /* does the _standard_ write method copy this into AG? */
- gboolean freeable; /* should clear_setting_data deallocate the names? */
-} Setting;
-
-#define GLOBAL TRUE
-#define SERVICE FALSE
-#define READABLE TRUE
-#define UNREADABLE FALSE
-#define WRITABLE TRUE
-#define UNWRITABLE FALSE
-
-typedef enum {
- SETTING_MC,
- SETTING_AG,
-} SettingType;
-
-Setting setting_map[] = {
- { MC_ENABLED_KEY , AG_ENABLED_KEY , GLOBAL , UNREADABLE, UNWRITABLE },
- { MCPP MC_ACCOUNT_KEY, AG_ACCOUNT_KEY , GLOBAL , READABLE , UNWRITABLE },
- { MCPP PASSWORD_KEY , PASSWORD_KEY , GLOBAL , READABLE , WRITABLE },
- { MC_LABEL_KEY , AG_LABEL_KEY , GLOBAL , READABLE , WRITABLE },
- { LIBACCT_ID_KEY , LIBACCT_ID_KEY , GLOBAL , UNREADABLE, UNWRITABLE },
- { MC_IDENTITY_KEY , MC_IDENTITY_KEY, SERVICE, READABLE , WRITABLE },
- { MC_CMANAGER_KEY , MC_CMANAGER_KEY, SERVICE, READABLE , UNWRITABLE },
- { MC_PROTOCOL_KEY , MC_PROTOCOL_KEY, SERVICE, READABLE , UNWRITABLE },
- { MC_SERVICE_KEY , MC_SERVICE_KEY , SERVICE, UNREADABLE, UNWRITABLE },
- { SERVICES_KEY , SERVICES_KEY , GLOBAL , UNREADABLE, UNWRITABLE },
- { NULL , NULL , SERVICE, UNREADABLE, UNWRITABLE }
-};
-
-static void
-clear_setting_data (Setting *setting)
-{
- if (setting == NULL)
- return;
-
- if (!setting->freeable)
- return;
-
- g_free (setting->mc_name);
- g_free (setting->ag_name);
- setting->mc_name = NULL;
- setting->ag_name = NULL;
-}
-
-static Setting *
-setting_data (const gchar *name, SettingType type)
-{
- guint i = 0;
- static Setting parameter = { NULL, NULL, SERVICE, READABLE, WRITABLE, TRUE };
- const gchar *prefix;
-
- for (; setting_map[i].mc_name != NULL; i++)
- {
- const gchar *setting_name = NULL;
-
- if (type == SETTING_MC)
- setting_name = setting_map[i].mc_name;
- else
- setting_name = setting_map[i].ag_name;
-
- if (g_strcmp0 (name, setting_name) == 0)
- return &setting_map[i];
- }
-
- prefix = (type == SETTING_MC) ? MCPP : AGPP;
-
- if (!g_str_has_prefix (name, prefix))
- { /* a non-parameter setting */
- parameter.mc_name = g_strdup (name);
- parameter.ag_name = g_strdup (name);
- }
- else
- { /* a setting that is a parameter on both sides (AG & MC) */
- const guint plength = strlen (prefix);
-
- parameter.mc_name = g_strdup_printf ("%s%s", MCPP, name + plength);
- parameter.ag_name = g_strdup_printf ("%s%s", AGPP, name + plength);
- }
-
- return &parameter;
-}
-
-
-/* logging helpers: */
-static void
-_g_log_handler (const gchar *log_domain,
- GLogLevelFlags log_level,
- const gchar *message,
- gpointer unused_data)
-{
- /* the libaccounts code is currently very chatty when debugging: *
- * we are only interested in or own debugging output for now. */
- if ((gchar *)log_domain != (gchar *)G_LOG_DOMAIN)
- return;
-
- g_log_default_handler (log_domain, log_level, message, unused_data);
-}
-
-static void
-toggle_mute (void)
-{
- static GLogFunc old = NULL;
-
- if (old == NULL)
- {
- old = g_log_set_default_handler (_g_log_handler, NULL);
- }
- else
- {
- g_log_set_default_handler (old, NULL);
- old = NULL;
- }
-}
-
-static gchar *
-_gvalue_to_string (const GValue *val)
-{
- switch (G_VALUE_TYPE (val))
- {
- case G_TYPE_STRING:
- return g_value_dup_string (val);
- case G_TYPE_BOOLEAN:
- return g_strdup (g_value_get_boolean (val) ? "true" : "false");
- case G_TYPE_CHAR:
- return g_strdup_printf ("%c", g_value_get_uchar (val));
- case G_TYPE_UCHAR:
- return g_strdup_printf ("%c", g_value_get_char (val));
- case G_TYPE_INT:
- return g_strdup_printf ("%i", g_value_get_int (val));
- case G_TYPE_UINT:
- return g_strdup_printf ("%u", g_value_get_uint (val));
- case G_TYPE_LONG:
- return g_strdup_printf ("%ld", g_value_get_long (val));
- case G_TYPE_ULONG:
- return g_strdup_printf ("%lu", g_value_get_ulong (val));
- case G_TYPE_INT64:
- return g_strdup_printf ("%" G_GINT64_FORMAT, g_value_get_int64 (val));
- case G_TYPE_UINT64:
- return g_strdup_printf ("%" G_GUINT64_FORMAT, g_value_get_uint64 (val));
- case G_TYPE_ENUM:
- return g_strdup_printf ("%d" , g_value_get_enum (val));
- case G_TYPE_FLAGS:
- return g_strdup_printf ("%u", g_value_get_flags (val));
- case G_TYPE_FLOAT:
- return g_strdup_printf ("%f", g_value_get_float (val));
- case G_TYPE_DOUBLE:
- return g_strdup_printf ("%g", g_value_get_double (val));
- default:
- g_warning ("Unsupported type %s", G_VALUE_TYPE_NAME (val));
- return NULL;
- }
-}
-
-static AgManager *
-get_ag_manager (void)
-{
- static AgManager *agm = NULL;
-
- toggle_mute ();
-
- if (agm != NULL)
- return agm;
-
- agm = ag_manager_new ();
-
- toggle_mute ();
-
- return agm;
-}
-
-static AgAccount *
-get_ag_account (const gchar *mc_account)
-{
- AgAccount *ag_account = NULL;
- AgManager *ag_manager = get_ag_manager ();
- GList *ag_ids = NULL;
- GList *ag_id;
-
- toggle_mute ();
-
- ag_ids = ag_manager_list_by_service_type (ag_manager, "IM");
- g_debug ("%d accounts in SSO", g_list_length (ag_ids));
-
- for (ag_id = ag_ids; ag_id != NULL; ag_id = g_list_next (ag_id))
- {
- AgAccountId id = GPOINTER_TO_UINT (ag_id->data);
- AgAccount *account = ag_manager_get_account (ag_manager, id);
-
- if (account != NULL)
- {
- GValue value = G_VALUE_INIT;
- AgSettingSource source = AG_SETTING_SOURCE_NONE;
-
- g_value_init (&value, G_TYPE_STRING);
- ag_account_select_service (account, NULL);
-
- source = ag_account_get_value (account, MC_IDENTITY_KEY, &value);
-
- if (source != AG_SETTING_SOURCE_NONE)
- {
- if (g_str_equal (g_value_get_string (&value), mc_account))
- {
- ag_account = g_object_ref (account);
- ag_id = NULL;
- }
-
- g_value_unset (&value);
- }
-
- g_object_unref (account);
- }
- }
-
- ag_manager_list_free (ag_ids);
-
- toggle_mute ();
-
- return ag_account;
-}
-
-static gboolean
-_ag_account_select_default_im_service (AgAccount *account)
-{
- gboolean have_im_service = FALSE;
- GList *first = ag_account_list_services_by_type (account, "IM");
-
- if (first != NULL && first->data != NULL)
- {
- have_im_service = TRUE;
- ag_account_select_service (account, first->data);
- }
-
- ag_service_list_free (first);
-
- return have_im_service;
-}
-
-/* enabled is actually a tri-state<->boolean mapping */
-static gboolean _sso_account_enabled (AgAccount *account, AgService *service)
-{
- gboolean local = FALSE;
- gboolean global = FALSE;
- AgService *original = ag_account_get_selected_service (account);
-
- if (service == NULL)
- {
- _ag_account_select_default_im_service (account);
- local = ag_account_get_enabled (account);
- }
- else
- {
- if (original != service)
- ag_account_select_service (account, service);
-
- local = ag_account_get_enabled (account);
- }
-
- ag_account_select_service (account, NULL);
- global = ag_account_get_enabled (account);
-
- ag_account_select_service (account, original);
-
- g_debug ("_sso_account_enabled: global:%d && local:%d", global, local);
-
- return local && global;
-}
-
-static void _sso_account_enable (AgAccount *account,
- AgService *service,
- gboolean on)
-{
- AgService *original = ag_account_get_selected_service (account);
-
- /* turn the local enabled flag on/off as required */
- if (service != NULL)
- ag_account_select_service (account, service);
- else
- _ag_account_select_default_im_service (account);
-
- ag_account_set_enabled (account, on);
-
- /* if we are turning the account on, the global flag must also be set *
- * NOTE: this isn't needed when turning the account off */
- if (on)
- {
- ag_account_select_service (account, NULL);
- ag_account_set_enabled (account, on);
- }
-
- ag_account_select_service (account, original);
-}
-
-/* saving settings other than the enabled tri-state */
-static void
-save_setting (AgAccount *account,
- const Setting *setting,
- const gchar *val)
-{
- AgService *service = ag_account_get_selected_service (account);
-
- if (!setting->writable)
- return;
-
- if (setting->global)
- ag_account_select_service (account, NULL);
- else if (service == NULL)
- _ag_account_select_default_im_service (account);
-
- if (val != NULL)
- {
- GValue value = G_VALUE_INIT;
-
- g_value_init (&value, G_TYPE_STRING);
- g_value_set_string (&value, val);
- ag_account_set_value (account, setting->ag_name, &value);
- g_value_unset (&value);
- }
- else
- {
- ag_account_set_value (account, setting->ag_name, NULL);
- }
-
- /* leave the selected service as we found it: */
- ag_account_select_service (account, service);
-}
-
-gchar *
-libaccounts_get (const gchar *mc_account, const gchar *key)
-{
- gchar *rval = NULL;
- AgAccount *ag_account = get_ag_account (mc_account);
- Setting *setting = setting_data (key, SETTING_MC);
-
- toggle_mute ();
-
- if (ag_account != NULL)
- {
-
- if (setting == NULL)
- {
- g_debug ("setting %s is unknown/unmapped, aborting update", key);
- rval = g_strdup ("");
- goto done;
- }
-
- g_debug ("MC key %s -> AG key %s", key, setting->ag_name);
-
- if (g_str_equal (setting->ag_name, AG_ENABLED_KEY))
- {
- gboolean on = _sso_account_enabled (ag_account, NULL);
-
- rval = g_strdup (on ? "true" : "false");
- goto done;
- }
- else
- {
- GValue value = G_VALUE_INIT;
- AgSettingSource source = AG_SETTING_SOURCE_NONE;
-
- g_value_init (&value, G_TYPE_STRING);
-
- /* the 'account' parameter is a special case for historical reasons */
- if (g_str_equal (key, MCPP MC_ACCOUNT_KEY))
- {
- _ag_account_select_default_im_service (ag_account);
- source =
- ag_account_get_value (ag_account, AG_ACCOUNT_ALT_KEY, &value);
-
- if (source != AG_SETTING_SOURCE_NONE)
- goto found;
- }
-
- if (setting->global)
- ag_account_select_service (ag_account, NULL);
- else
- _ag_account_select_default_im_service (ag_account);
-
- source = ag_account_get_value (ag_account, setting->ag_name, &value);
-
- found:
- if (source != AG_SETTING_SOURCE_NONE)
- {
- rval = _gvalue_to_string (&value);
- g_value_unset (&value);
- }
- }
- }
-
- done:
- toggle_mute ();
-
- if (ag_account)
- g_object_unref (ag_account);
-
- clear_setting_data (setting);
-
- return rval;
-}
-
-gboolean
-libaccounts_set (const gchar *mc_account,
- const gchar *key,
- const gchar *value)
-{
- gboolean done = FALSE;
- AgAccount *ag_account = get_ag_account (mc_account);
- Setting *setting = setting_data (key, SETTING_MC);
-
- toggle_mute ();
-
- if (ag_account != NULL)
- {
- if (setting == NULL)
- {
- g_debug ("setting %s is unknown/unmapped, aborting update", key);
- goto done;
- }
-
- if (g_str_equal (setting->ag_name, MC_ENABLED_KEY))
- {
- gboolean on = g_str_equal (value, "true");
-
- _sso_account_enable (ag_account, NULL, on);
- done = TRUE;
- goto done;
- }
- else
- {
- save_setting (ag_account, setting, value);
- done = TRUE;
- }
-
- if (done)
- ag_account_store (ag_account, NULL, NULL);
-
- }
-
- done:
- toggle_mute ();
-
- if (ag_account)
- g_object_unref (ag_account);
-
- clear_setting_data (setting);
-
- return done;
-}
-
-gboolean
-libaccounts_delete (const gchar *mc_account)
-{
- gboolean done = FALSE;
- AgAccount *ag_account = get_ag_account (mc_account);
-
- toggle_mute ();
-
- if(ag_account != NULL)
- {
- ag_account_delete (ag_account);
- ag_account_store (ag_account, NULL, NULL);
- g_object_unref (ag_account);
- done = TRUE;
- }
-
- toggle_mute ();
-
- return done;
-}
-
-gboolean
-libaccounts_exists (const gchar *mc_account)
-{
- gboolean exists = FALSE;
- AgAccount *ag_account = get_ag_account (mc_account);
-
- toggle_mute ();
-
- if (ag_account != NULL)
- {
- exists = TRUE;
- g_object_unref (ag_account);
- }
-
- toggle_mute ();
-
- return exists;
-}
-
-GStrv
-libaccounts_list (void)
-{
- AgManager *ag_manager = get_ag_manager ();
- GList *ag_ids = ag_manager_list_by_service_type (ag_manager, "IM");
- guint len = g_list_length (ag_ids);
- GStrv rval = NULL;
- GList *id;
- guint i = 0;
- Setting *setting = setting_data (MC_IDENTITY_KEY, SETTING_AG);
-
- if (len == 0)
- goto done;
-
- rval = g_new (gchar *, len + 1);
- rval[len] = NULL;
-
- for (id = ag_ids; id && i < len; id = g_list_next (id))
- {
- GValue value = G_VALUE_INIT;
- AgAccountId uid = GPOINTER_TO_UINT (id->data);
- AgAccount *ag_account = ag_manager_get_account (ag_manager, uid);
- AgSettingSource source = AG_SETTING_SOURCE_NONE;
-
- if (ag_account)
- {
- if (setting->global)
- ag_account_select_service (ag_account, NULL);
- else
- _ag_account_select_default_im_service (ag_account);
-
- source = ag_account_get_value (ag_account, setting->ag_name, &value);
- }
-
- if (source != AG_SETTING_SOURCE_NONE)
- {
- rval[i++] = _gvalue_to_string (&value);
- g_value_unset (&value);
- }
- else
- {
- GValue cmanager = G_VALUE_INIT;
- GValue protocol = G_VALUE_INIT;
- GValue account = G_VALUE_INIT;
- const gchar *acct = NULL;
- const gchar *cman = NULL;
- const gchar *proto = NULL;
-
- g_value_init (&cmanager, G_TYPE_STRING);
- g_value_init (&protocol, G_TYPE_STRING);
- g_value_init (&account, G_TYPE_STRING);
-
- _ag_account_select_default_im_service (ag_account);
-
- ag_account_get_value (ag_account, MC_CMANAGER_KEY, &cmanager);
- cman = g_value_get_string (&cmanager);
-
- ag_account_get_value (ag_account, MC_PROTOCOL_KEY, &protocol);
- proto = g_value_get_string (&protocol);
-
- ag_account_select_service (ag_account, NULL);
- ag_account_get_value (ag_account, AG_ACCOUNT_KEY, &account);
- acct = g_value_get_string (&account);
-
- rval[i++] = g_strdup_printf ("unnamed account #%u (%s/%s/%s)",
- uid, cman, proto, acct);
-
- g_value_unset (&cmanager);
- g_value_unset (&protocol);
- g_value_unset (&account);
- }
- }
-
- done:
- g_list_free (ag_ids);
- clear_setting_data (setting);
-
- return rval;
-}
diff --git a/tests/account-store-libaccounts.h b/tests/account-store-libaccounts.h
deleted file mode 100644
index 8e88f696..00000000
--- a/tests/account-store-libaccounts.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * MC account storage backend inspector, libaccounts backend
- *
- * Copyright © 2010 Nokia Corporation
- * 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
- */
-
-#include <glib-object.h>
-
-#ifndef _ACCOUNT_STORE_LIBACCOUNTS_H_
-#define _ACCOUNT_STORE_LIBACCOUNTS_H_
-
-G_BEGIN_DECLS
-
-gchar * libaccounts_get (const gchar *mc_account,
- const gchar *key);
-
-gboolean libaccounts_set (const gchar *mc_account,
- const gchar *key,
- const gchar *value);
-
-gboolean libaccounts_delete (const gchar *mc_account);
-
-gboolean libaccounts_exists (const gchar *mc_account);
-
-GStrv libaccounts_list (void);
-
-G_END_DECLS
-
-#endif
diff --git a/tests/account-store-variant-file.c b/tests/account-store-variant-file.c
new file mode 100644
index 00000000..b3fc7565
--- /dev/null
+++ b/tests/account-store-variant-file.c
@@ -0,0 +1,189 @@
+/*
+ * MC account storage inspector: MC 5.14 GVariant-file backend
+ *
+ * Copyright © 2010 Nokia Corporation
+ * Copyright © 2010-2013 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
+ */
+
+#include "config.h"
+#include "account-store-variant-file.h"
+
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+static gchar *
+get_path (const gchar *account)
+{
+ gchar *ret;
+ gchar *basename;
+
+ basename = g_strdup_printf ("%s.account", account);
+ g_strdelimit (basename, "/", '-');
+
+ ret = g_build_filename (g_get_user_data_dir (), "telepathy",
+ "mission-control", basename, NULL);
+ g_free (basename);
+ return ret;
+}
+
+static GVariant *
+load (const gchar *account)
+{
+ GError *error = NULL;
+ gchar *contents = NULL;
+ gsize len;
+ GVariant *ret = NULL;
+ gchar *path = NULL;
+
+ path = get_path (account);
+
+ if (!g_file_get_contents (path, &contents, &len, &error))
+ goto finally;
+
+ ret = g_variant_parse (G_VARIANT_TYPE_VARDICT, contents, contents + len,
+ NULL, &error);
+
+finally:
+ if (error != NULL)
+ g_warning ("variant file '%s' error: %s", path, error->message);
+
+ g_free (path);
+ g_clear_error (&error);
+ g_free (contents);
+ return ret;
+}
+
+gchar *
+variant_get (const gchar *account,
+ const gchar *key)
+{
+ GVariant *asv = load (account);
+ GVariant *v = NULL;
+ GString *ret = NULL;
+
+ if (asv == NULL)
+ return NULL;
+
+ if (g_str_has_prefix (key, "param-"))
+ {
+ GVariant *intermediate = g_variant_lookup_value (asv,
+ "Parameters", NULL);
+
+ if (intermediate != NULL)
+ {
+ g_assert (g_variant_is_of_type (intermediate,
+ G_VARIANT_TYPE ("a{sv}")));
+ v = g_variant_lookup_value (intermediate, key + 6, NULL);
+ }
+
+ intermediate = g_variant_lookup_value (asv,
+ "KeyFileParameters", NULL);
+
+ if (v == NULL && intermediate != NULL)
+ {
+ g_assert (g_variant_is_of_type (intermediate,
+ G_VARIANT_TYPE ("a{ss}")));
+ v = g_variant_lookup_value (intermediate, key + 6,
+ G_VARIANT_TYPE_STRING);
+
+ if (v != NULL)
+ ret = g_string_new ("keyfile-escaped ");
+ }
+ }
+ else
+ {
+ v = g_variant_lookup_value (asv, key, NULL);
+ }
+
+ if (v != NULL)
+ {
+ ret = g_variant_print_string (v, ret, TRUE);
+ g_variant_unref (v);
+ }
+
+ g_variant_unref (asv);
+
+ if (ret == NULL)
+ return NULL;
+
+ return g_string_free (ret, FALSE);
+}
+
+gboolean
+variant_delete (const gchar *account)
+{
+ gchar *path = get_path (account);
+
+ if (g_unlink (path) != 0)
+ {
+ g_warning ("%s", g_strerror (errno));
+ g_free (path);
+ return FALSE;
+ }
+
+ g_free (path);
+ return TRUE;
+}
+
+gboolean
+variant_exists (const gchar *account)
+{
+ gchar *path = get_path (account);
+ gboolean ret = g_file_test (path, G_FILE_TEST_EXISTS);
+
+ g_free (path);
+ return ret;
+}
+
+GStrv
+variant_list (void)
+{
+ GPtrArray *ret = g_ptr_array_new ();
+ gchar *dir_path = g_build_filename (g_get_user_data_dir (), "telepathy",
+ "mission-control", NULL);
+ GDir *dir = g_dir_open (dir_path, 0, NULL);
+
+ if (dir != NULL)
+ {
+ const gchar *name;
+
+ for (name = g_dir_read_name (dir);
+ name != NULL;
+ name = g_dir_read_name (dir))
+ {
+ gchar *dup;
+
+ if (!g_str_has_suffix (name, ".account"))
+ continue;
+
+ /* this is not production code so we're ignoring the possibility
+ * of invalid account names here */
+ dup = g_strdup (name);
+ g_strdelimit (dup, "-", '/');
+ g_strdelimit (dup, ".", '\0');
+ g_ptr_array_add (ret, dup);
+ }
+
+ g_dir_close (dir);
+ }
+
+ g_free (dir_path);
+ g_ptr_array_add (ret, NULL);
+ return (GStrv) g_ptr_array_free (ret, FALSE);
+}
diff --git a/plugins/mcp-dbus-aegis-acl.h b/tests/account-store-variant-file.h
index 96baaf46..dad07bf2 100644
--- a/plugins/mcp-dbus-aegis-acl.h
+++ b/tests/account-store-variant-file.h
@@ -1,8 +1,8 @@
/*
- * A pseudo-plugin that checks the caller's Aegis permission tokens
+ * MC account storage inspector: MC 5.14 GVariant-file backend
*
- * Copyright © 2010-2011 Nokia Corporation
- * Copyright © 2010-2011 Collabora Ltd.
+ * Copyright © 2010 Nokia Corporation
+ * Copyright © 2010-2012 Collabora Ltd.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -19,16 +19,19 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
-#ifndef AEGIS_ACL_H
-#define AEGIS_ACL_H
+#ifndef _ACCOUNT_STORE_VARIANT_FILE_H_
+#define _ACCOUNT_STORE_VARIANT_FILE_H_
-#include <mission-control-plugins/mission-control-plugins.h>
+#include <glib.h>
#include <glib-object.h>
-G_BEGIN_DECLS
+gchar *variant_get (const gchar *account,
+ const gchar *key);
-GObject *aegis_acl_new (void);
+gboolean variant_delete (const gchar *account);
-G_END_DECLS
+gboolean variant_exists (const gchar *account);
+
+GStrv variant_list (void);
#endif
diff --git a/tests/account-store.c b/tests/account-store.c
index 4482ea5b..419d178a 100644
--- a/tests/account-store.c
+++ b/tests/account-store.c
@@ -27,7 +27,8 @@
#include <glib.h>
#include <glib-object.h>
-#include "account-store-default.h"
+#include "account-store-keyfile.h"
+#include "account-store-variant-file.h"
#define DOCSTRING_A \
"%s OP BACKEND ACCOUNT [KEY [VALUE]]\n\n" \
@@ -40,10 +41,6 @@
" KEY := <manager | protocol | DisplayName | param-<PARAMETER>>\n" \
" VALUE := <STRING>\n\n"
-#if ENABLE_LIBACCOUNTS_SSO
-#include "account-store-libaccounts.h"
-#endif
-
typedef struct {
const gchar *name;
gchar * (*get) (const gchar *account, const gchar *key);
@@ -63,21 +60,19 @@ typedef enum {
} Operation;
const Backend backends[] = {
- { "default",
- default_get,
- default_set,
- default_delete,
- default_exists,
- default_list },
-
-#if ENABLE_LIBACCOUNTS_SSO
- { "libaccounts",
- libaccounts_get,
- libaccounts_set,
- libaccounts_delete,
- libaccounts_exists,
- libaccounts_list },
-#endif
+ { "keyfile",
+ keyfile_get,
+ keyfile_set,
+ keyfile_delete,
+ keyfile_exists,
+ keyfile_list },
+
+ { "variant-file",
+ variant_get,
+ NULL,
+ variant_delete,
+ variant_exists,
+ variant_list },
{ NULL }
};
@@ -182,6 +177,12 @@ int main (int argc, char **argv)
break;
case OP_SET:
+ if (store->set == NULL)
+ {
+ g_printerr ("Listing is unimplemented for this backend");
+ break;
+ }
+
success = store->set (account, setting, value);
output = g_strdup_printf ("%s.%s set to '%s' in %s",
account, setting, value, store->name);
diff --git a/tests/twisted/Makefile.am b/tests/twisted/Makefile.am
index 26ac627b..7091bfa8 100644
--- a/tests/twisted/Makefile.am
+++ b/tests/twisted/Makefile.am
@@ -19,6 +19,7 @@ TWISTED_BASIC_TESTS = \
account-manager/recover-from-disconnect.py \
account-manager/req-conn-fails.py \
account-manager/request-online.py \
+ account-manager/restricted-storage.py \
account-manager/service.py \
account-manager/update-parameters.py \
account-requests/cancel.py \
@@ -27,10 +28,8 @@ TWISTED_BASIC_TESTS = \
account/addressing.py \
capabilities/contact-caps.py \
dispatcher/already-has-channel.py \
- dispatcher/already-has-obsolete.py \
dispatcher/approver-fails.py \
dispatcher/bypass-approval.py \
- dispatcher/bypass-observers.py \
dispatcher/cancel.py \
dispatcher/capture-bundle.py \
dispatcher/cdo-claim.py \
@@ -75,9 +74,12 @@ TWISTED_BASIC_TESTS = \
# account-storage/*.py need their own instances.
TWISTED_SPECIAL_BUILD_TESTS = \
account-manager/connectivity.py \
- account-manager/hidden.py \
- account-storage/default-keyring-storage.py \
- account-storage/diverted-storage.py
+ account-storage/diverted-storage.py \
+ account-storage/5-12.py \
+ account-storage/5-14.py \
+ account-storage/create-new.py \
+ account-storage/load-keyfiles.py \
+ $(NULL)
# Tests that are usually too slow to run.
TWISTED_SLOW_TESTS = \
@@ -104,11 +106,10 @@ TWISTED_TESTS = \
TWISTED_OTHER_FILES = \
constants.py \
fakeaccountsservice.py \
- fakeclient.py \
- fakecm.py \
fakeconnectivity.py \
mctest.py \
servicetest.py \
+ account-storage/storage_helper.py \
telepathy/clients/README \
telepathy/clients/AbiWord.client \
telepathy/clients/Logger.client \
@@ -122,6 +123,14 @@ TWISTED_OTHER_FILES = \
mc-twisted-tests.list:
$(AM_V_GEN)echo $(TWISTED_BASIC_TESTS) $(TWISTED_SEPARATE_TESTS) > $@
+twisted-tests.test: Makefile
+ $(AM_V_GEN)( echo '[Test]'; \
+ echo 'Exec=${twistedtestsdir}/run-test.sh'; \
+ echo 'Type=session'; \
+ echo 'Output=TAP' ) > $@.tmp
+ @chmod +x $@.tmp
+ @mv $@.tmp $@
+
run-test.sh: run-test.sh.in Makefile
$(AM_V_GEN)sed \
-e "s|[@]mctestsdir[@]|@mctestsdir@|g" \
@@ -130,6 +139,9 @@ run-test.sh: run-test.sh.in Makefile
@chmod +x $@
if ENABLE_INSTALLED_TESTS
+insttestdir = ${datadir}/installed-tests/telepathy-mission-control
+nodist_insttest_DATA = twisted-tests.test
+
# Install files in each directory. They could be tests, pristine data files,
# scripts or built source
twistedtestsdir = @mctestsdir@/twisted
@@ -147,13 +159,6 @@ nobase_nodist_twistedtests_DATA = \
$(NULL)
endif
-
-if HAVE_MCE
-HAVE_MCE_PYBOOL = True
-else
-HAVE_MCE_PYBOOL = False
-endif
-
if HAVE_NM
HAVE_NM_PYBOOL = True
else
@@ -162,13 +167,13 @@ endif
config.py: Makefile
$(AM_V_GEN) { \
- echo "HAVE_MCE = $(HAVE_MCE_PYBOOL)"; \
echo "HAVE_NM = $(HAVE_NM_PYBOOL)"; \
} > $@
BUILT_SOURCES = \
config.py \
mc-twisted-tests.list \
+ twisted-tests.test \
run-test.sh \
$(NULL)
@@ -177,7 +182,6 @@ AM_CFLAGS = $(ERROR_CFLAGS)
plugins_list = \
mcp-plugin.la \
mcp-account-diversion.la \
- mcp-dbus-caller-permission.la \
libgiofakenetworkmonitor.la \
$(NULL)
@@ -215,9 +219,6 @@ libgiofakenetworkmonitor_la_LDFLAGS = $(mcp_plugin_la_LDFLAGS)
mcp_account_diversion_la_SOURCES = mcp-account-diversion.c
mcp_account_diversion_la_LDFLAGS = $(mcp_plugin_la_LDFLAGS)
-mcp_dbus_caller_permission_la_SOURCES = mcp-dbus-caller-permission.c
-mcp_dbus_caller_permission_la_LDFLAGS = $(mcp_plugin_la_LDFLAGS)
-
# A debug version of the normal MC executable, which exits cleanly on
# disconnection from D-Bus (so gcov info gets written out)
noinst_PROGRAMS = mc-debug-server
@@ -225,7 +226,7 @@ mc_debug_server_SOURCES = mc-debug-server.c
mc_debug_server_LDADD = \
$(top_builddir)/src/libmcd-convenience.la
-INCLUDES = \
+AM_CPPFLAGS = \
-I$(top_srcdir) -I$(top_builddir) \
-I$(top_srcdir)/src -I$(top_builddir)/src \
$(DBUS_CFLAGS) \
diff --git a/tests/twisted/account-manager/account-basics.py b/tests/twisted/account-manager/account-basics.py
index 18b35cb2..4e643cc9 100644
--- a/tests/twisted/account-manager/account-basics.py
+++ b/tests/twisted/account-manager/account-basics.py
@@ -46,7 +46,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_path = account.__dbus_object_path__
@@ -83,7 +83,6 @@ def test(q, bus, mc):
interfaces = properties.get('Interfaces')
assert cs.ACCOUNT_IFACE_AVATAR in interfaces, interfaces
- assert cs.ACCOUNT_IFACE_NOKIA_CONDITIONS in interfaces, interfaces
# sanity check
for k in properties:
@@ -174,32 +173,6 @@ def test(q, bus, mc):
)
assert account_props.Get(cs.ACCOUNT, 'Nickname') == 'Joe Bloggs'
- call_async(q, account_props, 'Set', cs.ACCOUNT_IFACE_NOKIA_CONDITIONS,
- 'Condition',
- dbus.Dictionary({':foo': 'bar'}, signature='ss'))
- # there's no change notification for the Condition
- q.expect_many(
- EventPattern('dbus-return', method='Set'),
- EventPattern('dbus-signal',
- interface=cs.TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- signal='DeferringSetAttribute',
- args=[account_path, 'condition-:foo', 'bar']),
- EventPattern('dbus-signal',
- interface=cs.TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- signal='CommittingOne',
- args=[account_path]),
- EventPattern('dbus-method-call',
- interface=cs.TEST_DBUS_ACCOUNT_SERVICE_IFACE,
- method='UpdateAttributes',
- args=[account_path[len(cs.ACCOUNT_PATH_PREFIX):],
- {'condition-:foo': 'bar'},
- {'condition-:foo': 0}, # flags
- []],
- ),
- )
- assert account_props.Get(cs.ACCOUNT_IFACE_NOKIA_CONDITIONS,
- 'Condition') == {':foo': 'bar'}
-
assertEquals(dbus.Array(signature='o'),
account_props.Get(cs.ACCOUNT, 'Supersedes'))
call_async(q, account_props, 'Set', cs.ACCOUNT, 'Supersedes',
@@ -271,16 +244,6 @@ def test(q, bus, mc):
else:
raise AssertionError('Setting %s with wrong type should fail' % p)
- for p in ('Condition',):
- try:
- account_props.Set(cs.ACCOUNT_IFACE_NOKIA_CONDITIONS, p,
- badly_typed)
- except dbus.DBusException, e:
- assert e.get_dbus_name() == cs.INVALID_ARGUMENT, \
- (p, e.get_dbus_name())
- else:
- raise AssertionError('Setting %s with wrong type should fail' % p)
-
# Make sure MC hasn't crashed yet, and make sure some properties are what
# we expect them to be
diff --git a/tests/twisted/account-manager/auto-connect.py b/tests/twisted/account-manager/auto-connect.py
index a623902c..28cfb2ab 100644
--- a/tests/twisted/account-manager/auto-connect.py
+++ b/tests/twisted/account-manager/auto-connect.py
@@ -21,22 +21,20 @@ import dbus
"""
import os
+import os.path
import dbus
import dbus.service
from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
call_async, assertEquals
-from mctest import exec_test, SimulatedConnection, create_fakecm_account, MC
+from mctest import (exec_test, SimulatedConnection,
+ SimulatedConnectionManager, MC)
import constants as cs
-cm_name_ref = dbus.service.BusName(
- cs.tp_name_prefix + '.ConnectionManager.fakecm', bus=dbus.SessionBus())
-
account_id = 'fakecm/fakeprotocol/jc_2edenton_40unatco_2eint'
def preseed(q, bus, fake_accounts_service):
-
accounts_dir = os.environ['MC_ACCOUNT_DIR']
try:
@@ -68,8 +66,12 @@ def preseed(q, bus, fake_accounts_service):
'password': r'\\\\ionstorm\\\\',
})
- os.makedirs(accounts_dir + '/' + account_id)
- avatar_bin = open(accounts_dir + '/' + account_id + '/avatar.bin', 'w')
+ avatar_filename = account_id
+ avatar_filename = avatar_filename.replace('/', '-') + '.avatar'
+ avatar_filename = (os.environ['XDG_DATA_HOME'] +
+ '/telepathy/mission-control/' + avatar_filename)
+ os.makedirs(os.path.dirname(avatar_filename))
+ avatar_bin = open(avatar_filename, 'w')
avatar_bin.write('Deus Ex')
avatar_bin.close()
@@ -78,6 +80,8 @@ def preseed(q, bus, fake_accounts_service):
account_connections_file.close()
def test(q, bus, unused, **kwargs):
+ simulated_cm = SimulatedConnectionManager(q, bus)
+
fake_accounts_service = kwargs['fake_accounts_service']
preseed(q, bus, fake_accounts_service)
@@ -124,7 +128,7 @@ def test(q, bus, unused, **kwargs):
assertEquals({}, prop_changed.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_CONNECTING,
prop_changed.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_REQUESTED,
+ assertEquals(cs.CSR_REQUESTED,
prop_changed.args[0].get('ConnectionStatusReason'))
q.dbus_return(request_conn.message, conn.bus_name, conn.object_path,
@@ -147,16 +151,16 @@ def test(q, bus, unused, **kwargs):
assertEquals({}, prop_changed.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_CONNECTING,
prop_changed.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_REQUESTED,
+ assertEquals(cs.CSR_REQUESTED,
prop_changed.args[0].get('ConnectionStatusReason'))
props = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE)
assert props['Connection'] == conn.object_path
assert props['ConnectionStatus'] == cs.CONN_STATUS_CONNECTING
- assert props['ConnectionStatusReason'] == cs.CONN_STATUS_REASON_REQUESTED
+ assert props['ConnectionStatusReason'] == cs.CSR_REQUESTED
print "becoming connected"
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
set_aliases, set_presence, set_avatar, prop_changed = q.expect_many(
EventPattern('dbus-method-call',
@@ -183,11 +187,11 @@ def test(q, bus, unused, **kwargs):
assertEquals({}, prop_changed.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_CONNECTED,
prop_changed.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_REQUESTED,
+ assertEquals(cs.CSR_REQUESTED,
prop_changed.args[0].get('ConnectionStatusReason'))
assert account.Get(cs.ACCOUNT, 'CurrentPresence',
- dbus_interface=cs.PROPERTIES_IFACE) == (cs.PRESENCE_TYPE_AVAILABLE,
+ dbus_interface=cs.PROPERTIES_IFACE) == (cs.PRESENCE_AVAILABLE,
'available', 'My vision is augmented')
q.dbus_return(set_aliases.message, signature='')
diff --git a/tests/twisted/account-manager/avatar-refresh.py b/tests/twisted/account-manager/avatar-refresh.py
index fe75d3a3..d914c439 100644
--- a/tests/twisted/account-manager/avatar-refresh.py
+++ b/tests/twisted/account-manager/avatar-refresh.py
@@ -28,12 +28,10 @@ import dbus.service
from servicetest import (EventPattern, tp_name_prefix, tp_path_prefix,
call_async, assertEquals, sync_dbus)
-from mctest import exec_test, SimulatedConnection, create_fakecm_account, MC
+from mctest import (exec_test, SimulatedConnection,
+ SimulatedConnectionManager, MC)
import constants as cs
-cm_name_ref = dbus.service.BusName(
- cs.tp_name_prefix + '.ConnectionManager.fakecm', bus=dbus.SessionBus())
-
class Account(object):
def __init__(self, fake_accounts_service, accounts_dir,
avatars_persist, server_delays, local_avatar, remote_avatar):
@@ -92,15 +90,6 @@ class Account(object):
avatar_bin = open(avatar_filename, 'w')
avatar_bin.write(local_avatar)
avatar_bin.close()
- elif not avatars_persist:
- self.avatar_location = 'old'
- # exercise migration from ~/.mission-control in a
- # situation where MC should "win"
- os.makedirs(accounts_dir + '/' + self.id)
- avatar_bin = open(
- accounts_dir + '/' + self.id + '/avatar.bin', 'w')
- avatar_bin.write(local_avatar)
- avatar_bin.close()
else:
# store it in the normal location
self.avatar_location = 'home'
@@ -187,23 +176,21 @@ class Account(object):
q.dbus_return(e.message, conn.bus_name, conn.object_path,
signature='so')
- forbidden = []
-
if self.winner != 'MC':
- forbidden.append(
- EventPattern('dbus-method-call', method='SetAvatar'))
+ q.forbid_events([
+ EventPattern('dbus-method-call', method='SetAvatar'),
+ ])
if self.winner != 'service':
- forbidden.append(
+ q.forbid_events([
EventPattern('dbus-signal', signal='AvatarChanged',
- path=account_path))
-
- q.forbid_events(forbidden)
+ path=account_path),
+ ])
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True, interface=cs.CONN)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
if self.winner == 'MC':
# MC should upload the avatar.
@@ -256,24 +243,13 @@ class Account(object):
byte_arrays=True) == conn.avatar
sync_dbus(bus, q, mc)
- q.unforbid_events(forbidden)
+ q.unforbid_all()
if self.local_avatar:
self.test_migration(bus, q, conn, account_proxy)
def test_migration(self, bus, q, conn, account_proxy):
- if self.avatar_location == 'old':
- # The avatar got migrated to the new location.
- assert not os.path.exists(os.environ['MC_ACCOUNT_DIR'] + '/' +
- self.id + '/avatar.bin')
- assert not os.path.exists(os.environ['MC_ACCOUNT_DIR'] + '/fakecm')
- avatar_filename = self.id
- avatar_filename = avatar_filename.replace('/', '-') + '.avatar'
- avatar_filename = (os.environ['XDG_DATA_HOME'] +
- '/telepathy/mission-control/' + avatar_filename)
- assertEquals(conn.avatar[0], ''.join(open(avatar_filename,
- 'r').readlines()))
- elif self.avatar_location == 'datadir' and self.winner == 'service':
+ if self.avatar_location == 'datadir' and self.winner == 'service':
# The avatar wasn't deleted from $XDG_DATA_DIRS, but it was
# overridden.
assert not os.path.exists(os.environ['MC_ACCOUNT_DIR'] + '/' +
@@ -359,6 +335,8 @@ def preseed(q, bus, fake_accounts_service):
return accounts
def test(q, bus, unused, **kwargs):
+ simulated_cm = SimulatedConnectionManager(q, bus)
+
fake_accounts_service = kwargs['fake_accounts_service']
accounts = preseed(q, bus, fake_accounts_service)
diff --git a/tests/twisted/account-manager/avatar.py b/tests/twisted/account-manager/avatar.py
index 353c8992..b31ab975 100644
--- a/tests/twisted/account-manager/avatar.py
+++ b/tests/twisted/account-manager/avatar.py
@@ -29,7 +29,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "me@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
diff --git a/tests/twisted/account-manager/backend-makes-changes.py b/tests/twisted/account-manager/backend-makes-changes.py
index 89eb4c1d..a4caeac0 100644
--- a/tests/twisted/account-manager/backend-makes-changes.py
+++ b/tests/twisted/account-manager/backend-makes-changes.py
@@ -34,7 +34,7 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
{}, # attr flags
{'account': 'ezio@firenze.fic', 'password': 'nothing is true'},
{}, # untyped parameters
- {'password': cs.PARAM_FLAG_SECRET}) # param flags
+ {'password': cs.PARAM_SECRET}) # param flags
q.expect_many(
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
@@ -47,7 +47,8 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
{'account': 'ezio@firenze.fic',
'password': 'nothing is true'},
{},
- {'account': 0, 'password': cs.PARAM_FLAG_SECRET}]),
+ {'account': 0, 'password': cs.PARAM_SECRET},
+ 0]),
EventPattern('dbus-signal',
path=cs.AM_PATH,
signal='AccountValidityChanged',
@@ -184,14 +185,14 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
account.Properties.Get(cs.ACCOUNT, 'Supersedes'))
fake_accounts_service.update_attributes(account_tail,
- {'AutomaticPresence': (dbus.UInt32(cs.PRESENCE_TYPE_HIDDEN), 'hidden',
+ {'AutomaticPresence': (dbus.UInt32(cs.PRESENCE_HIDDEN), 'hidden',
'in a haystack or something')})
q.expect_many(
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
signal='AttributesChanged',
args=[account_tail,
- {'AutomaticPresence': (cs.PRESENCE_TYPE_HIDDEN,
+ {'AutomaticPresence': (cs.PRESENCE_HIDDEN,
'hidden',
'in a haystack or something')},
{'AutomaticPresence': 0},
@@ -201,14 +202,14 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
signal='AccountPropertyChanged',
interface=cs.ACCOUNT,
args=[{'AutomaticPresence':
- (cs.PRESENCE_TYPE_HIDDEN, 'hidden',
+ (cs.PRESENCE_HIDDEN, 'hidden',
'in a haystack or something')}]),
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
signal='AttributeChanged',
args=[account_path, 'AutomaticPresence']),
)
- assertEquals((cs.PRESENCE_TYPE_HIDDEN, 'hidden',
+ assertEquals((cs.PRESENCE_HIDDEN, 'hidden',
'in a haystack or something'),
account.Properties.Get(cs.ACCOUNT, 'AutomaticPresence'))
@@ -276,13 +277,13 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
account.Properties.Get(cs.ACCOUNT, 'Service'))
fake_accounts_service.update_parameters(account_tail, {
- 'password': 'high profile'}, flags={'password': cs.PARAM_FLAG_SECRET})
+ 'password': 'high profile'}, flags={'password': cs.PARAM_SECRET})
q.expect_many(
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
signal='ParametersChanged',
args=[account_tail, {'password': 'high profile'},
- {}, {'password': cs.PARAM_FLAG_SECRET}, []]),
+ {}, {'password': cs.PARAM_SECRET}, []]),
EventPattern('dbus-signal',
path=account_path,
signal='AccountPropertyChanged',
@@ -296,13 +297,13 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
)
fake_accounts_service.update_parameters(account_tail, untyped={
- 'password': r'\\\n'}, flags={'password': cs.PARAM_FLAG_SECRET})
+ 'password': r'\\\n'}, flags={'password': cs.PARAM_SECRET})
q.expect_many(
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
signal='ParametersChanged',
args=[account_tail, {}, {'password': r'\\\n'},
- {'password': cs.PARAM_FLAG_SECRET}, []]),
+ {'password': cs.PARAM_SECRET}, []]),
EventPattern('dbus-signal',
path=account_path,
signal='AccountPropertyChanged',
diff --git a/tests/twisted/account-manager/bad-cm.py b/tests/twisted/account-manager/bad-cm.py
index 74277b46..008ac605 100644
--- a/tests/twisted/account-manager/bad-cm.py
+++ b/tests/twisted/account-manager/bad-cm.py
@@ -22,11 +22,12 @@
import dbus
from servicetest import call_async, assertEquals, assertContains
-from mctest import exec_test, AccountManager
+from mctest import (exec_test, SimulatedConnectionManager, AccountManager)
import constants as cs
def test(q, bus, mc):
am = AccountManager(bus)
+ simulated_cm = SimulatedConnectionManager(q, bus)
def call_create(cm='fakecm', protocol='fakeprotocol', parameters=None):
if parameters is None:
@@ -74,5 +75,13 @@ def test(q, bus, mc):
assertEquals(cs.INVALID_ARGUMENT, e.name)
assertContains("password", e.message)
+ # Create an account that will fail IdentifyAccount
+ call_create(parameters={ "account": "",
+ "password": "ohai",
+ })
+ e = q.expect('dbus-error', method='CreateAccount')
+ assertEquals(cs.INVALID_HANDLE, e.name)
+ assertContains("Invalid account name", e.message)
+
if __name__ == '__main__':
exec_test(test, {})
diff --git a/tests/twisted/account-manager/connectivity.py b/tests/twisted/account-manager/connectivity.py
index 8d80c1d4..1e378dc4 100644
--- a/tests/twisted/account-manager/connectivity.py
+++ b/tests/twisted/account-manager/connectivity.py
@@ -46,7 +46,7 @@ def test(q, bus, mc):
{"account": "yum yum network manager",
"password": "boo boo connman (although your API *is* simpler)",
}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
# While we're not connected to the internet, RequestConnection should not
# be called.
@@ -56,13 +56,13 @@ def test(q, bus, mc):
q.forbid_events(request_connection_event)
account.Properties.Set(cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy', 'hlaghalgh'))
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'hlaghalgh'))
# Turn the account on, re-request an online presence, and even tell it to
# connect automatically, to check that none of these make it sign in.
call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', True)
q.expect('dbus-return', method='Set')
- requested_presence = (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy', 'gtfo')
+ requested_presence = (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'gtfo')
call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'RequestedPresence',
requested_presence)
q.expect('dbus-return', method='Set')
@@ -149,7 +149,7 @@ def test(q, bus, mc):
# connection comes back up the account should not be brought back online.
q.forbid_events(request_connection_event)
account.Properties.Set(cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', ''))
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
mc.connectivity.go_online()
# Make sure MC has noticed that the network connection has come back.
sync_connectivity_state(mc)
diff --git a/tests/twisted/account-manager/crashy-cm.py b/tests/twisted/account-manager/crashy-cm.py
index 2eebeb8b..ca8f0ae5 100644
--- a/tests/twisted/account-manager/crashy-cm.py
+++ b/tests/twisted/account-manager/crashy-cm.py
@@ -38,14 +38,14 @@ def test(q, bus, mc):
{"account": "someguy@example.com",
"password": "secrecy",
}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params,
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params,
cm_bus=cm_bus)
account.Properties.Set(cs.ACCOUNT, 'Enabled', True)
# Set online presence
presence = dbus.Struct(
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy', 'Fixing MC bugs'),
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Fixing MC bugs'),
signature='uss')
account.Properties.Set(cs.ACCOUNT, 'RequestedPresence', presence)
@@ -65,11 +65,11 @@ def test(q, bus, mc):
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# CM crashes
conn.release_name()
- del cm_name_ref
+ simulated_cm.release_name()
cm_bus.flush()
cm_bus.close()
@@ -80,7 +80,7 @@ def test(q, bus, mc):
assertEquals('/', changed['Connection'])
assertEquals(cs.CONN_STATUS_DISCONNECTED, changed['ConnectionStatus'])
# In the absence of a better code, None will have to do.
- assertEquals(cs.CONN_STATUS_REASON_NONE, changed['ConnectionStatusReason'])
+ assertEquals(cs.CSR_NONE_SPECIFIED, changed['ConnectionStatusReason'])
# And NoReply will do as “it crashed”.
assertEquals(cs.DBUS_ERROR_NO_REPLY, changed['ConnectionError'])
diff --git a/tests/twisted/account-manager/create-auto-connect.py b/tests/twisted/account-manager/create-auto-connect.py
index fa2cb470..45acda05 100644
--- a/tests/twisted/account-manager/create-auto-connect.py
+++ b/tests/twisted/account-manager/create-auto-connect.py
@@ -28,7 +28,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "smcv@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -36,11 +36,11 @@ def test(q, bus, mc):
# Ensure that it's enabled but has offline RP
call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', ''))
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
q.expect('dbus-return', method='Set')
call_async(q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Testing automatic presence'))
q.expect('dbus-return', method='Set')
q.expect('dbus-signal', signal='AccountPropertyChanged',
diff --git a/tests/twisted/account-manager/create-twice.py b/tests/twisted/account-manager/create-twice.py
index 2f0c0e0c..3f1b8e20 100644
--- a/tests/twisted/account-manager/create-twice.py
+++ b/tests/twisted/account-manager/create-twice.py
@@ -22,7 +22,7 @@ import dbus.service
from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
call_async
-from mctest import exec_test, create_fakecm_account, get_account_manager
+from mctest import exec_test, SimulatedConnectionManager, get_account_manager
import constants as cs
def test(q, bus, mc):
@@ -35,8 +35,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "create-twice",
"password": "secrecy"}, signature='sv')
- cm_name_ref = dbus.service.BusName(cs.tp_name_prefix +
- '.ConnectionManager.fakecm', bus=bus)
+ simulated_cm = SimulatedConnectionManager(q, bus)
account_manager = bus.get_object(cs.AM, cs.AM_PATH)
am_iface = dbus.Interface(account_manager, cs.AM)
diff --git a/tests/twisted/account-manager/create-with-properties.py b/tests/twisted/account-manager/create-with-properties.py
index 6e208806..fb276c48 100644
--- a/tests/twisted/account-manager/create-with-properties.py
+++ b/tests/twisted/account-manager/create-with-properties.py
@@ -22,7 +22,7 @@ import dbus.service
from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
call_async, assertEquals, assertContains
-from mctest import exec_test, create_fakecm_account, AccountManager
+from mctest import (exec_test, SimulatedConnectionManager, AccountManager)
import constants as cs
def test(q, bus, mc):
@@ -45,33 +45,29 @@ def test(q, bus, mc):
assert (cs.ACCOUNT + '.Nickname') in supported
assert (cs.ACCOUNT + '.ConnectAutomatically') in supported
assert (cs.ACCOUNT_IFACE_AVATAR + '.Avatar') in supported
- assert (cs.ACCOUNT_IFACE_NOKIA_CONDITIONS + '.Condition') in supported
assert (cs.ACCOUNT + '.RequestedPresence') in supported
assert (cs.ACCOUNT + '.Supersedes') in supported
assertContains(cs.ACCOUNT + '.Service', supported)
- params = dbus.Dictionary({"account": "anarki@example.com",
+ params = dbus.Dictionary({"account": "aNaRkI@eXaMpLe.CoM",
"password": "secrecy"}, signature='sv')
- cm_name_ref = dbus.service.BusName(cs.tp_name_prefix +
- '.ConnectionManager.fakecm', bus=bus)
+ simulated_cm = SimulatedConnectionManager(q, bus)
creation_properties = dbus.Dictionary({
cs.ACCOUNT + '.Enabled': True,
cs.ACCOUNT + '.AutomaticPresence': dbus.Struct((
- dbus.UInt32(cs.PRESENCE_TYPE_BUSY),
+ dbus.UInt32(cs.PRESENCE_BUSY),
'busy', 'Exploding'), signature='uss'),
cs.ACCOUNT + '.RequestedPresence': dbus.Struct((
- dbus.UInt32(cs.PRESENCE_TYPE_AWAY),
+ dbus.UInt32(cs.PRESENCE_AWAY),
'away', 'Respawning'), signature='uss'),
cs.ACCOUNT + '.Icon': 'quake3arena',
cs.ACCOUNT + '.Nickname': 'AnArKi',
cs.ACCOUNT + '.ConnectAutomatically': True,
cs.ACCOUNT_IFACE_AVATAR + '.Avatar': (dbus.ByteArray('foo'),
'image/jpeg'),
- cs.ACCOUNT_IFACE_NOKIA_CONDITIONS + '.Condition':
- dbus.Dictionary({ 'has-quad-damage': ':y' }, signature='ss'),
cs.ACCOUNT + '.Supersedes': dbus.Array([
cs.ACCOUNT_PATH_PREFIX + 'q1/q1/Ranger',
cs.ACCOUNT_PATH_PREFIX + 'q2/q2/Grunt',
@@ -98,6 +94,9 @@ def test(q, bus, mc):
)
account_path = ret.value[0]
assert am_signal.args == [account_path, True], am_signal.args
+ # We called IdentifyAccount, which normalized the silly account name.
+ # The _xx hex-escaping and the trailing digit are implementation details.
+ assert account_path.endswith('/anarki_40example_2ecom0'), account_path
assert account_path is not None
@@ -107,10 +106,10 @@ def test(q, bus, mc):
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
properties = account_props.GetAll(cs.ACCOUNT)
- assert properties.get('AutomaticPresence') == (cs.PRESENCE_TYPE_BUSY,
+ assert properties.get('AutomaticPresence') == (cs.PRESENCE_BUSY,
'busy', 'Exploding'), \
properties.get('AutomaticPresence')
- assert properties.get('RequestedPresence') == (cs.PRESENCE_TYPE_AWAY,
+ assert properties.get('RequestedPresence') == (cs.PRESENCE_AWAY,
'away', 'Respawning'), \
properties.get('RequestedPresence')
assert properties.get('ConnectAutomatically') == True, \
@@ -135,11 +134,6 @@ def test(q, bus, mc):
assert properties.get('Avatar') == ([ord('f'), ord('o'), ord('o')],
'image/jpeg')
- properties = account_props.GetAll(cs.ACCOUNT_IFACE_NOKIA_CONDITIONS)
- assert properties.get('Condition') == {
- 'has-quad-damage': ':y',
- }
-
# tests for errors when creating an account
creation_properties2 = creation_properties.copy()
diff --git a/tests/twisted/account-manager/device-idle.py b/tests/twisted/account-manager/device-idle.py
index 196b6a04..dcc76ec9 100644
--- a/tests/twisted/account-manager/device-idle.py
+++ b/tests/twisted/account-manager/device-idle.py
@@ -82,8 +82,8 @@ def _create_and_enable(q, bus, mc, account_name, power_saving_supported,
extra_interfaces = [cs.CONN_IFACE_POWER_SAVING]
params = dbus.Dictionary({"account": account_name, "password": "secrecy"},
signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
- conn = enable_fakecm_account(q, bus, mc, account, params, has_requests=False,
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
+ conn = enable_fakecm_account(q, bus, mc, account, params,
extra_interfaces=extra_interfaces,
expect_after_connect=expect_after_connect)
diff --git a/tests/twisted/account-manager/enable-auto-connect.py b/tests/twisted/account-manager/enable-auto-connect.py
index 2cb91c31..d8ff3aee 100644
--- a/tests/twisted/account-manager/enable-auto-connect.py
+++ b/tests/twisted/account-manager/enable-auto-connect.py
@@ -28,7 +28,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "smcv@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -36,11 +36,11 @@ def test(q, bus, mc):
# Ensure that it's enabled but has offline RP
call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', ''))
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
q.expect('dbus-return', method='Set')
call_async(q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Testing automatic presence'))
q.expect('dbus-return', method='Set')
q.expect('dbus-signal', signal='AccountPropertyChanged',
diff --git a/tests/twisted/account-manager/enable.py b/tests/twisted/account-manager/enable.py
index 50e489d1..db659f3b 100644
--- a/tests/twisted/account-manager/enable.py
+++ b/tests/twisted/account-manager/enable.py
@@ -28,13 +28,13 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "smcv@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', ''))
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
q.expect('dbus-return', method='Set')
call_async(q, account_props, 'Set', cs.ACCOUNT, 'Enabled', False)
@@ -45,7 +45,7 @@ def test(q, bus, mc):
q.expect('dbus-return', method='Set')
call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy', 'Testing Enabled'))
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Testing Enabled'))
q.expect('dbus-return', method='Set')
# Go online by setting Enabled
diff --git a/tests/twisted/account-manager/hidden.py b/tests/twisted/account-manager/hidden.py
deleted file mode 100644
index 9e9351b0..00000000
--- a/tests/twisted/account-manager/hidden.py
+++ /dev/null
@@ -1,110 +0,0 @@
-# vim: set fileencoding=utf-8 : thanks python! you've been great
-# Copyright © 2010 Nokia Corporation
-# 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
-
-from mctest import (
- exec_test, create_fakecm_account, Account, AccountManager,
- tell_mc_to_die, resuscitate_mc,
- )
-from servicetest import (
- EventPattern, assertEquals, assertContains, assertDoesNotContain,
- call_async,
- )
-import constants as cs
-
-def test_unhidden_account(q, bus, mc):
- """
- Check that accounts don't default to being hidden, and don't show up in the
- lists of hidden accounts.
- """
- am = AccountManager(bus)
-
- params = { "account": "oh", "password": "hai" }
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
-
- assert not account.Properties.Get(cs.ACCOUNT_IFACE_HIDDEN, 'Hidden')
-
- am_hidden_props = am.Properties.GetAll(cs.AM_IFACE_HIDDEN)
- assertEquals([], am_hidden_props['ValidHiddenAccounts'])
- assertEquals([], am_hidden_props['InvalidHiddenAccounts'])
-
-def test_create_hidden_account(q, bus, mc):
- """
- Check that a newly-created hidden account does not show up on the main
- AccountManager interface, but does show up on AM.I.Hidden, has its
- Hidden property set to True, and can be removed.
- """
- am = AccountManager(bus)
-
- call_async(q, am.Properties, 'Get', cs.AM,
- 'SupportedAccountProperties')
- supported = q.expect('dbus-return', method='Get').value[0]
- assertContains(cs.ACCOUNT_IFACE_HIDDEN + '.Hidden', supported)
-
- # Make a new hidden account, and check that it really is hidden.
- params = { "account": "aperture@porti.co", "password": "tollgate" }
- properties = { cs.ACCOUNT_IFACE_HIDDEN + '.Hidden': True }
-
- q.forbid_events([
- EventPattern('dbus-signal', path=cs.AM_PATH,
- signal='AccountValidityChanged', interface=cs.AM),
- ])
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params, properties)
-
- valid_accounts = am.Properties.Get(cs.AM, 'ValidAccounts')
- assertDoesNotContain(account.object_path, valid_accounts)
-
- valid_hidden_accounts = am.Properties.Get(cs.AM_IFACE_HIDDEN,
- 'ValidHiddenAccounts')
- assertContains(account.object_path, valid_hidden_accounts)
-
- # Blow MC away, revive it, and check that the account is still hidden.
- tell_mc_to_die(q, bus)
- am, properties, interfaces = resuscitate_mc(q, bus, mc)
- account = Account(bus, account.object_path)
-
- assert account.Properties.Get(cs.ACCOUNT_IFACE_HIDDEN, 'Hidden')
-
- assertDoesNotContain(account.object_path, properties['ValidAccounts'])
-
- valid_hidden_accounts = am.Properties.Get(cs.AM_IFACE_HIDDEN,
- 'ValidHiddenAccounts')
- assertContains(account.object_path, valid_hidden_accounts)
-
- # Delete the account, and check that its removal is signalled only on
- # AM.I.Hidden, not on the main AM interface.
- q.forbid_events([
- EventPattern('dbus-signal', path=cs.AM_PATH,
- signal='AccountRemoved', interface=cs.AM,
- args=[account.object_path]),
- ])
-
- account.Remove()
- q.expect_many(
- EventPattern('dbus-signal', path=cs.AM_PATH,
- signal='HiddenAccountRemoved', interface=cs.AM_IFACE_HIDDEN),
- EventPattern('dbus-signal', path=account.object_path,
- signal='Removed', interface=cs.ACCOUNT),
- )
-
-def test(q, bus, mc):
- test_unhidden_account(q, bus, mc)
- test_create_hidden_account(q, bus, mc)
-
-if __name__ == '__main__':
- exec_test(test, {}, timeout=10)
diff --git a/tests/twisted/account-manager/irc.py b/tests/twisted/account-manager/irc.py
index 2b249f19..0d0de71f 100644
--- a/tests/twisted/account-manager/irc.py
+++ b/tests/twisted/account-manager/irc.py
@@ -32,7 +32,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "brucewayne",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -64,7 +64,7 @@ def test(q, bus, mc):
interface=cs.ACCOUNT,
predicate=lambda e:
e.args[0].get('CurrentPresence') ==
- (cs.PRESENCE_TYPE_UNSET, '', '')),
+ (cs.PRESENCE_UNSET, '', '')),
]
conn, get_aliases, set_aliases, _ = enable_fakecm_account(q, bus, mc,
diff --git a/tests/twisted/account-manager/make-valid.py b/tests/twisted/account-manager/make-valid.py
index 7c1df852..6e7ea34e 100644
--- a/tests/twisted/account-manager/make-valid.py
+++ b/tests/twisted/account-manager/make-valid.py
@@ -27,12 +27,10 @@ import dbus.service
from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
call_async, sync_dbus
-from mctest import exec_test, SimulatedConnection, create_fakecm_account, MC
+from mctest import (exec_test, SimulatedConnection, create_fakecm_account, MC,
+ SimulatedConnectionManager)
import constants as cs
-cm_name_ref = dbus.service.BusName(
- cs.tp_name_prefix + '.ConnectionManager.fakecm', bus=dbus.SessionBus())
-
account1_id = 'fakecm/fakeprotocol/jc_2edenton_40unatco_2eint'
account2_id = 'fakecm/fakeprotocol/jc_2edenton_40example_2ecom'
@@ -95,6 +93,7 @@ def preseed(q, bus, fake_accounts_service):
account_connections_file.close()
def test(q, bus, unused, **kwargs):
+ simulated_cm = SimulatedConnectionManager(q, bus)
# make sure RequestConnection doesn't get called yet
events = [EventPattern('dbus-method-call', method='RequestConnection')]
@@ -169,7 +168,7 @@ def test(q, bus, unused, **kwargs):
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True, interface=cs.CONN)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
set_presence, e = q.expect_many(
EventPattern('dbus-method-call', path=conn.object_path,
@@ -181,7 +180,7 @@ def test(q, bus, unused, **kwargs):
and e.args[0]['CurrentPresence'][2] != ''),
)
- assert e.args[0]['CurrentPresence'] == (cs.PRESENCE_TYPE_AVAILABLE,
+ assert e.args[0]['CurrentPresence'] == (cs.PRESENCE_AVAILABLE,
'available', 'My vision is augmented')
# Request an online presence on account 2, then make it valid
@@ -191,7 +190,7 @@ def test(q, bus, unused, **kwargs):
account_path = (cs.tp_path_prefix + '/Account/' + account2_id)
account = bus.get_object(cs.MC, account_path)
- requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY),
+ requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_BUSY),
'busy', 'Talking to Illuminati'))
account.Set(cs.ACCOUNT, 'RequestedPresence',
dbus.Struct(requested_presence, variant_level=1),
@@ -221,7 +220,7 @@ def test(q, bus, unused, **kwargs):
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True, interface=cs.CONN)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
set_presence = q.expect('dbus-method-call', path=conn.object_path,
interface=cs.CONN_IFACE_SIMPLE_PRESENCE, method='SetPresence',
@@ -232,7 +231,7 @@ def test(q, bus, unused, **kwargs):
predicate=lambda e: 'CurrentPresence' in e.args[0]
and e.args[0]['CurrentPresence'][1] == 'busy')
- assert e.args[0]['CurrentPresence'] == (cs.PRESENCE_TYPE_BUSY,
+ assert e.args[0]['CurrentPresence'] == (cs.PRESENCE_BUSY,
'busy', 'Talking to Illuminati')
if __name__ == '__main__':
diff --git a/tests/twisted/account-manager/nickname.py b/tests/twisted/account-manager/nickname.py
index b128942c..e10342d3 100644
--- a/tests/twisted/account-manager/nickname.py
+++ b/tests/twisted/account-manager/nickname.py
@@ -28,7 +28,7 @@ import constants as cs
def test(q, bus, mc, nickname):
params = dbus.Dictionary({"account": "wjt@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
diff --git a/tests/twisted/account-manager/param-types.py b/tests/twisted/account-manager/param-types.py
index 8dafd7f1..68eff808 100644
--- a/tests/twisted/account-manager/param-types.py
+++ b/tests/twisted/account-manager/param-types.py
@@ -22,13 +22,13 @@ import dbus.service
from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
call_async
-from mctest import exec_test, create_fakecm_account, get_account_manager
+from mctest import (exec_test, create_fakecm_account, get_account_manager,
+ SimulatedConnectionManager)
import constants as cs
def test(q, bus, mc):
- cm_name_ref = dbus.service.BusName(
- cs.tp_name_prefix + '.ConnectionManager.onewitheverything',
- bus=bus)
+ simulated_cm = SimulatedConnectionManager(q, bus,
+ cm_name='onewitheverything', protocol_names=['serializable'])
# Get the AccountManager interface
account_manager = get_account_manager(bus)
diff --git a/tests/twisted/account-manager/presence.py b/tests/twisted/account-manager/presence.py
index 5577f5a6..9f04f675 100755
--- a/tests/twisted/account-manager/presence.py
+++ b/tests/twisted/account-manager/presence.py
@@ -28,13 +28,13 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "jc.denton@example.com",
"password": "ionstorm"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
- presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Fighting conspiracies'), signature='uss')
def mk_offline(message=''):
- return dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline',
+ return dbus.Struct((dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline',
message), signature='uss')
offline = mk_offline()
@@ -78,10 +78,10 @@ def test(q, bus, mc):
requested_presence=presence,
expect_before_connect=[
EventPattern('dbus-method-call',
- interface=cs.CONN, method='GetInterfaces',
- args=[],
+ interface=cs.PROPERTIES_IFACE, method='Get',
+ args=[cs.CONN, 'Interfaces'],
handled=True,
- predicate=(lambda e: log.append('GetInterfaces') or True)),
+ predicate=(lambda e: log.append('Get(Interfaces)') or True)),
EventPattern('dbus-method-call',
interface=cs.PROPERTIES_IFACE, method='Get',
args=[cs.CONN_IFACE_SIMPLE_PRESENCE, 'Statuses'],
@@ -112,17 +112,17 @@ def test(q, bus, mc):
e.args[0].get('CurrentPresence') == presence),
])
- # The events before Connect must happen in this order. GetInterfaces() may
+ # The events before Connect must happen in this order. Get(Interfaces) may
# be called once or 2 times
if len(log) == 5:
- assert log == ['GetInterfaces', 'Get(Statuses)[1]', 'SetPresence[1]',
+ assert log == ['Get(Interfaces)', 'Get(Statuses)[1]', 'SetPresence[1]',
'Get(Statuses)[2]', 'SetPresence[2]'], log
else:
- assert log == ['GetInterfaces', 'GetInterfaces', 'Get(Statuses)[1]', 'SetPresence[1]',
+ assert log == ['Get(Interfaces)', 'Get(Interfaces)', 'Get(Statuses)[1]', 'SetPresence[1]',
'Get(Statuses)[2]', 'SetPresence[2]'], log
# Change requested presence after going online
- presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_AWAY), 'away',
+ presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_AWAY), 'away',
'In Hong Kong'), signature='uss')
call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'RequestedPresence',
presence)
@@ -151,7 +151,7 @@ def test(q, bus, mc):
predicate=lambda e: e.args[0].get('RequestedPresence') is not None)]
q.forbid_events(events)
- presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_AWAY), 'away',
+ presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_AWAY), 'away',
'In Hong Kong'), signature='uss')
call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'RequestedPresence',
presence)
diff --git a/tests/twisted/account-manager/reconnect.py b/tests/twisted/account-manager/reconnect.py
index 44af4100..39624a9c 100644
--- a/tests/twisted/account-manager/reconnect.py
+++ b/tests/twisted/account-manager/reconnect.py
@@ -27,13 +27,10 @@ from mctest import exec_test, SimulatedConnection, create_fakecm_account,\
import constants as cs
def test(q, bus, mc):
- cm_name_ref = dbus.service.BusName(
- tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
-
# Create an account
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
# Events that indicate that Reconnect might have done something
looks_like_reconnection = [
@@ -51,7 +48,7 @@ def test(q, bus, mc):
dbus_interface=cs.PROPERTIES_IFACE)
q.expect('dbus-return', method='Set')
- requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_AVAILABLE),
+ requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_AVAILABLE),
dbus.String(u'available'), dbus.String(u'')))
call_async(q, account, 'Set', cs.ACCOUNT,
'RequestedPresence', requested_presence,
@@ -65,7 +62,7 @@ def test(q, bus, mc):
# While we want to be offline but the account is enabled, Reconnect is
# still a no-op.
- requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE),
+ requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_OFFLINE),
dbus.String(u'offline'), dbus.String(u'')))
call_async(q, account, 'Set', cs.ACCOUNT,
'RequestedPresence', requested_presence,
@@ -98,7 +95,7 @@ def test(q, bus, mc):
q.unforbid_events(looks_like_reconnection)
- requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_AVAILABLE),
+ requested_presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_AVAILABLE),
dbus.String(u'brb'), dbus.String(u'Be back soon!')))
account.Set(cs.ACCOUNT,
'RequestedPresence', requested_presence,
@@ -125,13 +122,13 @@ def test(q, bus, mc):
path=conn.object_path, handled=True),
)
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# Assert that the NormalizedName is harvested from the Connection at some
# point
@@ -180,10 +177,10 @@ def test(q, bus, mc):
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# Put the account offline
- requested_presence = (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', '')
+ requested_presence = (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', '')
account.Set(cs.ACCOUNT,
'RequestedPresence', requested_presence,
dbus_interface=cs.PROPERTIES_IFACE)
diff --git a/tests/twisted/account-manager/recover-from-disconnect.py b/tests/twisted/account-manager/recover-from-disconnect.py
index 5cfe8686..932b4700 100644
--- a/tests/twisted/account-manager/recover-from-disconnect.py
+++ b/tests/twisted/account-manager/recover-from-disconnect.py
@@ -29,7 +29,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy",
"register": True}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', False)
q.expect('dbus-return', method='Set')
@@ -38,7 +38,7 @@ def test(q, bus, mc):
call_async(q, account.Properties, 'Set', cs.ACCOUNT, 'Enabled', True)
# Set online presence
- presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Fixing MC bugs'), signature='uss')
call_async(q, account.Properties, 'Set', cs.ACCOUNT,
'RequestedPresence', presence)
@@ -55,13 +55,13 @@ def test(q, bus, mc):
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
q.expect('dbus-method-call',
interface=cs.CONN_IFACE_SIMPLE_PRESENCE,
@@ -73,7 +73,7 @@ def test(q, bus, mc):
conn.ConnectionError('com.example.My.Network.Is.Full.Of.Eels',
{'eels': 23, 'capacity': 23, 'debug-message': 'Too many eels'})
conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
- cs.CONN_STATUS_REASON_NETWORK_ERROR)
+ cs.CSR_NETWORK_ERROR)
# MC reconnects. This time, we expect it to have deleted the 'register'
# parameter.
@@ -106,7 +106,7 @@ def test(q, bus, mc):
disconnected.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_DISCONNECTED,
disconnected.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_NETWORK_ERROR,
+ assertEquals(cs.CSR_NETWORK_ERROR,
disconnected.args[0].get('ConnectionStatusReason'))
assertEquals('/', connecting.args[0].get('Connection'))
@@ -117,7 +117,7 @@ def test(q, bus, mc):
connecting.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_CONNECTING,
connecting.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_REQUESTED,
+ assertEquals(cs.CSR_REQUESTED,
connecting.args[0].get('ConnectionStatusReason'))
# The object path needs to be different from the first simulated
@@ -130,8 +130,8 @@ def test(q, bus, mc):
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
connecting, _ = q.expect_many(
EventPattern('dbus-signal', signal='AccountPropertyChanged',
predicate=(lambda e:
@@ -150,7 +150,7 @@ def test(q, bus, mc):
connecting.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_CONNECTING,
connecting.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_REQUESTED,
+ assertEquals(cs.CSR_REQUESTED,
connecting.args[0].get('ConnectionStatusReason'))
assertEquals('com.example.My.Network.Is.Full.Of.Eels',
@@ -160,7 +160,7 @@ def test(q, bus, mc):
account.Properties.Get(cs.ACCOUNT, 'ConnectionErrorDetails'))
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
connected, _ = q.expect_many(
EventPattern('dbus-signal', signal='AccountPropertyChanged',
@@ -180,7 +180,7 @@ def test(q, bus, mc):
assertEquals({}, connected.args[0].get('ConnectionErrorDetails'))
assertEquals(cs.CONN_STATUS_CONNECTED,
connected.args[0].get('ConnectionStatus'))
- assertEquals(cs.CONN_STATUS_REASON_REQUESTED,
+ assertEquals(cs.CSR_REQUESTED,
connected.args[0].get('ConnectionStatusReason'))
assertEquals('', account.Properties.Get(cs.ACCOUNT, 'ConnectionError'))
diff --git a/tests/twisted/account-manager/req-conn-fails.py b/tests/twisted/account-manager/req-conn-fails.py
index bc3f01a2..b9f05cba 100644
--- a/tests/twisted/account-manager/req-conn-fails.py
+++ b/tests/twisted/account-manager/req-conn-fails.py
@@ -31,13 +31,13 @@ def test(q, bus, mc):
{"account": "someguy@example.com",
"password": "secrecy",
}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account.Properties.Set(cs.ACCOUNT, 'Enabled', True)
# Set online presence
presence = dbus.Struct(
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy', 'Fixing MC bugs'),
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy', 'Fixing MC bugs'),
signature='uss')
account.Properties.Set(cs.ACCOUNT, 'RequestedPresence', presence)
@@ -56,7 +56,7 @@ def test(q, bus, mc):
changed, = e.args
assertEquals('/', changed['Connection'])
assertEquals(cs.CONN_STATUS_DISCONNECTED, changed['ConnectionStatus'])
- assertEquals(cs.CONN_STATUS_REASON_NONE, changed['ConnectionStatusReason'])
+ assertEquals(cs.CSR_NONE_SPECIFIED, changed['ConnectionStatusReason'])
assertEquals(cs.NOT_IMPLEMENTED, changed['ConnectionError'])
if __name__ == '__main__':
diff --git a/tests/twisted/account-manager/request-online.py b/tests/twisted/account-manager/request-online.py
index 3d8a6016..18186843 100644
--- a/tests/twisted/account-manager/request-online.py
+++ b/tests/twisted/account-manager/request-online.py
@@ -30,9 +30,6 @@ from mctest import (
import constants as cs
def test(q, bus, mc):
- cm_name_ref = dbus.service.BusName(
- tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
-
http_fixed_properties = dbus.Dictionary({
cs.CHANNEL + '.TargetHandleType': 1L,
cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAM_TUBE,
@@ -50,7 +47,7 @@ def test(q, bus, mc):
# Create an account
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
# The account is initially valid but disabled, and hence offline
props = account.GetAll(cs.ACCOUNT, dbus_interface=cs.PROPERTIES_IFACE)
@@ -59,7 +56,7 @@ def test(q, bus, mc):
# The spec says it should be (Offline, "", "") but I don't think the
# strings really matter. If anything, the second one should start out at
# "offline".
- assertEquals(cs.PRESENCE_TYPE_OFFLINE, props['CurrentPresence'][0])
+ assertEquals(cs.PRESENCE_OFFLINE, props['CurrentPresence'][0])
# Enable the account
account.Set(cs.ACCOUNT, 'Enabled', True,
@@ -73,7 +70,7 @@ def test(q, bus, mc):
assert props['Enabled']
assert props['Valid']
# Ditto above re. string fields.
- assertEquals(cs.PRESENCE_TYPE_OFFLINE, props['CurrentPresence'][0])
+ assertEquals(cs.PRESENCE_OFFLINE, props['CurrentPresence'][0])
# Go online
requested_presence = dbus.Struct((dbus.UInt32(2L), dbus.String(u'brb'),
@@ -102,13 +99,14 @@ def test(q, bus, mc):
args=[cs.CONN_IFACE_REQUESTS],
path=conn.object_path, handled=True),
)
- # MC calls GetStatus (maybe) and then Connect
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# Assert that the NormalizedName is harvested from the Connection at some
# point
@@ -129,7 +127,7 @@ def test(q, bus, mc):
# Since this Connection doesn't support SimplePresence, but it's online,
# the spec says that CurrentPresence should be Unset.
- assertEquals((cs.PRESENCE_TYPE_UNSET, "", ""),
+ assertEquals((cs.PRESENCE_UNSET, "", ""),
properties.get('CurrentPresence'))
new_channel = http_fixed_properties
@@ -146,7 +144,7 @@ def test(q, bus, mc):
q.dbus_return(e.message, signature='')
# Put the account offline
- requested_presence = (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', '')
+ requested_presence = (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', '')
account.Set(cs.ACCOUNT,
'RequestedPresence', requested_presence,
dbus_interface=cs.PROPERTIES_IFACE)
diff --git a/tests/twisted/account-manager/restricted-storage.py b/tests/twisted/account-manager/restricted-storage.py
new file mode 100644
index 00000000..6724863b
--- /dev/null
+++ b/tests/twisted/account-manager/restricted-storage.py
@@ -0,0 +1,185 @@
+# Copyright (C) 2009 Nokia Corporation
+# Copyright (C) 2009-2012 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
+
+import dbus
+import dbus.service
+
+from servicetest import EventPattern, call_async, assertEquals
+from mctest import (exec_test, SimulatedConnection,
+ SimulatedConnectionManager, Account)
+import constants as cs
+
+def test(q, bus, mc, fake_accounts_service=None, **kwargs):
+ simulated_cm = SimulatedConnectionManager(q, bus)
+
+ for enabled in (True, False):
+ for online in (True, False):
+ account_tail = ('fakecm/fakeprotocol/ezio_2efirenze_40fic'
+ + (enabled and '_enabled' or '_disabled')
+ + (online and '_online' or '_offline'))
+ account_path = cs.ACCOUNT_PATH_PREFIX + account_tail
+
+ try_to_connect = [
+ EventPattern('dbus-method-call', method='RequestConnection',
+ destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
+ path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
+ interface=cs.tp_name_prefix + '.ConnectionManager',
+ predicate=lambda e:
+ e.args[1]['account'] == account_tail,
+ handled=False)
+ ]
+
+ if enabled and online:
+ also_expected = try_to_connect[:]
+ else:
+ also_expected = []
+ q.forbid_events(try_to_connect)
+
+ args = (
+ {
+ 'Enabled': enabled,
+ 'ConnectAutomatically': online,
+ 'manager': 'fakecm',
+ 'protocol': 'fakeprotocol',
+ 'AutomaticPresence':
+ dbus.Struct((dbus.UInt32(cs.PRESENCE_HIDDEN),
+ 'hidden', 'press X to blend'),
+ signature='uss'),
+ },
+ {
+ 'Enabled': 0,
+ 'ConnectAutomatically': 0,
+ 'manager': 0,
+ 'protocol': 0,
+ 'AutomaticPresence': 0,
+ },
+ {
+ 'account': account_tail,
+ 'password': 'nothing is true'
+ },
+ {}, # untyped parameters
+ {
+ 'account': 0,
+ 'password': cs.PARAM_SECRET
+ },
+ cs.StorageRestrictionFlags.CANNOT_SET_PRESENCE |
+ cs.StorageRestrictionFlags.CANNOT_SET_ENABLED,
+ )
+
+ fake_accounts_service.create_account(account_tail, *args)
+
+ events = q.expect_many(
+ EventPattern('dbus-signal',
+ path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
+ signal='AccountCreated',
+ args=[account_tail] + list(args)),
+ EventPattern('dbus-signal',
+ path=cs.AM_PATH,
+ signal='AccountValidityChanged',
+ args=[account_path, True]),
+ *also_expected)
+ account = Account(bus, account_path)
+
+ if enabled and online:
+ conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol',
+ account_tail.replace('/', '_'), 'ezio',
+ has_presence=True)
+ q.dbus_return(events[-1].message, conn.bus_name,
+ conn.object_path, signature='so')
+ q.expect('dbus-method-call', method='SetPresence',
+ # the fake CM doesn't support 'hidden' by default
+ args=['busy', 'press X to blend'])
+
+ requested_presence = (dbus.UInt32(cs.PRESENCE_HIDDEN), 'hidden',
+ 'press X to blend')
+ else:
+ requested_presence = (dbus.UInt32(cs.PRESENCE_OFFLINE),
+ 'offline', '')
+
+ call_async(q, account.Properties, 'Get', cs.ACCOUNT,
+ 'RequestedPresence')
+ q.expect('dbus-return', method='Get', value=(requested_presence,))
+
+ # changes that are not really changes are fine
+ call_async(q, account.Properties, 'Set', cs.ACCOUNT,
+ 'Enabled', enabled)
+ q.expect('dbus-return', method='Set')
+ call_async(q, account.Properties, 'Set', cs.ACCOUNT,
+ 'ConnectAutomatically', online)
+ q.expect('dbus-return', method='Set')
+
+ # changes that actually change the restrictive properties
+ # are not allowed
+ call_async(q, account.Properties, 'Set', cs.ACCOUNT,
+ 'RequestedPresence',
+ ((dbus.UInt32(cs.PRESENCE_AVAILABLE), 'available',
+ 'highly conspicuous')))
+ q.expect('dbus-error', method='Set')
+ call_async(q, account.Properties, 'Set', cs.ACCOUNT,
+ 'AutomaticPresence',
+ ((dbus.UInt32(cs.PRESENCE_AVAILABLE), 'available',
+ 'highly conspicuous')))
+ q.expect('dbus-error', method='Set')
+ call_async(q, account.Properties, 'Set', cs.ACCOUNT,
+ 'Enabled', not enabled)
+ q.expect('dbus-error', method='Set')
+ call_async(q, account.Properties, 'Set', cs.ACCOUNT,
+ 'ConnectAutomatically', not online)
+ q.expect('dbus-error', method='Set')
+
+ call_async(q, account, 'Remove')
+ q.expect('dbus-error', method='Remove')
+
+ # ... but the backend can still change them
+ if enabled and online:
+ q.forbid_events(try_to_connect)
+ fake_accounts_service.update_attributes(account_tail,
+ {
+ 'Enabled': False,
+ 'ConnectAutomatically': False,
+ })
+ q.expect('dbus-method-call', method='Disconnect')
+ q.unforbid_events(try_to_connect)
+ else:
+ q.unforbid_events(try_to_connect)
+ fake_accounts_service.update_attributes(account_tail,
+ {
+ 'Enabled': True,
+ 'ConnectAutomatically': True,
+ })
+
+ events = q.expect_many(*try_to_connect)
+ conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol',
+ account_tail.replace('/', '_'), 'ezio',
+ has_presence=True)
+ q.dbus_return(events[-1].message, conn.bus_name,
+ conn.object_path, signature='so')
+
+ # we are connected: deleting the account should
+ # disconnect us
+ fake_accounts_service.delete_account(account_tail)
+ q.expect_many(
+ EventPattern('dbus-signal', signal='AccountRemoved',
+ args=[account_path]),
+ EventPattern('dbus-signal', signal='Removed',
+ path=account_path),
+ EventPattern('dbus-method-call', method='Disconnect'),
+ )
+
+if __name__ == '__main__':
+ exec_test(test, {}, pass_kwargs=True)
diff --git a/tests/twisted/account-manager/server-drops-us.py b/tests/twisted/account-manager/server-drops-us.py
index b4db423f..9a9d6ca7 100644
--- a/tests/twisted/account-manager/server-drops-us.py
+++ b/tests/twisted/account-manager/server-drops-us.py
@@ -30,11 +30,8 @@ params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
def test(q, bus, mc):
- cm_name_ref = dbus.service.BusName(
- tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
-
# Create an account
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -48,7 +45,7 @@ def test(q, bus, mc):
dbus_interface=cs.PROPERTIES_IFACE)
# Set online presence
- presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Fixing MC bugs'), signature='uss')
call_async(q, account, 'Set', cs.ACCOUNT,
'RequestedPresence', presence,
@@ -66,13 +63,13 @@ def test(q, bus, mc):
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
conn = drop_and_expect_reconnect(q, bus, conn)
conn = drop_and_expect_reconnect(q, bus, conn)
@@ -83,7 +80,7 @@ def test(q, bus, mc):
# Connection falls over for a miscellaneous reason
conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
- cs.CONN_STATUS_REASON_NETWORK_ERROR)
+ cs.CSR_NETWORK_ERROR)
# Right, that's it, I'm giving up...
# This test can be considered to have succeeded if we don't
@@ -98,7 +95,7 @@ def test(q, bus, mc):
def drop_and_expect_reconnect(q, bus, conn):
# Connection falls over for a miscellaneous reason
conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
- cs.CONN_STATUS_REASON_NETWORK_ERROR)
+ cs.CSR_NETWORK_ERROR)
# MC reconnects
@@ -114,13 +111,13 @@ def drop_and_expect_reconnect(q, bus, conn):
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
return conn
diff --git a/tests/twisted/account-manager/service.py b/tests/twisted/account-manager/service.py
index f7df9903..7bed951a 100644
--- a/tests/twisted/account-manager/service.py
+++ b/tests/twisted/account-manager/service.py
@@ -27,7 +27,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "wjt@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
srv_name = 'fu-bar-42'
account_iface = dbus.Interface(account, cs.ACCOUNT)
diff --git a/tests/twisted/account-manager/update-parameters.py b/tests/twisted/account-manager/update-parameters.py
index a7ec6a0a..a030a01f 100644
--- a/tests/twisted/account-manager/update-parameters.py
+++ b/tests/twisted/account-manager/update-parameters.py
@@ -30,16 +30,13 @@ from mctest import exec_test, SimulatedConnection, create_fakecm_account,\
import constants as cs
def test(q, bus, mc, **kwargs):
- cm_name_ref = dbus.service.BusName(
- tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
-
# Create an account
params = dbus.Dictionary(
{"account": "someguy@example.com",
"password": "secrecy",
"nickname": "albinoblacksheep",
}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
# Enable the account
account.Set(cs.ACCOUNT, 'Enabled', True,
@@ -77,13 +74,13 @@ def test(q, bus, mc, **kwargs):
path=conn.object_path, handled=True),
)
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# Assert that the NormalizedName is harvested from the Connection at some
# point
@@ -255,13 +252,11 @@ def test(q, bus, mc, **kwargs):
assertEquals(r'\\',
kwargs['fake_accounts_service'].accounts
[account.object_path[len(cs.ACCOUNT_PATH_PREFIX):]]
- [2] # parameters of known type
- ['account'])
+ .params['account'])
assertEquals(None,
kwargs['fake_accounts_service'].accounts
[account.object_path[len(cs.ACCOUNT_PATH_PREFIX):]]
- [3] # parameters of unknown type
- .get('account', None))
+ .untyped_params.get('account', None))
if __name__ == '__main__':
exec_test(test, {}, pass_kwargs=True)
diff --git a/tests/twisted/account-requests/cancel.py b/tests/twisted/account-requests/cancel.py
index f236e5b8..9effcbec 100644
--- a/tests/twisted/account-requests/cancel.py
+++ b/tests/twisted/account-requests/cancel.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/account-requests/create-text.py b/tests/twisted/account-requests/create-text.py
index e71aca9d..c6d5922e 100644
--- a/tests/twisted/account-requests/create-text.py
+++ b/tests/twisted/account-requests/create-text.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/account-requests/delete-account-during-request.py b/tests/twisted/account-requests/delete-account-during-request.py
index 348c45a7..0b448eb8 100644
--- a/tests/twisted/account-requests/delete-account-during-request.py
+++ b/tests/twisted/account-requests/delete-account-during-request.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/account-storage/5-12.py b/tests/twisted/account-storage/5-12.py
new file mode 100644
index 00000000..9075d767
--- /dev/null
+++ b/tests/twisted/account-storage/5-12.py
@@ -0,0 +1,29 @@
+# Test for a former default account storage backend:
+# ~/.mission-control/accounts.cfg, as used in MC 5.0 to 5.13.1
+#
+# Copyright (C) 2009-2010 Nokia Corporation
+# Copyright (C) 2009-2014 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
+
+from storage_helper import test_keyfile
+from mctest import exec_test
+
+def test_5_12(q, bus, mc):
+ test_keyfile(q, bus, mc, '5.12')
+
+if __name__ == '__main__':
+ exec_test(test_5_12, {}, preload_mc=False, use_fake_accounts_service=False)
diff --git a/tests/twisted/account-storage/5-14.py b/tests/twisted/account-storage/5-14.py
new file mode 100644
index 00000000..42deb3ec
--- /dev/null
+++ b/tests/twisted/account-storage/5-14.py
@@ -0,0 +1,29 @@
+# Test for a former default account storage backend:
+# XDG_DATA_HOME/telepathy/mission-control/accounts.cfg, as used in MC 5.14
+#
+# Copyright (C) 2009-2010 Nokia Corporation
+# Copyright (C) 2009-2014 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
+
+from storage_helper import test_keyfile
+from mctest import exec_test
+
+def test_5_14(q, bus, mc):
+ test_keyfile(q, bus, mc, '5.14')
+
+if __name__ == '__main__':
+ exec_test(test_5_14, {}, preload_mc=False, use_fake_accounts_service=False)
diff --git a/tests/twisted/account-storage/create-new.py b/tests/twisted/account-storage/create-new.py
new file mode 100644
index 00000000..f77624a9
--- /dev/null
+++ b/tests/twisted/account-storage/create-new.py
@@ -0,0 +1,136 @@
+# Test for "stringified GVariant per account" storage backend introduced in
+# Mission Control 5.16, when creating a new account stored in this default
+# backend
+#
+# Copyright (C) 2009-2010 Nokia Corporation
+# Copyright (C) 2009-2014 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
+
+import time
+import os
+import os.path
+import signal
+
+import dbus
+import dbus.service
+
+from servicetest import (
+ EventPattern, assertEquals,
+ )
+from mctest import (
+ exec_test, create_fakecm_account, connect_to_mc,
+ )
+from storage_helper import (account_store)
+import constants as cs
+
+def test(q, bus, mc):
+ ctl_dir = os.environ['MC_ACCOUNT_DIR']
+ old_key_file_name = os.path.join(ctl_dir, 'accounts.cfg')
+ newer_key_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control', 'accounts.cfg')
+ new_variant_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert_40example_2ecom0.account')
+
+ account_manager, properties, interfaces = connect_to_mc(q, bus, mc)
+
+ assert properties.get('ValidAccounts') == [], \
+ properties.get('ValidAccounts')
+ assert properties.get('InvalidAccounts') == [], \
+ properties.get('InvalidAccounts')
+
+ params = dbus.Dictionary({"account": "dontdivert@example.com",
+ "password": "secrecy",
+ "snakes": dbus.UInt32(23)}, signature='sv')
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
+
+ account_path = account.__dbus_object_path__
+
+ # Check the account is correctly created
+ properties = account_manager.GetAll(cs.AM,
+ dbus_interface=cs.PROPERTIES_IFACE)
+ assert properties is not None
+ assert properties.get('ValidAccounts') == [account_path], properties
+ account_path = properties['ValidAccounts'][0]
+ assert isinstance(account_path, dbus.ObjectPath), repr(account_path)
+ assert properties.get('InvalidAccounts') == [], properties
+
+ account_iface = dbus.Interface(account, cs.ACCOUNT)
+ account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
+
+ # Alter some miscellaneous r/w properties
+
+ account_props.Set(cs.ACCOUNT, 'DisplayName', 'Work account')
+ account_props.Set(cs.ACCOUNT, 'Icon', 'im-jabber')
+ account_props.Set(cs.ACCOUNT, 'Nickname', 'Joe Bloggs')
+ account_props.Set(cs.ACCOUNT, 'ConnectAutomatically', True)
+ account_props.Set(cs.ACCOUNT, 'AutomaticPresence',
+ (dbus.UInt32(cs.PRESENCE_EXTENDED_AWAY), 'xa',
+ 'never online'))
+
+ # .. let's check the keyfile
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(new_variant_file_name)
+ assert 'Joe Bloggs' in open(new_variant_file_name).read()
+ assertEquals("'fakecm'", account_store('get', 'variant-file', 'manager'))
+ assertEquals("'fakeprotocol'", account_store('get', 'variant-file',
+ 'protocol'))
+ assertEquals("'Work account'", account_store('get', 'variant-file',
+ 'DisplayName'))
+ assertEquals("'im-jabber'", account_store('get', 'variant-file',
+ 'Icon'))
+ assertEquals("'Joe Bloggs'", account_store('get', 'variant-file',
+ 'Nickname'))
+ assertEquals('true', account_store('get', 'variant-file',
+ 'ConnectAutomatically'))
+ assertEquals("(uint32 4, 'xa', 'never online')",
+ account_store('get', 'variant-file', 'AutomaticPresence'))
+ assertEquals("'dontdivert@example.com'",
+ account_store('get', 'variant-file', 'param-account'))
+ assertEquals("uint32 23",
+ account_store('get', 'variant-file', 'param-snakes'))
+ assertEquals("'secrecy'",
+ account_store('get', 'variant-file', 'param-password'))
+
+ assertEquals({'password': 'secrecy', 'account': 'dontdivert@example.com',
+ 'snakes': 23}, account.Properties.Get(cs.ACCOUNT, 'Parameters'))
+
+ # Delete the account
+ assert account_iface.Remove() is None
+ account_event, account_manager_event = q.expect_many(
+ EventPattern('dbus-signal',
+ path=account_path,
+ signal='Removed',
+ interface=cs.ACCOUNT,
+ args=[]
+ ),
+ EventPattern('dbus-signal',
+ path=cs.AM_PATH,
+ signal='AccountRemoved',
+ interface=cs.AM,
+ args=[account_path]
+ ),
+ )
+
+ # Check the account is correctly deleted
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert not os.path.exists(new_variant_file_name)
+
+if __name__ == '__main__':
+ exec_test(test, {}, timeout=10, use_fake_accounts_service=False)
diff --git a/tests/twisted/account-storage/default-keyring-storage.py b/tests/twisted/account-storage/default-keyring-storage.py
deleted file mode 100644
index 2d3b2fcf..00000000
--- a/tests/twisted/account-storage/default-keyring-storage.py
+++ /dev/null
@@ -1,230 +0,0 @@
-# Test for default account storage backend.
-#
-# Copyright (C) 2009-2010 Nokia Corporation
-# Copyright (C) 2009-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
-
-import time
-import os
-import os.path
-import signal
-
-import dbus
-import dbus.service
-
-from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
- call_async, assertEquals
-from mctest import (
- exec_test, create_fakecm_account, get_fakecm_account, connect_to_mc,
- keyfile_read, tell_mc_to_die, resuscitate_mc
- )
-import constants as cs
-
-# This doesn't escape its parameters before passing them to the shell,
-# so be careful.
-def account_store(op, backend, key=None, value=None,
- account='fakecm/fakeprotocol/dontdivert_40example_2ecom0'):
- cmd = [ '../account-store', op, backend, account ]
- if key:
- cmd.append(key)
- if value:
- cmd.append(value)
-
- lines = os.popen(' '.join(cmd)).read()
- ret = []
- for line in lines.split('\n'):
- if line.startswith('** '):
- continue
-
- if line:
- ret.append(line)
-
- if len(ret) > 0:
- return ret[0]
- else:
- return None
-
-def test(q, bus, mc):
- ctl_dir = os.environ['MC_ACCOUNT_DIR']
- old_key_file_name = os.path.join(ctl_dir, 'accounts.cfg')
- new_key_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
- 'telepathy', 'mission-control', 'accounts.cfg')
- group = 'fakecm/fakeprotocol/dontdivert_40example_2ecom0'
-
- account_manager, properties, interfaces = connect_to_mc(q, bus, mc)
-
- assert properties.get('ValidAccounts') == [], \
- properties.get('ValidAccounts')
- assert properties.get('InvalidAccounts') == [], \
- properties.get('InvalidAccounts')
-
- params = dbus.Dictionary({"account": "dontdivert@example.com",
- "password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
-
- account_path = account.__dbus_object_path__
-
- # Check the account is correctly created
- properties = account_manager.GetAll(cs.AM,
- dbus_interface=cs.PROPERTIES_IFACE)
- assert properties is not None
- assert properties.get('ValidAccounts') == [account_path], properties
- account_path = properties['ValidAccounts'][0]
- assert isinstance(account_path, dbus.ObjectPath), repr(account_path)
- assert properties.get('InvalidAccounts') == [], properties
-
- account_iface = dbus.Interface(account, cs.ACCOUNT)
- account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
-
- # Alter some miscellaneous r/w properties
-
- account_props.Set(cs.ACCOUNT, 'DisplayName', 'Work account')
- account_props.Set(cs.ACCOUNT, 'Icon', 'im-jabber')
- account_props.Set(cs.ACCOUNT, 'Nickname', 'Joe Bloggs')
-
- tell_mc_to_die(q, bus)
-
- # .. let's check the keyfile
- assert not os.path.exists(old_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert group in kf, kf
- assert kf[group]['manager'] == 'fakecm'
- assert kf[group]['protocol'] == 'fakeprotocol'
- assert kf[group]['param-account'] == params['account'], kf
- assert kf[group]['DisplayName'] == 'Work account', kf
- assert kf[group]['Icon'] == 'im-jabber', kf
- assert kf[group]['Nickname'] == 'Joe Bloggs', kf
-
- # This works wherever the password is stored
- pwd = account_store('get', 'default', 'param-password')
- assert pwd == params['password'], pwd
-
- # We no longer use gnome-keyring, so the password is stored as clear-text.
- assert kf[group]['param-password'] == params['password'], kf
-
- # Reactivate MC
- account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
- account = get_fakecm_account(bus, mc, account_path)
- account_iface = dbus.Interface(account, cs.ACCOUNT)
-
- # Delete the account
- assert account_iface.Remove() is None
- account_event, account_manager_event = q.expect_many(
- EventPattern('dbus-signal',
- path=account_path,
- signal='Removed',
- interface=cs.ACCOUNT,
- args=[]
- ),
- EventPattern('dbus-signal',
- path=cs.AM_PATH,
- signal='AccountRemoved',
- interface=cs.AM,
- args=[account_path]
- ),
- )
-
- # Check the account is correctly deleted
- assert not os.path.exists(old_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert group not in kf, kf
-
- # Tell MC to die, again
- tell_mc_to_die(q, bus)
-
- low_prio_key_file_name = os.path.join(
- os.environ['XDG_DATA_DIRS'].split(':')[0],
- 'telepathy', 'mission-control', 'accounts.cfg')
- os.makedirs(os.path.dirname(low_prio_key_file_name), 0700)
-
- # This is deliberately a lower-priority location
- os.remove(new_key_file_name)
- open(low_prio_key_file_name, 'w').write(
-r"""# Telepathy accounts
-[%s]
-manager=fakecm
-protocol=fakeprotocol
-param-account=dontdivert@example.com
-param-password=password_in_keyfile
-DisplayName=New and improved account
-AutomaticPresence=2;available;;
-""" % group)
-
- account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
- account = get_fakecm_account(bus, mc, account_path)
- account_iface = dbus.Interface(account, cs.ACCOUNT)
-
- # Files in lower-priority XDG locations aren't copied until something
- # actually changes, and they aren't deleted.
- assert not os.path.exists(new_key_file_name)
- assert os.path.exists(low_prio_key_file_name)
-
- # Delete the password (only), like Empathy 3.0-3.4 do when migrating
- account_iface.UpdateParameters({}, ['password'])
- q.expect('dbus-signal',
- path=account_path,
- signal='AccountPropertyChanged',
- interface=cs.ACCOUNT,
- predicate=(lambda e:
- 'Parameters' in e.args[0]),
- )
-
- # Tell MC to die yet again
- tell_mc_to_die(q, bus)
-
- # Check the account has copied (not moved! XDG_DATA_DIRS are,
- # conceptually, read-only) from the old to the new name
- assert not os.path.exists(old_key_file_name)
- assert os.path.exists(low_prio_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert 'param-password' not in kf[group]
- pwd = account_store('get', 'default', 'param-password')
- assertEquals(None, pwd)
-
- # Write out an account configuration in the old keyfile, to test
- # migration
- os.remove(new_key_file_name)
- os.remove(low_prio_key_file_name)
- open(old_key_file_name, 'w').write(
-r"""# Telepathy accounts
-[%s]
-manager=fakecm
-protocol=fakeprotocol
-param-account=dontdivert@example.com
-DisplayName=Ye olde account
-AutomaticPresence=2;available;;
-""" % group)
-
- account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
- account = get_fakecm_account(bus, mc, account_path)
- account_iface = dbus.Interface(account, cs.ACCOUNT)
-
- # This time it *does* get moved (really copied+deleted) automatically
- # during MC startup
- assert not os.path.exists(old_key_file_name)
- assert not os.path.exists(low_prio_key_file_name)
- kf = keyfile_read(new_key_file_name)
- assert 'param-password' not in kf[group]
- assertEquals('Ye olde account', kf[group]['DisplayName'])
-
-if __name__ == '__main__':
- ctl_dir = os.environ['MC_ACCOUNT_DIR']
- try:
- os.mkdir(ctl_dir, 0700)
- except OSError:
- pass
- exec_test(test, {}, timeout=10, use_fake_accounts_service=False)
diff --git a/tests/twisted/account-storage/diverted-storage.py b/tests/twisted/account-storage/diverted-storage.py
index 8692b09b..7aa011e8 100644
--- a/tests/twisted/account-storage/diverted-storage.py
+++ b/tests/twisted/account-storage/diverted-storage.py
@@ -53,7 +53,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_path = account.__dbus_object_path__
@@ -88,10 +88,6 @@ def test(q, bus, mc):
assert kf[group]['Icon'] == 'im-jabber', kf
assert kf[group]['Nickname'] == 'Joe Bloggs', kf
- # default keyfile should be empty
- ekf = keyfile_read(empty_key_file_name)
- assert ekf == { None: {} }, ekf
-
# Reactivate MC
account_manager, properties, interfaces = resuscitate_mc(q, bus, mc)
account = get_fakecm_account(bus, mc, account_path)
diff --git a/tests/twisted/account-storage/libaccounts-sso-storage.py b/tests/twisted/account-storage/libaccounts-sso-storage.py
deleted file mode 100644
index a2e7b512..00000000
--- a/tests/twisted/account-storage/libaccounts-sso-storage.py
+++ /dev/null
@@ -1,89 +0,0 @@
-# Copyright (C) 2009-2010 Nokia Corporation
-# Copyright (C) 2009-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
-
-raise AssertionError('Disabled for 5.6 branch')
-
-import time
-import os
-import os.path
-import signal
-import sys
-
-import dbus
-import dbus.service
-
-from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
- call_async
-from mctest import exec_test, create_fakecm_account, get_account_manager, \
- get_fakecm_account
-import constants as cs
-
-if ('ACCOUNTS' not in os.environ or not os.environ['ACCOUNTS']):
- print "Not testing accounts-sso storage"
- sys.exit(0)
-
-def account_store(op, backend, key=None, value=None):
- cmd = [ '../account-store', op, backend,
- 'colltest42@googlemail.com' ]
- if key:
- cmd.append(key)
- if value:
- cmd.append(value)
-
- lines = os.popen(' '.join(cmd)).read()
- ret = []
- for line in lines.split('\n'):
- if line.startswith('** '):
- continue
-
- if line:
- ret.append(line)
-
- if len(ret) > 0:
- return ret[0]
- else:
- return None
-
-def prepare_accounts_db(ctl_dir):
- os.system('cp %s/../tools/example-accounts.db %s/accounts.db' % (ctl_dir, ctl_dir))
- os.system('cp %s/../tools/accounts-sso-example.service %s/google-talk.service' % (ctl_dir, ctl_dir))
-
-def test(q, bus, mc):
- account_manager, properties, interfaces = connect_to_mc(q, bus, mc)
-
- va = properties.get('ValidAccounts')
- assert va == [], va
-
- ia = properties.get('InvalidAccounts')
- assert len(ia) == 1
-
- account_path = ia[0]
- print repr(account_path)
-
- account = get_fakecm_account(bus, mc, account_path)
- account_iface = dbus.Interface(account, cs.ACCOUNT)
- account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
-
- # FIXME at this point MC crashes
- properties = account_props.GetAll(cs.ACCOUNT)
-
-
-if __name__ == '__main__':
- ctl_dir = os.environ['ACCOUNTS']
- prepare_accounts_db(ctl_dir)
- exec_test(test, {}, timeout=10, use_fake_accounts_service=False)
diff --git a/tests/twisted/account-storage/load-keyfiles.py b/tests/twisted/account-storage/load-keyfiles.py
new file mode 100644
index 00000000..b6c9d2ef
--- /dev/null
+++ b/tests/twisted/account-storage/load-keyfiles.py
@@ -0,0 +1,283 @@
+# Test for "stringified GVariant per account" storage backend introduced in
+# Mission Control 5.16, when loading pre-prepared files
+#
+# Copyright (C) 2009-2010 Nokia Corporation
+# Copyright (C) 2009-2014 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
+
+import errno
+import os
+import os.path
+
+import dbus
+
+from servicetest import (
+ assertEquals, assertContains, assertDoesNotContain,
+ )
+from mctest import (
+ MC, exec_test, get_fakecm_account, connect_to_mc,
+ SimulatedConnectionManager,
+ )
+from storage_helper import (
+ account_store,
+ )
+import constants as cs
+
+def test(q, bus, mc):
+ simulated_cm = SimulatedConnectionManager(q, bus)
+
+ ctl_dir = os.environ['MC_ACCOUNT_DIR']
+ old_key_file_name = os.path.join(ctl_dir, 'accounts.cfg')
+ newer_key_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control', 'accounts.cfg')
+
+ # We do several scenarios in one MC run, to speed up testing a bit.
+ scenarios = ('low', 'priority', 'masked', 'migration', 'absentcm')
+
+ variant_file_names = {}
+ low_prio_variant_file_names = {}
+ account_paths = {}
+ tails = {}
+
+ for s in scenarios:
+ variant_file_names[s] = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert%s_40example_2ecom0.account'
+ % s)
+ tails[s] = ('fakecm/fakeprotocol/dontdivert%s_40example_2ecom0' % s)
+ account_paths[s] = cs.ACCOUNT_PATH_PREFIX + tails[s]
+ low_prio_variant_file_names[s] = os.path.join(
+ os.environ['XDG_DATA_DIRS'].split(':')[0],
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert%s_40example_2ecom0.account' %
+ s)
+
+ try:
+ os.makedirs(os.path.dirname(variant_file_names[s]), 0700)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ try:
+ os.makedirs(os.path.dirname(low_prio_variant_file_names[s]), 0700)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ # This is deliberately a lower-priority location
+ open(low_prio_variant_file_names['low'], 'w').write(
+"""{
+'manager': <'fakecm'>,
+'protocol': <'fakeprotocol'>,
+'DisplayName': <'Account in a low-priority location'>,
+'AutomaticPresence': <(uint32 2, 'available', '')>,
+'Parameters': <{
+ 'account': <'dontdivertlow@example.com'>,
+ 'password': <'password_in_variant_file'>,
+ 'snakes': <uint32 42>
+ }>
+}
+""")
+
+ # This is in a lower-priority location and we don't know the
+ # parameters' types yet
+ open(low_prio_variant_file_names['migration'], 'w').write(
+"""{
+'manager': <'fakecm'>,
+'protocol': <'fakeprotocol'>,
+'DisplayName': <'Account in a low-priority location with KeyFileParameters'>,
+'AutomaticPresence': <(uint32 2, 'available', '')>,
+'KeyFileParameters': <{
+ 'account': 'dontdivertmigration@example.com',
+ 'password': 'password_in_variant_file',
+ 'snakes': '42'
+ }>
+}
+""")
+
+ # This is in a lower-priority location, and we don't know the
+ # parameters' types, and we can't learn them by asking the CM
+ # because it isn't installed
+ open(low_prio_variant_file_names['absentcm'], 'w').write(
+"""{
+'manager': <'absentcm'>,
+'protocol': <'absentprotocol'>,
+'DisplayName': <'Account in a low-priority location with absent CM'>,
+'AutomaticPresence': <(uint32 2, 'available', '')>,
+'KeyFileParameters': <{
+ 'account': 'dontdivertabsentcm@example.com',
+ 'password': 'hello',
+ 'snakes': '42'
+ }>
+}
+""")
+
+ # This version of this account will be used
+ open(variant_file_names['priority'], 'w').write("""{
+'manager': <'fakecm'>,
+'protocol': <'fakeprotocol'>,
+'DisplayName': <'Visible'>,
+'AutomaticPresence': <(uint32 2, 'available', '')>,
+'KeyFileParameters': <{'account': 'dontdivertpriority@example.com',
+ 'password': 'password_in_variant_file',
+ 'snakes': '42'
+ }>
+}
+""")
+ # This one won't, because it's "masked" by the higher-priority one
+ open(low_prio_variant_file_names['priority'], 'w').write("""{
+'manager': <'fakecm'>,
+'protocol': <'fakeprotocol'>,
+'DisplayName': <'Hidden'>,
+'Nickname': <'Hidden'>,
+'AutomaticPresence': <(uint32 2, 'available', '')>,
+'KeyFileParameters': <{'account': 'dontdivertpriority@example.com',
+ 'password': 'password_in_variant_file',
+ 'snakes': '42'
+ }>
+}
+""")
+
+ # This empty file is considered to "mask" the lower-priority one
+ open(variant_file_names['masked'], 'w').write('')
+ open(low_prio_variant_file_names['masked'], 'w').write("""{
+'manager': <'fakecm'>,
+'protocol': <'fakeprotocol'>,
+'AutomaticPresence': <(uint32 2, 'available', '')>,
+'KeyFileParameters': <{'account': 'dontdivert@example.com',
+ 'password': 'password_in_variant_file',
+ 'snakes': '42'
+ }>
+}
+""")
+
+ mc = MC(q, bus)
+ account_manager, properties, interfaces = connect_to_mc(q, bus, mc)
+
+ for s in scenarios:
+ if s == 'masked':
+ assertDoesNotContain(account_paths[s], properties['ValidAccounts'])
+ assertDoesNotContain(account_paths[s], properties['InvalidAccounts'])
+ elif s == 'absentcm':
+ assertContains(account_paths[s], properties['InvalidAccounts'])
+ assertDoesNotContain(account_paths[s], properties['ValidAccounts'])
+ else:
+ assertContains(account_paths[s], properties['ValidAccounts'])
+ assertDoesNotContain(account_paths[s], properties['InvalidAccounts'])
+
+ accounts = {}
+ account_ifaces = {}
+
+ for s in scenarios:
+ if s != 'masked':
+ accounts[s] = get_fakecm_account(bus, mc, account_paths[s])
+ account_ifaces[s] = dbus.Interface(accounts[s], cs.ACCOUNT)
+
+ if s not in ('masked', 'absentcm'):
+ # We can't get untyped parameters if we don't know what types
+ # the CM gives them.
+ assertEquals(42, accounts[s].Properties.Get(cs.ACCOUNT,
+ 'Parameters')['snakes'])
+ assertEquals(dbus.UInt32,
+ type(accounts[s].Properties.Get(cs.ACCOUNT,
+ 'Parameters')['snakes']))
+
+ # Files in lower-priority XDG locations aren't copied until something
+ # actually changes, and they aren't deleted.
+
+ if s == 'low':
+ assert os.path.exists(low_prio_variant_file_names[s])
+
+ # Delete the password (only), like Empathy 3.0-3.4 do when migrating.
+ # This results in the higher-priority file being written out.
+ account_ifaces['low'].UpdateParameters({}, ['password'])
+ q.expect('dbus-signal',
+ path=account_paths['low'],
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ predicate=(lambda e:
+ 'Parameters' in e.args[0]),
+ )
+ # Check the account has copied (not moved! XDG_DATA_DIRS are,
+ # conceptually, read-only) 'low' from the old to the new name
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(low_prio_variant_file_names['low'])
+ assert os.path.exists(variant_file_names['low'])
+
+ # test that priority works
+ assertContains(account_paths["priority"], properties['ValidAccounts'])
+ assertEquals('',
+ accounts['priority'].Properties.Get(cs.ACCOUNT, 'Nickname'))
+ assertEquals('Visible',
+ accounts['priority'].Properties.Get(cs.ACCOUNT, 'DisplayName'))
+
+ # test what happens when we delete an account that has a lower-priority
+ # "other self": it becomes masked
+ assert accounts['priority'].Remove() is None
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(low_prio_variant_file_names['priority'])
+ assert os.path.exists(variant_file_names['priority'])
+ assert open(variant_file_names['priority'], 'r').read() == ''
+ assertContains('password_in_variant_file',
+ open(low_prio_variant_file_names['priority'], 'r').read())
+
+ # The masked account is still masked
+ assert open(variant_file_names['masked'], 'r').read() == ''
+
+ # Because the CM exists, we can work out the correct types
+ # for the 'migration' account's parameters. This triggers a commit
+ # even though nothing has conceptually changed, so we have the type
+ # for later. The file is copied, not moved, because XDG_DATA_DIRS are,
+ # conceptually, read-only.
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(low_prio_variant_file_names['migration'])
+ assert os.path.exists(variant_file_names['migration'])
+ assertEquals("'password_in_variant_file'",
+ account_store('get', 'variant-file', 'param-password',
+ account=tails['migration']))
+ assertEquals("uint32 42", account_store('get', 'variant-file',
+ 'param-snakes', account=tails['migration']))
+
+ # Setting the password still does the right thing.
+ account_ifaces['migration'].UpdateParameters({'password': 'hello'}, [])
+ q.expect('dbus-signal',
+ path=account_paths['migration'],
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ predicate=(lambda e:
+ 'Parameters' in e.args[0]),
+ )
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(low_prio_variant_file_names['migration'])
+ assert os.path.exists(variant_file_names['migration'])
+ assertEquals("'hello'",
+ account_store('get', 'variant-file', 'param-password',
+ account=tails['migration']))
+
+ # 'absentcm' is still only in the low-priority location: we can't
+ # known the types of its parameters, so it doesn't get migrated.
+ assert not os.path.exists(old_key_file_name)
+ assert not os.path.exists(newer_key_file_name)
+ assert os.path.exists(low_prio_variant_file_names['absentcm'])
+ assert not os.path.exists(variant_file_names['absentcm'])
+
+if __name__ == '__main__':
+ exec_test(test, {}, preload_mc=False, use_fake_accounts_service=False)
diff --git a/tests/twisted/account-storage/storage_helper.py b/tests/twisted/account-storage/storage_helper.py
new file mode 100644
index 00000000..0f67df92
--- /dev/null
+++ b/tests/twisted/account-storage/storage_helper.py
@@ -0,0 +1,174 @@
+# Helper code for former default account storage backends
+#
+# Copyright (C) 2009-2010 Nokia Corporation
+# Copyright (C) 2009-2014 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
+
+import errno
+import os
+import os.path
+
+import dbus
+
+from servicetest import (
+ assertEquals, assertContains, assertLength,
+ )
+from mctest import (
+ exec_test, get_fakecm_account, connect_to_mc,
+ MC, SimulatedConnectionManager,
+ )
+import constants as cs
+
+# This doesn't escape its parameters before passing them to the shell,
+# so be careful.
+def account_store(op, backend, key=None, value=None,
+ account='fakecm/fakeprotocol/dontdivert_40example_2ecom0'):
+ cmd = [ '../account-store', op, backend, account ]
+ if key:
+ cmd.append(key)
+ if value:
+ cmd.append(value)
+
+ lines = os.popen(' '.join(cmd)).read()
+ ret = []
+ for line in lines.split('\n'):
+ if line.startswith('** '):
+ continue
+
+ if line:
+ ret.append(line)
+
+ if len(ret) > 0:
+ return ret[0]
+ else:
+ return None
+
+def test_keyfile(q, bus, mc, how_old='5.12'):
+ simulated_cm = SimulatedConnectionManager(q, bus)
+
+ if how_old == '5.12':
+ # This is not actually ~/.mission-control, but it uses the same
+ # code paths.
+ dot_mission_control = os.environ['MC_ACCOUNT_DIR']
+ old_key_file_name = os.path.join(dot_mission_control, 'accounts.cfg')
+
+ os.makedirs(dot_mission_control +
+ '/fakecm/fakeprotocol/dontdivert1_40example_2ecom0')
+ avatar_bin = open(dot_mission_control +
+ '/fakecm/fakeprotocol/dontdivert1_40example_2ecom0/avatar.bin',
+ 'w')
+ avatar_bin.write('hello, world')
+ avatar_bin.close()
+ elif how_old == '5.14':
+ # Same format, different location.
+ old_key_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control', 'accounts.cfg')
+
+ # exercise override of an avatar in XDG_DATA_DIRS
+ avatar_dir = (os.environ['XDG_DATA_DIRS'].split(':')[0] +
+ '/telepathy/mission-control')
+ os.makedirs(avatar_dir)
+ avatar_bin = open(avatar_dir +
+ '/fakecm-fakeprotocol-dontdivert1_40example_2ecom0.avatar',
+ 'w')
+ avatar_bin.write('hello, world')
+ avatar_bin.close()
+ else:
+ raise AssertionError('Unsupported value for how_old')
+
+ a1_new_variant_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert1_40example_2ecom0.account')
+ a1_tail = 'fakecm/fakeprotocol/dontdivert1_40example_2ecom0'
+
+ a2_new_variant_file_name = os.path.join(os.environ['XDG_DATA_HOME'],
+ 'telepathy', 'mission-control',
+ 'fakecm-fakeprotocol-dontdivert2_40example_2ecom0.account')
+ a2_tail = 'fakecm/fakeprotocol/dontdivert2_40example_2ecom0'
+
+ try:
+ os.makedirs(os.path.dirname(old_key_file_name), 0700)
+ except OSError as e:
+ if e.errno != errno.EEXIST:
+ raise
+
+ open(old_key_file_name, 'w').write(
+r"""# Telepathy accounts
+[%s]
+manager=fakecm
+protocol=fakeprotocol
+param-account=dontdivert1@example.com
+param-password=1
+DisplayName=First among equals
+AutomaticPresence=2;available;;
+AvatarMime=text/plain
+avatar_token=hello, world
+
+[%s]
+manager=fakecm
+protocol=fakeprotocol
+param-account=dontdivert2@example.com
+param-password=2
+DisplayName=Second to none
+AutomaticPresence=2;available;;
+""" % (a1_tail, a2_tail))
+
+ mc = MC(q, bus)
+ account_manager, properties, interfaces = connect_to_mc(q, bus, mc)
+
+ # During MC startup, it moved the old keyfile's contents into
+ # variant-based files, and deleted the old keyfile.
+ assert not os.path.exists(old_key_file_name)
+ assert os.path.exists(a1_new_variant_file_name)
+ assert os.path.exists(a2_new_variant_file_name)
+ assertEquals("'First among equals'",
+ account_store('get', 'variant-file', 'DisplayName',
+ account=a1_tail))
+ assertEquals("'Second to none'",
+ account_store('get', 'variant-file', 'DisplayName',
+ account=a2_tail))
+ # Because the CM is installed, we can work out the right types
+ # for the parameters, too.
+ assertEquals("'dontdivert1@example.com'",
+ account_store('get', 'variant-file', 'param-account',
+ account=a1_tail))
+ assertEquals("'dontdivert2@example.com'",
+ account_store('get', 'variant-file', 'param-account',
+ account=a2_tail))
+
+ # Also, MC has both accounts in memory...
+ assertContains(cs.ACCOUNT_PATH_PREFIX + a1_tail,
+ properties['ValidAccounts'])
+ account = get_fakecm_account(bus, mc, cs.ACCOUNT_PATH_PREFIX + a1_tail)
+ assertEquals('dontdivert1@example.com',
+ account.Properties.Get(cs.ACCOUNT, 'Parameters')['account'])
+ assertEquals('First among equals',
+ account.Properties.Get(cs.ACCOUNT, 'DisplayName'))
+ assertEquals((dbus.ByteArray('hello, world'), 'text/plain'),
+ account.Properties.Get(cs.ACCOUNT_IFACE_AVATAR, 'Avatar',
+ byte_arrays=True))
+
+ assertContains(cs.ACCOUNT_PATH_PREFIX + a2_tail,
+ properties['ValidAccounts'])
+ account = get_fakecm_account(bus, mc, cs.ACCOUNT_PATH_PREFIX + a2_tail)
+ assertEquals('dontdivert2@example.com',
+ account.Properties.Get(cs.ACCOUNT, 'Parameters')['account'])
+ assertEquals('Second to none',
+ account.Properties.Get(cs.ACCOUNT, 'DisplayName'))
+
+ # ... and no other accounts.
+ assertLength(2, properties['ValidAccounts'])
diff --git a/tests/twisted/account/addressing.py b/tests/twisted/account/addressing.py
index e303c935..222546b0 100755
--- a/tests/twisted/account/addressing.py
+++ b/tests/twisted/account/addressing.py
@@ -31,7 +31,7 @@ def test(q, bus, mc):
params = dbus.Dictionary ({"account": "jc.denton@example.com",
"password": "ionstorm"},
signature='sv')
- (cm_name_ref, account) = create_fakecm_account (q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account (q, bus, mc, params)
account_iface = dbus.Interface (account, cs.ACCOUNT)
account_props = dbus.Interface (account, cs.PROPERTIES_IFACE)
diff --git a/tests/twisted/capabilities/contact-caps.py b/tests/twisted/capabilities/contact-caps.py
index 7a348df0..320a8c5e 100644
--- a/tests/twisted/capabilities/contact-caps.py
+++ b/tests/twisted/capabilities/contact-caps.py
@@ -33,13 +33,6 @@ from mctest import exec_test, SimulatedConnection, SimulatedClient, \
import constants as cs
def test(q, bus, mc):
- forbidden = [
- EventPattern('dbus-method-call', handled=False,
- interface=cs.CONN_IFACE_CAPS,
- method='AdvertiseCapabilities'),
- ]
- q.forbid_events(forbidden)
-
# Two clients want to handle channels: MediaCall is running, and AbiWord
# is activatable.
@@ -56,13 +49,13 @@ def test(q, bus, mc):
}, signature='sv')
media_fixed_properties = dbus.Dictionary({
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAMED_MEDIA,
+ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL,
}, signature='sv')
media_call = SimulatedClient(q, bus, 'MediaCall',
observe=[], approve=[], handle=[media_fixed_properties],
- cap_tokens=[cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/ice-udp',
- cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/audio/speex',
- cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/video/theora'],
+ cap_tokens=[cs.CHANNEL_TYPE_CALL + '/ice',
+ cs.CHANNEL_TYPE_CALL + '/audio/speex',
+ cs.CHANNEL_TYPE_CALL + '/video/theora'],
bypass_approval=False)
# wait for MC to download the properties
@@ -89,11 +82,11 @@ def test(q, bus, mc):
assert len(filters[cs.CLIENT + '.AbiWord']) == 2
assert len(tokens[cs.CLIENT + '.MediaCall']) == 3
- assert cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/ice-udp' in \
+ assert cs.CHANNEL_TYPE_CALL + '/ice' in \
tokens[cs.CLIENT + '.MediaCall']
- assert cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/audio/speex' in \
+ assert cs.CHANNEL_TYPE_CALL + '/audio/speex' in \
tokens[cs.CLIENT + '.MediaCall']
- assert cs.CHANNEL_IFACE_MEDIA_SIGNALLING + '/video/theora' in \
+ assert cs.CHANNEL_TYPE_CALL + '/video/theora' in \
tokens[cs.CLIENT + '.MediaCall']
assert len(tokens[cs.CLIENT + '.AbiWord']) == 2
@@ -104,10 +97,9 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn, before = enable_fakecm_account(q, bus, mc, account, params,
- extra_interfaces=[cs.CONN_IFACE_CONTACT_CAPS,
- cs.CONN_IFACE_CAPS],
+ extra_interfaces=[cs.CONN_IFACE_CONTACT_CAPS],
expect_before_connect=[
EventPattern('dbus-method-call', handled=False,
interface=cs.CONN_IFACE_CONTACT_CAPS,
diff --git a/tests/twisted/constants.py b/tests/twisted/constants.py
index 3a844d54..2a4b69b8 100644
--- a/tests/twisted/constants.py
+++ b/tests/twisted/constants.py
@@ -1,5 +1,5 @@
# Copyright (C) 2009 Nokia Corporation
-# Copyright (C) 2009-2012 Collabora Ltd.
+# Copyright (C) 2009-2013 Collabora Ltd.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -21,31 +21,59 @@ Some handy constants for other tests to share and enjoy.
"""
from dbus import PROPERTIES_IFACE, INTROSPECTABLE_IFACE
-from servicetest import tp_name_prefix, tp_path_prefix
-CM = "org.freedesktop.Telepathy.ConnectionManager"
+PREFIX = "org.freedesktop.Telepathy"
+PATH_PREFIX = '/' + PREFIX.replace('.', '/')
-DBUS_ERROR_NO_REPLY = 'org.freedesktop.DBus.Error.NoReply'
+tp_name_prefix = PREFIX
+tp_path_prefix = PATH_PREFIX
+
+CM = PREFIX + ".ConnectionManager"
+HT_NONE = 0
HT_CONTACT = 1
HT_ROOM = 2
+HT_LIST = 3
+HT_GROUP = 4
+
+CHANNEL = PREFIX + ".Channel"
-CHANNEL = tp_name_prefix + ".Channel"
+CHANNEL_IFACE_CALL_STATE = CHANNEL + ".Interface.CallState"
+CHANNEL_IFACE_CHAT_STATE = CHANNEL + '.Interface.ChatState'
CHANNEL_IFACE_DESTROYABLE = CHANNEL + ".Interface.Destroyable"
+CHANNEL_IFACE_DTMF = CHANNEL + ".Interface.DTMF"
CHANNEL_IFACE_GROUP = CHANNEL + ".Interface.Group"
CHANNEL_IFACE_HOLD = CHANNEL + ".Interface.Hold"
CHANNEL_IFACE_MEDIA_SIGNALLING = CHANNEL + ".Interface.MediaSignalling"
+CHANNEL_IFACE_MESSAGES = CHANNEL + ".Interface.Messages"
+CHANNEL_IFACE_PASSWORD = CHANNEL + ".Interface.Password"
+CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube"
+CHANNEL_IFACE_SASL_AUTH = CHANNEL + ".Interface.SASLAuthentication"
+CHANNEL_IFACE_CONFERENCE = CHANNEL + '.Interface.Conference'
+CHANNEL_IFACE_ROOM = CHANNEL + '.Interface.Room2'
+CHANNEL_IFACE_ROOM_CONFIG = CHANNEL + '.Interface.RoomConfig1'
+CHANNEL_IFACE_SUBJECT = CHANNEL + '.Interface.Subject2'
+CHANNEL_IFACE_FILE_TRANSFER_METADATA = CHANNEL + '.Interface.FileTransfer.Metadata'
+
+CHANNEL_TYPE_CALL = CHANNEL + ".Type.Call1"
+CHANNEL_TYPE_CONTACT_LIST = CHANNEL + ".Type.ContactList"
+CHANNEL_TYPE_CONTACT_SEARCH = CHANNEL + ".Type.ContactSearch"
CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text"
CHANNEL_TYPE_TUBES = CHANNEL + ".Type.Tubes"
-CHANNEL_IFACE_TUBE = CHANNEL + ".Interface.Tube"
CHANNEL_TYPE_STREAM_TUBE = CHANNEL + ".Type.StreamTube"
CHANNEL_TYPE_DBUS_TUBE = CHANNEL + ".Type.DBusTube"
-CHANNEL_TYPE_STREAMED_MEDIA = CHANNEL + ".Type.StreamedMedia"
CHANNEL_TYPE_TEXT = CHANNEL + ".Type.Text"
-
-TP_AWKWARD_PROPERTIES = tp_name_prefix + ".Properties"
+CHANNEL_TYPE_FILE_TRANSFER = CHANNEL + ".Type.FileTransfer"
+CHANNEL_TYPE_ROOM_LIST = CHANNEL + ".Type.RoomList"
+CHANNEL_TYPE_SERVER_AUTHENTICATION = \
+ CHANNEL + ".Type.ServerAuthentication"
+CHANNEL_TYPE_SERVER_TLS_CONNECTION = \
+ CHANNEL + ".Type.ServerTLSConnection"
+
+TP_AWKWARD_PROPERTIES = PREFIX + ".Properties"
PROPERTY_FLAG_READ = 1
PROPERTY_FLAG_WRITE = 2
+PROPERTY_FLAGS_RW = PROPERTY_FLAG_READ | PROPERTY_FLAG_WRITE
CHANNEL_TYPE = CHANNEL + '.ChannelType'
TARGET_HANDLE_TYPE = CHANNEL + '.TargetHandleType'
@@ -56,69 +84,200 @@ INITIATOR_HANDLE = CHANNEL + '.InitiatorHandle'
INITIATOR_ID = CHANNEL + '.InitiatorID'
INTERFACES = CHANNEL + '.Interfaces'
-CONN = tp_name_prefix + ".Connection"
-CONN_IFACE_ALIASING = CONN + '.Interface.Aliasing'
+CALL_CONTENTS = CHANNEL_TYPE_CALL + '.Contents'
+CALL_CALL_STATE_DETAILS = CHANNEL_TYPE_CALL + '.CallStateDetails'
+CALL_CALL_STATE = CHANNEL_TYPE_CALL + '.CallState'
+CALL_CALL_FLAGS = CHANNEL_TYPE_CALL + '.CallFlags'
+CALL_CALL_STATE_REASON = CHANNEL_TYPE_CALL + '.CallStateReason'
+CALL_HARDWARE_STREAMING = CHANNEL_TYPE_CALL + '.HardwareStreaming'
+CALL_CALL_MEMBERS = CHANNEL_TYPE_CALL + '.CallMembers'
+CALL_MEMBER_IDENTIFIERS = CHANNEL_TYPE_CALL + '.MemberIdentifiers'
+CALL_INITIAL_TRANSPORT = CHANNEL_TYPE_CALL + '.InitialTransport'
+CALL_INITIAL_AUDIO = CHANNEL_TYPE_CALL + '.InitialAudio'
+CALL_INITIAL_AUDIO_NAME = CHANNEL_TYPE_CALL + '.InitialAudioName'
+CALL_INITIAL_VIDEO = CHANNEL_TYPE_CALL + '.InitialVideo'
+CALL_INITIAL_VIDEO_NAME = CHANNEL_TYPE_CALL + '.InitialVideoName'
+CALL_MUTABLE_CONTENTS = CHANNEL_TYPE_CALL + '.MutableContents'
+
+CALL_CONTENT = PREFIX + '.Call1.Content'
+CALL_CONTENT_IFACE_MEDIA = CALL_CONTENT + '.Interface.Media'
+CALL_CONTENT_IFACE_DTMF = CALL_CONTENT + '.Interface.DTMF'
+
+CALL_CONTENT_MEDIA_DESCRIPTION = CALL_CONTENT + '.MediaDescription'
+
+CALL_STREAM = PREFIX + '.Call1.Stream'
+CALL_STREAM_IFACE_MEDIA = CALL_STREAM + '.Interface.Media'
+
+CALL_STREAM_ENDPOINT = CALL_STREAM + '.Endpoint'
+
+CALL_MEDIA_TYPE_AUDIO = 0
+CALL_MEDIA_TYPE_VIDEO = 1
+
+CALL_CONTENT_PACKETIZATION_RTP = 0
+CALL_CONTENT_PACKETIZATION_RAW = 1
+CALL_CONTENT_PACKETIZATION_MSN_WEBCAM = 2
+
+CALL_STREAM_TRANSPORT_UNKNOWN = 0
+CALL_STREAM_TRANSPORT_RAW_UDP = 1
+CALL_STREAM_TRANSPORT_ICE = 2
+CALL_STREAM_TRANSPORT_GTALK_P2P = 3
+CALL_STREAM_TRANSPORT_WLM_2009 = 4
+CALL_STREAM_TRANSPORT_SHM = 5
+CALL_STREAM_TRANSPORT_MULTICAST = 6
+
+CALL_STATE_UNKNOWN = 0
+CALL_STATE_PENDING_INITIATOR = 1
+CALL_STATE_INITIALISING = 2
+CALL_STATE_INITIALISED = 3
+CALL_STATE_ACCEPTED = 4
+CALL_STATE_ACTIVE = 5
+CALL_STATE_ENDED = 6
+
+CALL_FLAG_LOCALLY_HELD = 1
+CALL_FLAG_LOCALLY_RINGING = 2
+CALL_FLAG_LOCALLY_QUEUED = 4
+CALL_FLAG_FORWARDED = 8
+CALL_FLAG_CLEARING = 16
+
+CALL_MEMBER_FLAG_RINGING = 1
+CALL_MEMBER_FLAG_HELD = 2
+
+CALL_DISPOSITION_NONE = 0
+CALL_DISPOSITION_INITIAL = 1
+
+CALL_SENDING_STATE_NONE = 0
+CALL_SENDING_STATE_PENDING_SEND = 1
+CALL_SENDING_STATE_SENDING = 2
+CALL_SENDING_STATE_PENDING_STOP_SENDING = 3
+
+CALL_STREAM_FLOW_STATE_STOPPED = 0
+CALL_STREAM_FLOW_STATE_PENDING_START = 1
+CALL_STREAM_FLOW_STATE_PENDING_STOP = 2
+CALL_STREAM_FLOW_STATE_STARTED = 3
+
+CALL_STREAM_ENDPOINT_STATE_CONNECTING = 0
+CALL_STREAM_ENDPOINT_STATE_PROVISIONALLY_CONNECTED = 1
+CALL_STREAM_ENDPOINT_STATE_FULLY_CONNECTED = 2
+CALL_STREAM_ENDPOINT_STATE_EXHAUSTED_CANDIDATES = 3
+CALL_STREAM_ENDPOINT_STATE_FAILED = 4
+
+CALL_STREAM_CANDIDATE_TYPE_HOST = 1
+CALL_STREAM_CANDIDATE_TYPE_SERVER_REFLEXIVE = 2
+CALL_STREAM_CANDIDATE_TYPE_RELAY = 4
+
+CALL_STATE_CHANGE_REASON_UNKNOWN = 0
+CALL_STATE_CHANGE_REASON_PROGRESS_MADE = 1
+CALL_STATE_CHANGE_REASON_USER_REQUESTED = 2
+CALL_STATE_CHANGE_REASON_FORWARDED = 3
+CALL_STATE_CHANGE_REASON_REJECTED = 4
+CALL_STATE_CHANGE_REASON_NO_ANSWER = 5
+CALL_STATE_CHANGE_REASON_INVALID_CONTACT = 6
+CALL_STATE_CHANGE_REASON_PERMISSION_DENIED = 7
+CALL_STATE_CHANGE_REASON_BUSY = 8
+CALL_STATE_CHANGE_REASON_INTERNAL_ERROR = 9
+CALL_STATE_CHANGE_REASON_SERVICE_ERROR = 10
+CALL_STATE_CHANGE_REASON_NETWORK_ERROR = 11
+CALL_STATE_CHANGE_REASON_MEDIA_ERROR = 12
+CALL_STATE_CHANGE_REASON_CONNECTIVITY_ERROR = 13
+
+CALL_STREAM_COMPONENT_UNKNOWN = 0
+CALL_STREAM_COMPONENT_DATA = 1
+CALL_STREAM_COMPONENT_CONTROL = 2
+
+SUBSCRIPTION_STATE_UNKNOWN = 0
+SUBSCRIPTION_STATE_NO = 1
+SUBSCRIPTION_STATE_REMOVED_REMOTELY = 2
+SUBSCRIPTION_STATE_ASK = 3
+SUBSCRIPTION_STATE_YES = 4
+
+CONTACT_LIST_STATE_NONE = 0
+CONTACT_LIST_STATE_WAITING = 1
+CONTACT_LIST_STATE_FAILURE = 2
+CONTACT_LIST_STATE_SUCCESS = 3
+
+CONN = PREFIX + ".Connection"
CONN_IFACE_AVATARS = CONN + '.Interface.Avatars'
+CONN_IFACE_ALIASING = CONN + '.Interface.Aliasing'
CONN_IFACE_CAPS = CONN + '.Interface.Capabilities'
CONN_IFACE_CONTACTS = CONN + '.Interface.Contacts'
CONN_IFACE_CONTACT_CAPS = CONN + '.Interface.ContactCapabilities'
-CONN_IFACE_REQUESTS = CONN + '.Interface.Requests'
+CONN_IFACE_CONTACT_INFO = CONN + ".Interface.ContactInfo"
+CONN_IFACE_PRESENCE = CONN + '.Interface.Presence'
CONN_IFACE_SIMPLE_PRESENCE = CONN + '.Interface.SimplePresence'
+CONN_IFACE_REQUESTS = CONN + '.Interface.Requests'
+CONN_IFACE_LOCATION = CONN + '.Interface.Location'
+CONN_IFACE_GABBLE_DECLOAK = CONN + '.Interface.Gabble.Decloak'
+CONN_IFACE_MAIL_NOTIFICATION = CONN + '.Interface.MailNotification'
+CONN_IFACE_CONTACT_LIST = CONN + '.Interface.ContactList'
+CONN_IFACE_CONTACT_GROUPS = CONN + '.Interface.ContactGroups'
+CONN_IFACE_CLIENT_TYPES = CONN + '.Interface.ClientTypes'
CONN_IFACE_POWER_SAVING = CONN + '.Interface.PowerSaving'
+CONN_IFACE_CONTACT_BLOCKING = CONN + '.Interface.ContactBlocking'
+CONN_IFACE_ADDRESSING = CONN + '.Interface.Addressing1'
CONN_IFACE_SERVICE_POINT = CONN + '.Interface.ServicePoint'
-CONN_STATUS_CONNECTED = 0
-CONN_STATUS_CONNECTING = 1
-CONN_STATUS_DISCONNECTED = 2
-
ATTR_CONTACT_ID = CONN + '/contact-id'
ATTR_ALIAS = CONN_IFACE_ALIASING + '/alias'
ATTR_AVATAR_TOKEN = CONN_IFACE_AVATARS + '/token'
+ATTR_CONTACT_CAPABILITIES = CONN_IFACE_CONTACT_CAPS + '/capabilities'
ATTR_PRESENCE = CONN_IFACE_SIMPLE_PRESENCE + '/presence'
+ATTR_SUBSCRIBE = CONN_IFACE_CONTACT_LIST + '/subscribe'
+ATTR_PUBLISH = CONN_IFACE_CONTACT_LIST + '/publish'
+ATTR_GROUPS = CONN_IFACE_CONTACT_GROUPS + '/groups'
+
+STREAM_HANDLER = PREFIX + '.Media.StreamHandler'
-CONN_STATUS_REASON_NONE = 0
-CONN_STATUS_REASON_REQUESTED = 1
-CONN_STATUS_REASON_NETWORK_ERROR = 2
-
-GROUP_REASON_NONE = 0
-GROUP_REASON_OFFLINE = 1
-GROUP_REASON_KICKED = 2
-GROUP_REASON_BUSY = 3
-GROUP_REASON_INVITED = 4
-GROUP_REASON_BANNED = 5
-GROUP_REASON_ERROR = 6
-GROUP_REASON_INVALID_CONTACT = 7
-GROUP_REASON_NO_ANSWER = 8
-GROUP_REASON_RENAMED = 9
-GROUP_REASON_PERMISSION_DENIED = 10
-GROUP_REASON_SEPARATED = 11
-
-PRESENCE_TYPE_UNSET = 0
-PRESENCE_TYPE_OFFLINE = 1
-PRESENCE_TYPE_AVAILABLE = 2
-PRESENCE_TYPE_AWAY = 3
-PRESENCE_TYPE_XA = 4
-PRESENCE_TYPE_HIDDEN = 5
-PRESENCE_TYPE_BUSY = 6
-PRESENCE_TYPE_UNKNOWN = 7
-PRESENCE_TYPE_ERROR = 8
-
-ERROR = tp_name_prefix + '.Error'
+ERROR = PREFIX + '.Error'
INVALID_ARGUMENT = ERROR + '.InvalidArgument'
-INVALID_HANDLE = ERROR + '.InvalidHandle'
NOT_IMPLEMENTED = ERROR + '.NotImplemented'
NOT_AVAILABLE = ERROR + '.NotAvailable'
PERMISSION_DENIED = ERROR + '.PermissionDenied'
+OFFLINE = ERROR + '.Offline'
+NOT_CAPABLE = ERROR + '.NotCapable'
+CONNECTION_REFUSED = ERROR + '.ConnectionRefused'
+CONNECTION_FAILED = ERROR + '.ConnectionFailed'
+CONNECTION_LOST = ERROR + '.ConnectionLost'
CANCELLED = ERROR + '.Cancelled'
NOT_YOURS = ERROR + '.NotYours'
DISCONNECTED = ERROR + '.Disconnected'
-NOT_CAPABLE = ERROR + '.NotCapable'
+REGISTRATION_EXISTS = ERROR + '.RegistrationExists'
+AUTHENTICATION_FAILED = ERROR + '.AuthenticationFailed'
+CONNECTION_REPLACED = ERROR + '.ConnectionReplaced'
+ALREADY_CONNECTED = ERROR + '.AlreadyConnected'
+NETWORK_ERROR = ERROR + '.NetworkError'
+NOT_YET = ERROR + '.NotYet'
+INVALID_HANDLE = ERROR + '.InvalidHandle'
+CERT_UNTRUSTED = ERROR + '.Cert.Untrusted'
+SERVICE_BUSY = ERROR + '.ServiceBusy'
+SERVICE_CONFUSED = ERROR + '.ServiceConfused'
+SOFTWARE_UPGRADE_REQUIRED = ERROR + '.SoftwareUpgradeRequired'
+
+BANNED = ERROR + '.Channel.Banned'
+
+DBUS_ERROR_UNKNOWN_METHOD = 'org.freedesktop.DBus.Error.UnknownMethod'
+DBUS_ERROR_NO_REPLY = 'org.freedesktop.DBus.Error.NoReply'
TUBE_PARAMETERS = CHANNEL_IFACE_TUBE + '.Parameters'
TUBE_STATE = CHANNEL_IFACE_TUBE + '.State'
STREAM_TUBE_SERVICE = CHANNEL_TYPE_STREAM_TUBE + '.Service'
DBUS_TUBE_SERVICE_NAME = CHANNEL_TYPE_DBUS_TUBE + '.ServiceName'
DBUS_TUBE_DBUS_NAMES = CHANNEL_TYPE_DBUS_TUBE + '.DBusNames'
+DBUS_TUBE_SUPPORTED_ACCESS_CONTROLS = CHANNEL_TYPE_DBUS_TUBE + '.SupportedAccessControls'
+STREAM_TUBE_SUPPORTED_SOCKET_TYPES = CHANNEL_TYPE_STREAM_TUBE + '.SupportedSocketTypes'
+
+CONFERENCE_INITIAL_CHANNELS = CHANNEL_IFACE_CONFERENCE + '.InitialChannels'
+CONFERENCE_INITIAL_INVITEE_HANDLES = CHANNEL_IFACE_CONFERENCE + '.InitialInviteeHandles'
+CONFERENCE_INITIAL_INVITEE_IDS = CHANNEL_IFACE_CONFERENCE + '.InitialInviteeIDs'
+
+CONTACT_SEARCH_ASK = CHANNEL_TYPE_CONTACT_SEARCH + '.AvailableSearchKeys'
+CONTACT_SEARCH_SERVER = CHANNEL_TYPE_CONTACT_SEARCH + '.Server'
+CONTACT_SEARCH_STATE = CHANNEL_TYPE_CONTACT_SEARCH + '.SearchState'
+
+SEARCH_NOT_STARTED = 0
+SEARCH_IN_PROGRESS = 1
+SEARCH_MORE_AVAILABLE = 2
+SEARCH_COMPLETED = 3
+SEARCH_FAILED = 4
TUBE_CHANNEL_STATE_LOCAL_PENDING = 0
TUBE_CHANNEL_STATE_REMOTE_PENDING = 1
@@ -128,6 +287,13 @@ TUBE_CHANNEL_STATE_NOT_OFFERED = 3
MEDIA_STREAM_TYPE_AUDIO = 0
MEDIA_STREAM_TYPE_VIDEO = 1
+MEDIA_STREAM_BASE_PROTO_UDP = 0
+MEDIA_STREAM_BASE_PROTO_TCP = 1
+
+MEDIA_STREAM_TRANSPORT_TYPE_LOCAL = 0
+MEDIA_STREAM_TRANSPORT_TYPE_DERIVED = 1
+MEDIA_STREAM_TRANSPORT_TYPE_RELAY = 2
+
SOCKET_ADDRESS_TYPE_UNIX = 0
SOCKET_ADDRESS_TYPE_ABSTRACT_UNIX = 1
SOCKET_ADDRESS_TYPE_IPV4 = 2
@@ -166,41 +332,287 @@ MEDIA_STREAM_DIRECTION_SEND = 1
MEDIA_STREAM_DIRECTION_RECEIVE = 2
MEDIA_STREAM_DIRECTION_BIDIRECTIONAL = 3
+FT_STATE_NONE = 0
+FT_STATE_PENDING = 1
+FT_STATE_ACCEPTED = 2
+FT_STATE_OPEN = 3
+FT_STATE_COMPLETED = 4
+FT_STATE_CANCELLED = 5
+
+FT_STATE_CHANGE_REASON_NONE = 0
+FT_STATE_CHANGE_REASON_REQUESTED = 1
+FT_STATE_CHANGE_REASON_LOCAL_STOPPED = 2
+FT_STATE_CHANGE_REASON_REMOTE_STOPPED = 3
+FT_STATE_CHANGE_REASON_LOCAL_ERROR = 4
+FT_STATE_CHANGE_REASON_REMOTE_ERROR = 5
+
+FILE_HASH_TYPE_NONE = 0
+FILE_HASH_TYPE_MD5 = 1
+FILE_HASH_TYPE_SHA1 = 2
+FILE_HASH_TYPE_SHA256 = 3
+
+FT_STATE = CHANNEL_TYPE_FILE_TRANSFER + '.State'
+FT_CONTENT_TYPE = CHANNEL_TYPE_FILE_TRANSFER + '.ContentType'
+FT_FILENAME = CHANNEL_TYPE_FILE_TRANSFER + '.Filename'
+FT_SIZE = CHANNEL_TYPE_FILE_TRANSFER + '.Size'
+FT_CONTENT_HASH_TYPE = CHANNEL_TYPE_FILE_TRANSFER + '.ContentHashType'
+FT_CONTENT_HASH = CHANNEL_TYPE_FILE_TRANSFER + '.ContentHash'
+FT_DESCRIPTION = CHANNEL_TYPE_FILE_TRANSFER + '.Description'
+FT_DATE = CHANNEL_TYPE_FILE_TRANSFER + '.Date'
+FT_AVAILABLE_SOCKET_TYPES = CHANNEL_TYPE_FILE_TRANSFER + '.AvailableSocketTypes'
+FT_TRANSFERRED_BYTES = CHANNEL_TYPE_FILE_TRANSFER + '.TransferredBytes'
+FT_INITIAL_OFFSET = CHANNEL_TYPE_FILE_TRANSFER + '.InitialOffset'
+FT_FILE_COLLECTION = CHANNEL_TYPE_FILE_TRANSFER + '.FUTURE.FileCollection'
+FT_URI = CHANNEL_TYPE_FILE_TRANSFER + '.URI'
+FT_SERVICE_NAME = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.ServiceName'
+FT_METADATA = CHANNEL_IFACE_FILE_TRANSFER_METADATA + '.Metadata'
+
+GF_CAN_ADD = 1
+GF_CAN_REMOVE = 2
+GF_CAN_RESCIND = 4
+GF_MESSAGE_ADD = 8
+GF_MESSAGE_REMOVE = 16
+GF_MESSAGE_ACCEPT = 32
+GF_MESSAGE_REJECT = 64
+GF_MESSAGE_RESCIND = 128
+GF_CHANNEL_SPECIFIC_HANDLES = 256
+GF_ONLY_ONE_GROUP = 512
+GF_HANDLE_OWNERS_NOT_AVAILABLE = 1024
+GF_PROPERTIES = 2048
+GF_MEMBERS_CHANGED_DETAILED = 4096
+
+GC_REASON_NONE = 0
+GC_REASON_OFFLINE = 1
+GC_REASON_KICKED = 2
+GC_REASON_BUSY = 3
+GC_REASON_INVITED = 4
+GC_REASON_BANNED = 5
+GC_REASON_ERROR = 6
+GC_REASON_INVALID_CONTACT = 7
+GC_REASON_NO_ANSWER = 8
+GC_REASON_RENAMED = 9
+GC_REASON_PERMISSION_DENIED = 10
+GC_REASON_SEPARATED = 11
+
+HS_UNHELD = 0
+HS_HELD = 1
+HS_PENDING_HOLD = 2
+HS_PENDING_UNHOLD = 3
+
+HSR_NONE = 0
+HSR_REQUESTED = 1
+HSR_RESOURCE_NOT_AVAILABLE = 2
+
+CONN_STATUS_CONNECTED = 0
+CONN_STATUS_CONNECTING = 1
+CONN_STATUS_DISCONNECTED = 2
+
+CSR_NONE_SPECIFIED = 0
+CSR_REQUESTED = 1
+CSR_NETWORK_ERROR = 2
+CSR_AUTHENTICATION_FAILED = 3
+CSR_ENCRYPTION_ERROR = 4
+CSR_NAME_IN_USE = 5
+CSR_CERT_NOT_PROVIDED = 6
+CSR_CERT_UNTRUSTED = 7
+CSR_CERT_EXPIRED = 8
+CSR_CERT_NOT_ACTIVATED = 9
+CSR_CERT_HOSTNAME_MISMATCH = 10
+CSR_CERT_FINGERPRINT_MISMATCH = 11
+CSR_CERT_SELF_SIGNED = 12
+CSR_CERT_OTHER_ERROR = 13
+
+BUDDY_INFO = 'org.laptop.Telepathy.BuddyInfo'
+ACTIVITY_PROPERTIES = 'org.laptop.Telepathy.ActivityProperties'
+
+CHAT_STATE_GONE = 0
+CHAT_STATE_INACTIVE = 1
+CHAT_STATE_ACTIVE = 2
+CHAT_STATE_PAUSED = 3
+CHAT_STATE_COMPOSING = 4
+
+# Channel_Media_Capabilities
+MEDIA_CAP_AUDIO = 1
+MEDIA_CAP_VIDEO = 2
+MEDIA_CAP_STUN = 4
+MEDIA_CAP_GTALKP2P = 8
+MEDIA_CAP_ICEUDP = 16
+MEDIA_CAP_IMMUTABLE_STREAMS = 32
+
+CLIENT = PREFIX + '.Client'
+
+PRESENCE_UNSET = 0
+PRESENCE_OFFLINE = 1
+PRESENCE_AVAILABLE = 2
+PRESENCE_AWAY = 3
+PRESENCE_EXTENDED_AWAY = 4
+PRESENCE_HIDDEN = 5
+PRESENCE_BUSY = 6
+PRESENCE_UNKNOWN = 7
+PRESENCE_ERROR = 8
+
+CONTACT_INFO_FLAG_CAN_SET = 1
+CONTACT_INFO_FLAG_PUSH = 2
+CONTACT_INFO_FIELD_FLAG_PARAMETERS_EXACT = 1
+CONTACT_INFO_FIELD_FLAG_OVERWRITTEN_BY_NICKNAME = 2
+
+# Channel_Interface_SaslAuthentication
+SASL_STATUS_NOT_STARTED = 0
+SASL_STATUS_IN_PROGRESS = 1
+SASL_STATUS_SERVER_SUCCEEDED = 2
+SASL_STATUS_CLIENT_ACCEPTED = 3
+SASL_STATUS_SUCCEEDED = 4
+SASL_STATUS_SERVER_FAILED = 5
+SASL_STATUS_CLIENT_FAILED = 6
+
+SASL_ABORT_REASON_INVALID_CHALLENGE = 0
+SASL_ABORT_REASON_USER_ABORT = 1
+
+AUTH_METHOD = CHANNEL_TYPE_SERVER_AUTHENTICATION + ".AuthenticationMethod"
+SASL_AVAILABLE_MECHANISMS = CHANNEL_IFACE_SASL_AUTH + ".AvailableMechanisms"
+SASL_STATUS = CHANNEL_IFACE_SASL_AUTH + ".SASLStatus"
+SASL_ERROR = CHANNEL_IFACE_SASL_AUTH + ".SASLError"
+SASL_ERROR_DETAILS = CHANNEL_IFACE_SASL_AUTH + ".SASLErrorDetails"
+SASL_CONTEXT = CHANNEL_IFACE_SASL_AUTH + ".SASLContext"
+SASL_AUTHORIZATION_IDENTITY = CHANNEL_IFACE_SASL_AUTH + ".AuthorizationIdentity"
+SASL_DEFAULT_REALM = CHANNEL_IFACE_SASL_AUTH + ".DefaultRealm"
+SASL_DEFAULT_USERNAME = CHANNEL_IFACE_SASL_AUTH + ".DefaultUsername"
+
+# Channel_Type_ServerTLSConnection
+TLS_CERT_PATH = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ServerCertificate"
+TLS_HOSTNAME = CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".Hostname"
+TLS_REFERENCE_IDENTITIES = \
+ CHANNEL_TYPE_SERVER_TLS_CONNECTION + ".ReferenceIdentities"
+
+# Connection.Interface.Location
+
+LOCATION_FEATURE_CAN_SET = 1
+
+# Channel.Type.Text
+
+MT_NORMAL = 0
+MT_ACTION = 1
+MT_NOTICE = 2
+MT_AUTO_REPLY = 3
+MT_DELIVERY_REPORT = 4
+
+class MessageFlag(object):
+ TRUNCATED = 1
+ NON_TEXT_CONTENT = 2
+ SCROLLBACK = 4
+ RESCUED = 8
+
+class SendError(object):
+ UNKNOWN = 0
+ OFFLINE = 1
+ INVALID_CONTACT = 2
+ PERMISSION_DENIED = 3
+ TOO_LONG = 4
+ NOT_IMPLEMENTED = 5
+
+PROTOCOL = PREFIX + '.Protocol'
+PROTOCOL_IFACE_PRESENCES = PROTOCOL + '.Interface.Presence'
+PROTOCOL_IFACE_ADDRESSING = PROTOCOL + '.Interface.Addressing'
+PROTOCOL_IFACE_AVATARS = PROTOCOL + '.Interface.Avatars'
+
+PARAM_REQUIRED = 1
+PARAM_REGISTER = 2
+PARAM_HAS_DEFAULT = 4
+PARAM_SECRET = 8
+PARAM_DBUS_PROPERTY = 16
+
+AUTHENTICATION = PREFIX + '.Authentication'
+AUTH_TLS_CERT = AUTHENTICATION + ".TLSCertificate"
+
+TLS_CERT_STATE_PENDING = 0
+TLS_CERT_STATE_ACCEPTED = 1
+TLS_CERT_STATE_REJECTED = 2
+
+TLS_REJECT_REASON_UNKNOWN = 0
+TLS_REJECT_REASON_UNTRUSTED = 1
+
+# Channel.Interface.Messages
+
+MESSAGE_PART_SUPPORT_FLAGS = CHANNEL_IFACE_MESSAGES + '.MessagePartSupportFlags'
+DELIVERY_REPORTING_SUPPORT = CHANNEL_IFACE_MESSAGES + '.DeliveryReportingSupport'
+SUPPORTED_CONTENT_TYPES = CHANNEL_IFACE_MESSAGES + '.SupportedContentTypes'
+
+MSG_SENDING_FLAGS_REPORT_DELIVERY = 1
+MSG_SENDING_FLAGS_REPORT_READ = 2
+MSG_SENDING_FLAGS_REPORT_DELETED = 4
+
+DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_FAILURES = 1
+DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_SUCCESSES = 2
+DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_READ = 4
+DELIVERY_REPORTING_SUPPORT_FLAGS_RECEIVE_DELETED = 8
+
+DELIVERY_STATUS_UNKNOWN = 0
+DELIVERY_STATUS_DELIVERED = 1
+DELIVERY_STATUS_TEMPORARILY_FAILED = 2
+DELIVERY_STATUS_PERMANENTLY_FAILED = 3
+DELIVERY_STATUS_ACCEPTED = 4
+DELIVERY_STATUS_READ = 5
+DELIVERY_STATUS_DELETED = 6
+
+MEDIA_STREAM_ERROR_UNKNOWN = 0
+MEDIA_STREAM_ERROR_EOS = 1
+MEDIA_STREAM_ERROR_CODEC_NEGOTIATION_FAILED = 2
+MEDIA_STREAM_ERROR_CONNECTION_FAILED = 3
+MEDIA_STREAM_ERROR_NETWORK_ERROR = 4
+MEDIA_STREAM_ERROR_NO_CODECS = 5
+MEDIA_STREAM_ERROR_INVALID_CM_BEHAVIOR = 6
+MEDIA_STREAM_ERROR_MEDIA_ERROR = 7
+
+PASSWORD_FLAG_PROVIDE = 8
+
+# Channel.Interface.Room
+ROOM_NAME = CHANNEL_IFACE_ROOM + '.RoomName'
+ROOM_SERVER = CHANNEL_IFACE_ROOM + '.Server'
+
+# Channel.Interface.Subject
+SUBJECT = CHANNEL_IFACE_ROOM + '.Subject'
+SUBJECT_PRESENT = 1
+SUBJECT_CAN_SET = 2
+
+DEBUG_IFACE = PREFIX + '.Debug'
+DEBUG_PATH = PATH_PREFIX + '/debug'
+
SERVICE_POINT_TYPE_NONE = 0
SERVICE_POINT_TYPE_EMERGENCY = 1
SERVICE_POINT_TYPE_COUNSELING = 2
-CLIENT = tp_name_prefix + '.Client'
-CLIENT_PATH = tp_path_prefix + '/Client'
-OBSERVER = tp_name_prefix + '.Client.Observer'
-APPROVER = tp_name_prefix + '.Client.Approver'
-HANDLER = tp_name_prefix + '.Client.Handler'
+CLIENT = PREFIX + '.Client'
+CLIENT_PATH = PATH_PREFIX + '/Client'
+OBSERVER = PREFIX + '.Client.Observer'
+APPROVER = PREFIX + '.Client.Approver'
+HANDLER = PREFIX + '.Client.Handler'
CLIENT_IFACE_REQUESTS = CLIENT + '.Interface.Requests'
-ACCOUNT = tp_name_prefix + '.Account'
+ACCOUNT = PREFIX + '.Account'
ACCOUNT_IFACE_AVATAR = ACCOUNT + '.Interface.Avatar'
ACCOUNT_IFACE_ADDRESSING = ACCOUNT + '.Interface.Addressing'
-ACCOUNT_IFACE_HIDDEN = ACCOUNT + '.Interface.Hidden.DRAFT1'
-ACCOUNT_IFACE_NOKIA_CONDITIONS = 'com.nokia.Account.Interface.Conditions'
-ACCOUNT_PATH_PREFIX = tp_path_prefix + '/Account/'
+ACCOUNT_PATH_PREFIX = PATH_PREFIX + '/Account/'
-AM = tp_name_prefix + '.AccountManager'
-AM_IFACE_HIDDEN = AM + '.Interface.Hidden.DRAFT1'
-AM_PATH = tp_path_prefix + '/AccountManager'
+AM = PREFIX + '.AccountManager'
+AM_PATH = PATH_PREFIX + '/AccountManager'
-CR = tp_name_prefix + '.ChannelRequest'
-CDO = tp_name_prefix + '.ChannelDispatchOperation'
+CR = PREFIX + '.ChannelRequest'
+CDO = PREFIX + '.ChannelDispatchOperation'
-CD = tp_name_prefix + '.ChannelDispatcher'
-CD_IFACE_OP_LIST = tp_name_prefix + '.ChannelDispatcher.Interface.OperationList'
-CD_PATH = tp_path_prefix + '/ChannelDispatcher'
+CD = PREFIX + '.ChannelDispatcher'
+CD_IFACE_OP_LIST = PREFIX + '.ChannelDispatcher.Interface.OperationList'
+CD_PATH = PATH_PREFIX + '/ChannelDispatcher'
CD_REDISPATCH = CD + '.Interface.Redispatch.DRAFT'
-MC = tp_name_prefix + '.MissionControl5'
-MC_PATH = tp_path_prefix + '/MissionControl5'
+MC = PREFIX + '.MissionControl5'
+MC_PATH = PATH_PREFIX + '/MissionControl5'
+
+DTMF_CURRENTLY_SENDING_TONES = CHANNEL_IFACE_DTMF + '.CurrentlySendingTones'
+DTMF_INITIAL_TONES = CHANNEL_IFACE_DTMF + '.InitialTones'
+DTMF_DEFERRED_TONES = CHANNEL_IFACE_DTMF + '.DeferredTones'
-TESTDOT = "org.freedesktop.Telepathy.MC.Test."
-TESTSLASH = "/org/freedesktop/Telepathy/MC/Test/"
+TESTDOT = PREFIX + ".Test."
+TESTSLASH = PATH_PREFIX + "/Test/"
TEST_DBUS_ACCOUNT_SERVICE = TESTDOT + "DBusAccountService"
TEST_DBUS_ACCOUNT_SERVICE_PATH = TESTSLASH + "DBusAccountService"
@@ -209,8 +621,8 @@ TEST_DBUS_ACCOUNT_SERVICE_IFACE = TEST_DBUS_ACCOUNT_SERVICE
TEST_DBUS_ACCOUNT_PLUGIN_PATH = TESTSLASH + "DBusAccountPlugin"
TEST_DBUS_ACCOUNT_PLUGIN_IFACE = TESTDOT + "DBusAccountPlugin"
-PARAM_FLAG_REQUIRED = 1
-PARAM_FLAG_REGISTER = 2
-PARAM_FLAG_HAS_DEFAULT = 4
-PARAM_FLAG_SECRET = 8
-PARAM_FLAG_DBUS_PROPERTY = 16
+class StorageRestrictionFlags(object):
+ CANNOT_SET_PARAMETERS = 1
+ CANNOT_SET_ENABLED = 2
+ CANNOT_SET_PRESENCE = 4
+ CANNOT_SET_SERVICE = 8
diff --git a/tests/twisted/crash-recovery/crash-recovery.py b/tests/twisted/crash-recovery/crash-recovery.py
index 2bc45349..1656ab12 100644
--- a/tests/twisted/crash-recovery/crash-recovery.py
+++ b/tests/twisted/crash-recovery/crash-recovery.py
@@ -27,7 +27,7 @@ import dbus.service
from servicetest import EventPattern, call_async
from mctest import exec_test, SimulatedConnection, SimulatedClient, \
- create_fakecm_account, enable_fakecm_account, SimulatedChannel, \
+ SimulatedChannel, \
expect_client_setup, MC
import constants as cs
diff --git a/tests/twisted/dbus-account-plugin.c b/tests/twisted/dbus-account-plugin.c
index 16b1c9c0..79464ed9 100644
--- a/tests/twisted/dbus-account-plugin.c
+++ b/tests/twisted/dbus-account-plugin.c
@@ -23,10 +23,15 @@
#include "config.h"
#include "dbus-account-plugin.h"
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
#define DEBUG(format, ...) g_debug ("%s: " format, G_STRFUNC, ##__VA_ARGS__)
+#define CRITICAL(format, ...) \
+ g_critical ("%s: " format, G_STRFUNC, ##__VA_ARGS__)
-#define TESTDOT "org.freedesktop.Telepathy.MC.Test."
-#define TESTSLASH "/org/freedesktop/Telepathy/MC/Test/"
+#define TESTDOT "org.freedesktop.Telepathy.Test."
+#define TESTSLASH "/org/freedesktop/Telepathy/Test/"
#define TEST_DBUS_ACCOUNT_SERVICE TESTDOT "DBusAccountService"
#define TEST_DBUS_ACCOUNT_SERVICE_PATH TESTSLASH "DBusAccountService"
@@ -51,7 +56,8 @@ typedef struct {
GHashTable *parameter_flags;
/* set of strings */
GHashTable *uncommitted_parameters;
- enum { UNCOMMITTED_CREATION, UNCOMMITTED_DELETION } flags;
+ enum { UNCOMMITTED_CREATION = 1 } flags;
+ TpStorageRestrictionFlags restrictions;
} Account;
static void
@@ -116,29 +122,6 @@ async_data_free (AsyncData *ad)
g_slice_free (AsyncData, ad);
}
-typedef enum {
- EVENT_PARAMS,
- EVENT_ATTRS,
- EVENT_CREATION,
- EVENT_DELETION
-} EventType;
-
-typedef struct {
- EventType type;
- GVariant *args;
-} Event;
-
-static Event *
-event_new (EventType type,
- GVariant *args)
-{
- Event *e = g_slice_new0 (Event);
-
- e->type = type;
- e->args = g_variant_ref_sink (args);
- return e;
-}
-
static Account *
lookup_account (TestDBusAccountPlugin *self,
const gchar *account_name)
@@ -154,7 +137,7 @@ ensure_account (TestDBusAccountPlugin *self,
if (account == NULL)
{
- account = g_slice_new (Account);
+ account = g_slice_new0 (Account);
account->path = g_strdup_printf ("%s%s", TP_ACCOUNT_OBJECT_PATH_BASE,
account_name);
@@ -179,7 +162,6 @@ ensure_account (TestDBusAccountPlugin *self,
g_hash_table_insert (self->accounts, g_strdup (account_name), account);
}
- account->flags &= ~UNCOMMITTED_DELETION;
return account;
}
@@ -207,18 +189,14 @@ service_vanished_cb (GDBusConnection *bus,
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
GHashTableIter iter;
- gpointer k, v;
+ gpointer k;
self->active = FALSE;
g_hash_table_iter_init (&iter, self->accounts);
- while (g_hash_table_iter_next (&iter, &k, &v))
+ while (g_hash_table_iter_next (&iter, &k, NULL))
{
- Account *account = v;
-
- if ((account->flags & UNCOMMITTED_DELETION) == 0)
- mcp_account_storage_emit_deleted (MCP_ACCOUNT_STORAGE (self), k);
-
+ mcp_account_storage_emit_deleted (MCP_ACCOUNT_STORAGE (self), k);
g_hash_table_iter_remove (&iter);
}
@@ -264,7 +242,8 @@ test_dbus_account_plugin_add_account (TestDBusAccountPlugin *self,
GVariant *attribute_flags,
GVariant *parameters,
GVariant *untyped_parameters,
- GVariant *param_flags)
+ GVariant *param_flags,
+ TpStorageRestrictionFlags restrictions)
{
GVariantIter iter;
const gchar *k;
@@ -303,13 +282,21 @@ test_dbus_account_plugin_add_account (TestDBusAccountPlugin *self,
g_hash_table_insert (account->parameter_flags, g_strdup (k),
GUINT_TO_POINTER (u));
+ account->restrictions = restrictions;
+
return account;
}
static void
-test_dbus_account_plugin_process_account_creation (TestDBusAccountPlugin *self,
- GVariant *args)
+account_created_cb (GDBusConnection *bus,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *iface_name,
+ const gchar *signal_name,
+ GVariant *tuple,
+ gpointer user_data)
{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
const gchar *account_name;
Account *account;
GVariant *attrs;
@@ -317,10 +304,12 @@ test_dbus_account_plugin_process_account_creation (TestDBusAccountPlugin *self,
GVariant *untyped_params;
GVariant *attr_flags;
GVariant *param_flags;
+ guint32 restrictions;
- g_variant_get (args, "(&s@a{sv}@a{su}@a{sv}@a{ss}@a{su})",
+ g_variant_get (tuple, "(&s@a{sv}@a{su}@a{sv}@a{ss}@a{su}u)",
&account_name, &attrs, &attr_flags,
- &params, &untyped_params, &param_flags);
+ &params, &untyped_params, &param_flags,
+ &restrictions);
DEBUG ("%s", account_name);
account = lookup_account (self, account_name);
@@ -336,7 +325,7 @@ test_dbus_account_plugin_process_account_creation (TestDBusAccountPlugin *self,
* a lot of rubbish */
account = test_dbus_account_plugin_add_account (self,
account_name, attrs, attr_flags,
- params, untyped_params, param_flags);
+ params, untyped_params, param_flags, restrictions);
mcp_account_storage_emit_created (
MCP_ACCOUNT_STORAGE (self), account_name);
@@ -355,19 +344,25 @@ test_dbus_account_plugin_process_account_creation (TestDBusAccountPlugin *self,
}
static void
-test_dbus_account_plugin_process_account_deletion (TestDBusAccountPlugin *self,
- GVariant *args)
+account_deleted_cb (GDBusConnection *bus,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *iface_name,
+ const gchar *signal_name,
+ GVariant *tuple,
+ gpointer user_data)
{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
const gchar *account_name;
Account *account;
- g_variant_get (args, "(&s)", &account_name);
+ g_variant_get (tuple, "(&s)", &account_name);
DEBUG ("%s", account_name);
account = lookup_account (self, account_name);
if (account == NULL)
{
- g_warning ("accounts service deleted %s but we don't "
+ CRITICAL ("accounts service deleted %s but we don't "
"have any record of that account", account_name);
}
else
@@ -389,23 +384,29 @@ test_dbus_account_plugin_process_account_deletion (TestDBusAccountPlugin *self,
}
static void
-test_dbus_account_plugin_process_attributes (TestDBusAccountPlugin *self,
- GVariant *args)
+attributes_changed_cb (GDBusConnection *bus,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *iface_name,
+ const gchar *signal_name,
+ GVariant *tuple,
+ gpointer user_data)
{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
const gchar *account_name;
Account *account;
GVariant *attrs;
GVariant *attr_flags;
GVariant *deleted;
- g_variant_get (args, "(&s@a{sv}@a{su}@as)",
+ g_variant_get (tuple, "(&s@a{sv}@a{su}@as)",
&account_name, &attrs, &attr_flags, &deleted);
DEBUG ("%s", account_name);
account = lookup_account (self, account_name);
if (account == NULL)
{
- g_warning ("accounts service altered %s but we don't "
+ CRITICAL ("accounts service altered %s but we don't "
"have any record of that account", account_name);
}
else
@@ -439,8 +440,6 @@ test_dbus_account_plugin_process_attributes (TestDBusAccountPlugin *self,
g_hash_table_insert (account->attributes,
g_strdup (attr), g_variant_ref (value));
- mcp_account_manager_set_attribute (self->feedback,
- account_name, attr, value, flags);
mcp_account_storage_emit_altered_one (
MCP_ACCOUNT_STORAGE (self), account_name, attr);
@@ -464,8 +463,6 @@ test_dbus_account_plugin_process_attributes (TestDBusAccountPlugin *self,
DEBUG ("%s deleted", attr);
g_hash_table_remove (account->attributes, attr);
- mcp_account_manager_set_attribute (self->feedback,
- account_name, attr, NULL, 0);
mcp_account_storage_emit_altered_one (
MCP_ACCOUNT_STORAGE (self), account_name, attr);
@@ -499,9 +496,15 @@ test_dbus_account_plugin_process_attributes (TestDBusAccountPlugin *self,
}
static void
-test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
- GVariant *args)
+parameters_changed_cb (GDBusConnection *bus,
+ const gchar *sender_name,
+ const gchar *object_path,
+ const gchar *iface_name,
+ const gchar *signal_name,
+ GVariant *tuple,
+ gpointer user_data)
{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
const gchar *account_name;
Account *account;
GVariant *params;
@@ -509,14 +512,14 @@ test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
GVariant *param_flags;
GVariant *deleted;
- g_variant_get (args, "(&s@a{sv}@a{ss}@a{su}@as)",
+ g_variant_get (tuple, "(&s@a{sv}@a{ss}@a{su}@as)",
&account_name, &params, &untyped_params, &param_flags, &deleted);
DEBUG ("%s", account_name);
account = lookup_account (self, account_name);
if (account == NULL)
{
- g_warning ("accounts service altered %s but we don't "
+ CRITICAL ("accounts service altered %s but we don't "
"have any record of that account", account_name);
}
else
@@ -548,8 +551,6 @@ test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
g_hash_table_insert (account->parameters,
g_strdup (param), g_variant_ref (value));
key = g_strdup_printf ("param-%s", param);
- mcp_account_manager_set_parameter (self->feedback,
- account_name, param, value, flags);
mcp_account_storage_emit_altered_one (
MCP_ACCOUNT_STORAGE (self), account_name, key);
g_free (key);
@@ -577,11 +578,10 @@ test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
(stored == NULL ||
!g_variant_equal (value, stored)))
{
+ g_hash_table_remove (account->parameters, param);
g_hash_table_insert (account->untyped_parameters,
g_strdup (param), g_strdup (escaped));
key = g_strdup_printf ("param-%s", param);
- mcp_account_manager_set_value (self->feedback,
- account_name, key, escaped);
mcp_account_storage_emit_altered_one (
MCP_ACCOUNT_STORAGE (self), account_name, key);
g_free (key);
@@ -611,8 +611,6 @@ test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
g_hash_table_remove (account->untyped_parameters,
param);
key = g_strdup_printf ("param-%s", param);
- mcp_account_manager_set_parameter (self->feedback,
- account_name, param, NULL, 0);
mcp_account_storage_emit_altered_one (
MCP_ACCOUNT_STORAGE (self), account_name, key);
g_free (key);
@@ -633,126 +631,9 @@ test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
g_variant_unref (deleted);
}
-static void
-test_dbus_account_plugin_process_events (TestDBusAccountPlugin *self)
-{
- Event *event;
-
- if (self->feedback == NULL)
- return;
-
- while ((event = g_queue_pop_head (&self->events)) != NULL)
- {
- switch (event->type)
- {
- case EVENT_CREATION:
- test_dbus_account_plugin_process_account_creation (self,
- event->args);
- break;
-
- case EVENT_DELETION:
- test_dbus_account_plugin_process_account_deletion (self,
- event->args);
- break;
-
- case EVENT_ATTRS:
- test_dbus_account_plugin_process_attributes (self,
- event->args);
- break;
-
- case EVENT_PARAMS:
- test_dbus_account_plugin_process_parameters (self,
- event->args);
- break;
- }
-
- g_variant_unref (event->args);
- g_slice_free (Event, event);
- }
-}
-
-static void
-account_created_cb (GDBusConnection *bus,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *iface_name,
- const gchar *signal_name,
- GVariant *tuple,
- gpointer user_data)
-{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
- const gchar *account_name;
-
- g_variant_get (tuple, "(&s@a{sv}@a{su}@a{sv}@a{ss}@a{su})",
- &account_name, NULL, NULL, NULL, NULL, NULL);
- DEBUG ("%s", account_name);
-
- g_queue_push_tail (&self->events, event_new (EVENT_CREATION, tuple));
- test_dbus_account_plugin_process_events (self);
-}
-
-static void
-account_deleted_cb (GDBusConnection *bus,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *iface_name,
- const gchar *signal_name,
- GVariant *tuple,
- gpointer user_data)
-{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
- const gchar *account_name;
-
- g_variant_get (tuple, "(&s)", &account_name);
- DEBUG ("%s", account_name);
-
- g_queue_push_tail (&self->events, event_new (EVENT_DELETION, tuple));
- test_dbus_account_plugin_process_events (self);
-}
-
-static void
-attributes_changed_cb (GDBusConnection *bus,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *iface_name,
- const gchar *signal_name,
- GVariant *tuple,
- gpointer user_data)
-{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
- const gchar *account_name;
-
- g_variant_get (tuple, "(&s@a{sv}@a{su}@as)", &account_name,
- NULL, NULL, NULL);
- DEBUG ("%s", account_name);
-
- g_queue_push_tail (&self->events, event_new (EVENT_ATTRS, tuple));
- test_dbus_account_plugin_process_events (self);
-}
-
-static void
-parameters_changed_cb (GDBusConnection *bus,
- const gchar *sender_name,
- const gchar *object_path,
- const gchar *iface_name,
- const gchar *signal_name,
- GVariant *tuple,
- gpointer user_data)
-{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (user_data);
- const gchar *account_name;
-
- g_variant_get (tuple, "(&s@a{sv}@a{ss}@a{su}@as)", &account_name,
- NULL, NULL, NULL, NULL);
- DEBUG ("%s", account_name);
-
- g_queue_push_tail (&self->events, event_new (EVENT_PARAMS, tuple));
- test_dbus_account_plugin_process_events (self);
-}
-
static GList *
-test_dbus_account_plugin_list (const McpAccountStorage *storage,
- const McpAccountManager *am)
+test_dbus_account_plugin_list (McpAccountStorage *storage,
+ McpAccountManager *am)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
GError *error = NULL;
@@ -762,6 +643,7 @@ test_dbus_account_plugin_list (const McpAccountStorage *storage,
GVariantIter account_iter;
const gchar *account_name;
GList *ret = NULL;
+ guint32 restrictions;
DEBUG ("called");
@@ -820,7 +702,7 @@ test_dbus_account_plugin_list (const McpAccountStorage *storage,
TEST_DBUS_ACCOUNT_SERVICE_IFACE,
"GetAccounts",
NULL, /* no parameters */
- G_VARIANT_TYPE ("(a{s(a{sv}a{su}a{sv}a{ss}a{su})})"),
+ G_VARIANT_TYPE ("(a{s(a{sv}a{su}a{sv}a{ss}a{su}u)})"),
G_DBUS_CALL_FLAGS_NONE,
-1,
NULL, /* no cancellable */
@@ -843,13 +725,13 @@ test_dbus_account_plugin_list (const McpAccountStorage *storage,
g_variant_iter_init (&account_iter, accounts);
while (g_variant_iter_loop (&account_iter,
- "{s(@a{sv}@a{su}@a{sv}@a{ss}@a{su})}", &account_name,
+ "{s(@a{sv}@a{su}@a{sv}@a{ss}@a{su}u)}", &account_name,
&attributes, &attribute_flags,
- &parameters, &untyped_parameters, &param_flags))
+ &parameters, &untyped_parameters, &param_flags, &restrictions))
{
test_dbus_account_plugin_add_account (self, account_name,
attributes, attribute_flags, parameters, untyped_parameters,
- param_flags);
+ param_flags, restrictions);
ret = g_list_prepend (ret, g_strdup (account_name));
}
@@ -859,27 +741,12 @@ test_dbus_account_plugin_list (const McpAccountStorage *storage,
return ret;
}
-static void
-test_dbus_account_plugin_ready (const McpAccountStorage *storage,
- const McpAccountManager *am)
-{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
-
- DEBUG ("called");
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "Ready", NULL, NULL);
- self->feedback = MCP_ACCOUNT_MANAGER (am);
-
- test_dbus_account_plugin_process_events (self);
-}
-
static gchar *
-test_dbus_account_plugin_create (const McpAccountStorage *storage,
- const McpAccountManager *am,
+test_dbus_account_plugin_create (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *manager,
const gchar *protocol,
- GHashTable *params,
+ const gchar *identifier,
GError **error)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
@@ -890,7 +757,7 @@ test_dbus_account_plugin_create (const McpAccountStorage *storage,
return FALSE;
name = mcp_account_manager_get_unique_name ((McpAccountManager *) am,
- manager, protocol, params);
+ manager, protocol, identifier);
account = ensure_account (self, name);
g_dbus_connection_emit_signal (self->bus, NULL,
TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
@@ -898,218 +765,192 @@ test_dbus_account_plugin_create (const McpAccountStorage *storage,
return name;
}
-static gboolean
-test_dbus_account_plugin_delete (const McpAccountStorage *storage,
- const McpAccountManager *am,
+static void delete_account_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data);
+
+static void
+test_dbus_account_plugin_delete_async (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account_name,
- const gchar *key)
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
Account *account = lookup_account (self, account_name);
+ GTask *task = g_task_new (self, cancellable, callback, user_data);
- DEBUG ("called");
-
- if (account == NULL || !self->active)
- return FALSE;
-
- if (key == NULL)
- {
- account->flags |= UNCOMMITTED_DELETION;
- g_hash_table_remove_all (account->attributes);
- g_hash_table_remove_all (account->parameters);
- g_hash_table_remove_all (account->untyped_parameters);
- g_hash_table_remove_all (account->attribute_flags);
- g_hash_table_remove_all (account->parameter_flags);
+ g_task_set_task_data (task, g_strdup (user_data), g_free);
- account->flags &= ~UNCOMMITTED_CREATION;
- g_hash_table_remove_all (account->uncommitted_attributes);
- g_hash_table_remove_all (account->uncommitted_parameters);
-
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "DeferringDelete", g_variant_new_parsed ("(%o,)", account->path),
- NULL);
- }
- else if (g_str_has_prefix (key, "param-"))
- {
- g_hash_table_remove (account->parameters, key + 6);
- g_hash_table_remove (account->untyped_parameters, key + 6);
- g_hash_table_remove (account->parameter_flags, key + 6);
- g_hash_table_add (account->uncommitted_parameters, g_strdup (key + 6));
+ DEBUG ("called");
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "DeferringDeleteParameter",
- g_variant_new_parsed ("(%o, %s)", account->path, key + 6), NULL);
- }
- else
- {
- g_hash_table_remove (account->attributes, key);
- g_hash_table_remove (account->attribute_flags, key);
- g_hash_table_add (account->uncommitted_attributes, g_strdup (key));
+ g_return_if_fail (self->active);
+ g_return_if_fail (account != NULL);
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "DeferringDeleteAttribute",
- g_variant_new_parsed ("(%o, %s)", account->path, key), NULL);
- }
+ /* deletion used to be delayed, so the regression tests will expect this
+ * to happen - leave them unmodified for now */
+ g_dbus_connection_emit_signal (self->bus, NULL,
+ TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
+ "DeferringDelete", g_variant_new_parsed ("(%o,)", account->path),
+ NULL);
+ g_dbus_connection_emit_signal (self->bus, NULL,
+ TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
+ "CommittingOne", g_variant_new_parsed ("(%o,)", account->path), NULL);
- return TRUE;
+ g_dbus_connection_call (self->bus,
+ TEST_DBUS_ACCOUNT_SERVICE,
+ TEST_DBUS_ACCOUNT_SERVICE_PATH,
+ TEST_DBUS_ACCOUNT_SERVICE_IFACE,
+ "DeleteAccount",
+ g_variant_new_parsed ("(%s,)", account_name),
+ G_VARIANT_TYPE_UNIT,
+ G_DBUS_CALL_FLAGS_NONE,
+ -1,
+ NULL, /* no cancellable */
+ delete_account_cb,
+ task);
}
static gboolean
-test_dbus_account_plugin_get (const McpAccountStorage *storage,
- const McpAccountManager *am,
+test_dbus_account_plugin_delete_finish (McpAccountStorage *storage,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
+
+static GVariant *
+test_dbus_account_plugin_get_attribute (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account_name,
- const gchar *key)
+ const gchar *attribute,
+ const GVariantType *type,
+ McpAttributeFlags *flags)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
Account *account = lookup_account (self, account_name);
+ GVariant *v;
- if (!self->active || account == NULL || (account->flags & UNCOMMITTED_DELETION))
- return FALSE;
-
- if (key == NULL)
- {
- GHashTableIter iter;
- gpointer k, v;
-
- /* get everything */
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "GetAllKeys",
- g_variant_new_parsed ("(%o,)", account->path), NULL);
-
- g_hash_table_iter_init (&iter, account->attributes);
-
- while (g_hash_table_iter_next (&iter, &k, &v))
- {
- gchar *escaped = mcp_account_manager_escape_variant_for_keyfile (am,
- v);
+ if (flags != NULL)
+ *flags = 0;
- mcp_account_manager_set_value (am, account_name, k, escaped);
- g_free (escaped);
- }
+ g_return_val_if_fail (self->active, NULL);
+ g_return_val_if_fail (account != NULL, NULL);
- g_hash_table_iter_init (&iter, account->untyped_parameters);
+ v = g_hash_table_lookup (account->attributes, attribute);
- while (g_hash_table_iter_next (&iter, &k, &v))
- {
- gchar *param_foo;
- McpParameterFlags flags;
-
- param_foo = g_strdup_printf ("param-%s", (const gchar *) k);
- mcp_account_manager_set_value (am, account_name, param_foo, v);
+ g_dbus_connection_emit_signal (self->bus, NULL,
+ TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
+ "GetAttribute",
+ g_variant_new_parsed ("(%o, %s)", account->path, attribute), NULL);
- flags = GPOINTER_TO_UINT (g_hash_table_lookup (
- account->parameter_flags, k));
+ if (v != NULL)
+ {
+ return g_variant_ref (v);
+ }
+ else
+ {
+ return NULL;
+ }
+}
- if (flags & MCP_PARAMETER_FLAG_SECRET)
- mcp_account_manager_parameter_make_secret (am, account_name,
- param_foo);
+static GVariant *
+test_dbus_account_plugin_get_parameter (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account_name,
+ const gchar *parameter,
+ const GVariantType *type,
+ McpParameterFlags *flags)
+{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
+ Account *account = lookup_account (self, account_name);
+ GVariant *v;
+ const gchar *s;
- g_free (param_foo);
- }
+ if (flags != NULL)
+ *flags = 0;
- g_hash_table_iter_init (&iter, account->parameters);
+ g_return_val_if_fail (self->active, NULL);
+ g_return_val_if_fail (account != NULL, NULL);
- while (g_hash_table_iter_next (&iter, &k, &v))
- {
- gchar *param_foo;
- guint32 flags;
- gchar *escaped = mcp_account_manager_escape_variant_for_keyfile (am,
- v);
+ g_dbus_connection_emit_signal (self->bus, NULL,
+ TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
+ "GetParameter",
+ g_variant_new_parsed ("(%o, %s)", account->path, parameter), NULL);
- param_foo = g_strdup_printf ("param-%s", (const gchar *) k);
- mcp_account_manager_set_value (am, account_name, param_foo, escaped);
- g_free (escaped);
+ v = g_hash_table_lookup (account->parameters, parameter);
+ s = g_hash_table_lookup (account->untyped_parameters, parameter);
- flags = GPOINTER_TO_UINT (g_hash_table_lookup (account->parameter_flags,
- k));
+ if (v != NULL)
+ {
+ return g_variant_ref (v);
+ }
+ else if (s != NULL && type != NULL)
+ {
+ return mcp_account_manager_unescape_variant_from_keyfile (am,
+ s, type, NULL);
+ }
+ else
+ {
+ return NULL;
+ }
+}
- if (flags & MCP_PARAMETER_FLAG_SECRET)
- mcp_account_manager_parameter_make_secret (am, account_name,
- param_foo);
+static gchar **
+test_dbus_account_plugin_list_typed_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account_name)
+{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
+ Account *account = lookup_account (self, account_name);
+ GPtrArray *arr;
+ GHashTableIter iter;
+ gpointer k;
- g_free (param_foo);
- }
+ g_return_val_if_fail (self->active, NULL);
+ g_return_val_if_fail (account != NULL, NULL);
- return TRUE;
- }
+ arr = g_ptr_array_sized_new (g_hash_table_size (account->parameters) + 1);
- /* get one parameter */
+ g_hash_table_iter_init (&iter, account->parameters);
- if (g_str_has_prefix (key, "param-"))
- {
- GVariant *v = g_hash_table_lookup (account->parameters, key + 6);
- const gchar *s = g_hash_table_lookup (account->untyped_parameters, key + 6);
- guint32 flags = GPOINTER_TO_UINT (
- g_hash_table_lookup (account->parameter_flags, key + 6));
+ while (g_hash_table_iter_next (&iter, &k, NULL))
+ g_ptr_array_add (arr, g_strdup (k));
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "GetParameter",
- g_variant_new_parsed ("(%o, %s)", account->path, key + 6), NULL);
+ g_ptr_array_add (arr, NULL);
- if (flags & MCP_PARAMETER_FLAG_SECRET)
- mcp_account_manager_parameter_make_secret (am, account_name, key);
+ return (gchar **) g_ptr_array_free (arr, FALSE);
+}
- if (v != NULL)
- {
- gchar *escaped = mcp_account_manager_escape_variant_for_keyfile (am,
- v);
+static gchar **
+test_dbus_account_plugin_list_untyped_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account_name)
+{
+ TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
+ Account *account = lookup_account (self, account_name);
+ GPtrArray *arr;
+ GHashTableIter iter;
+ gpointer k;
- mcp_account_manager_set_value (am, account_name, key, escaped);
- g_free (escaped);
- }
- else if (s != NULL)
- {
- mcp_account_manager_set_value (am, account_name, key, s);
- }
- else
- {
- return FALSE;
- }
- }
- else
- {
- GVariant *v = g_hash_table_lookup (account->attributes, key);
+ g_return_val_if_fail (self->active, NULL);
+ g_return_val_if_fail (account != NULL, NULL);
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "GetAttribute",
- g_variant_new_parsed ("(%o, %s)", account->path, key), NULL);
+ arr = g_ptr_array_sized_new (
+ g_hash_table_size (account->untyped_parameters) + 1);
- if (v != NULL)
- {
- gchar *escaped = mcp_account_manager_escape_variant_for_keyfile (am,
- v);
+ g_hash_table_iter_init (&iter, account->untyped_parameters);
- mcp_account_manager_set_value (am, account_name, key, escaped);
- g_free (escaped);
- }
- else
- {
- return FALSE;
- }
- }
+ while (g_hash_table_iter_next (&iter, &k, NULL))
+ g_ptr_array_add (arr, g_strdup (k));
- return TRUE;
-}
+ g_ptr_array_add (arr, NULL);
-static gboolean
-test_dbus_account_plugin_set (const McpAccountStorage *storage,
- const McpAccountManager *am,
- const gchar *account_name,
- const gchar *key,
- const gchar *value)
-{
- /* Now that we implement set_attribute and set_parameter, this no longer
- * needs a real implementation. */
- return FALSE;
+ return (gchar **) g_ptr_array_free (arr, FALSE);
}
-static gboolean
+static McpAccountStorageSetResult
test_dbus_account_plugin_set_attribute (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account_name,
@@ -1119,17 +960,40 @@ test_dbus_account_plugin_set_attribute (McpAccountStorage *storage,
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
Account *account = lookup_account (self, account_name);
+ GVariant *old;
+ guint old_flags;
g_return_val_if_fail (account_name != NULL, FALSE);
g_return_val_if_fail (attribute != NULL, FALSE);
- /* for deletions, MC would call delete() instead */
- g_return_val_if_fail (value != NULL, FALSE);
DEBUG ("%s of %s", attribute, account_name);
- if (!self->active || account == NULL ||
- (account->flags & UNCOMMITTED_DELETION))
- return FALSE;
+ g_return_val_if_fail (self->active, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+ g_return_val_if_fail (account != NULL, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+
+ if (value == NULL)
+ {
+ if (!g_hash_table_contains (account->attributes, attribute))
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
+
+ g_hash_table_remove (account->attributes, attribute);
+ g_hash_table_remove (account->attribute_flags, attribute);
+ g_hash_table_add (account->uncommitted_attributes, g_strdup (attribute));
+
+ g_dbus_connection_emit_signal (self->bus, NULL,
+ TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
+ "DeferringDeleteAttribute",
+ g_variant_new_parsed ("(%o, %s)", account->path, attribute), NULL);
+
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED;
+ }
+
+ old = g_hash_table_lookup (account->attributes, attribute);
+ old_flags = GPOINTER_TO_UINT (g_hash_table_lookup (
+ account->attribute_flags, attribute));
+
+ if (old != NULL && g_variant_equal (old, value) && old_flags == flags)
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
g_hash_table_insert (account->attributes, g_strdup (attribute),
g_variant_ref (value));
@@ -1143,10 +1007,10 @@ test_dbus_account_plugin_set_attribute (McpAccountStorage *storage,
g_variant_new_parsed ("(%o, %s, %v)", account->path, attribute, value),
NULL);
- return TRUE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED;
}
-static gboolean
+static McpAccountStorageSetResult
test_dbus_account_plugin_set_parameter (McpAccountStorage *storage,
McpAccountManager *am,
const gchar *account_name,
@@ -1156,17 +1020,42 @@ test_dbus_account_plugin_set_parameter (McpAccountStorage *storage,
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
Account *account = lookup_account (self, account_name);
+ GVariant *old;
+ guint old_flags;
g_return_val_if_fail (account_name != NULL, FALSE);
g_return_val_if_fail (parameter != NULL, FALSE);
- /* for deletions, MC would call delete() instead */
- g_return_val_if_fail (value != NULL, FALSE);
DEBUG ("%s of %s", parameter, account_name);
- if (!self->active || account == NULL ||
- (account->flags & UNCOMMITTED_DELETION))
- return FALSE;
+ g_return_val_if_fail (self->active, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+ g_return_val_if_fail (account != NULL, MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED);
+
+ if (value == NULL)
+ {
+ if (!g_hash_table_contains (account->parameters, parameter) &&
+ !g_hash_table_contains (account->untyped_parameters, parameter))
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
+
+ g_hash_table_remove (account->parameters, parameter);
+ g_hash_table_remove (account->untyped_parameters, parameter);
+ g_hash_table_remove (account->parameter_flags, parameter);
+ g_hash_table_add (account->uncommitted_parameters, g_strdup (parameter));
+
+ g_dbus_connection_emit_signal (self->bus, NULL,
+ TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
+ "DeferringDeleteParameter",
+ g_variant_new_parsed ("(%o, %s)", account->path, parameter), NULL);
+
+ return TRUE;
+ }
+
+ old = g_hash_table_lookup (account->parameters, parameter);
+ old_flags = GPOINTER_TO_UINT (g_hash_table_lookup (
+ account->parameter_flags, parameter));
+
+ if (old != NULL && g_variant_equal (old, value) && old_flags == flags)
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
g_hash_table_remove (account->untyped_parameters, parameter);
g_hash_table_insert (account->parameters, g_strdup (parameter),
@@ -1181,37 +1070,7 @@ test_dbus_account_plugin_set_parameter (McpAccountStorage *storage,
g_variant_new_parsed ("(%o, %s, %v)", account->path, parameter, value),
NULL);
- return TRUE;
-}
-
-static gboolean
-test_dbus_account_plugin_commit (const McpAccountStorage *storage,
- const McpAccountManager *am)
-{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
- GHashTableIter iter;
- gpointer k;
-
- DEBUG ("called");
-
- if (!self->active)
- return FALSE;
-
- g_dbus_connection_emit_signal (self->bus, NULL,
- TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
- "CommittingAll", NULL, NULL);
-
- g_hash_table_iter_init (&iter, self->accounts);
-
- while (g_hash_table_iter_next (&iter, &k, NULL))
- {
- if (!mcp_account_storage_commit_one (storage, am, k))
- {
- g_warning ("declined to commit account %s", (const gchar *) k);
- }
- }
-
- return TRUE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED;
}
static void
@@ -1219,27 +1078,31 @@ delete_account_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
- AsyncData *ad = user_data;
+ GTask *task = user_data;
GVariant *tuple;
GError *error = NULL;
+ TestDBusAccountPlugin *self = g_task_get_source_object (task);
+ const gchar *account_name = g_task_get_task_data (task);
- tuple = g_dbus_connection_call_finish (ad->self->bus, res, &error);
+ tuple = g_dbus_connection_call_finish (self->bus, res, &error);
if (tuple != NULL)
{
- g_hash_table_remove (ad->self->accounts, ad->account_name);
+ /* we'll emit ::deleted when we see the signal, which probably
+ * already happened */
+ g_hash_table_remove (self->accounts, account_name);
g_variant_unref (tuple);
+ g_task_return_boolean (task, TRUE);
}
else
{
- g_warning ("Unable to delete account %s: %s", ad->account_name,
- error->message);
- g_clear_error (&error);
- /* FIXME: we could roll back the deletion by claiming that
- * the service re-created the account? */
+ g_prefix_error (&error, "Unable to delete account %s: ",
+ account_name);
+ g_warning ("%s", error->message);
+ g_task_return_error (task, error);
}
- async_data_free (ad);
+ g_object_unref (task);
}
static void
@@ -1345,12 +1208,12 @@ update_parameters_cb (GObject *source_object,
}
static gboolean
-test_dbus_account_plugin_commit_one (const McpAccountStorage *storage,
- const McpAccountManager *am,
+test_dbus_account_plugin_commit (McpAccountStorage *storage,
+ McpAccountManager *am,
const gchar *account_name)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
- Account *account = lookup_account (self, account_name);
+ Account *account;
GHashTableIter iter;
gpointer k;
GVariantBuilder a_sv_builder;
@@ -1360,36 +1223,15 @@ test_dbus_account_plugin_commit_one (const McpAccountStorage *storage,
DEBUG ("%s", account_name);
- /* MC does not call @commit_one with parameter %NULL (meaning "all accounts")
- * if we also implement commit(), which, as it happens, we do */
- g_return_val_if_fail (account_name != NULL, FALSE);
+ account = lookup_account (self, account_name);
- if (!self->active || account == NULL)
- return FALSE;
+ g_return_val_if_fail (self->active, FALSE);
+ g_return_val_if_fail (account != NULL, FALSE);
g_dbus_connection_emit_signal (self->bus, NULL,
TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
"CommittingOne", g_variant_new_parsed ("(%o,)", account->path), NULL);
- if (account->flags & UNCOMMITTED_DELETION)
- {
- g_dbus_connection_call (self->bus,
- TEST_DBUS_ACCOUNT_SERVICE,
- TEST_DBUS_ACCOUNT_SERVICE_PATH,
- TEST_DBUS_ACCOUNT_SERVICE_IFACE,
- "DeleteAccount",
- g_variant_new_parsed ("(%s,)", account_name),
- G_VARIANT_TYPE_UNIT,
- G_DBUS_CALL_FLAGS_NONE,
- -1,
- NULL, /* no cancellable */
- delete_account_cb,
- async_data_new (self, account_name));
-
- /* this doesn't mean we succeeded: it means we tried */
- return TRUE;
- }
-
if (account->flags & UNCOMMITTED_CREATION)
{
g_dbus_connection_call (self->bus,
@@ -1516,7 +1358,7 @@ test_dbus_account_plugin_commit_one (const McpAccountStorage *storage,
}
static void
-test_dbus_account_plugin_get_identifier (const McpAccountStorage *storage,
+test_dbus_account_plugin_get_identifier (McpAccountStorage *storage,
const gchar *account_name,
GValue *identifier)
{
@@ -1525,8 +1367,8 @@ test_dbus_account_plugin_get_identifier (const McpAccountStorage *storage,
DEBUG ("%s", account_name);
- if (!self->active || account == NULL || (account->flags & UNCOMMITTED_DELETION))
- return;
+ g_return_if_fail (self->active);
+ g_return_if_fail (account != NULL);
/* Our "library-specific unique identifier" is just the object-path
* as a string. */
@@ -1535,7 +1377,7 @@ test_dbus_account_plugin_get_identifier (const McpAccountStorage *storage,
}
static GHashTable *
-test_dbus_account_plugin_get_additional_info (const McpAccountStorage *storage,
+test_dbus_account_plugin_get_additional_info (McpAccountStorage *storage,
const gchar *account_name)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
@@ -1544,8 +1386,8 @@ test_dbus_account_plugin_get_additional_info (const McpAccountStorage *storage,
DEBUG ("%s", account_name);
- if (!self->active || account == NULL || (account->flags & UNCOMMITTED_DELETION))
- return NULL;
+ g_return_val_if_fail (self->active, NULL);
+ g_return_val_if_fail (account != NULL, NULL);
ret = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, (GDestroyNotify) tp_g_value_slice_free);
@@ -1556,7 +1398,7 @@ test_dbus_account_plugin_get_additional_info (const McpAccountStorage *storage,
}
static guint
-test_dbus_account_plugin_get_restrictions (const McpAccountStorage *storage,
+test_dbus_account_plugin_get_restrictions (McpAccountStorage *storage,
const gchar *account_name)
{
TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
@@ -1564,27 +1406,17 @@ test_dbus_account_plugin_get_restrictions (const McpAccountStorage *storage,
DEBUG ("%s", account_name);
- if (!self->active || account == NULL || (account->flags & UNCOMMITTED_DELETION))
- return 0;
+ g_return_val_if_fail (self->active, 0);
+ g_return_val_if_fail (account != NULL, 0);
- /* FIXME: actually enforce this restriction */
- return TP_STORAGE_RESTRICTION_FLAG_CANNOT_SET_SERVICE;
+ return account->restrictions;
}
-static gboolean
-test_dbus_account_plugin_owns (McpAccountStorage *storage,
- McpAccountManager *am,
- const gchar *account_name)
+static McpAccountStorageFlags
+test_dbus_account_plugin_get_flags (McpAccountStorage *storage,
+ const gchar *account)
{
- TestDBusAccountPlugin *self = TEST_DBUS_ACCOUNT_PLUGIN (storage);
- Account *account = lookup_account (self, account_name);
-
- DEBUG ("%s", account_name);
-
- if (!self->active || account == NULL || (account->flags & UNCOMMITTED_DELETION))
- return FALSE;
-
- return TRUE;
+ return MCP_ACCOUNT_STORAGE_FLAG_STORES_TYPES;
}
static void
@@ -1595,18 +1427,21 @@ account_storage_iface_init (McpAccountStorageIface *iface)
/* this should be higher priority than the diverted-keyfile one */
iface->priority = MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_NORMAL + 100;
- iface->get = test_dbus_account_plugin_get;
- iface->set = test_dbus_account_plugin_set;
+ iface->get_flags = test_dbus_account_plugin_get_flags;
+ iface->get_attribute = test_dbus_account_plugin_get_attribute;
+ iface->get_parameter = test_dbus_account_plugin_get_parameter;
+ iface->list_typed_parameters =
+ test_dbus_account_plugin_list_typed_parameters;
+ iface->list_untyped_parameters =
+ test_dbus_account_plugin_list_untyped_parameters;
iface->set_attribute = test_dbus_account_plugin_set_attribute;
iface->set_parameter = test_dbus_account_plugin_set_parameter;
iface->list = test_dbus_account_plugin_list;
- iface->ready = test_dbus_account_plugin_ready;
- iface->delete = test_dbus_account_plugin_delete;
+ iface->delete_async = test_dbus_account_plugin_delete_async;
+ iface->delete_finish = test_dbus_account_plugin_delete_finish;
iface->commit = test_dbus_account_plugin_commit;
- iface->commit_one = test_dbus_account_plugin_commit_one;
iface->get_identifier = test_dbus_account_plugin_get_identifier;
iface->get_additional_info = test_dbus_account_plugin_get_additional_info;
iface->get_restrictions = test_dbus_account_plugin_get_restrictions;
iface->create = test_dbus_account_plugin_create;
- iface->owns = test_dbus_account_plugin_owns;
}
diff --git a/tests/twisted/dispatcher/already-has-channel.py b/tests/twisted/dispatcher/already-has-channel.py
index 547acdf2..6b666e12 100644
--- a/tests/twisted/dispatcher/already-has-channel.py
+++ b/tests/twisted/dispatcher/already-has-channel.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
text_fixed_properties = dbus.Dictionary({
cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
@@ -68,25 +68,19 @@ def test(q, bus, mc):
interface=cs.tp_name_prefix + '.ConnectionManager',
handled=False)
- # Don't allow the Connection to become ready until we want it to, by
- # avoiding a return from GetInterfaces
+ # Don't allow the Connection to have its list of channels
+ # until we want it to, by avoiding a return from GetAll(Requests).
conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
- 'myself', implement_get_interfaces=False)
-
+ 'myself', implement_get_channels=False)
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
- # this is the pre-Connect one
- e = q.expect('dbus-method-call', method='GetInterfaces',
- path=conn.object_path, handled=False)
- q.dbus_raise(e.message, cs.DISCONNECTED, 'Not connected yet')
+ get_all_requests_call = q.expect('dbus-method-call',
+ method='GetAll', args=[cs.CONN_IFACE_REQUESTS])
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
-
- get_interfaces_call = q.expect('dbus-method-call', method='GetInterfaces',
- path=conn.object_path, handled=False)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# subscribe to the OperationList interface (MC assumes that until this
# property has been retrieved once, nobody cares)
@@ -95,7 +89,7 @@ def test(q, bus, mc):
cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
- # Before returning from GetInterfaces, make a Channel spring into
+ # Before returning from GetAll(Requests), make a Channel spring into
# existence
channel_properties = dbus.Dictionary(text_fixed_properties,
@@ -112,8 +106,8 @@ def test(q, bus, mc):
chan = SimulatedChannel(conn, channel_properties)
chan.announce()
- # Now reply to GetInterfaces and say we have Requests
- conn.GetInterfaces(get_interfaces_call)
+ # Now reply to GetAll(Requests)
+ conn.GetAll_Requests(get_all_requests_call)
# A channel dispatch operation is created for the channel we already had
diff --git a/tests/twisted/dispatcher/already-has-obsolete.py b/tests/twisted/dispatcher/already-has-obsolete.py
deleted file mode 100644
index 05dcb115..00000000
--- a/tests/twisted/dispatcher/already-has-obsolete.py
+++ /dev/null
@@ -1,221 +0,0 @@
-# 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
-
-import dbus
-"""Regression test for dispatching an incoming Text channel that was already
-there before the Connection became ready.
-"""
-
-import dbus
-import dbus.service
-
-from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
- call_async
-from mctest import exec_test, SimulatedConnection, SimulatedClient, \
- create_fakecm_account, SimulatedChannel, expect_client_setup
-import constants as cs
-
-def test(q, bus, mc):
- params = dbus.Dictionary({"account": "someguy@example.com",
- "password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
-
- text_fixed_properties = dbus.Dictionary({
- cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
- }, signature='sv')
-
- # Two clients want to observe, approve and handle channels
- 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)
-
- # wait for MC to download the properties
- expect_client_setup(q, [empathy, kopete])
-
- # Enable the account
- account.Set(cs.ACCOUNT, 'Enabled', True,
- dbus_interface=cs.PROPERTIES_IFACE)
-
- requested_presence = dbus.Struct((dbus.UInt32(2L),
- dbus.String(u'available'), dbus.String(u'')))
- account.Set(cs.ACCOUNT,
- 'RequestedPresence', requested_presence,
- dbus_interface=cs.PROPERTIES_IFACE)
-
- e = q.expect('dbus-method-call', method='RequestConnection',
- args=['fakeprotocol', params],
- destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
- path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
- interface=cs.tp_name_prefix + '.ConnectionManager',
- handled=False)
-
- # Don't allow the Connection to become ready until we want it to, by
- # avoiding a return from GetInterfaces
- conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
- 'myself', implement_get_interfaces=False, has_requests=False)
-
- q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
-
- # this is the pre-Connect one
- e = q.expect('dbus-method-call', method='GetInterfaces',
- path=conn.object_path, handled=False)
- q.dbus_raise(e.message, cs.DISCONNECTED, 'Not connected yet')
-
- q.expect('dbus-method-call', method='Connect',
- path=conn.object_path, handled=True)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
-
- get_interfaces_call = q.expect('dbus-method-call', method='GetInterfaces',
- path=conn.object_path, handled=False)
-
- # subscribe to the OperationList interface (MC assumes that until this
- # property has been retrieved once, nobody cares)
-
- cd = bus.get_object(cs.CD, cs.CD_PATH)
- cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
- assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
-
- # Before returning from GetInterfaces, make a Channel spring into
- # existence
-
- channel_properties = dbus.Dictionary(text_fixed_properties,
- signature='sv')
- channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet'
- channel_properties[cs.CHANNEL + '.TargetHandle'] = \
- conn.ensure_handle(cs.HT_CONTACT, 'juliet')
- channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet'
- channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
- conn.ensure_handle(cs.HT_CONTACT, 'juliet')
- channel_properties[cs.CHANNEL + '.Requested'] = False
- channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')
-
- chan = SimulatedChannel(conn, channel_properties)
- chan.announce()
-
- # Now reply to GetInterfaces and say we don't have Requests
- conn.GetInterfaces(get_interfaces_call)
- q.expect('dbus-method-call',
- interface=cs.CONN, method='ListChannels', args=[],
- path=conn.object_path, handled=True)
-
- # A channel dispatch operation is created for the channel we already had
-
- e = q.expect('dbus-signal',
- path=cs.CD_PATH,
- interface=cs.CD_IFACE_OP_LIST,
- signal='NewDispatchOperation')
-
- cdo_path = e.args[0]
- cdo_properties = e.args[1]
-
- assert cdo_properties[cs.CDO + '.Account'] == account.object_path
- assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
-
- handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
- handlers.sort()
- assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
- cs.tp_name_prefix + '.Client.Kopete'], handlers
-
- assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
- assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
- [(cdo_path, cdo_properties)]
-
- cdo = bus.get_object(cs.CD, cdo_path)
- cdo_iface = dbus.Interface(cdo, cs.CDO)
-
- # Both Observers are told about the new channel
-
- 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] == cdo_path, e.args
- assert e.args[4] == [], e.args # no requests satisfied
- channels = e.args[2]
- assert len(channels) == 1, channels
- assert channels[0][0] == chan.object_path, channels
-
- assert k.args == e.args
-
- # Both Observers indicate that they are ready to proceed
- q.dbus_return(k.message, signature='')
- q.dbus_return(e.message, signature='')
-
- # The Approvers are next
-
- e, k = q.expect_many(
- EventPattern('dbus-method-call',
- path=empathy.object_path,
- interface=cs.APPROVER, method='AddDispatchOperation',
- handled=False),
- EventPattern('dbus-method-call',
- path=kopete.object_path,
- interface=cs.APPROVER, method='AddDispatchOperation',
- handled=False),
- )
-
- assert len(e.args) == 3
- assert len(e.args[0]) == 1
- assert e.args[0][0][0] == chan.object_path
- assert e.args[1] == cdo_path
- assert e.args[2] == cdo_properties
- assert k.args == e.args
-
- q.dbus_return(e.message, signature='')
- q.dbus_return(k.message, signature='')
-
- # Both Approvers now have a flashing icon or something, trying to get the
- # user's attention
-
- # The user responds to Empathy first
- call_async(q, cdo_iface, 'HandleWith',
- cs.tp_name_prefix + '.Client.Empathy')
-
- # Empathy is asked to handle the channels
- e = q.expect('dbus-method-call',
- path=empathy.object_path,
- interface=cs.HANDLER, method='HandleChannels',
- handled=False)
-
- # Empathy accepts the channels
- q.dbus_return(e.message, signature='')
-
- q.expect_many(
- EventPattern('dbus-return', method='HandleWith'),
- EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
- EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
- signal='DispatchOperationFinished'),
- )
-
- # Now there are no more active channel dispatch operations
- assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
-
-if __name__ == '__main__':
- exec_test(test, {})
diff --git a/tests/twisted/dispatcher/approver-fails.py b/tests/twisted/dispatcher/approver-fails.py
index 67ce36a3..b8705bb7 100644
--- a/tests/twisted/dispatcher/approver-fails.py
+++ b/tests/twisted/dispatcher/approver-fails.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/bypass-approval.py b/tests/twisted/dispatcher/bypass-approval.py
index 0655a9a9..eddb3155 100644
--- a/tests/twisted/dispatcher/bypass-approval.py
+++ b/tests/twisted/dispatcher/bypass-approval.py
@@ -181,7 +181,7 @@ def expect_and_exercise_approval(q, bus, chan, channel_properties,
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
# Two clients want to observe, approve and handle channels. Additionally,
diff --git a/tests/twisted/dispatcher/bypass-observers.py b/tests/twisted/dispatcher/bypass-observers.py
deleted file mode 100644
index d8b02660..00000000
--- a/tests/twisted/dispatcher/bypass-observers.py
+++ /dev/null
@@ -1,291 +0,0 @@
-# Copyright (C) 2009-2010 Nokia Corporation
-# Copyright (C) 2009-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
-
-import dbus
-"""Regression test for dispatching an incoming Text channel with bypassed
-observers.
-"""
-
-import dbus
-import dbus.service
-
-from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
- call_async, sync_dbus, assertEquals, assertLength, assertContains
-from mctest import exec_test, SimulatedConnection, SimulatedClient, \
- create_fakecm_account, enable_fakecm_account, SimulatedChannel, \
- expect_client_setup
-import constants as cs
-
-text_fixed_properties = dbus.Dictionary({
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
- }, signature='sv')
-contact_text_fixed_properties = dbus.Dictionary({
- cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
- }, signature='sv')
-secret_fixed_properties = dbus.Dictionary({
- cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
- 'com.example.Secrecy.Secret': True,
- }, signature='sv')
-
-def announce_common(q, bus, empathy, kopete, account, conn, cd_props,
- secret=False):
- if secret:
- jid = 'friar.lawrence'
- else:
- jid = 'juliet'
-
- channel_properties = dbus.Dictionary(contact_text_fixed_properties,
- signature='sv')
- channel_properties[cs.CHANNEL + '.TargetID'] = jid
- channel_properties[cs.CHANNEL + '.TargetHandle'] = \
- conn.ensure_handle(cs.HT_CONTACT, jid)
- channel_properties[cs.CHANNEL + '.InitiatorID'] = jid
- channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
- conn.ensure_handle(cs.HT_CONTACT, jid)
- channel_properties[cs.CHANNEL + '.Requested'] = False
- channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')
-
- if secret:
- channel_properties['com.example.Secrecy.Secret'] = True
-
- chan = SimulatedChannel(conn, channel_properties)
- chan.announce()
-
- # A channel dispatch operation is created
-
- e = q.expect('dbus-signal',
- path=cs.CD_PATH,
- interface=cs.CD_IFACE_OP_LIST,
- signal='NewDispatchOperation')
-
- cdo_path = e.args[0]
- cdo_properties = e.args[1]
-
- assertEquals(cdo_properties[cs.CDO + '.Account'], account.object_path)
- assertEquals(cdo_properties[cs.CDO + '.Connection'], conn.object_path)
- assertContains(cs.CDO + '.Interfaces', cdo_properties)
-
- handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
-
- if secret:
- # The handler with BypassApproval is first
- assertEquals(cs.tp_name_prefix + '.Client.Kopete.Bypasser',
- handlers[0])
- else:
- handlers.sort()
- assertEquals([cs.tp_name_prefix + '.Client.Empathy',
- cs.tp_name_prefix + '.Client.Kopete'], handlers)
-
- assertContains(cs.CD_IFACE_OP_LIST, cd_props.Get(cs.CD, 'Interfaces'))
-
- assertEquals([(cdo_path, cdo_properties)],
- cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations'))
-
- cdo = bus.get_object(cs.CD, cdo_path)
- cdo_iface = dbus.Interface(cdo, cs.CDO)
-
- # Both Observers are told about the new channel
-
- if secret:
- observe_events = []
- else:
- 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),
- )
- assertEquals(account.object_path, e.args[0])
- assertEquals(conn.object_path, e.args[1])
- assertEquals(cdo_path, e.args[3])
- assertEquals([], e.args[4]) # no requests satisfied
- channels = e.args[2]
- assertLength(1, channels)
- assertEquals(chan.object_path, channels[0][0])
- assertEquals(channel_properties, channels[0][1])
-
- assertEquals(k.args, e.args)
- observe_events = [e, k]
-
- return cdo_iface, chan, channel_properties, observe_events
-
-def expect_and_exercise_approval(q, bus, chan, channel_properties,
- empathy, kopete, cdo_iface, cd_props):
- # The Approvers are next
-
- e, k = q.expect_many(
- EventPattern('dbus-method-call',
- path=empathy.object_path,
- interface=cs.APPROVER, method='AddDispatchOperation',
- handled=False),
- EventPattern('dbus-method-call',
- path=kopete.object_path,
- interface=cs.APPROVER, method='AddDispatchOperation',
- handled=False),
- )
-
- assertEquals([(chan.object_path, channel_properties)], e.args[0])
- assertEquals(k.args, e.args)
-
- # Both Approvers indicate that they are ready to proceed
- q.dbus_return(e.message, signature='')
- q.dbus_return(k.message, signature='')
-
- # Both Approvers now have a flashing icon or something, trying to get the
- # user's attention
-
- # The user responds to Kopete first
- call_async(q, cdo_iface, 'HandleWith',
- cs.tp_name_prefix + '.Client.Kopete')
-
- # Kopete is asked to handle the channels
- e = q.expect('dbus-method-call',
- path=kopete.object_path,
- interface=cs.HANDLER, method='HandleChannels',
- handled=False)
-
- # Kopete accepts the channels
- q.dbus_return(e.message, signature='')
-
- q.expect_many(
- EventPattern('dbus-return', method='HandleWith'),
- EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
- EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
- signal='DispatchOperationFinished'),
- )
-
- # Now there are no more active channel dispatch operations
- assertEquals([], cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations'))
-
-
-def test(q, bus, mc):
- 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)
-
- # Two clients want to observe, approve and handle channels. Additionally,
- # Kopete recognises a "Secret" flag on certain incoming channels, and
- # wants to bypass approval and observers for them. Also, Empathy is a
- # respawnable observer, which wants to get notified of existing channels
- # if it gets restarted.
- empathy = SimulatedClient(q, bus, 'Empathy',
- observe=[text_fixed_properties], approve=[text_fixed_properties],
- handle=[text_fixed_properties], bypass_approval=False,
- wants_recovery=True)
- kopete = SimulatedClient(q, bus, 'Kopete',
- observe=[contact_text_fixed_properties],
- approve=[contact_text_fixed_properties],
- handle=[contact_text_fixed_properties], bypass_approval=False)
- bypass = SimulatedClient(q, bus, 'Kopete.Bypasser',
- observe=[], approve=[],
- handle=[secret_fixed_properties],
- bypass_approval=True, bypass_observers=True)
-
- # wait for MC to download the properties
- expect_client_setup(q, [empathy, kopete, bypass])
-
- # subscribe to the OperationList interface (MC assumes that until this
- # property has been retrieved once, nobody cares)
-
- cd = bus.get_object(cs.CD, cs.CD_PATH)
- cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
- assertEquals([], cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations'))
-
- # First, a non-secret channel is created
-
- cdo_iface, chan, channel_properties, observe_events = announce_common(q,
- bus, empathy, kopete, account, conn, cd_props, False)
-
- # Both Observers indicate that they are ready to proceed
- for e in observe_events:
- q.dbus_return(e.message, signature='')
-
- expect_and_exercise_approval(q, bus, chan, channel_properties,
- empathy, kopete, cdo_iface, cd_props)
-
- nonsecret_chan = chan
-
- # Now a channel that bypasses approval and observers comes in.
- # During this process, we should never be asked to approve or
- # observe anything.
-
- approval = [
- EventPattern('dbus-method-call', method='AddDispatchOperation'),
- ]
-
- q.forbid_events(approval)
-
- cdo_iface, chan, channel_properties, observe_events = announce_common(q,
- bus, empathy, kopete, account, conn, cd_props, True)
-
- # Both Observers indicate that they are ready to proceed
- for e in observe_events:
- q.dbus_return(e.message, signature='')
-
- # Kopete's BypassApproval part is asked to handle the channels
- e = q.expect('dbus-method-call',
- path=bypass.object_path,
- interface=cs.HANDLER, method='HandleChannels',
- handled=False)
- # Kopete accepts the channels
- q.dbus_return(e.message, signature='')
-
- q.unforbid_events(approval)
-
- # Empathy, the observer, crashes
- empathy.release_name()
-
- e = q.expect('dbus-signal',
- signal='NameOwnerChanged',
- predicate=(lambda e:
- e.args[0] == empathy.bus_name and e.args[2] == ''),
- )
- empathy_unique_name = e.args[1]
-
- bus.flush()
-
- # Empathy gets restarted
- empathy.reacquire_name()
-
- e = q.expect('dbus-signal',
- signal='NameOwnerChanged',
- predicate=(lambda e:
- e.args[0] == empathy.bus_name and e.args[1] == ''),
- )
- empathy_unique_name = e.args[2]
-
- # Empathy is told to observe only the non-secret channel
- e = q.expect('dbus-method-call',
- path=empathy.object_path,
- interface=cs.OBSERVER, method='ObserveChannels',
- handled=False)
-
- channels = e.args[2]
- assertLength(1, channels)
- assertEquals(nonsecret_chan.object_path, channels[0][0])
-
-if __name__ == '__main__':
- exec_test(test, {})
-
diff --git a/tests/twisted/dispatcher/cancel.py b/tests/twisted/dispatcher/cancel.py
index 5b8d90af..fe23f005 100644
--- a/tests/twisted/dispatcher/cancel.py
+++ b/tests/twisted/dispatcher/cancel.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/capture-bundle.py b/tests/twisted/dispatcher/capture-bundle.py
index de773844..44e18e87 100644
--- a/tests/twisted/dispatcher/capture-bundle.py
+++ b/tests/twisted/dispatcher/capture-bundle.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
@@ -43,7 +43,7 @@ def test(q, bus, mc):
}, signature='sv')
voip_fixed_properties = dbus.Dictionary({
cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAMED_MEDIA,
+ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL,
}, signature='sv')
# Two clients want to observe, approve and handle text and VoIP channels.
diff --git a/tests/twisted/dispatcher/cdo-claim.py b/tests/twisted/dispatcher/cdo-claim.py
index ec98b93f..89474f9b 100644
--- a/tests/twisted/dispatcher/cdo-claim.py
+++ b/tests/twisted/dispatcher/cdo-claim.py
@@ -30,7 +30,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/connect-for-request.py b/tests/twisted/dispatcher/connect-for-request.py
index 1be141fe..034cd054 100644
--- a/tests/twisted/dispatcher/connect-for-request.py
+++ b/tests/twisted/dispatcher/connect-for-request.py
@@ -29,7 +29,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "smcv@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -38,11 +38,11 @@ def test(q, bus, mc):
# automatically
call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', ''))
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
q.expect('dbus-return', method='Set')
call_async(q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Testing automatic presence'))
q.expect('dbus-return', method='Set')
q.expect('dbus-signal', signal='AccountPropertyChanged',
@@ -102,14 +102,14 @@ def test(q, bus, mc):
handled=False)
conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
- 'myself', has_requests=True, has_presence=True)
+ 'myself', has_presence=True)
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
- conn.presence = dbus.Struct((cs.PRESENCE_TYPE_AVAILABLE, 'available', ''),
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
+ conn.presence = dbus.Struct((cs.PRESENCE_AVAILABLE, 'available', ''),
signature='uss')
_, cm_request_call = q.expect_many(
@@ -123,7 +123,7 @@ def test(q, bus, mc):
q.dbus_emit(conn.object_path, cs.CONN_IFACE_SIMPLE_PRESENCE,
'PresencesChanged',
- {conn.self_handle: (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ {conn.self_handle: (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Testing automatic presence')},
signature='a{u(uss)}')
diff --git a/tests/twisted/dispatcher/create-at-startup.py b/tests/twisted/dispatcher/create-at-startup.py
index e0d73722..fb515723 100644
--- a/tests/twisted/dispatcher/create-at-startup.py
+++ b/tests/twisted/dispatcher/create-at-startup.py
@@ -28,7 +28,7 @@ import dbus.service
from servicetest import EventPattern, tp_name_prefix, tp_path_prefix, \
call_async
from mctest import exec_test, SimulatedConnection, SimulatedClient, \
- create_fakecm_account, enable_fakecm_account, SimulatedChannel, \
+ SimulatedConnectionManager, SimulatedChannel, \
expect_client_setup, MC
import constants as cs
@@ -76,8 +76,7 @@ def test(q, bus, unused, **kwargs):
observe=[text_fixed_properties], approve=[text_fixed_properties],
handle=[text_fixed_properties], bypass_approval=False,
implement_get_interfaces=False)
- cm_name_ref = dbus.service.BusName(
- cs.tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
+ simulated_cm = SimulatedConnectionManager(q, bus)
# service-activate MC; it will try to introspect the running client.
mc = MC(q, bus, wait_for_names=False)
@@ -133,7 +132,7 @@ def test(q, bus, unused, **kwargs):
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
# A channel appears spontaneously
diff --git a/tests/twisted/dispatcher/create-delayed-by-mini-plugin.py b/tests/twisted/dispatcher/create-delayed-by-mini-plugin.py
index 8c2925c1..fcf021b9 100644
--- a/tests/twisted/dispatcher/create-delayed-by-mini-plugin.py
+++ b/tests/twisted/dispatcher/create-delayed-by-mini-plugin.py
@@ -41,7 +41,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn, e = enable_fakecm_account(q, bus, mc, account, params,
extra_interfaces=[cs.CONN_IFACE_SERVICE_POINT],
expect_after_connect=[
@@ -55,13 +55,6 @@ def test(q, bus, mc):
q.dbus_return(e.message, points, signature='v')
- # MC looks up the handles for these numbers
- patterns = [EventPattern('dbus-method-call', path=conn.object_path,
- interface=cs.CONN, method='RequestHandles',
- args=[cs.HT_CONTACT, [num]],
- handled=True) for num in e_numbers]
- q.expect_many(*patterns)
-
# the service points change
e_numbers = ['911', '112', '999']
points = dbus.Array([((cs.SERVICE_POINT_TYPE_EMERGENCY, 'urn:service:sos'),
@@ -69,13 +62,6 @@ def test(q, bus, mc):
q.dbus_emit(conn.object_path, cs.CONN_IFACE_SERVICE_POINT,
'ServicePointsChanged', points, signature='a((us)as)')
- # MC looks up the new handles
- patterns = [EventPattern('dbus-method-call', path=conn.object_path,
- interface=cs.CONN, method='RequestHandles',
- args=[cs.HT_CONTACT, [num]],
- handled=True) for num in e_numbers]
- q.expect_many(*patterns)
-
# MC used to critical if more than one emergency service point was
# given by the CM. That's silly, so let's test it.
e_numbers1 = ['911']
@@ -89,12 +75,6 @@ def test(q, bus, mc):
e_numbers = e_numbers1 + e_numbers2
- patterns = [EventPattern('dbus-method-call', path=conn.object_path,
- interface=cs.CONN, method='RequestHandles',
- args=[cs.HT_CONTACT, [num]],
- handled=True) for num in e_numbers]
- q.expect_many(*patterns)
-
fixed_properties = dbus.Dictionary({
cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
cs.CHANNEL + '.ChannelType': DELAYED_CTYPE,
diff --git a/tests/twisted/dispatcher/create-handler-fails.py b/tests/twisted/dispatcher/create-handler-fails.py
index ccdae2f9..13523636 100644
--- a/tests/twisted/dispatcher/create-handler-fails.py
+++ b/tests/twisted/dispatcher/create-handler-fails.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/create-hints.py b/tests/twisted/dispatcher/create-hints.py
index daf8cdcd..3b8cf94b 100644
--- a/tests/twisted/dispatcher/create-hints.py
+++ b/tests/twisted/dispatcher/create-hints.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/create-no-preferred-handler.py b/tests/twisted/dispatcher/create-no-preferred-handler.py
index 3e078415..11ac44b5 100644
--- a/tests/twisted/dispatcher/create-no-preferred-handler.py
+++ b/tests/twisted/dispatcher/create-no-preferred-handler.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/create-rejected-by-mini-plugin.py b/tests/twisted/dispatcher/create-rejected-by-mini-plugin.py
index 2f517589..ecd5f6e6 100644
--- a/tests/twisted/dispatcher/create-rejected-by-mini-plugin.py
+++ b/tests/twisted/dispatcher/create-rejected-by-mini-plugin.py
@@ -47,7 +47,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/create-text.py b/tests/twisted/dispatcher/create-text.py
index 5a0efe1a..a0897ba4 100644
--- a/tests/twisted/dispatcher/create-text.py
+++ b/tests/twisted/dispatcher/create-text.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
@@ -71,7 +71,7 @@ def test(q, bus, mc):
test_channel_creation(q, bus, account, client, conn, True)
test_channel_creation(q, bus, account, client, conn, False, unsuitable)
test_channel_creation(q, bus, account, client, conn, False, unsuitable,
- cs.CHANNEL_TYPE_STREAMED_MEDIA)
+ cs.CHANNEL_TYPE_CALL)
def test_channel_creation(q, bus, account, client, conn,
ensure=False, prefer=None, channel_type=cs.CHANNEL_TYPE_TEXT):
diff --git a/tests/twisted/dispatcher/created-behind-our-back.py b/tests/twisted/dispatcher/created-behind-our-back.py
index 55d1b4b0..d87e69ac 100644
--- a/tests/twisted/dispatcher/created-behind-our-back.py
+++ b/tests/twisted/dispatcher/created-behind-our-back.py
@@ -39,7 +39,7 @@ def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/delay-approvers.py b/tests/twisted/dispatcher/delay-approvers.py
index a627159d..2a7295f8 100644
--- a/tests/twisted/dispatcher/delay-approvers.py
+++ b/tests/twisted/dispatcher/delay-approvers.py
@@ -29,7 +29,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/delay-then-call-handle-with.py b/tests/twisted/dispatcher/delay-then-call-handle-with.py
index 2f79b10e..28fdfb3e 100644
--- a/tests/twisted/dispatcher/delay-then-call-handle-with.py
+++ b/tests/twisted/dispatcher/delay-then-call-handle-with.py
@@ -29,7 +29,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/delay-then-dont-call-approvers.py b/tests/twisted/dispatcher/delay-then-dont-call-approvers.py
index 90040228..25ebd908 100644
--- a/tests/twisted/dispatcher/delay-then-dont-call-approvers.py
+++ b/tests/twisted/dispatcher/delay-then-dont-call-approvers.py
@@ -29,7 +29,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/dispatch-activatable.py b/tests/twisted/dispatcher/dispatch-activatable.py
index cb7b9cb1..6da442b2 100644
--- a/tests/twisted/dispatcher/dispatch-activatable.py
+++ b/tests/twisted/dispatcher/dispatch-activatable.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
abiword_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/dispatch-before-connected.py b/tests/twisted/dispatcher/dispatch-before-connected.py
index 9925e0fe..1037ef4c 100644
--- a/tests/twisted/dispatcher/dispatch-before-connected.py
+++ b/tests/twisted/dispatcher/dispatch-before-connected.py
@@ -29,17 +29,10 @@ from mctest import exec_test, SimulatedConnection, SimulatedClient, \
expect_client_setup
import constants as cs
-CHANNEL_TYPE_SERVER_VERIFICATION = \
- 'org.freedesktop.Telepathy.Channel.Type.ServerVerification.DRAFT'
-CHANNEL_IFACE_VERIFICATION = \
- 'org.freedesktop.Telepathy.Channel.Interface.Verification.DRAFT '
-CHANNEL_IFACE_IDENT_EXCHANGE = \
- 'org.freedesktop.Telepathy.Channel.Interface.IdentityExchange.DRAFT'
-
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someone@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -49,7 +42,7 @@ def test(q, bus, mc):
verification_filter = dbus.Dictionary({
cs.CHANNEL + '.TargetHandleType': 0,
- cs.CHANNEL + '.ChannelType': CHANNEL_TYPE_SERVER_VERIFICATION,
+ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_SERVER_TLS_CONNECTION,
}, signature='sv')
verifier_bus = dbus.bus.BusConnection()
@@ -61,7 +54,7 @@ def test(q, bus, mc):
expect_client_setup(q, [verifier])
account_props.Set(cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_AVAILABLE), 'available', ''))
+ (dbus.UInt32(cs.PRESENCE_AVAILABLE), 'available', ''))
account_props.Set(cs.ACCOUNT, 'Enabled', True)
@@ -73,7 +66,7 @@ def test(q, bus, mc):
handled=False)
conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol', '_',
- 'myself', has_requests=True, has_presence=True)
+ 'myself', has_presence=True)
q.dbus_return(e.message, conn.bus_name, conn.object_path, signature='so')
@@ -87,10 +80,7 @@ def test(q, bus, mc):
channel_properties[cs.CHANNEL + '.InitiatorID'] = ''
channel_properties[cs.CHANNEL + '.InitiatorHandle'] = 0
channel_properties[cs.CHANNEL + '.Requested'] = False
- channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array([
- CHANNEL_IFACE_IDENT_EXCHANGE,
- CHANNEL_IFACE_VERIFICATION,
- cs.CHANNEL], signature='s')
+ channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array([], signature='s')
chan = SimulatedChannel(conn, channel_properties)
chan.announce()
diff --git a/tests/twisted/dispatcher/dispatch-delayed-by-mini-plugin.py b/tests/twisted/dispatcher/dispatch-delayed-by-mini-plugin.py
index eeab38cb..d2c0855d 100644
--- a/tests/twisted/dispatcher/dispatch-delayed-by-mini-plugin.py
+++ b/tests/twisted/dispatcher/dispatch-delayed-by-mini-plugin.py
@@ -99,7 +99,7 @@ def signal_channel_expect_query(q, bus, account, conn, empathy, kopete):
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
policy_bus_name_ref = dbus.service.BusName('com.example.Policy', bus)
@@ -145,10 +145,8 @@ def test(q, bus, mc):
args=[cdo_path]),
EventPattern('dbus-method-call',
path=chan.object_path,
- interface=cs.CHANNEL_IFACE_GROUP,
- # this error message is from the plugin
- method='RemoveMembersWithReason', args=[[conn.self_handle],
- "Computer says no", cs.GROUP_REASON_PERMISSION_DENIED],
+ interface=cs.CHANNEL_IFACE_DESTROYABLE,
+ method='Destroy',
handled=False),
)
q.dbus_return(e.message, signature='')
diff --git a/tests/twisted/dispatcher/dispatch-obsolete.py b/tests/twisted/dispatcher/dispatch-obsolete.py
index 4431631a..16d76517 100644
--- a/tests/twisted/dispatcher/dispatch-obsolete.py
+++ b/tests/twisted/dispatcher/dispatch-obsolete.py
@@ -34,158 +34,18 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params,
has_requests=False)
- text_fixed_properties = dbus.Dictionary({
- cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_TEXT,
- }, signature='sv')
-
- # Two clients want to observe, approve and handle channels
- 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)
-
- # wait for MC to download the properties
- expect_client_setup(q, [empathy, kopete])
-
- # subscribe to the OperationList interface (MC assumes that until this
- # property has been retrieved once, nobody cares)
-
- cd = bus.get_object(cs.CD, cs.CD_PATH)
- cd_props = dbus.Interface(cd, cs.PROPERTIES_IFACE)
- assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
-
- channel_properties = dbus.Dictionary(text_fixed_properties,
- signature='sv')
- channel_properties[cs.CHANNEL + '.TargetID'] = 'juliet'
- channel_properties[cs.CHANNEL + '.TargetHandle'] = \
- conn.ensure_handle(cs.HT_CONTACT, 'juliet')
- channel_properties[cs.CHANNEL + '.InitiatorID'] = 'juliet'
- channel_properties[cs.CHANNEL + '.InitiatorHandle'] = \
- conn.ensure_handle(cs.HT_CONTACT, 'juliet')
- channel_properties[cs.CHANNEL + '.Requested'] = False
- channel_properties[cs.CHANNEL + '.Interfaces'] = dbus.Array(signature='s')
-
- chan = SimulatedChannel(conn, channel_properties)
- chan.announce()
-
- # A channel dispatch operation is created
-
- e = q.expect('dbus-signal',
- path=cs.CD_PATH,
- interface=cs.CD_IFACE_OP_LIST,
- signal='NewDispatchOperation')
-
- cdo_path = e.args[0]
- cdo_properties = e.args[1]
-
- assert cdo_properties[cs.CDO + '.Account'] == account.object_path
- assert cdo_properties[cs.CDO + '.Connection'] == conn.object_path
- assert cs.CDO + '.Interfaces' in cdo_properties
-
- handlers = cdo_properties[cs.CDO + '.PossibleHandlers'][:]
- handlers.sort()
- assert handlers == [cs.tp_name_prefix + '.Client.Empathy',
- cs.tp_name_prefix + '.Client.Kopete'], handlers
-
- assert cs.CD_IFACE_OP_LIST in cd_props.Get(cs.CD, 'Interfaces')
- assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') ==\
- [(cdo_path, cdo_properties)]
-
- cdo = bus.get_object(cs.CD, cdo_path)
- cdo_iface = dbus.Interface(cdo, cs.CDO)
-
- # Both Observers are told about the new channel
-
- 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] == cdo_path, e.args
- assert e.args[4] == [], e.args # no requests satisfied
- channels = e.args[2]
- assert len(channels) == 1, channels
- assert channels[0][0] == chan.object_path, channels
- # the announced channel properties are some subset of what it actually has
- for key in channels[0][1]:
- assert channel_properties[key] == channels[0][1][key], key
- assert cs.CHANNEL + '.TargetHandleType' in channels[0][1]
- assert cs.CHANNEL + '.ChannelType' in channels[0][1]
- assert cs.CHANNEL + '.TargetHandle' in channels[0][1]
-
- assert k.args == e.args
-
- # Both Observers indicate that they are ready to proceed
- q.dbus_return(k.message, signature='')
- q.dbus_return(e.message, signature='')
-
- # The Approvers are next
-
- e, k = q.expect_many(
- EventPattern('dbus-method-call',
- path=empathy.object_path,
- interface=cs.APPROVER, method='AddDispatchOperation',
- handled=False),
- EventPattern('dbus-method-call',
- path=kopete.object_path,
- interface=cs.APPROVER, method='AddDispatchOperation',
- handled=False),
- )
-
- assert e.args[1:] == [cdo_path, cdo_properties]
- channels = e.args[0]
- assert len(channels) == 1, channels
- assert channels[0][0] == chan.object_path, channels
- # the announced channel properties are some subset of what it actually has
- for key in channels[0][1]:
- assert channel_properties[key] == channels[0][1][key], key
- assert cs.CHANNEL + '.TargetHandleType' in channels[0][1]
- assert cs.CHANNEL + '.ChannelType' in channels[0][1]
- assert cs.CHANNEL + '.TargetHandle' in channels[0][1]
- assert k.args == e.args
-
- q.dbus_return(e.message, signature='')
- q.dbus_return(k.message, signature='')
-
- # Both Approvers now have a flashing icon or something, trying to get the
- # user's attention
-
- # The user responds to Empathy first
- call_async(q, cdo_iface, 'HandleWith',
- cs.tp_name_prefix + '.Client.Empathy')
-
- # Empathy is asked to handle the channels
- e = q.expect('dbus-method-call',
- path=empathy.object_path,
- interface=cs.HANDLER, method='HandleChannels',
- handled=False)
-
- # Empathy accepts the channels
- q.dbus_return(e.message, signature='')
-
q.expect_many(
- EventPattern('dbus-return', method='HandleWith'),
- EventPattern('dbus-signal', interface=cs.CDO, signal='Finished'),
- EventPattern('dbus-signal', interface=cs.CD_IFACE_OP_LIST,
- signal='DispatchOperationFinished'),
+ EventPattern('dbus-signal', signal='AccountPropertyChanged',
+ predicate=lambda e:
+ e.args[0].get('ConnectionError') ==
+ cs.SOFTWARE_UPGRADE_REQUIRED),
+ EventPattern('dbus-method-call', method='Disconnect',
+ handled=True),
)
- # Now there are no more active channel dispatch operations
- assert cd_props.Get(cs.CD_IFACE_OP_LIST, 'DispatchOperations') == []
-
if __name__ == '__main__':
exec_test(test, {})
diff --git a/tests/twisted/dispatcher/dispatch-rejected-by-mini-plugin.py b/tests/twisted/dispatcher/dispatch-rejected-by-mini-plugin.py
index eeb6e9ec..37a87105 100644
--- a/tests/twisted/dispatcher/dispatch-rejected-by-mini-plugin.py
+++ b/tests/twisted/dispatcher/dispatch-rejected-by-mini-plugin.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
@@ -205,9 +205,8 @@ def test(q, bus, mc):
args=[cdo_path]),
EventPattern('dbus-method-call',
path=chan.object_path,
- interface=cs.CHANNEL_IFACE_GROUP,
- method='RemoveMembersWithReason', args=[[conn.self_handle],
- "Can't touch this", cs.GROUP_REASON_PERMISSION_DENIED],
+ interface=cs.CHANNEL_IFACE_DESTROYABLE,
+ method='Destroy',
handled=False),
)
q.dbus_return(e.message, signature='')
diff --git a/tests/twisted/dispatcher/dispatch-text.py b/tests/twisted/dispatcher/dispatch-text.py
index b1f6ce60..689639ca 100644
--- a/tests/twisted/dispatcher/dispatch-text.py
+++ b/tests/twisted/dispatcher/dispatch-text.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/ensure-and-redispatch.py b/tests/twisted/dispatcher/ensure-and-redispatch.py
index 4d526c2e..f5a77a56 100644
--- a/tests/twisted/dispatcher/ensure-and-redispatch.py
+++ b/tests/twisted/dispatcher/ensure-and-redispatch.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/ensure-is-approval.py b/tests/twisted/dispatcher/ensure-is-approval.py
index a2fb0850..63c6f8a7 100644
--- a/tests/twisted/dispatcher/ensure-is-approval.py
+++ b/tests/twisted/dispatcher/ensure-is-approval.py
@@ -35,7 +35,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
# One client (Kopete) has less specific filters than the other (Empathy),
diff --git a/tests/twisted/dispatcher/ensure-rapidly.py b/tests/twisted/dispatcher/ensure-rapidly.py
index a338799b..f90a1f68 100644
--- a/tests/twisted/dispatcher/ensure-rapidly.py
+++ b/tests/twisted/dispatcher/ensure-rapidly.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/exploding-bundles.py b/tests/twisted/dispatcher/exploding-bundles.py
index 27d3be3a..27d1727e 100644
--- a/tests/twisted/dispatcher/exploding-bundles.py
+++ b/tests/twisted/dispatcher/exploding-bundles.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
@@ -43,7 +43,7 @@ def test(q, bus, mc):
media_fixed_properties = dbus.Dictionary({
cs.CHANNEL + '.TargetHandleType': cs.HT_CONTACT,
- cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_STREAMED_MEDIA,
+ cs.CHANNEL + '.ChannelType': cs.CHANNEL_TYPE_CALL,
}, signature='sv')
misc_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/fdo-21034.py b/tests/twisted/dispatcher/fdo-21034.py
index 5a1ca3ca..e0ed001a 100644
--- a/tests/twisted/dispatcher/fdo-21034.py
+++ b/tests/twisted/dispatcher/fdo-21034.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/handle-channels-fails.py b/tests/twisted/dispatcher/handle-channels-fails.py
index 04b51ef7..4b3ae22e 100644
--- a/tests/twisted/dispatcher/handle-channels-fails.py
+++ b/tests/twisted/dispatcher/handle-channels-fails.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/lose-text.py b/tests/twisted/dispatcher/lose-text.py
index d652658c..42083c2c 100644
--- a/tests/twisted/dispatcher/lose-text.py
+++ b/tests/twisted/dispatcher/lose-text.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/recover-from-disconnect.py b/tests/twisted/dispatcher/recover-from-disconnect.py
index 9ae81e51..9e0d3c42 100644
--- a/tests/twisted/dispatcher/recover-from-disconnect.py
+++ b/tests/twisted/dispatcher/recover-from-disconnect.py
@@ -48,13 +48,10 @@ def test(q, bus, mc):
# wait for MC to download the properties
expect_client_setup(q, [empathy, kopete])
- cm_name_ref = dbus.service.BusName(
- tp_name_prefix + '.ConnectionManager.fakecm', bus=bus)
-
# Create an account
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
@@ -68,7 +65,7 @@ def test(q, bus, mc):
dbus_interface=cs.PROPERTIES_IFACE)
# Set online presence
- presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Fixing MC bugs'), signature='uss')
call_async(q, account, 'Set', cs.ACCOUNT,
'RequestedPresence', presence,
@@ -93,19 +90,19 @@ def test(q, bus, mc):
path=conn.object_path, handled=True),
)
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
test_dispatching(q, bus, conn, account, empathy, kopete)
# Connection falls over for a miscellaneous reason
conn.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
- cs.CONN_STATUS_REASON_NETWORK_ERROR)
+ cs.CSR_NETWORK_ERROR)
# MC reconnects
@@ -128,13 +125,13 @@ def test(q, bus, mc):
path=conn.object_path, handled=True),
)
- # MC calls GetStatus (maybe) and then Connect
-
+ # MC prepares the connection, does any pre-Connect setup, then
+ # calls Connect
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
# Connect succeeds
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
test_dispatching(q, bus, conn, account, empathy, kopete)
diff --git a/tests/twisted/dispatcher/redispatch-channels.py b/tests/twisted/dispatcher/redispatch-channels.py
index 6178a379..41800b1c 100644
--- a/tests/twisted/dispatcher/redispatch-channels.py
+++ b/tests/twisted/dispatcher/redispatch-channels.py
@@ -185,7 +185,7 @@ def test_delegate_channel(q, bus, mc, account, conn, chan, empathy, empathy_bus,
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/request-disabled-account.py b/tests/twisted/dispatcher/request-disabled-account.py
index 863f0540..c3f1640b 100644
--- a/tests/twisted/dispatcher/request-disabled-account.py
+++ b/tests/twisted/dispatcher/request-disabled-account.py
@@ -29,17 +29,17 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "smcv@example.com",
"password": "secrecy"}, signature='sv')
- (cm_name_ref, account) = create_fakecm_account(q, bus, mc, params)
+ (simulated_cm, account) = create_fakecm_account(q, bus, mc, params)
account_iface = dbus.Interface(account, cs.ACCOUNT)
account_props = dbus.Interface(account, cs.PROPERTIES_IFACE)
call_async(q, account_props, 'Set', cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline', ''))
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline', ''))
q.expect('dbus-return', method='Set')
call_async(q, account_props, 'Set', cs.ACCOUNT, 'AutomaticPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_BUSY), 'busy',
+ (dbus.UInt32(cs.PRESENCE_BUSY), 'busy',
'Testing automatic presence'))
q.expect('dbus-return', method='Set')
q.expect('dbus-signal', signal='AccountPropertyChanged',
diff --git a/tests/twisted/dispatcher/respawn-activatable-observers.py b/tests/twisted/dispatcher/respawn-activatable-observers.py
index 8f83ffbb..14727b40 100644
--- a/tests/twisted/dispatcher/respawn-activatable-observers.py
+++ b/tests/twisted/dispatcher/respawn-activatable-observers.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/respawn-observers.py b/tests/twisted/dispatcher/respawn-observers.py
index 81061ae6..bf69a794 100644
--- a/tests/twisted/dispatcher/respawn-observers.py
+++ b/tests/twisted/dispatcher/respawn-observers.py
@@ -34,7 +34,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/some-delay-approvers.py b/tests/twisted/dispatcher/some-delay-approvers.py
index e06b13a6..16e0b7b0 100644
--- a/tests/twisted/dispatcher/some-delay-approvers.py
+++ b/tests/twisted/dispatcher/some-delay-approvers.py
@@ -29,7 +29,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/undispatchable.py b/tests/twisted/dispatcher/undispatchable.py
index de63fbca..8a18ec03 100644
--- a/tests/twisted/dispatcher/undispatchable.py
+++ b/tests/twisted/dispatcher/undispatchable.py
@@ -35,7 +35,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
text_fixed_properties = dbus.Dictionary({
diff --git a/tests/twisted/dispatcher/vanishing-client.py b/tests/twisted/dispatcher/vanishing-client.py
index 92a4079b..143ea4cb 100644
--- a/tests/twisted/dispatcher/vanishing-client.py
+++ b/tests/twisted/dispatcher/vanishing-client.py
@@ -33,7 +33,7 @@ import constants as cs
def test(q, bus, mc):
params = dbus.Dictionary({"account": "someguy@example.com",
"password": "secrecy"}, signature='sv')
- cm_name_ref, account = create_fakecm_account(q, bus, mc, params)
+ simulated_cm, account = create_fakecm_account(q, bus, mc, params)
conn = enable_fakecm_account(q, bus, mc, account, params)
bus_name = '.'.join([tp_name_prefix, 'Client.CrashMe'])
diff --git a/tests/twisted/fakeaccountsservice.py b/tests/twisted/fakeaccountsservice.py
index 3c10a156..d8c87a0b 100644
--- a/tests/twisted/fakeaccountsservice.py
+++ b/tests/twisted/fakeaccountsservice.py
@@ -25,12 +25,27 @@ from servicetest import (Event, EventPattern)
import constants as cs
-# indices into the tuple of dicts representing an account
-ATTRS = 0
-ATTR_FLAGS = 1
-PARAMS = 2
-UNTYPED_PARAMS = 3
-PARAM_FLAGS = 4
+class FakeAccount(object):
+
+ def __init__(self):
+ self.attrs = dbus.Dictionary({}, signature='sv')
+ self.attr_flags = dbus.Dictionary({}, signature='su')
+ self.params = dbus.Dictionary({}, signature='sv')
+ self.untyped_params = dbus.Dictionary({}, signature='ss')
+ self.param_flags = dbus.Dictionary({}, signature='su')
+ self.restrictions = 0
+
+ SIGNATURE = 'a{sv}a{su}a{sv}a{ss}a{su}u'
+
+ def to_dbus(self):
+ return (
+ self.attrs,
+ self.attr_flags,
+ self.params,
+ self.untyped_params,
+ self.param_flags,
+ dbus.UInt32(self.restrictions),
+ )
class FakeAccountsService(object):
def __init__(self, q, bus):
@@ -68,25 +83,28 @@ class FakeAccountsService(object):
method='UpdateParameters')
def create_account(self, account, attrs={}, attr_flags={}, params={},
- untyped_params={}, param_flags={}):
+ untyped_params={}, param_flags={}, restrictions=0):
+
if account in self.accounts:
raise KeyError('Account %s already exists' % account)
- self.accounts[account] = ({}, {}, {}, {}, {})
- self.accounts[account][ATTRS].update(attrs)
+
+ self.accounts[account] = FakeAccount()
+ self.accounts[account].restrictions = restrictions
+ self.accounts[account].attrs.update(attrs)
for attr in attrs:
- self.accounts[account][ATTR_FLAGS][attr] = dbus.UInt32(0)
- self.accounts[account][ATTR_FLAGS].update(attr_flags)
- self.accounts[account][PARAMS].update(params)
+ self.accounts[account].attr_flags[attr] = dbus.UInt32(0)
+ self.accounts[account].attr_flags.update(attr_flags)
+ self.accounts[account].params.update(params)
for param in params:
- self.accounts[account][PARAM_FLAGS][param] = dbus.UInt32(0)
- self.accounts[account][UNTYPED_PARAMS].update(untyped_params)
+ self.accounts[account].param_flags[param] = dbus.UInt32(0)
+ self.accounts[account].untyped_params.update(untyped_params)
for param in untyped_params:
- self.accounts[account][PARAM_FLAGS][param] = dbus.UInt32(0)
- self.accounts[account][PARAM_FLAGS].update(param_flags)
+ self.accounts[account].param_flags[param] = dbus.UInt32(0)
+ self.accounts[account].param_flags.update(param_flags)
self.q.dbus_emit(self.object_path, cs.TEST_DBUS_ACCOUNT_SERVICE_IFACE,
'AccountCreated',
- account, *self.accounts[account],
- signature='sa{sv}a{su}a{sv}a{ss}a{su}')
+ account, *(self.accounts[account].to_dbus()),
+ signature='s' + FakeAccount.SIGNATURE)
def CreateAccount(self, e):
try:
@@ -111,28 +129,31 @@ class FakeAccountsService(object):
self.q.dbus_return(e.message, signature='')
def GetAccounts(self, e):
- self.q.dbus_return(e.message, self.accounts,
- signature='a{s(a{sv}a{su}a{sv}a{ss}a{su})}')
+ accounts = {}
+ for a in self.accounts:
+ accounts[a] = self.accounts[a].to_dbus()
+ self.q.dbus_return(e.message, accounts,
+ signature='a{s(' + FakeAccount.SIGNATURE + ')}')
def update_attributes(self, account, changed={}, flags={}, deleted=[]):
if account not in self.accounts:
self.create_account(account)
for (attribute, value) in changed.items():
- self.accounts[account][ATTRS][attribute] = value
- self.accounts[account][ATTR_FLAGS][attribute] = flags.get(
+ self.accounts[account].attrs[attribute] = value
+ self.accounts[account].attr_flags[attribute] = flags.get(
attribute, dbus.UInt32(0))
for attribute in deleted:
- if attribute in self.accounts[account][ATTRS]:
- del self.accounts[account][ATTRS][attribute]
- if attribute in self.accounts[account][ATTR_FLAGS]:
- del self.accounts[account][ATTR_FLAGS][attribute]
+ if attribute in self.accounts[account].attrs:
+ del self.accounts[account].attrs[attribute]
+ if attribute in self.accounts[account].attr_flags:
+ del self.accounts[account].attr_flags[attribute]
self.q.dbus_emit(self.object_path, cs.TEST_DBUS_ACCOUNT_SERVICE_IFACE,
'AttributesChanged',
account, changed,
- dict([(a, self.accounts[account][ATTR_FLAGS][a])
+ dict([(a, self.accounts[account].attr_flags[a])
for a in changed]),
deleted, signature='sa{sv}a{su}as')
@@ -150,31 +171,31 @@ class FakeAccountsService(object):
self.create_account(account)
for (param, value) in changed.items():
- self.accounts[account][PARAMS][param] = value
- if param in self.accounts[account][UNTYPED_PARAMS]:
- del self.accounts[account][UNTYPED_PARAMS][param]
- self.accounts[account][PARAM_FLAGS][param] = flags.get(
+ self.accounts[account].params[param] = value
+ if param in self.accounts[account].untyped_params:
+ del self.accounts[account].untyped_params[param]
+ self.accounts[account].param_flags[param] = flags.get(
param, dbus.UInt32(0))
for (param, value) in untyped.items():
- self.accounts[account][UNTYPED_PARAMS][param] = value
- if param in self.accounts[account][PARAMS]:
- del self.accounts[account][PARAMS][param]
- self.accounts[account][PARAM_FLAGS][param] = flags.get(
+ self.accounts[account].untyped_params[param] = value
+ if param in self.accounts[account].params:
+ del self.accounts[account].params[param]
+ self.accounts[account].param_flags[param] = flags.get(
param, dbus.UInt32(0))
for param in deleted:
- if param in self.accounts[account][PARAMS]:
- del self.accounts[account][PARAMS][param]
- if param in self.accounts[account][UNTYPED_PARAMS]:
- del self.accounts[account][UNTYPED_PARAMS][param]
- if param in self.accounts[account][PARAM_FLAGS]:
- del self.accounts[account][PARAM_FLAGS][param]
+ if param in self.accounts[account].params:
+ del self.accounts[account].params[param]
+ if param in self.accounts[account].untyped_params:
+ del self.accounts[account].untyped_params[param]
+ if param in self.accounts[account].param_flags:
+ del self.accounts[account].param_flags[param]
self.q.dbus_emit(self.object_path, cs.TEST_DBUS_ACCOUNT_SERVICE_IFACE,
'ParametersChanged',
account, changed, untyped,
- dict([(p, self.accounts[account][PARAM_FLAGS][p])
+ dict([(p, self.accounts[account].param_flags[p])
for p in (set(changed.keys()) | set(untyped.keys()))]),
deleted,
signature='sa{sv}a{ss}a{su}as')
diff --git a/tests/twisted/fakeclient.py b/tests/twisted/fakeclient.py
deleted file mode 100644
index d3c43813..00000000
--- a/tests/twisted/fakeclient.py
+++ /dev/null
@@ -1,99 +0,0 @@
-# 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
-
-import dbus
-import dbus.service
-from servicetest import Event
-from servicetest import EventPattern, tp_name_prefix, tp_path_prefix
-
-client_iface = "org.freedesktop.Telepathy.Client"
-client_observer_iface = "org.freedesktop.Telepathy.Client.Observer"
-client_approver_iface = "org.freedesktop.Telepathy.Client.Approver"
-client_handler_iface = "org.freedesktop.Telepathy.Client.Handler"
-
-properties_iface = "org.freedesktop.DBus.Properties"
-
-empty_caps = dbus.Array([], signature='a{sv}')
-
-class FakeClient(dbus.service.Object):
- def __init__(self, object_path, q, bus, bus_name, nameref,
- caps = empty_caps):
- self.object_path = object_path
- self.q = q
- self.bus = bus
- self.bus_name = bus_name
- # keep a reference on nameref, otherwise, the name will be lost!
- self.nameref = nameref
- self.caps = caps
- dbus.service.Object.__init__(self, bus, object_path)
-
- @dbus.service.method(dbus_interface=properties_iface,
- in_signature='ss', out_signature='v')
- def Get(self, interface_name, property_name):
- self.q.append(Event('dbus-method-call', name="Get",
- obj=self, interface_name=interface_name,
- property_name=property_name))
- if interface_name == client_iface and property_name == "Interfaces":
- return dbus.Array([
- client_observer_iface,
- client_approver_iface,
- client_handler_iface
- ], signature='s')
- if interface_name == client_observer_iface and \
- property_name == "ObserverChannelFilter":
- return empty_caps
- if interface_name == client_approver_iface and \
- property_name == "ApproverChannelFilter":
- return empty_caps
- if interface_name == client_handler_iface and \
- property_name == "HandlerChannelFilter":
- return self.caps
- print "Error: interface_name=%s property_name=%s" % \
- (interface_name, property_name)
- return None
-
- @dbus.service.method(dbus_interface=properties_iface,
- in_signature='s', out_signature='a{sv}')
- def GetAll(self, interface_name):
- self.q.append(Event('dbus-method-call', name="GetAll",
- obj=self, interface_name=interface_name))
- if interface_name == client_iface:
- return dbus.Dictionary({
- 'Interfaces': dbus.Array([
- client_observer_iface,
- client_approver_iface,
- client_handler_iface
- ])
- }, signature='sv')
- return None
-
- @dbus.service.method(dbus_interface=client_handler_iface,
- in_signature='ooa(oa{sv})aot', out_signature='')
- def HandleChannels(self, account, connection, channels,
- requests_satisfied, user_action_time):
- self.q.append(Event('dbus-method-call', name="HandleChannels",
- obj=self, account=account, connection=connection,
- channels=channels, requests_satisfied=requests_satisfied,
- user_action_time=user_action_time))
-
-def start_fake_client(q, bus, bus_name, object_path, caps):
- nameref = dbus.service.BusName(bus_name, bus=bus)
- client = FakeClient(object_path, q, bus, bus_name, nameref, caps)
- return client
-
-
diff --git a/tests/twisted/fakecm.py b/tests/twisted/fakecm.py
deleted file mode 100644
index fb534e7b..00000000
--- a/tests/twisted/fakecm.py
+++ /dev/null
@@ -1,292 +0,0 @@
-# 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
-
-import dbus
-import dbus.service
-from servicetest import Event
-from servicetest import EventPattern, tp_name_prefix, tp_path_prefix
-from twisted.internet import reactor
-
-properties_iface = "org.freedesktop.DBus.Properties"
-cm_iface = "org.freedesktop.Telepathy.ConnectionManager"
-conn_iface = "org.freedesktop.Telepathy.Connection"
-caps_iface = \
- "org.freedesktop.Telepathy.Connection.Interface.ContactCapabilities.DRAFT"
-requests_iface = "org.freedesktop.Telepathy.Connection.Interface.Requests"
-channel_iface = "org.freedesktop.Telepathy.Channel"
-
-class FakeChannel(dbus.service.Object):
- def __init__(self, conn, object_path, q, bus, nameref, props):
- self.conn = conn
- self.object_path = object_path
- self.q = q
- self.bus = bus
- # keep a reference on nameref, otherwise, the name will be lost!
- self.nameref = nameref
- self.props = props
-
- if channel_iface + '.TargetHandle' not in props:
- self.props[channel_iface + '.TargetHandle'] = \
- self.conn.get_handle(props[channel_iface + '.TargetID'])
-
- dbus.service.Object.__init__(self, bus, object_path)
-
- def called(self, method):
- self.q.append(Event('dbus-method-call', name=method, obj=self,
- path=self.object_path))
-
- @dbus.service.method(dbus_interface=channel_iface,
- in_signature='', out_signature='as')
- def GetInterfaces(self):
- self.called('GetInterfaces')
- return [self.props[channel_iface + '.ChannelType']]
-
- @dbus.service.method(dbus_interface=channel_iface,
- in_signature='', out_signature='u')
- def GetHandle(self):
- return self.props[channel_iface + '.TargetHandle']
-
- @dbus.service.method(dbus_interface=channel_iface,
- in_signature='', out_signature='')
- def Close(self):
- self.Closed()
-
- @dbus.service.signal(dbus_interface=channel_iface, signature='')
- def Closed(self):
- pass
-
-
-class FakeConn(dbus.service.Object):
- def __init__(self, object_path, q, bus, nameref):
- self.object_path = object_path
- self.q = q
- self.bus = bus
- # keep a reference on nameref, otherwise, the name will be lost!
- self.nameref = nameref
- self.status = 2 # Connection_Status_Disconnected
- self.next_channel_id = 1
- self.channels = []
- self.handles = {}
- self.next_handle = 1337 # break people depending on SelfHandle == 1
- dbus.service.Object.__init__(self, bus, object_path)
-
- # interface Connection
-
- @dbus.service.method(dbus_interface=conn_iface,
- in_signature='', out_signature='')
- def Connect(self):
- self.StatusChanged(1, 1)
- self.StatusChanged(0, 1)
- self.q.append(Event('dbus-method-call', name="Connect", obj=self,
- path=self.object_path))
- return None
-
- @dbus.service.method(dbus_interface=conn_iface,
- in_signature='', out_signature='as')
- def GetInterfaces(self):
- self.q.append(Event('dbus-method-call', name="GetInterfaces",
- obj=self, path=self.object_path))
- return dbus.Array([conn_iface, caps_iface, requests_iface])
-
- def get_handle(self, id):
- for handle, id_ in self.handles.iteritems():
- if id_ == id:
- return handle
- handle = self.next_handle
- self.next_handle += 1
-
- self.handles[handle] = id
- return handle
-
- @dbus.service.method(dbus_interface=conn_iface,
- in_signature='', out_signature='u')
- def GetSelfHandle(self):
- self.q.append(Event('dbus-method-call', name="GetSelfHandle",
- obj=self, path=self.object_path))
- return self.get_handle('fakeaccount')
-
- @dbus.service.method(dbus_interface=conn_iface,
- in_signature='', out_signature='u')
- def GetStatus(self):
- self.q.append(Event('dbus-method-call', name="GetStatus",
- obj=self, path=self.object_path))
- return self.status
-
- @dbus.service.method(dbus_interface=conn_iface,
- in_signature='uau', out_signature='as')
- def InspectHandles(self, handle_type, handles):
- self.q.append(Event('dbus-method-call', name="InspectHandles",
- obj=self, path=self.object_path, handle_type=handle_type,
- handles=handles))
- if handle_type != 1:
- raise "non-contact handles don't exist"
-
- ret = []
- for handle in handles:
- if handle not in self.handles:
- raise "%d is not a valid handle" % handle
- ret.append(self.handles[handle])
-
- return ret
-
- @dbus.service.method(dbus_interface=conn_iface,
- in_signature='uas', out_signature='au')
- def RequestHandles(self, type, ids):
- if type != 1:
- raise "non-contact handles don't exist"
-
- ret = []
- for id in ids:
- ret.append(self.get_handle(id))
-
- return ret
-
- @dbus.service.signal(dbus_interface=conn_iface,
- signature='uu')
- def StatusChanged(self, status, reason):
- self.status = status
-
- # interface Connection.Interface.ContactCapabilities.DRAFT
-
- @dbus.service.method(dbus_interface=caps_iface,
- in_signature='aa{sv}', out_signature='')
- def SetSelfCapabilities(self, caps):
- self.q.append(Event('dbus-method-call', name="SetSelfCapabilities",
- obj=self, path=self.object_path, caps=caps))
- return None
-
- @dbus.service.signal(dbus_interface=requests_iface,
- signature='a(oa{sv})')
- def NewChannels(self, array):
- self.channels = self.channels + array
-
- @dbus.service.signal(dbus_interface=conn_iface,
- signature='osuub')
- def NewChannel(self, object_path, channel_type, handle_type, handle,
- suppress_handle):
- pass
-
- @dbus.service.method(dbus_interface=properties_iface,
- in_signature='ss', out_signature='v')
- def Get(self, interface_name, property_name):
- self.q.append(Event('dbus-method-call', name="Get",
- obj=self, interface_name=interface_name,
- property_name=property_name))
- if interface_name == requests_iface and \
- property_name == "Channels":
- return dbus.Array(self.channels, signature='(oa{sv})')
- print "Error: interface_name=%s property_name=%s" % \
- (interface_name, property_name)
- return None
-
- @dbus.service.method(dbus_interface=properties_iface,
- in_signature='s', out_signature='a{sv}')
- def GetAll(self, interface_name):
- self.q.append(Event('dbus-method-call', name="GetAll",
- obj=self, interface_name=interface_name))
- if interface_name == conn_iface:
- return dbus.Dictionary({
- 'SelfHandle': 0L
- }, signature='sv')
- if interface_name == requests_iface:
- return dbus.Dictionary({
- 'Channels': dbus.Array(self.channels,
- signature='(oa{sv})')
- }, signature='sv')
- return None
-
- def new_incoming_channel(self, object_path, asv):
- self.NewChannels(dbus.Array([(object_path, asv)],
- signature='(oa{sv})'))
- self.NewChannel(object_path,
- asv['org.freedesktop.Telepathy.Channel.ChannelType'],
- asv['org.freedesktop.Telepathy.Channel.TargetHandleType'],
- asv['org.freedesktop.Telepathy.Channel.TargetHandle'],
- False)
-
- # interface Connection.Interface.Requests
- def make_channel(self, props):
- path = self.object_path + "/channel%d" % self.next_channel_id
- self.next_channel_id += 1
- chan = FakeChannel(self, path, self.q, self.bus, self.nameref, props)
- reactor.callLater(0, self.NewChannels, [(chan, props)])
- return chan
-
- @dbus.service.method(dbus_interface=requests_iface,
- in_signature='a{sv}', out_signature='oa{sv}')
- def CreateChannel(self, request):
- self.q.append(Event('dbus-method-call', name="CreateChannel",
- obj=self, interface_name=requests_iface))
- chan = self.make_channel(request)
- return (chan, request)
-
- @dbus.service.method(dbus_interface=requests_iface,
- in_signature='a{sv}', out_signature='boa{sv}')
- def EnsureChannel(self, request):
- self.q.append(Event('dbus-method-call', name="EnsureChannel",
- obj=self, interface_name=requests_iface))
- chan = self.make_channel(request)
- self.q
- return (True, chan, request)
-
- @dbus.service.signal(dbus_interface=requests_iface,
- signature="o")
- def ChannelClosed(self, channel):
- pass
-
-
-
-class FakeCM(dbus.service.Object):
- def __init__(self, object_path, q, bus, bus_name, nameref):
- self.object_path = object_path
- self.q = q
- self.bus = bus
- self.bus_name = bus_name
- # keep a reference on nameref, otherwise, the name will be lost!
- self.nameref = nameref
- dbus.service.Object.__init__(self, bus, object_path)
-
- @dbus.service.method(dbus_interface=cm_iface,
- in_signature='s', out_signature='a(susv)')
- def GetParameters(self, protocol):
- self.q.append(Event('dbus-method-call', name="GetParameters",
- protocol=protocol, obj=self))
- return []
-
- @dbus.service.method(dbus_interface=cm_iface,
- in_signature='', out_signature='as')
- def ListProtocols(self, protocol):
- self.q.append(Event('dbus-method-call', name="ListProtocols", obj=self))
- return ['fakeprotocol']
-
- @dbus.service.method(dbus_interface=cm_iface,
- in_signature='sa{sv}', out_signature='so')
- def RequestConnection(self, protocol, parameters):
- conn_path = tp_path_prefix + "/Connection/fakecm/fakeprotocol/conn1"
- conn = FakeConn(conn_path, self.q, self.bus, self.nameref)
- self.q.append(Event('dbus-method-call', name="RequestConnection",
- protocol=protocol, parameters=parameters,
- conn=conn, obj=self))
- return [self.bus_name, conn_path]
-
-def start_fake_connection_manager(q, bus, bus_name, object_path):
- nameref = dbus.service.BusName(bus_name, bus=bus)
- cm = FakeCM(object_path, q, bus, bus_name, nameref)
- return cm
-
-
diff --git a/tests/twisted/mc-debug-server.c b/tests/twisted/mc-debug-server.c
index 48f02484..559f3f58 100644
--- a/tests/twisted/mc-debug-server.c
+++ b/tests/twisted/mc-debug-server.c
@@ -154,6 +154,7 @@ main (int argc, char **argv)
{
GError *error = NULL;
GDBusConnection *gdbus = NULL;
+ GDBusConnection *gdbus_system = NULL;
DBusConnection *connection = NULL;
int ret = 1;
GMainLoop *teardown_loop;
@@ -174,26 +175,18 @@ main (int argc, char **argv)
G_LOG_FATAL_MASK | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
gdbus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &error);
-
- if (gdbus == NULL)
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- error = NULL;
- goto out;
- }
-
+ g_assert_no_error (error);
+ g_assert (gdbus != NULL);
g_dbus_connection_set_exit_on_close (gdbus, FALSE);
- bus_daemon = tp_dbus_daemon_dup (&error);
+ gdbus_system = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
+ g_assert_no_error (error);
+ g_assert (gdbus_system != NULL);
+ g_dbus_connection_set_exit_on_close (gdbus_system, FALSE);
- if (bus_daemon == NULL)
- {
- g_warning ("%s", error->message);
- g_error_free (error);
- error = NULL;
- goto out;
- }
+ bus_daemon = tp_dbus_daemon_dup (&error);
+ g_assert_no_error (error);
+ g_assert (bus_daemon != NULL);
/* It appears that dbus-glib registers a filter that wrongly returns
* DBUS_HANDLER_RESULT_HANDLED for signals, so for *our* filter to have any
@@ -230,14 +223,13 @@ main (int argc, char **argv)
g_main_loop_run (teardown_loop);
-out:
-
if (connection != NULL)
{
dbus_connection_flush (connection);
}
tp_clear_object (&gdbus);
+ tp_clear_object (&gdbus_system);
tp_clear_object (&bus_daemon);
dbus_shutdown ();
diff --git a/tests/twisted/mcp-account-diversion.c b/tests/twisted/mcp-account-diversion.c
index a9967648..0e8bfbc8 100644
--- a/tests/twisted/mcp-account-diversion.c
+++ b/tests/twisted/mcp-account-diversion.c
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
+#include <config.h>
#include <mission-control-plugins/mission-control-plugins.h>
#define DONT_DIVERT "fakecm/fakeprotocol/dontdivert"
@@ -110,109 +111,243 @@ _create_config (void)
DEBUG ("created %s", file);
}
-static gboolean
-_set (const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key,
- const gchar *val)
+static McpAccountStorageSetResult
+_set (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *key,
+ GVariant *val,
+ McpParameterFlags flags)
{
AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (self);
+ gchar *val_str;
+ gboolean changed;
if (g_str_has_prefix (account, DONT_DIVERT))
- return FALSE;
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED;
- adp->save = TRUE;
- g_key_file_set_value (adp->keyfile, account, key, val);
-
- return TRUE;
-}
+ if (val == NULL)
+ {
+ gsize n;
+ GStrv keys;
-static gboolean
-_get (const McpAccountStorage *self,
- const McpAccountManager *am,
- const gchar *account,
- const gchar *key)
-{
- AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (self);
+ if (g_key_file_remove_key (adp->keyfile, account, key, NULL))
+ {
+ adp->save = TRUE;
+ changed = TRUE;
+ }
- if (key != NULL)
- {
- gchar *v = g_key_file_get_value (adp->keyfile, account, key, NULL);
+ keys = g_key_file_get_keys (adp->keyfile, account, &n, NULL);
- if (v == NULL)
- return FALSE;
+ if (keys == NULL || n == 0)
+ g_key_file_remove_group (adp->keyfile, account, NULL);
- mcp_account_manager_set_value (am, account, key, v);
- g_free (v);
+ g_strfreev (keys);
}
else
{
- gsize i;
- gsize n;
- GStrv keys = g_key_file_get_keys (adp->keyfile, account, &n, NULL);
+ gchar *old;
- if (keys == NULL)
- n = 0;
+ val_str = mcp_account_manager_escape_variant_for_keyfile (am, val);
- for (i = 0; i < n; i++)
- {
- gchar *v = g_key_file_get_value (adp->keyfile, account, keys[i], NULL);
-
- if (v != NULL)
- mcp_account_manager_set_value (am, account, keys[i], v);
+ old = g_key_file_get_value (adp->keyfile, account, key, NULL);
- g_free (v);
+ if (tp_strdiff (old, val_str))
+ {
+ g_key_file_set_value (adp->keyfile, account, key, val_str);
+ adp->save = TRUE;
+ changed = TRUE;
}
- g_strfreev (keys);
+ g_free (val_str);
+ g_free (old);
}
- return TRUE;
+ if (changed)
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_CHANGED;
+ else
+ return MCP_ACCOUNT_STORAGE_SET_RESULT_UNCHANGED;
}
-static gboolean
-_delete (const McpAccountStorage *self,
- const McpAccountManager *am,
+static McpAccountStorageSetResult
+_set_attribute (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *attribute,
+ GVariant *val,
+ McpAttributeFlags flags)
+{
+ return _set (self, am, account, attribute, val, flags);
+}
+
+static McpAccountStorageSetResult
+_set_parameter (McpAccountStorage *self,
+ McpAccountManager *am,
const gchar *account,
- const gchar *key)
+ const gchar *parameter,
+ GVariant *val,
+ McpParameterFlags flags)
+{
+ gchar *param = g_strdup_printf ("param-%s", parameter);
+ gboolean ret;
+
+ ret = _set (self, am, account, param, val, flags);
+ g_free (param);
+
+ return ret;
+}
+
+static GVariant *
+_get_attribute (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *attribute,
+ const GVariantType *type,
+ McpAttributeFlags *flags)
+{
+ AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (self);
+ gchar *v;
+ GVariant *ret;
+
+ if (flags != NULL)
+ *flags = 0;
+
+ v = g_key_file_get_value (adp->keyfile, account, attribute, NULL);
+
+ if (v == NULL)
+ return NULL;
+
+ ret = mcp_account_manager_unescape_variant_from_keyfile (am, v, type, NULL);
+ g_free (v);
+ return ret;
+}
+
+static GVariant *
+_get_parameter (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ const gchar *parameter,
+ const GVariantType *type,
+ McpParameterFlags *flags)
{
AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (self);
+ gchar *key;
+ gchar *v;
+ GVariant *ret;
+
+ if (flags != NULL)
+ *flags = 0;
+
+ /* this plugin does not store parameters' types, so we can't invent
+ * a sensible type from nowhere */
+ if (type == NULL)
+ return NULL;
- if (key == NULL)
+ key = g_strdup_printf ("param-%s", parameter);
+ v = g_key_file_get_value (adp->keyfile, account, key, NULL);
+ g_free (key);
+
+ if (v == NULL)
+ return NULL;
+
+ ret = mcp_account_manager_unescape_variant_from_keyfile (am, v, type, NULL);
+ g_free (v);
+ return ret;
+}
+
+static gchar **
+list_typed_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account_name)
+{
+ /* this plugin can't store parameters' types */
+ return NULL;
+}
+
+static gchar **
+list_untyped_parameters (McpAccountStorage *storage,
+ McpAccountManager *am,
+ const gchar *account_name)
+{
+ AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (storage);
+ gchar **keys;
+ gsize i;
+ GPtrArray *arr;
+
+ keys = g_key_file_get_keys (adp->keyfile, account_name, &i, NULL);
+
+ if (keys == NULL)
+ return NULL;
+
+ arr = g_ptr_array_sized_new (i);
+
+ for (i = 0; keys[i] != NULL; i++)
{
- if (g_key_file_remove_group (adp->keyfile, account, NULL))
- adp->save = TRUE;
+ if (g_str_has_prefix (keys[i], "param-"))
+ g_ptr_array_add (arr, g_strdup (keys[i] + 6));
}
- else
- {
- gsize n;
- GStrv keys;
- if (g_key_file_remove_key (adp->keyfile, account, key, NULL))
- adp->save = TRUE;
+ g_strfreev (keys);
+ g_ptr_array_add (arr, NULL);
+ return (gchar **) g_ptr_array_free (arr, FALSE);
+}
- keys = g_key_file_get_keys (adp->keyfile, account, &n, NULL);
+static gboolean _commit (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account_name);
- if (keys == NULL || n == 0)
- g_key_file_remove_group (adp->keyfile, account, NULL);
+static void
+delete_async (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (self);
+ GTask *task = g_task_new (adp, cancellable, callback, user_data);
- g_strfreev (keys);
+ if (g_key_file_remove_group (adp->keyfile, account, NULL))
+ adp->save = TRUE;
+
+ if (_commit (self, am, account))
+ {
+ mcp_account_storage_emit_deleted (self, account);
+ g_task_return_boolean (task, TRUE);
+ }
+ else
+ {
+ g_task_return_new_error (task, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "_commit()'s error handling is not good enough to know why "
+ "I couldn't commit the deletion of %s", account);
}
- return TRUE;
+ g_object_unref (task);
}
+static gboolean
+delete_finish (McpAccountStorage *storage,
+ GAsyncResult *res,
+ GError **error)
+{
+ return g_task_propagate_boolean (G_TASK (res), error);
+}
static gboolean
-_commit (const McpAccountStorage *self,
- const McpAccountManager *am)
+_commit (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *account_name G_GNUC_UNUSED)
{
gsize n;
gchar *data;
AccountDiversionPlugin *adp = ACCOUNT_DIVERSION_PLUGIN (self);
gboolean rval = FALSE;
+ /* This simple implementation ignores account_name and commits everything:
+ * we're writing out the whole keyfile anyway. If MC is looping over
+ * accounts, the second and subsequent accounts will find that
+ * adp->save is false, so there's no write-amplification. */
+
if (!adp->save)
return TRUE;
@@ -228,8 +363,8 @@ _commit (const McpAccountStorage *self,
}
static GList *
-_list (const McpAccountStorage *self,
- const McpAccountManager *am)
+_list (McpAccountStorage *self,
+ McpAccountManager *am)
{
gsize i;
gsize n;
@@ -254,6 +389,35 @@ _list (const McpAccountStorage *self,
return rval;
}
+static gchar *
+create (McpAccountStorage *self,
+ McpAccountManager *am,
+ const gchar *manager,
+ const gchar *protocol,
+ const gchar *identification,
+ GError **error)
+{
+ gchar *unique_name;
+
+ unique_name = mcp_account_manager_get_unique_name (MCP_ACCOUNT_MANAGER (am),
+ manager, protocol,
+ identification);
+
+ g_return_val_if_fail (unique_name != NULL, NULL);
+
+ if (g_str_has_prefix (unique_name, DONT_DIVERT))
+ {
+ g_free (unique_name);
+ return NULL;
+ }
+
+ /* No need to actually create anything: we'll happily return values
+ * from get(., ., ., NULL) regardless of whether we have that account
+ * in our list */
+
+ return unique_name;
+}
+
static void
account_storage_iface_init (McpAccountStorageIface *iface,
gpointer unused G_GNUC_UNUSED)
@@ -262,11 +426,17 @@ account_storage_iface_init (McpAccountStorageIface *iface,
iface->desc = PLUGIN_DESCRIPTION;
iface->priority = PLUGIN_PRIORITY;
- iface->get = _get;
- iface->set = _set;
- iface->delete = _delete;
+ iface->get_attribute = _get_attribute;
+ iface->get_parameter = _get_parameter;
+ iface->list_typed_parameters = list_typed_parameters;
+ iface->list_untyped_parameters = list_untyped_parameters;
+ iface->set_attribute = _set_attribute;
+ iface->set_parameter = _set_parameter;
+ iface->delete_async = delete_async;
+ iface->delete_finish = delete_finish;
iface->commit = _commit;
iface->list = _list;
+ iface->create = create;
}
diff --git a/tests/twisted/mcp-dbus-caller-permission.c b/tests/twisted/mcp-dbus-caller-permission.c
deleted file mode 100644
index 96162baf..00000000
--- a/tests/twisted/mcp-dbus-caller-permission.c
+++ /dev/null
@@ -1,264 +0,0 @@
-/*
- * A demonstration plugin that checks a DBus caller's md5sum
- *
- * Copyright © 2010 Nokia Corporation
- * 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
- */
-
-#include <mission-control-plugins/mission-control-plugins.h>
-#include <sys/types.h>
-
-#define CONFFILE "mcp-dbus-caller-permissions.conf"
-
-#define DEBUG g_debug
-
-#define PLUGIN_NAME "dbus-caller-permission-checker"
-#define PLUGIN_DESCRIPTION \
- "Test plugin that checks the md5 checksum of a DBus caller. " \
- "gkeyfile g_get_user_cache_dir()/" CONFFILE " holds the [paths " \
- "to] the binaries, and the permission tokens associated with each."
-
-/* Example conf file:
-[/usr/local/bin/mc-tool]
-org.freedesktop.Telepathy.AccountManager=1
-*=1
-*/
-
-static void dbus_acl_iface_init (McpDBusAclIface *,
- gpointer);
-
-typedef struct {
- GObject parent;
- GKeyFile *permits;
- gboolean loaded;
-} DBusCallerPermission;
-
-typedef struct {
- GObjectClass parent_class;
-} DBusCallerPermissionClass;
-
-GType dbus_caller_permission_get_type (void) G_GNUC_CONST;
-
-#define DBUS_CALLER_PERMISSION(o) \
- (G_TYPE_CHECK_INSTANCE_CAST ((o), dbus_caller_permission_get_type (), \
- DBusCallerPermission))
-
-G_DEFINE_TYPE_WITH_CODE (DBusCallerPermission, dbus_caller_permission,
- G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, dbus_acl_iface_init));
-
-static void
-dbus_caller_permission_init (DBusCallerPermission *self)
-{
- const gchar *dir;
- gchar *file = NULL;
-
- self->permits = g_key_file_new ();
-
- dir = g_get_user_cache_dir ();
- file = g_build_path (G_DIR_SEPARATOR_S, dir, CONFFILE, NULL);
-
- if (!g_file_test (file, G_FILE_TEST_EXISTS))
- {
- g_mkdir_with_parents (dir, 0700);
- g_file_set_contents (file, "# MC DBus permissions\n", -1, NULL);
- }
-
- DEBUG ("conf file %s", file);
- g_key_file_load_from_file (self->permits, file, G_KEY_FILE_NONE, NULL);
-
- g_free (file);
-}
-
-static void
-dbus_caller_permission_class_init (DBusCallerPermissionClass *cls)
-{
-}
-
-static gboolean is_filtered (const McpDBusAcl *self,
- DBusAclType type,
- const gchar *name)
-{
- DBusCallerPermission *plugin = DBUS_CALLER_PERMISSION (self);
- GKeyFile *permits = plugin->permits;
-
- switch (type)
- {
- case DBUS_ACL_TYPE_METHOD:
- return g_key_file_get_boolean (permits, "methods", name, NULL);
- case DBUS_ACL_TYPE_GET_PROPERTY:
- return g_key_file_get_boolean (permits, "get-property", name, NULL);
- case DBUS_ACL_TYPE_SET_PROPERTY:
- return g_key_file_get_boolean (permits, "set-property", name, NULL);
- default:
- return FALSE;
- }
-}
-
-static gboolean
-pid_is_permitted (const McpDBusAcl *self, const gchar *name, pid_t pid)
-{
- gboolean ok = FALSE;
-
- if (pid != 0)
- {
- gchar *path = g_strdup_printf ("/proc/%d/exe", pid);
- gchar *executable = g_file_read_link (path, NULL);
-
- if (executable != NULL)
- {
- DBusCallerPermission *plugin = DBUS_CALLER_PERMISSION (self);
- GKeyFile *permits = plugin->permits;
-
- DEBUG ("executable to check for permission is %s", executable);
- ok = g_key_file_get_boolean (permits, executable, name, NULL);
- DEBUG ("%s:%s = %s", executable, name, ok ? "TRUE" : "FALSE");
-
- g_free (executable);
- }
-
- g_free (path);
- }
-
- return ok;
-}
-
-static gboolean
-caller_authorised (const McpDBusAcl *self,
- const TpDBusDaemon *dbus,
- const DBusGMethodInvocation *call,
- DBusAclType type,
- const gchar *name,
- const GHashTable *params)
-{
- DBusGConnection *dgc = tp_proxy_get_dbus_connection ((TpDBusDaemon *)dbus);
- gboolean ok = TRUE;
-
- if (is_filtered (self, type, name))
- {
- pid_t pid = 0;
- GError *error = NULL;
- gchar *caller = dbus_g_method_get_sender ((DBusGMethodInvocation *) call);
- DBusGProxy *proxy = dbus_g_proxy_new_for_name (dgc,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- dbus_g_proxy_call (proxy, "GetConnectionUnixProcessID", &error,
- G_TYPE_STRING, caller,
- G_TYPE_INVALID,
- G_TYPE_UINT, &pid,
- G_TYPE_INVALID);
-
- ok = pid_is_permitted (self, name, pid);
-
- g_free (caller);
- g_object_unref (proxy);
- }
-
- DEBUG ("sync caller-permission ACL check [%s]", ok ? "Allowed" : "Forbidden");
-
- return ok;
-}
-
-static void
-async_authorised_cb (DBusGProxy *proxy,
- DBusGProxyCall *call,
- gpointer data)
-{
- GError *error = NULL;
- DBusAclAuthData *ad = data;
- pid_t pid = 0;
- const McpDBusAcl *self = ad->acl;
- gboolean permitted = FALSE;
-
- /* if this returns FALSE, there's no PID, which means something bizarre *
- * and untrustowrthy is going on, which in turn means we must deny: can't *
- * authorise without first authenticating */
- permitted = dbus_g_proxy_end_call (proxy, call, &error,
- G_TYPE_UINT, &pid,
- G_TYPE_INVALID);
-
- if (permitted)
- permitted = pid_is_permitted (self, ad->name, pid);
- else
- g_error_free (error);
-
- DEBUG ("finished async caller-permission ACL check [%u -> %s]",
- pid, permitted ? "Allowed" : "Forbidden");
-
- mcp_dbus_acl_authorised_async_step (ad, permitted);
-}
-
-static void
-caller_async_authorised (const McpDBusAcl *self,
- DBusAclAuthData *data)
-{
- DBusGConnection *dgc = tp_proxy_get_dbus_connection (data->dbus);
- DBusGProxy *proxy = dbus_g_proxy_new_for_name (dgc,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS);
-
- DEBUG ("starting async caller-permission ACL check");
-
- if (is_filtered (self, data->type, data->name))
- {
- gchar *caller = dbus_g_method_get_sender (data->context);
-
- dbus_g_proxy_begin_call (proxy, "GetConnectionUnixProcessID",
- async_authorised_cb,
- data,
- NULL,
- G_TYPE_STRING, caller,
- G_TYPE_INVALID);
-
- g_free (caller);
- }
- else /* not filtered, so the call is allowed: */
- {
- mcp_dbus_acl_authorised_async_step (data, TRUE);
- }
-}
-
-
-static void
-dbus_acl_iface_init (McpDBusAclIface *iface,
- gpointer unused G_GNUC_UNUSED)
-{
- mcp_dbus_acl_iface_set_name (iface, PLUGIN_NAME);
- mcp_dbus_acl_iface_set_desc (iface, PLUGIN_DESCRIPTION);
-
- mcp_dbus_acl_iface_implement_authorised (iface, caller_authorised);
- mcp_dbus_acl_iface_implement_authorised_async (iface, caller_async_authorised);
-}
-
-GObject *
-mcp_plugin_ref_nth_object (guint n)
-{
- DEBUG ("Initializing mcp-dbus-caller-id plugin (n=%u)", n);
-
- switch (n)
- {
- case 0:
- return g_object_new (dbus_caller_permission_get_type (), NULL);
-
- default:
- return NULL;
- }
-}
-
diff --git a/tests/twisted/mcp-plugin.c b/tests/twisted/mcp-plugin.c
index 7d347b11..de74134f 100644
--- a/tests/twisted/mcp-plugin.c
+++ b/tests/twisted/mcp-plugin.c
@@ -49,7 +49,6 @@ GType test_no_op_plugin_get_type (void) G_GNUC_CONST;
G_DEFINE_TYPE_WITH_CODE (TestNoOpPlugin, test_no_op_plugin,
G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (MCP_TYPE_DBUS_ACL, NULL);
G_IMPLEMENT_INTERFACE (MCP_TYPE_REQUEST_POLICY, NULL);
G_IMPLEMENT_INTERFACE (MCP_TYPE_DISPATCH_OPERATION_POLICY, NULL))
@@ -137,11 +136,8 @@ permission_cb (DBusPendingCall *pc,
}
else
{
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- mcp_dispatch_operation_leave_channels (ctx->dispatch_operation,
- TRUE, TP_CHANNEL_GROUP_CHANGE_REASON_PERMISSION_DENIED,
- "Computer says no");
- G_GNUC_END_IGNORE_DEPRECATIONS
+ mcp_dispatch_operation_destroy_channels (ctx->dispatch_operation,
+ TRUE);
}
}
else
@@ -513,12 +509,8 @@ test_rejection_plugin_check_cdo (McpDispatchOperationPolicy *policy,
}
else if (!tp_strdiff (target_id, "mc.hammer@example.net"))
{
- DEBUG ("MC Hammer detected, leaving channels when observers have run");
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- mcp_dispatch_operation_leave_channels (dispatch_operation, TRUE,
- TP_CHANNEL_GROUP_CHANGE_REASON_PERMISSION_DENIED,
- "Can't touch this");
- G_GNUC_END_IGNORE_DEPRECATIONS
+ DEBUG ("MC Hammer detected, destroying channels when observers have run");
+ mcp_dispatch_operation_destroy_channels (dispatch_operation, TRUE);
}
g_hash_table_unref (properties);
diff --git a/tests/twisted/mctest.py b/tests/twisted/mctest.py
index 2909acc9..549a742c 100644
--- a/tests/twisted/mctest.py
+++ b/tests/twisted/mctest.py
@@ -166,7 +166,7 @@ def exec_test_deferred (fun, params, protocol=None, timeout=None,
try:
account.Properties.Set(cs.ACCOUNT, 'RequestedPresence',
- (dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE), 'offline',
+ (dbus.UInt32(cs.PRESENCE_OFFLINE), 'offline',
''))
except dbus.DBusException, e:
print >> sys.stderr, "Can't set %s offline: %s" % (a, e)
@@ -222,7 +222,7 @@ class SimulatedConnection(object):
def __init__(self, q, bus, cmname, protocol, account_part, self_ident,
self_alias=None,
- implement_get_interfaces=True, has_requests=True,
+ implement_get_channels=True, has_requests=True,
has_presence=False, has_aliasing=False, has_avatars=False,
avatars_persist=True, extra_interfaces=[], has_hidden=False,
implement_get_aliases=True, initial_avatar=None,
@@ -292,10 +292,12 @@ class SimulatedConnection(object):
interface=cs.PROPERTIES_IFACE, method='GetAll',
args=[cs.CONN])
- if implement_get_interfaces:
- q.add_dbus_method_impl(self.GetInterfaces,
- path=self.object_path, interface=cs.CONN,
- method='GetInterfaces')
+ q.add_dbus_method_impl(self.GetInterfaces,
+ path=self.object_path, interface=cs.CONN,
+ method='GetInterfaces')
+ q.add_dbus_method_impl(self.Get_Interfaces,
+ path=self.object_path, interface=cs.PROPERTIES_IFACE,
+ method='Get', args=[cs.CONN, 'Interfaces'])
q.add_dbus_method_impl(self.RequestHandles,
path=self.object_path, interface=cs.CONN,
@@ -306,10 +308,12 @@ class SimulatedConnection(object):
q.add_dbus_method_impl(self.HoldHandles,
path=self.object_path, interface=cs.CONN,
method='HoldHandles')
- q.add_dbus_method_impl(self.GetAll_Requests,
- path=self.object_path,
- interface=cs.PROPERTIES_IFACE, method='GetAll',
- args=[cs.CONN_IFACE_REQUESTS])
+
+ if implement_get_channels and has_requests:
+ q.add_dbus_method_impl(self.GetAll_Requests,
+ path=self.object_path,
+ interface=cs.PROPERTIES_IFACE, method='GetAll',
+ args=[cs.CONN_IFACE_REQUESTS])
q.add_dbus_method_impl(self.GetContactAttributes,
path=self.object_path,
@@ -373,22 +377,22 @@ class SimulatedConnection(object):
method='SetAvatar')
self.statuses = dbus.Dictionary({
- 'available': (cs.PRESENCE_TYPE_AVAILABLE, True, True),
- 'away': (cs.PRESENCE_TYPE_AWAY, True, True),
- 'lunch': (cs.PRESENCE_TYPE_XA, True, True),
- 'busy': (cs.PRESENCE_TYPE_BUSY, True, True),
- 'phone': (cs.PRESENCE_TYPE_BUSY, True, True),
- 'offline': (cs.PRESENCE_TYPE_OFFLINE, False, False),
- 'error': (cs.PRESENCE_TYPE_ERROR, False, False),
- 'unknown': (cs.PRESENCE_TYPE_UNKNOWN, False, False),
+ 'available': (cs.PRESENCE_AVAILABLE, True, True),
+ 'away': (cs.PRESENCE_AWAY, True, True),
+ 'lunch': (cs.PRESENCE_EXTENDED_AWAY, True, True),
+ 'busy': (cs.PRESENCE_BUSY, True, True),
+ 'phone': (cs.PRESENCE_BUSY, True, True),
+ 'offline': (cs.PRESENCE_OFFLINE, False, False),
+ 'error': (cs.PRESENCE_ERROR, False, False),
+ 'unknown': (cs.PRESENCE_UNKNOWN, False, False),
}, signature='s(ubb)')
if has_hidden:
- self.statuses['hidden'] = (cs.PRESENCE_TYPE_HIDDEN, True, True)
+ self.statuses['hidden'] = (cs.PRESENCE_HIDDEN, True, True)
# "dbus.UInt32" to work around
# https://bugs.freedesktop.org/show_bug.cgi?id=69967
- self.presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_TYPE_OFFLINE),
+ self.presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_OFFLINE),
'offline', ''), signature='uss')
def change_self_ident(self, ident):
@@ -495,7 +499,7 @@ class SimulatedConnection(object):
else:
# stub - MC doesn't care
ret[contact] = dbus.Struct(
- (cs.PRESENCE_TYPE_UNKNOWN, 'unknown', ''),
+ (cs.PRESENCE_UNKNOWN, 'unknown', ''),
signature='uss')
self.q.dbus_return(e.message, ret, signature='a{u(uss)}')
@@ -530,14 +534,19 @@ class SimulatedConnection(object):
def GetInterfaces(self, e):
self.q.dbus_return(e.message, self.interfaces, signature='as')
+ def Get_Interfaces(self, e):
+ self.q.dbus_return(e.message,
+ dbus.Array(self.interfaces, signature='s'),
+ signature='v')
+
def Connect(self, e):
self.StatusChanged(cs.CONN_STATUS_CONNECTING,
- cs.CONN_STATUS_REASON_REQUESTED)
+ cs.CSR_REQUESTED)
self.q.dbus_return(e.message, signature='')
def Disconnect(self, e):
self.StatusChanged(cs.CONN_STATUS_DISCONNECTED,
- cs.CONN_STATUS_REASON_REQUESTED)
+ cs.CSR_REQUESTED)
self.q.dbus_return(e.message, signature='')
for c in self.channels:
c.close()
@@ -581,11 +590,10 @@ class SimulatedConnection(object):
self.q.dbus_emit(self.object_path, cs.CONN, 'StatusChanged',
status, reason, signature='uu')
if self.status == cs.CONN_STATUS_CONNECTED and self.has_presence:
- if self.presence[0] == cs.PRESENCE_TYPE_OFFLINE:
+ if self.presence[0] == cs.PRESENCE_OFFLINE:
# "dbus.UInt32" to work around
# https://bugs.freedesktop.org/show_bug.cgi?id=69967
- self.presence = dbus.Struct((
- dbus.UInt32(cs.PRESENCE_TYPE_AVAILABLE),
+ self.presence = dbus.Struct((dbus.UInt32(cs.PRESENCE_AVAILABLE),
'available', ''), signature='uss')
self.q.dbus_emit(self.object_path,
@@ -837,7 +845,7 @@ class SimulatedClient(object):
observe=[], approve=[], handle=[],
cap_tokens=[], bypass_approval=False, wants_recovery=False,
request_notification=True, implement_get_interfaces=True,
- is_handler=None, bypass_observers=False, delay_approvers=False):
+ is_handler=None, delay_approvers=False):
self.q = q
self.bus = bus
self.bus_name = '.'.join([cs.tp_name_prefix, 'Client', clientname])
@@ -847,7 +855,6 @@ class SimulatedClient(object):
self.approve = aasv(approve)
self.handle = aasv(handle)
self.bypass_approval = bool(bypass_approval)
- self.bypass_observers = bool(bypass_observers)
self.delay_approvers = bool(delay_approvers)
self.wants_recovery = bool(wants_recovery)
self.request_notification = bool(request_notification)
@@ -963,7 +970,6 @@ class SimulatedClient(object):
self.q.dbus_return(e.message, {
'HandlerChannelFilter': self.handle,
'BypassApproval': self.bypass_approval,
- 'BypassObservers': self.bypass_observers,
'HandledChannels': self.handled_channels,
'Capabilities': self.cap_tokens,
},
@@ -987,21 +993,173 @@ class SimulatedClient(object):
self.q.dbus_return(e.message, self.bypass_approval, signature='v',
bus=self.bus)
- def Get_BypassApproval(self, e):
- assert self.handle
- self.q.dbus_return(e.message, self.bypass_observers, signature='v',
- bus=self.bus)
-
def Get_Recover(self, e):
assert self.handle
self.q.dbus_return(e.message, self.recover, signature='v',
bus=self.bus)
+class SimulatedConnectionManager(object):
+ def __init__(self, q, bus, cm_name='fakecm',
+ protocol_names=['fakeprotocol']):
+ self.q = q
+ self.bus = bus
+ self.cm_name = cm_name
+ self.bus_name = '.'.join([cs.CM, cm_name])
+ self._bus_name_ref = dbus.service.BusName(self.bus_name, self.bus)
+ self.object_path = '/' + self.bus_name.replace('.', '/')
+ self.protocol_names = list(protocol_names)
+
+ q.add_dbus_method_impl(self.GetAll_CM,
+ path=self.object_path,
+ interface=cs.PROPERTIES_IFACE, method='GetAll',
+ args=[cs.CM])
+
+ for protocol_name in protocol_names:
+ assert '-' not in protocol_name
+
+ q.add_dbus_method_impl(self.IdentifyAccount,
+ interface=cs.PROTOCOL, method='IdentifyAccount')
+ q.add_dbus_method_impl(self.NormalizeContact,
+ interface=cs.PROTOCOL, method='NormalizeContact')
+
+ def release_name(self):
+ del self._bus_name_ref
+
+ def reacquire_name(self):
+ self._bus_name_ref = dbus.service.BusName(self.bus_name, self.bus)
+
+ def get_protocols(self):
+ ret = dbus.Dictionary(signature='sa{sv}')
+
+ for p in self.protocol_names:
+ # stub: assume all the protocols look "reasonably normal"
+ ret[p] = {
+ cs.PROTOCOL + '.Interfaces': dbus.Array(signature='s'),
+ cs.PROTOCOL + '.ConnectionInterfaces':
+ dbus.Array(signature='s'),
+ cs.PROTOCOL + '.RequestableChannelClasses':
+ dbus.Array(signature='(a{sv}as)'),
+ cs.PROTOCOL + '.VCardField': 'x-' + self.cm_name,
+ cs.PROTOCOL + '.EnglishName': self.cm_name,
+ cs.PROTOCOL + '.Icon': 'im-' + self.cm_name,
+ cs.PROTOCOL + '.AuthenticationTypes':
+ dbus.Array(signature='s'),
+ cs.PROTOCOL + '.Parameters': dbus.Array([
+ ('account', cs.PARAM_REQUIRED, 's', ''),
+ ('password', cs.PARAM_SECRET, 's', ''),
+ ], signature='(susv)'),
+ }
+
+ if self.cm_name == 'fakecm' and p == 'fakeprotocol':
+ ret[p][cs.PROTOCOL + '.Parameters'] = dbus.Array([
+ ('account', cs.PARAM_REQUIRED|cs.PARAM_REGISTER,
+ 's', ''),
+ ('password',
+ cs.PARAM_SECRET|cs.PARAM_REQUIRED|cs.PARAM_REGISTER,
+ 's', ''),
+ ('nickname', cs.PARAM_REGISTER, 's', ''),
+ ('register', cs.PARAM_HAS_DEFAULT, 'b', False),
+ ('com.example.Badgerable.Badgered',
+ cs.PARAM_HAS_DEFAULT|cs.PARAM_DBUS_PROPERTY,
+ 'b', False),
+ ('secret-mushroom', cs.PARAM_SECRET, 's', ''),
+ ('snakes', 0, 'u', dbus.UInt32(0)),
+ ('contrived-example', cs.PARAM_HAS_DEFAULT, 'u',
+ dbus.UInt32(5)),
+ ], signature='(susv)')
+
+ if self.cm_name == 'onewitheverything' and p == 'serializable':
+ ret[p][cs.PROTOCOL + '.Parameters'] = dbus.Array([
+ ('s', cs.PARAM_REQUIRED, 's', ''),
+ ('o', 0, 'o', dbus.ObjectPath('/')),
+ ('b', 0, 'b', False),
+ ('q', 0, 'q', dbus.UInt16(0)),
+ ('u', 0, 'u', dbus.UInt32(0)),
+ ('t', 0, 't', dbus.UInt64(0)),
+ ('n', 0, 'n', dbus.Int16(0)),
+ ('i', 0, 'i', dbus.Int32(0)),
+ ('x', 0, 'x', dbus.Int64(0)),
+ ('d', 0, 'd', 0.0),
+ ('as', 0, 'as', dbus.Array(signature='s')),
+ ('y', 0, 'y', dbus.Byte(0)),
+ ], signature='(susv)')
+
+ if self.cm_name == 'onewitheverything' and p == 'defaults':
+ ret[p][cs.PROTOCOL + '.Parameters'] = dbus.Array([
+ ('s', cs.PARAM_HAS_DEFAULT, 's', 'foo'),
+ ('o', cs.PARAM_HAS_DEFAULT, 'o', dbus.ObjectPath('/foo')),
+ ('b', cs.PARAM_HAS_DEFAULT, 'b', True),
+ ('q', cs.PARAM_HAS_DEFAULT, 'q', dbus.UInt16(1)),
+ ('u', cs.PARAM_HAS_DEFAULT, 'u', dbus.UInt32(1)),
+ ('t', cs.PARAM_HAS_DEFAULT, 't', dbus.UInt64(1)),
+ ('n', cs.PARAM_HAS_DEFAULT, 'n', dbus.Int16(-1)),
+ ('i', cs.PARAM_HAS_DEFAULT, 'i', dbus.Int32(-1)),
+ ('x', cs.PARAM_HAS_DEFAULT, 'x', dbus.Int64(-1)),
+ ('d', cs.PARAM_HAS_DEFAULT, 'd', 1.5),
+ ('as', cs.PARAM_HAS_DEFAULT, 'as',
+ dbus.Array(['foo', 'bar', 'baz'], signature='s')),
+ ('y', cs.PARAM_HAS_DEFAULT, 'y', dbus.Byte(1)),
+ ], signature='(susv)')
+
+ if self.cm_name == 'onewitheverything' and p == 'flags':
+ ret[p][cs.PROTOCOL + '.Parameters'] = dbus.Array([
+ ('account', cs.PARAM_REQUIRED|cs.PARAM_REGISTER, 's', ''),
+ ('name', cs.PARAM_REGISTER, 's', ''),
+ ('key',
+ cs.PARAM_REGISTER|cs.PARAM_REQUIRED|cs.PARAM_SECRET,
+ 's', ''),
+ ('com.example.Badgerable.Badgers', cs.PARAM_DBUS_PROPERTY,
+ 's', ''),
+ ], signature='(susv)')
+
+ return ret
+
+ def get_interfaces(self):
+ return dbus.Array([], signature='s')
+
+ def GetAll_CM(self, e):
+ self.q.dbus_return(e.message, {
+ 'Protocols': self.get_protocols(),
+ 'Interfaces': self.get_interfaces(),
+ }, signature='a{sv}', bus=self.bus)
+
+ def IdentifyAccount(self, e):
+ if e.path.startswith(self.object_path + '/'):
+ protocol = e.path[len(self.object_path + '/'):]
+
+ if protocol not in self.protocol_names:
+ self.q.dbus_raise(e.message, cs.DBUS_ERROR_UNKNOWN_METHOD,
+ 'Not my protocol')
+ return
+ else:
+ self.q.dbus_raise(e.message, cs.DBUS_ERROR_UNKNOWN_METHOD,
+ 'Not even my object path')
+ return
+
+ if protocol in ('serializable', 'defaults') and 's' in e.args[0]:
+ ret = e.args[0]['s'].lower()
+ if ret:
+ self.q.dbus_return(e.message, ret, signature='s')
+ return
+
+ if 'account' in e.args[0]:
+ ret = e.args[0]['account'].lower()
+ if ret:
+ self.q.dbus_return(e.message, ret, signature='s')
+ return
+
+ self.q.dbus_raise(e.message, cs.INVALID_HANDLE,
+ 'Invalid account name %r' % e.args[0].get('account'))
+
+ def NormalizeContact(self, e):
+ self.q.dbus_return(e.message, e.args[0].lower(), signature='s')
+
def take_fakecm_name(bus):
return dbus.service.BusName(cs.CM + '.fakecm', bus=bus)
def create_fakecm_account(q, bus, mc, params, properties={},
- cm_bus=None):
+ cm_bus=None, simulated_cm=None,
+ cm_name='fakecm', protocol_name='fakeprotocol'):
"""Create a fake connection manager and an account that uses it.
Optional keyword arguments:
@@ -1016,23 +1174,17 @@ def create_fakecm_account(q, bus, mc, params, properties={},
if cm_bus is None:
cm_bus = bus
- cm_name_ref = take_fakecm_name(cm_bus)
+ if simulated_cm is None:
+ simulated_cm = SimulatedConnectionManager(q, bus,
+ cm_name=cm_name, protocol_names=[protocol_name])
account_manager = AccountManager(bus)
servicetest.call_async(q, account_manager, 'CreateAccount',
- 'fakecm', 'fakeprotocol', 'fakeaccount', params, properties)
-
- # Check whether the account being created is to be hidden; if so, then
- # expect a different signal. It annoys me that this has to be in here, but,
- # eh.
- if properties.get(cs.ACCOUNT_IFACE_HIDDEN + '.Hidden', False):
- validity_changed_pattern = servicetest.EventPattern('dbus-signal',
- path=cs.AM_PATH, signal='HiddenAccountValidityChanged',
- interface=cs.AM_IFACE_HIDDEN)
- else:
- validity_changed_pattern = servicetest.EventPattern('dbus-signal',
- path=cs.AM_PATH, signal='AccountValidityChanged', interface=cs.AM)
+ cm_name, protocol_name, 'fakeaccount', params, properties)
+
+ validity_changed_pattern = servicetest.EventPattern('dbus-signal',
+ path=cs.AM_PATH, signal='AccountValidityChanged', interface=cs.AM)
# The spec has no order guarantee here.
# FIXME: MC ought to also introspect the CM and find out that the params
@@ -1056,7 +1208,7 @@ def create_fakecm_account(q, bus, mc, params, properties={},
interface, prop = key.rsplit('.', 1)
servicetest.assertEquals(value, account.Properties.Get(interface, prop))
- return (cm_name_ref, account)
+ return (simulated_cm, account)
def get_fakecm_account(bus, mc, account_path):
account = Account(bus, account_path)
@@ -1096,19 +1248,25 @@ def expect_fakecm_connection(q, bus, mc, account, expected_params,
extra_interfaces=[],
expect_before_connect=(), expect_after_connect=(),
has_hidden=False,
- self_ident='myself'):
+ self_ident='myself',
+ cm_name='fakecm',
+ protocol_name='fakeprotocol'):
# make (safely) mutable copies
expect_before_connect = list(expect_before_connect)
expect_after_connect = list(expect_after_connect)
+ # for simplicity we assume the sort of name that is invariant between
+ # Telepathy 0 and Telepathy 1
+ assert '-' not in protocol_name
+
e = q.expect('dbus-method-call', method='RequestConnection',
- args=['fakeprotocol', expected_params],
- destination=cs.tp_name_prefix + '.ConnectionManager.fakecm',
- path=cs.tp_path_prefix + '/ConnectionManager/fakecm',
- interface=cs.tp_name_prefix + '.ConnectionManager',
+ args=[protocol_name, expected_params],
+ destination=cs.CM + '.' + cm_name,
+ path='/' + cs.CM.replace('.', '/') + '/' + cm_name,
+ interface=cs.CM,
handled=False)
- conn = SimulatedConnection(q, bus, 'fakecm', 'fakeprotocol',
+ conn = SimulatedConnection(q, bus, cm_name, protocol_name,
account.object_path.split('/')[-1],
self_ident, has_requests=has_requests, has_presence=has_presence,
has_aliasing=has_aliasing, has_avatars=has_avatars,
@@ -1133,21 +1291,12 @@ def expect_fakecm_connection(q, bus, mc, account, expected_params,
q.expect('dbus-method-call', method='Connect',
path=conn.object_path, handled=True)
- conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CONN_STATUS_REASON_NONE)
+ conn.StatusChanged(cs.CONN_STATUS_CONNECTED, cs.CSR_NONE_SPECIFIED)
expect_after_connect = list(expect_after_connect)
- if not has_requests:
- expect_after_connect.append(
- servicetest.EventPattern('dbus-method-call',
- interface=cs.CONN, method='ListChannels', args=[],
- path=conn.object_path, handled=True))
-
events = events + list(q.expect_many(*expect_after_connect))
- if not has_requests:
- del events[-1]
-
if events:
return (conn,) + tuple(events)
diff --git a/tests/twisted/run-test.sh.in b/tests/twisted/run-test.sh.in
index 56ade7b3..5f29132d 100644
--- a/tests/twisted/run-test.sh.in
+++ b/tests/twisted/run-test.sh.in
@@ -19,7 +19,7 @@ export MC_TEST_CURDIR
if test "x$MC_TEST_UNINSTALLED" = x; then
script_fullname=`readlink -e "@mctestsdir@/twisted/run-test.sh"`
if [ `readlink -e "$0"` != "$script_fullname" ] ; then
- echo "This script is meant to be installed at $script_fullname" >&2
+ echo "Bail out! This script is meant to be installed at $script_fullname"
exit 1
fi
@@ -35,11 +35,11 @@ if test "x$MC_TEST_UNINSTALLED" = x; then
export MC_TWISTED_PATH
else
if test -z "$MC_ABS_TOP_SRCDIR"; then
- echo "MC_ABS_TOP_SRCDIR must be set" >&2
+ echo "Bail out! MC_ABS_TOP_SRCDIR must be set"
exit 1
fi
if test -z "$MC_ABS_TOP_BUILDDIR"; then
- echo "MC_ABS_TOP_BUILDDIR must be set" >&2
+ echo "Bail out! MC_ABS_TOP_BUILDDIR must be set"
exit 1
fi
@@ -59,9 +59,6 @@ MC_DEBUG=all
export MC_DEBUG
G_DEBUG=fatal-criticals
export G_DEBUG
-# for ENABLE_LIBACCOUNTS_SSO
-AG_DEBUG=all
-export AG_DEBUG
GIO_EXTRA_MODULES="${plugins}"
export GIO_EXTRA_MODULES
@@ -82,11 +79,20 @@ else
list=$(cat "${test_build}"/twisted/mc-twisted-tests.list)
fi
-any_failed=0
+n=0
for i in $list ; do
- echo "Testing $i ..."
+ n=$(( $n + 1 ))
+done
+
+echo "1..$n"
+
+i=0
+n_failed=0
+for t in $list ; do
+ i=$(( $i + 1 ))
+ echo "# Testing $i/$n: $t ..."
- tmp="${MC_TEST_CURDIR}/tmp-`echo $i | tr ./ __`"
+ tmp="${MC_TEST_CURDIR}/tmp-`echo $t | tr ./ __`"
rm -fr "$tmp"
mkdir "$tmp"
@@ -105,12 +111,6 @@ for i in $list ; do
XDG_CACHE_DIR="${tmp}/cache"
export XDG_CACHE_DIR
- # for ENABLE_LIBACCOUNTS_SSO
- ACCOUNTS="${tmp}/libaccounts-accounts"
- export ACCOUNTS
- AG_SERVICES="${tmp}/libaccounts-services"
- export AG_SERVICES
-
CHECK_TWISTED_VERBOSE=1
export CHECK_TWISTED_VERBOSE
@@ -120,32 +120,38 @@ for i in $list ; do
--also-for-system \
--config-file="${config_file}" \
-- \
- @TEST_PYTHON@ -u "${test_src}/twisted/$i" \
+ @TEST_PYTHON@ -u "${test_src}/twisted/$t" \
> "$tmp"/test.log 2>&1 || e=$?
case "$e" in
(0)
- echo "PASS: $i"
+ echo "ok $i - $t"
if test -z "$MC_TEST_KEEP_TEMP"; then
rm -fr "$tmp"
fi
;;
(77)
- echo "SKIP: $i"
+ echo "ok $i # SKIP $t"
if test -z "$MC_TEST_KEEP_TEMP"; then
rm -fr "$tmp"
fi
;;
(*)
- any_failed=1
- echo "FAIL: $i ($e)"
+ n_failed=$(( $n_failed + 1 ))
+ echo "not ok $i - $t ($e)"
(
cd $tmp && for x in *.log; do
- echo "===== log file: $x ====="
- cat "$x"
+ echo "# ===== log file: $x ====="
+ sed 's/^/# /' "$x"
done
+ echo "# ===== end of log files for $t ====="
)
;;
esac
done
-exit $any_failed
+if test $n_failed != 0; then
+ echo "# Tests run: $n; tests failed: $n_failed"
+ exit 1
+else
+ exit 0
+fi
diff --git a/tests/twisted/servicetest.py b/tests/twisted/servicetest.py
index 4dc604f3..821240b0 100644
--- a/tests/twisted/servicetest.py
+++ b/tests/twisted/servicetest.py
@@ -1,5 +1,5 @@
# Copyright (C) 2009 Nokia Corporation
-# Copyright (C) 2009 Collabora Ltd.
+# Copyright (C) 2009-2013 Collabora Ltd.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -17,30 +17,55 @@
# 02110-1301 USA
"""
-Infrastructure code for testing Mission Control
+Infrastructure code for testing Telepathy services.
"""
from twisted.internet import glib2reactor
from twisted.internet.protocol import Protocol, Factory, ClientFactory
glib2reactor.install()
import sys
+import time
+import os
import pprint
import unittest
import dbus
import dbus.lowlevel
-import dbus.glib
+from dbus.mainloop.glib import DBusGMainLoop
+DBusGMainLoop(set_as_default=True)
from twisted.internet import reactor
-tp_name_prefix = 'org.freedesktop.Telepathy'
-tp_path_prefix = '/org/freedesktop/Telepathy'
+import constants as cs
-class Event:
+tp_name_prefix = cs.PREFIX
+tp_path_prefix = cs.PATH_PREFIX
+
+class DictionarySupersetOf (object):
+ """Utility class for expecting "a dictionary with at least these keys"."""
+ def __init__(self, dictionary):
+ self._dictionary = dictionary
+ def __repr__(self):
+ return "DictionarySupersetOf(%s)" % self._dictionary
+ def __eq__(self, other):
+ """would like to just do:
+ return set(other.items()).issuperset(self._dictionary.items())
+ but it turns out that this doesn't work if you have another dict
+ nested in the values of your dicts"""
+ try:
+ for k,v in self._dictionary.items():
+ if k not in other or other[k] != v:
+ return False
+ return True
+ except TypeError: # other is not iterable
+ return False
+
+class Event(object):
def __init__(self, type, **kw):
self.__dict__.update(kw)
self.type = type
+ (self.subqueue, self.subtype) = type.split ("-", 1)
def __str__(self):
return '\n'.join([ str(type(self)) ] + format_event(self))
@@ -48,7 +73,7 @@ class Event:
def format_event(event):
ret = ['- type %s' % event.type]
- for key in dir(event):
+ for key in sorted(dir(event)):
if key != 'type' and not key.startswith('_'):
ret.append('- %s: %s' % (
key, pprint.pformat(getattr(event, key))))
@@ -61,16 +86,17 @@ def format_event(event):
class EventPattern:
def __init__(self, type, **properties):
self.type = type
- self.predicate = lambda x: True
+ self.predicate = None
if 'predicate' in properties:
self.predicate = properties['predicate']
del properties['predicate']
self.properties = properties
+ (self.subqueue, self.subtype) = type.split ("-", 1)
def __repr__(self):
properties = dict(self.properties)
- if self.predicate:
+ if self.predicate is not None:
properties['predicate'] = self.predicate
return '%s(%r, **%r)' % (
@@ -87,7 +113,7 @@ class EventPattern:
except AttributeError:
return False
- if self.predicate(event):
+ if self.predicate is None or self.predicate(event):
return True
return False
@@ -112,8 +138,8 @@ class BaseEventQueue:
def __init__(self, timeout=None):
self.verbose = False
- self.past_events = []
self.forbidden_events = set()
+ self.event_queues = {}
if timeout is None:
self.timeout = 5
@@ -124,28 +150,14 @@ class BaseEventQueue:
if self.verbose:
print s
- def log_event(self, event):
- if self.verbose:
- self.log('got event:')
-
- if self.verbose:
- map(self.log, format_event(event))
-
- def flush_past_events(self):
- self.past_events = []
+ def log_queues(self, queues):
+ self.log ("Waiting for event on: %s" % ", ".join(queues))
- def expect_racy(self, type, **kw):
- pattern = EventPattern(type, **kw)
-
- for event in self.past_events:
- if pattern.match(event):
- self.log('past event handled')
- map(self.log, format_event(event))
- self.log('')
- self.past_events.remove(event)
- return event
+ def log_event(self, event):
+ self.log('got event:')
- return self.expect(type, **kw)
+ if self.verbose:
+ map(self.log, format_event(event))
def forbid_events(self, patterns):
"""
@@ -163,34 +175,86 @@ class BaseEventQueue:
"""
self.forbidden_events.difference_update(set(patterns))
+ def unforbid_all(self):
+ """
+ Remove all patterns from the set of forbidden events.
+ """
+ self.forbidden_events.clear()
+
def _check_forbidden(self, event):
for e in self.forbidden_events:
if e.match(event):
raise ForbiddenEventOccurred(event)
def expect(self, type, **kw):
+ """
+ Waits for an event matching the supplied pattern to occur, and returns
+ it. For example, to await a D-Bus signal with particular arguments:
+
+ e = q.expect('dbus-signal', signal='Badgers', args=["foo", 42])
+ """
pattern = EventPattern(type, **kw)
+ t = time.time()
while True:
- event = self.wait()
- self.log_event(event)
+ try:
+ event = self.wait([pattern.subqueue])
+ except TimeoutError:
+ self.log('timeout')
+ self.log('still expecting:')
+ self.log(' - %r' % pattern)
+ raise
+
self._check_forbidden(event)
if pattern.match(event):
- self.log('handled')
+ self.log('handled, took %0.3f ms'
+ % ((time.time() - t) * 1000.0) )
self.log('')
return event
- self.past_events.append(event)
self.log('not handled')
self.log('')
def expect_many(self, *patterns):
+ """
+ Waits for events matching all of the supplied EventPattern instances to
+ return, and returns a list of events in the same order as the patterns
+ they matched. After a pattern is successfully matched, it is not
+ considered for future events; if more than one unsatisfied pattern
+ matches an event, the first "wins".
+
+ Note that the expected events may occur in any order. If you're
+ expecting a series of events in a particular order, use repeated calls
+ to expect() instead.
+
+ This method is useful when you're awaiting a number of events which may
+ happen in any order. For instance, in telepathy-gabble, calling a D-Bus
+ method often causes a value to be returned immediately, as well as a
+ query to be sent to the server. Since these events may reach the test
+ in either order, the following is incorrect and will fail if the IQ
+ happens to reach the test first:
+
+ ret = q.expect('dbus-return', method='Foo')
+ query = q.expect('stream-iq', query_ns=ns.FOO)
+
+ The following would be correct:
+
+ ret, query = q.expect_many(
+ EventPattern('dbus-return', method='Foo'),
+ EventPattern('stream-iq', query_ns=ns.FOO),
+ )
+ """
ret = [None] * len(patterns)
+ t = time.time()
while None in ret:
try:
- event = self.wait()
+ queues = set()
+ for i, pattern in enumerate(patterns):
+ if ret[i] is None:
+ queues.add(pattern.subqueue)
+ event = self.wait(queues)
except TimeoutError:
self.log('timeout')
self.log('still expecting:')
@@ -198,17 +262,16 @@ class BaseEventQueue:
if ret[i] is None:
self.log(' - %r' % pattern)
raise
- self.log_event(event)
self._check_forbidden(event)
for i, pattern in enumerate(patterns):
if ret[i] is None and pattern.match(event):
- self.log('handled')
+ self.log('handled, took %0.3f ms'
+ % ((time.time() - t) * 1000.0) )
self.log('')
ret[i] = event
break
else:
- self.past_events.append(event)
self.log('not handled')
self.log('')
@@ -217,8 +280,7 @@ class BaseEventQueue:
def demand(self, type, **kw):
pattern = EventPattern(type, **kw)
- event = self.wait()
- self.log_event(event)
+ event = self.wait([pattern.subqueue])
if pattern.match(event):
self.log('handled')
@@ -228,19 +290,39 @@ class BaseEventQueue:
self.log('not handled')
raise RuntimeError('expected %r, got %r' % (pattern, event))
+ def queues_available(self, queues):
+ if queues == None:
+ return self.event_queues.keys()
+ else:
+ available = self.event_queues.keys()
+ return filter(lambda x: x in available, queues)
+
+
+ def pop_next(self, queue):
+ events = self.event_queues[queue]
+ e = events.pop(0)
+ if not events:
+ self.event_queues.pop (queue)
+ return e
+
+ def append(self, event):
+ self.log ("Adding to queue")
+ self.log_event (event)
+ self.event_queues[event.subqueue] = \
+ self.event_queues.get(event.subqueue, []) + [event]
+
class IteratingEventQueue(BaseEventQueue):
"""Event queue that works by iterating the Twisted reactor."""
def __init__(self, timeout=None):
BaseEventQueue.__init__(self, timeout)
- self.events = []
self._dbus_method_impls = []
self._buses = []
# a message filter which will claim we handled everything
self._dbus_dev_null = \
lambda bus, message: dbus.lowlevel.HANDLER_RESULT_HANDLED
- def wait(self):
+ def wait(self, queues=None):
stop = [False]
def later():
@@ -248,21 +330,21 @@ class IteratingEventQueue(BaseEventQueue):
delayed_call = reactor.callLater(self.timeout, later)
- while (not self.events) and (not stop[0]):
- reactor.iterate(0.1)
+ self.log_queues(queues)
+
+ qa = self.queues_available(queues)
+ while not qa and (not stop[0]):
+ reactor.iterate(0.01)
+ qa = self.queues_available(queues)
- if self.events:
+ if qa:
delayed_call.cancel()
- return self.events.pop(0)
+ e = self.pop_next (qa[0])
+ self.log_event (e)
+ return e
else:
raise TimeoutError
- def append(self, event):
- self.events.append(event)
-
- # compatibility
- handle_event = append
-
def add_dbus_method_impl(self, cb, bus=None, **kwargs):
if bus is None:
bus = self._buses[0]
@@ -387,50 +469,74 @@ class IteratingEventQueue(BaseEventQueue):
class TestEventQueue(BaseEventQueue):
def __init__(self, events):
BaseEventQueue.__init__(self)
- self.events = events
+ for e in events:
+ self.append (e)
- def wait(self):
- if self.events:
- return self.events.pop(0)
+ def wait(self, queues = None):
+ qa = self.queues_available(queues)
+
+ if qa:
+ return self.pop_next (qa[0])
else:
raise TimeoutError
class EventQueueTest(unittest.TestCase):
def test_expect(self):
- queue = TestEventQueue([Event('foo'), Event('bar')])
- assert queue.expect('foo').type == 'foo'
- assert queue.expect('bar').type == 'bar'
+ queue = TestEventQueue([Event('test-foo'), Event('test-bar')])
+ assert queue.expect('test-foo').type == 'test-foo'
+ assert queue.expect('test-bar').type == 'test-bar'
def test_expect_many(self):
- queue = TestEventQueue([Event('foo'), Event('bar')])
+ queue = TestEventQueue([Event('test-foo'),
+ Event('test-bar')])
bar, foo = queue.expect_many(
- EventPattern('bar'),
- EventPattern('foo'))
- assert bar.type == 'bar'
- assert foo.type == 'foo'
+ EventPattern('test-bar'),
+ EventPattern('test-foo'))
+ assert bar.type == 'test-bar'
+ assert foo.type == 'test-foo'
def test_expect_many2(self):
# Test that events are only matched against patterns that haven't yet
# been matched. This tests a regression.
- queue = TestEventQueue([Event('foo', x=1), Event('foo', x=2)])
+ queue = TestEventQueue([Event('test-foo', x=1), Event('test-foo', x=2)])
foo1, foo2 = queue.expect_many(
- EventPattern('foo'),
- EventPattern('foo'))
- assert foo1.type == 'foo' and foo1.x == 1
- assert foo2.type == 'foo' and foo2.x == 2
+ EventPattern('test-foo'),
+ EventPattern('test-foo'))
+ assert foo1.type == 'test-foo' and foo1.x == 1
+ assert foo2.type == 'test-foo' and foo2.x == 2
+
+ def test_expect_queueing(self):
+ queue = TestEventQueue([Event('foo-test', x=1),
+ Event('foo-test', x=2)])
+
+ queue.append(Event('bar-test', x=1))
+ queue.append(Event('bar-test', x=2))
+
+ queue.append(Event('baz-test', x=1))
+ queue.append(Event('baz-test', x=2))
+
+ for x in xrange(1,2):
+ e = queue.expect ('baz-test')
+ assertEquals (x, e.x)
+
+ e = queue.expect ('bar-test')
+ assertEquals (x, e.x)
+
+ e = queue.expect ('foo-test')
+ assertEquals (x, e.x)
def test_timeout(self):
queue = TestEventQueue([])
- self.assertRaises(TimeoutError, queue.expect, 'foo')
+ self.assertRaises(TimeoutError, queue.expect, 'test-foo')
def test_demand(self):
- queue = TestEventQueue([Event('foo'), Event('bar')])
- foo = queue.demand('foo')
- assert foo.type == 'foo'
+ queue = TestEventQueue([Event('test-foo'), Event('test-bar')])
+ foo = queue.demand('test-foo')
+ assert foo.type == 'test-foo'
def test_demand_fail(self):
- queue = TestEventQueue([Event('foo'), Event('bar')])
- self.assertRaises(RuntimeError, queue.demand, 'bar')
+ queue = TestEventQueue([Event('test-foo'), Event('test-bar')])
+ self.assertRaises(RuntimeError, queue.demand, 'test-bar')
def unwrap(x):
"""Hack to unwrap D-Bus values, so that they're easier to read when
@@ -459,11 +565,11 @@ def call_async(test, proxy, method, *args, **kw):
resulting method return/error."""
def reply_func(*ret):
- test.handle_event(Event('dbus-return', method=method,
+ test.append(Event('dbus-return', method=method,
value=unwrap(ret)))
def error_func(err):
- test.handle_event(Event('dbus-error', method=method, error=err,
+ test.append(Event('dbus-error', method=method, error=err,
name=err.get_dbus_name(), message=str(err)))
method_proxy = getattr(proxy, method)
@@ -481,7 +587,7 @@ def sync_dbus(bus, q, proxy):
q.expect('dbus-error', method='DummySyncDBus')
class ProxyWrapper:
- def __init__(self, object, default, others):
+ def __init__(self, object, default, others={}):
self.object = object
self.default_interface = dbus.Interface(object, default)
self.Properties = dbus.Interface(object, dbus.PROPERTIES_IFACE)
@@ -500,6 +606,41 @@ class ProxyWrapper:
return getattr(self.default_interface, name)
+class ConnWrapper(ProxyWrapper):
+ def inspect_contact_sync(self, handle):
+ return self.inspect_contacts_sync([handle])[0]
+
+ def inspect_contacts_sync(self, handles):
+ h2asv = self.Contacts.GetContactAttributes(handles, [], True)
+ ret = []
+ for h in handles:
+ ret.append(h2asv[h][cs.ATTR_CONTACT_ID])
+ return ret
+
+ def get_contact_handle_sync(self, identifier):
+ return self.Contacts.GetContactByID(identifier, [])[0]
+
+ def get_contact_handles_sync(self, ids):
+ return [self.get_contact_handle_sync(i) for i in ids]
+
+def wrap_connection(conn):
+ return ConnWrapper(conn, tp_name_prefix + '.Connection',
+ dict([
+ (name, tp_name_prefix + '.Connection.Interface.' + name)
+ for name in ['Aliasing', 'Avatars', 'Capabilities', 'Contacts',
+ 'SimplePresence', 'Requests']] +
+ [('Peer', 'org.freedesktop.DBus.Peer'),
+ ('ContactCapabilities', cs.CONN_IFACE_CONTACT_CAPS),
+ ('ContactInfo', cs.CONN_IFACE_CONTACT_INFO),
+ ('Location', cs.CONN_IFACE_LOCATION),
+ ('Future', tp_name_prefix + '.Connection.FUTURE'),
+ ('MailNotification', cs.CONN_IFACE_MAIL_NOTIFICATION),
+ ('ContactList', cs.CONN_IFACE_CONTACT_LIST),
+ ('ContactGroups', cs.CONN_IFACE_CONTACT_GROUPS),
+ ('PowerSaving', cs.CONN_IFACE_POWER_SAVING),
+ ('Addressing', cs.CONN_IFACE_ADDRESSING),
+ ]))
+
def wrap_channel(chan, type_, extra=None):
interfaces = {
type_: tp_name_prefix + '.Channel.Type.' + type_,
@@ -513,14 +654,26 @@ def wrap_channel(chan, type_, extra=None):
return ProxyWrapper(chan, tp_name_prefix + '.Channel', interfaces)
+
+def wrap_content(chan, extra=None):
+ interfaces = { }
+
+ if extra:
+ interfaces.update(dict([
+ (name, tp_name_prefix + '.Call1.Content.Interface.' + name)
+ for name in extra]))
+
+ return ProxyWrapper(chan, tp_name_prefix + '.Call1.Content', interfaces)
+
def make_connection(bus, event_func, name, proto, params):
cm = bus.get_object(
tp_name_prefix + '.ConnectionManager.%s' % name,
- tp_path_prefix + '/ConnectionManager/%s' % name)
+ tp_path_prefix + '/ConnectionManager/%s' % name,
+ introspect=False)
cm_iface = dbus.Interface(cm, tp_name_prefix + '.ConnectionManager')
connection_name, connection_path = cm_iface.RequestConnection(
- proto, params)
+ proto, dbus.Dictionary(params, signature='sv'))
conn = wrap_connection(bus.get_object(connection_name, connection_path))
return conn
@@ -540,7 +693,7 @@ class EventProtocol(Protocol):
def dataReceived(self, data):
if self.queue is not None:
- self.queue.handle_event(Event('socket-data', protocol=self,
+ self.queue.append(Event('socket-data', protocol=self,
data=data))
def sendData(self, data):
@@ -552,7 +705,7 @@ class EventProtocol(Protocol):
def connectionLost(self, reason=None):
if self.queue is not None:
- self.queue.handle_event(Event('socket-disconnected', protocol=self))
+ self.queue.append(Event('socket-disconnected', protocol=self))
class EventProtocolFactory(Factory):
def __init__(self, queue, block_reading=False):
@@ -564,7 +717,7 @@ class EventProtocolFactory(Factory):
def buildProtocol(self, addr):
proto = self._create_protocol()
- self.queue.handle_event(Event('socket-connected', protocol=proto))
+ self.queue.append(Event('socket-connected', protocol=proto))
return proto
class EventProtocolClientFactory(EventProtocolFactory, ClientFactory):
@@ -572,7 +725,7 @@ class EventProtocolClientFactory(EventProtocolFactory, ClientFactory):
def watch_tube_signals(q, tube):
def got_signal_cb(*args, **kwargs):
- q.handle_event(Event('tube-signal',
+ q.append(Event('tube-signal',
path=kwargs['path'],
signal=kwargs['member'],
args=map(unwrap, args),
@@ -590,6 +743,15 @@ def assertEquals(expected, value):
raise AssertionError(
"expected:\n%s\ngot:\n%s" % (pretty(expected), pretty(value)))
+def assertSameSets(expected, value):
+ exp_set = set(expected)
+ val_set = set(value)
+
+ if exp_set != val_set:
+ raise AssertionError(
+ "expected contents:\n%s\ngot:\n%s" % (
+ pretty(exp_set), pretty(val_set)))
+
def assertNotEquals(expected, value):
if expected == value:
raise AssertionError(
@@ -624,15 +786,11 @@ def assertFlagsUnset(flags, value):
"expected none of flags %u, but %u are set in %u" % (
flags, masked, value))
-def assertSameSets(expected, value):
- exp_set = set(expected)
- val_set = set(value)
-
- if exp_set != val_set:
+def assertDBusError(name, error):
+ if error.get_dbus_name() != name:
raise AssertionError(
- "expected contents:\n%s\ngot:\n%s" % (
- pretty(exp_set), pretty(val_set)))
-
+ "expected DBus error named:\n %s\ngot:\n %s\n(with message: %s)"
+ % (name, error.get_dbus_name(), error.message))
def install_colourer():
def red(s):
@@ -652,14 +810,26 @@ def install_colourer():
self.patterns = patterns
def write(self, s):
- f = self.patterns.get(s, lambda x: x)
- self.fh.write(f(s))
+ for p, f in self.patterns.items():
+ if s.startswith(p):
+ self.fh.write(f(p) + s[len(p):])
+ return
+
+ self.fh.write(s)
sys.stdout = Colourer(sys.stdout, patterns)
return sys.stdout
+# this is just to shut up unittest.
+class DummyStream(object):
+ def write(self, s):
+ if 'CHECK_TWISTED_VERBOSE' in os.environ:
+ print s,
+ def flush(self):
+ pass
if __name__ == '__main__':
- unittest.main()
-
+ stream = DummyStream()
+ runner = unittest.TextTestRunner(stream=stream)
+ unittest.main(testRunner=runner)
diff --git a/tests/twisted/tools/Makefile.am b/tests/twisted/tools/Makefile.am
index ffe04eff..9eb17c79 100644
--- a/tests/twisted/tools/Makefile.am
+++ b/tests/twisted/tools/Makefile.am
@@ -27,25 +27,25 @@ run-mc.sh: run-mc.sh.in Makefile
@chmod +x $@
servicedir-uninstalled/%.conf: servicedir-uninstalled/%.conf.in Makefile
- $(AM_V_at)$(mkdir_p) servicedir-uninstalled
+ $(AM_V_at)$(MKDIR_P) servicedir-uninstalled
$(AM_V_GEN)sed -e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" $< > $@
servicedir-installed/%.conf: servicedir-installed/%.conf.in Makefile
- $(AM_V_at)$(mkdir_p) servicedir-installed
+ $(AM_V_at)$(MKDIR_P) servicedir-installed
$(AM_V_GEN)sed -e "s|[@]mctestsdir[@]|@mctestsdir@|g" $< > $@
# We don't use the full filename for the .in because > 99 character filenames
# in tarballs are non-portable (and automake 1.8 doesn't let us build
# non-archaic tarballs)
servicedir-uninstalled/org.freedesktop.Telepathy.%.service: servicedir-uninstalled/%.service.in Makefile
- $(AM_V_at)$(mkdir_p) servicedir-uninstalled
+ $(AM_V_at)$(MKDIR_P) servicedir-uninstalled
$(AM_V_GEN)sed \
-e "s|[@]abs_top_srcdir[@]|@abs_top_srcdir@|g" \
-e "s|[@]abs_top_builddir[@]|@abs_top_builddir@|g" \
$< > $@
servicedir-installed/org.freedesktop.Telepathy.%.service: servicedir-installed/%.service.in Makefile
- $(AM_V_at)$(mkdir_p) servicedir-installed
+ $(AM_V_at)$(MKDIR_P) servicedir-installed
$(AM_V_GEN)sed \
-e "s|[@]mctestsdir[@]|@mctestsdir@|g" \
$< > $@
diff --git a/tests/value-is-same.c b/tests/value-is-same.c
index 1f7854ba..74097908 100644
--- a/tests/value-is-same.c
+++ b/tests/value-is-same.c
@@ -23,6 +23,8 @@
*
*/
+#include <config.h>
+
/* Yes, this is a hack */
#include "mcd-account.c"
diff --git a/tools/Makefile.am b/tools/Makefile.am
index a6db81e3..563b9ff0 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -1,35 +1,8 @@
EXTRA_DIST = \
- c-constants-generator.xsl \
- c-interfaces-generator.xsl \
- doc-generator.xsl \
- glib-client-gen.py \
- glib-blocking-client-gen.py \
- glib-client-marshaller-gen.py \
- glib-interfaces-generator.xsl \
- glib-interfaces-body-generator.xsl \
- glib-ginterface-gen.py \
- glib-gtypes-generator.py \
- identity.xsl \
lcov.am \
- libtpcodegen.py \
- libglibcodegen.py \
run_and_bt.gdb \
- spec-to-introspect.xsl \
telepathy.am
-CLEANFILES = libglibcodegen.pyc libglibcodegen.pyo
-
-all: $(EXTRA_DIST)
-
-libglibcodegen.py: libtpcodegen.py
- $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
-glib-client-marshaller-gen.py: libglibcodegen.py
- $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
-glib-ginterface-gen.py: libglibcodegen.py
- $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
-glib-gtypes-generator.py: libglibcodegen.py
- $(AM_V_GEN)test -e ${srcdir}/$@ && touch ${srcdir}/$@
-
TELEPATHY_GLIB_SRCDIR = $(top_srcdir)/../telepathy-glib
maintainer-update-from-telepathy-glib:
set -e && cd $(srcdir) && \
diff --git a/tools/c-constants-generator.xsl b/tools/c-constants-generator.xsl
deleted file mode 100644
index 18b2e495..00000000
--- a/tools/c-constants-generator.xsl
+++ /dev/null
@@ -1,299 +0,0 @@
-<!-- Stylesheet to extract C enumerations from the Telepathy spec.
-The master copy of this stylesheet is in telepathy-glib - please make any
-changes there.
-
-Copyright (C) 2006, 2007 Collabora Limited
-
-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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
--->
-
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- exclude-result-prefixes="tp">
-
- <xsl:output method="text" indent="no" encoding="ascii"/>
-
- <xsl:param name="mixed-case-prefix" select="''"/>
-
- <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
- <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
-
- <xsl:variable name="upper-case-prefix" select="concat(translate($mixed-case-prefix, $lower, $upper), '_')"/>
- <xsl:variable name="lower-case-prefix" select="concat(translate($mixed-case-prefix, $upper, $lower), '_')"/>
-
-
- <xsl:template match="tp:flags">
- <xsl:variable name="name">
- <xsl:choose>
- <xsl:when test="@plural">
- <xsl:value-of select="@plural"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="value-prefix">
- <xsl:choose>
- <xsl:when test="@singular">
- <xsl:value-of select="@singular"/>
- </xsl:when>
- <xsl:when test="@value-prefix">
- <xsl:value-of select="@value-prefix"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:text>/**&#10;</xsl:text>
- <xsl:text> *&#10;</xsl:text>
- <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>
- <xsl:text>:&#10;</xsl:text>
- <xsl:apply-templates mode="flag-or-enumvalue-gtkdoc">
- <xsl:with-param name="value-prefix" select="$value-prefix"/>
- </xsl:apply-templates>
- <xsl:text> *&#10;</xsl:text>
- <xsl:if test="tp:docstring">
- <xsl:text> * &lt;![CDATA[</xsl:text>
- <xsl:value-of select="translate(string (tp:docstring), '&#13;&#10;', ' ')"/>
- <xsl:text>]]&gt;&#10;</xsl:text>
- <xsl:text> *&#10;</xsl:text>
- </xsl:if>
- <xsl:text> * Bitfield/set of flags generated from the Telepathy specification.&#10;</xsl:text>
- <xsl:text> */&#10;</xsl:text>
- <xsl:text>typedef enum {&#10;</xsl:text>
- <xsl:apply-templates>
- <xsl:with-param name="value-prefix" select="$value-prefix"/>
- </xsl:apply-templates>
- <xsl:text>} </xsl:text>
- <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>
- <xsl:text>;&#10;</xsl:text>
- <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="text()" mode="flag-or-enumvalue-gtkdoc"/>
-
- <xsl:template match="tp:enumvalue" mode="flag-or-enumvalue-gtkdoc">
- <xsl:param name="value-prefix"/>
- <xsl:text> * @</xsl:text>
- <xsl:value-of select="translate(concat($upper-case-prefix, $value-prefix, '_', @suffix), $lower, $upper)"/>
- <xsl:text>: &lt;![CDATA[</xsl:text>
- <xsl:value-of select="translate(string(tp:docstring), '&#13;&#10;', ' ')"/>
- <xsl:text>]]&gt;&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="tp:flag" mode="flag-or-enumvalue-gtkdoc">
- <xsl:param name="value-prefix"/>
- <xsl:text> * @</xsl:text>
- <xsl:value-of select="translate(concat($upper-case-prefix, $value-prefix, '_', @suffix), $lower, $upper)"/>
- <xsl:text>: &lt;![CDATA[</xsl:text>
- <xsl:value-of select="translate(string(tp:docstring), '&#13;&#10;', ' ')"/>
- <xsl:text>]]&gt;&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="tp:enum">
- <xsl:variable name="name">
- <xsl:choose>
- <xsl:when test="@singular">
- <xsl:value-of select="@singular"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="value-prefix">
- <xsl:choose>
- <xsl:when test="@singular">
- <xsl:value-of select="@singular"/>
- </xsl:when>
- <xsl:when test="@value-prefix">
- <xsl:value-of select="@value-prefix"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="name-plural">
- <xsl:choose>
- <xsl:when test="@plural">
- <xsl:value-of select="@plural"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/><xsl:text>s</xsl:text>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:text>/**&#10;</xsl:text>
- <xsl:text> *&#10;</xsl:text>
- <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>
- <xsl:text>:&#10;</xsl:text>
- <xsl:apply-templates mode="flag-or-enumvalue-gtkdoc">
- <xsl:with-param name="value-prefix" select="$value-prefix"/>
- </xsl:apply-templates>
- <xsl:text> *&#10;</xsl:text>
- <xsl:if test="tp:docstring">
- <xsl:text> * &lt;![CDATA[</xsl:text>
- <xsl:value-of select="translate(string (tp:docstring), '&#13;&#10;', ' ')"/>
- <xsl:text>]]&gt;&#10;</xsl:text>
- <xsl:text> *&#10;</xsl:text>
- </xsl:if>
- <xsl:text> * Bitfield/set of flags generated from the Telepathy specification.&#10;</xsl:text>
- <xsl:text> */&#10;</xsl:text>
- <xsl:text>typedef enum {&#10;</xsl:text>
- <xsl:apply-templates>
- <xsl:with-param name="value-prefix" select="$value-prefix"/>
- </xsl:apply-templates>
- <xsl:text>} </xsl:text>
- <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>
- <xsl:text>;&#10;</xsl:text>
- <xsl:text>&#10;</xsl:text>
- <xsl:text>/**&#10;</xsl:text>
- <xsl:text> * NUM_</xsl:text>
- <xsl:value-of select="translate(concat($upper-case-prefix, $name-plural), $lower, $upper)"/>
- <xsl:text>:&#10;</xsl:text>
- <xsl:text> *&#10;</xsl:text>
- <xsl:text> * 1 higher than the highest valid value of #</xsl:text>
- <xsl:value-of select="translate(concat($mixed-case-prefix, $name), '_', '')"/>
- <xsl:text>.&#10;</xsl:text>
- <xsl:text> */&#10;</xsl:text>
- <xsl:text>#define NUM_</xsl:text>
- <xsl:value-of select="translate(concat($upper-case-prefix, $name-plural), $lower, $upper)"/>
- <xsl:text> (</xsl:text>
- <xsl:value-of select="tp:enumvalue[position() = last()]/@value"/>
- <xsl:text>+1)&#10;</xsl:text>
- <xsl:text>&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="tp:flags/tp:flag">
- <xsl:param name="value-prefix"/>
- <xsl:variable name="suffix">
- <xsl:choose>
- <xsl:when test="@suffix">
- <xsl:value-of select="@suffix"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="name" select="translate(concat($upper-case-prefix, $value-prefix, '_', $suffix), $lower, $upper)"/>
-
- <xsl:if test="@name and @suffix and @name != @suffix">
- <xsl:message terminate="yes">
- <xsl:text>Flag name </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text> != suffix </xsl:text>
- <xsl:value-of select="@suffix"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
- <xsl:text> </xsl:text>
- <xsl:value-of select="$name"/>
- <xsl:text> = </xsl:text>
- <xsl:value-of select="@value"/>
- <xsl:text>,&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="tp:enum/tp:enumvalue">
- <xsl:param name="value-prefix"/>
- <xsl:variable name="suffix">
- <xsl:choose>
- <xsl:when test="@suffix">
- <xsl:value-of select="@suffix"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:variable name="name" select="translate(concat($upper-case-prefix, $value-prefix, '_', $suffix), $lower, $upper)"/>
-
- <xsl:if test="@name and @suffix and @name != @suffix">
- <xsl:message terminate="yes">
- <xsl:text>Enumvalue name </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text> != suffix </xsl:text>
- <xsl:value-of select="@suffix"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="preceding-sibling::tp:enumvalue and number(preceding-sibling::tp:enumvalue[1]/@value) > number(@value)">
- <xsl:message terminate="yes">
- <xsl:text>Enum values must be in ascending numeric order, but </xsl:text>
- <xsl:value-of select="$name"/>
- <xsl:text> is less than the previous value</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:text> </xsl:text>
- <xsl:value-of select="$name"/>
- <xsl:text> = </xsl:text>
- <xsl:value-of select="@value"/>
- <xsl:text>,&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="tp:flag">
- <xsl:message terminate="yes">tp:flag found outside tp:flags&#10;</xsl:message>
- </xsl:template>
-
- <xsl:template match="tp:enumvalue">
- <xsl:message terminate="yes">tp:enumvalue found outside tp:enum&#10;</xsl:message>
- </xsl:template>
-
- <xsl:template match="text()"/>
-
- <xsl:template match="/tp:spec">
- <xsl:if test="$mixed-case-prefix = ''">
- <xsl:message terminate="yes">
- <xsl:text>mixed-case-prefix param must be set&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:text>/* Generated from </xsl:text>
- <xsl:value-of select="tp:title"/>
- <xsl:if test="tp:version">
- <xsl:text>, version </xsl:text>
- <xsl:value-of select="tp:version"/>
- </xsl:if>
- <xsl:text>&#10;</xsl:text>
- <xsl:text>&#10;</xsl:text>
- <xsl:for-each select="tp:copyright">
- <xsl:value-of select="."/>
- <xsl:text>&#10;</xsl:text>
- </xsl:for-each>
- <xsl:value-of select="tp:license"/>
- <xsl:text>&#10;</xsl:text>
- <xsl:value-of select="tp:docstring"/>
- <xsl:text>&#10;</xsl:text>
- <xsl:text> */&#10;</xsl:text>
- <xsl:text>&#10;</xsl:text>
- <xsl:text>#ifdef __cplusplus&#10;</xsl:text>
- <xsl:text>extern "C" {&#10;</xsl:text>
- <xsl:text>#endif&#10;</xsl:text>
- <xsl:text>&#10;</xsl:text>
- <xsl:apply-templates/>
- <xsl:text>&#10;</xsl:text>
- <xsl:text>#ifdef __cplusplus&#10;</xsl:text>
- <xsl:text>}&#10;</xsl:text>
- <xsl:text>#endif&#10;</xsl:text>
- </xsl:template>
-
-</xsl:stylesheet>
-
-<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/c-interfaces-generator.xsl b/tools/c-interfaces-generator.xsl
deleted file mode 100644
index f965a705..00000000
--- a/tools/c-interfaces-generator.xsl
+++ /dev/null
@@ -1,84 +0,0 @@
-<!-- Stylesheet to extract C enumerations from the Telepathy spec.
-The master copy of this stylesheet is in telepathy-glib - please make any
-changes there.
-
-Copyright (C) 2006, 2007 Collabora Limited
-
-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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
--->
-
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- exclude-result-prefixes="tp">
-
- <xsl:param name="mixed-case-prefix" select="''"/>
-
- <xsl:variable name="PREFIX"
- select="translate($mixed-case-prefix, $lower, $upper)"/>
- <xsl:variable name="Prefix" select="$mixed-case-prefix"/>
- <xsl:variable name="prefix"
- select="translate($mixed-case-prefix, $upper, $lower)"/>
-
- <xsl:output method="text" indent="no" encoding="ascii"/>
-
- <xsl:variable name="upper" select="'ABCDEFGHIJKLMNOPQRSTUVWXYZ'"/>
- <xsl:variable name="lower" select="'abcdefghijklmnopqrstuvwxyz'"/>
-
- <xsl:template match="interface">
- <xsl:text>/**&#10; * </xsl:text>
- <xsl:value-of select="$PREFIX"/>
- <xsl:text>_IFACE_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($lower, '/'), $upper)"/>
- <xsl:text>:&#10; * &#10; * The interface name "</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>"&#10; */&#10;#define </xsl:text>
- <xsl:value-of select="$PREFIX"/>
- <xsl:text>_IFACE_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($lower, '/'), $upper)"/>
- <xsl:text> \&#10;"</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>"&#10;&#10;</xsl:text>
- </xsl:template>
-
- <xsl:template match="text()"/>
-
- <xsl:template match="/tp:spec">
- <xsl:if test="$mixed-case-prefix = ''">
- <xsl:message terminate="yes">
- <xsl:text>mixed-case-prefix param must be set&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:text>/* Generated from: </xsl:text>
- <xsl:value-of select="tp:title"/>
- <xsl:if test="tp:version">
- <xsl:text> version </xsl:text>
- <xsl:value-of select="tp:version"/>
- </xsl:if>
- <xsl:text>&#10;&#10;</xsl:text>
- <xsl:for-each select="tp:copyright">
- <xsl:value-of select="."/>
- <xsl:text>&#10;</xsl:text>
- </xsl:for-each>
- <xsl:text>&#10;</xsl:text>
- <xsl:value-of select="tp:license"/>
- <xsl:value-of select="tp:docstring"/>
- <xsl:text>&#10; */&#10;&#10;</xsl:text>
- <xsl:apply-templates/>
- </xsl:template>
-
-</xsl:stylesheet>
-
-<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/doc-generator.xsl b/tools/doc-generator.xsl
deleted file mode 100644
index 76fc9696..00000000
--- a/tools/doc-generator.xsl
+++ /dev/null
@@ -1,1199 +0,0 @@
-<!-- Generate HTML documentation from the Telepathy specification.
-The master copy of this stylesheet is in the Telepathy spec repository -
-please make any changes there.
-
-Copyright (C) 2006-2008 Collabora Limited
-
-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
--->
-
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:html="http://www.w3.org/1999/xhtml"
- exclude-result-prefixes="tp html">
- <!--Don't move the declaration of the HTML namespace up here — XMLNSs
- don't work ideally in the presence of two things that want to use the
- absence of a prefix, sadly. -->
-
- <xsl:param name="allow-undefined-interfaces" select="false()"/>
-
- <xsl:template match="html:* | @*" mode="html">
- <xsl:copy>
- <xsl:apply-templates mode="html"/>
- </xsl:copy>
- </xsl:template>
-
- <xsl:template match="tp:type" mode="html">
- <xsl:call-template name="tp-type">
- <xsl:with-param name="tp-type" select="string(.)"/>
- </xsl:call-template>
- </xsl:template>
-
- <!-- tp:dbus-ref: reference a D-Bus interface, signal, method or property -->
- <xsl:template match="tp:dbus-ref" mode="html">
- <xsl:variable name="name">
- <xsl:choose>
- <xsl:when test="@namespace">
- <xsl:value-of select="@namespace"/>
- <xsl:text>.</xsl:text>
- </xsl:when>
- </xsl:choose>
- <xsl:value-of select="string(.)"/>
- </xsl:variable>
-
- <xsl:choose>
- <xsl:when test="//interface[@name=$name]
- or //interface/method[concat(../@name, '.', @name)=$name]
- or //interface/signal[concat(../@name, '.', @name)=$name]
- or //interface/property[concat(../@name, '.', @name)=$name]
- or //interface[@name=concat($name, '.DRAFT')]
- or //interface/method[
- concat(../@name, '.', @name)=concat($name, '.DRAFT')]
- or //interface/signal[
- concat(../@name, '.', @name)=concat($name, '.DRAFT')]
- or //interface/property[
- concat(../@name, '.', @name)=concat($name, '.DRAFT')]
- ">
- <a xmlns="http://www.w3.org/1999/xhtml" href="#{$name}">
- <xsl:value-of select="string(.)"/>
- </a>
- </xsl:when>
-
- <xsl:when test="$allow-undefined-interfaces">
- <span xmlns="http://www.w3.org/1999/xhtml" title="defined elsewhere">
- <xsl:value-of select="string(.)"/>
- </span>
- </xsl:when>
-
- <xsl:otherwise>
- <xsl:message terminate="yes">
- <xsl:text>ERR: cannot find D-Bus interface, method, </xsl:text>
- <xsl:text>signal or property called '</xsl:text>
- <xsl:value-of select="$name"/>
- <xsl:text>'&#10;</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <!-- tp:member-ref: reference a property of the current interface -->
- <xsl:template match="tp:member-ref" mode="html">
- <xsl:variable name="prefix" select="concat(ancestor::interface/@name,
- '.')"/>
- <xsl:variable name="name" select="string(.)"/>
-
- <xsl:if test="not(ancestor::interface)">
- <xsl:message terminate="yes">
- <xsl:text>ERR: Cannot use tp:member-ref when not in an</xsl:text>
- <xsl:text> &lt;interface&gt;&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:choose>
- <xsl:when test="ancestor::interface/signal[@name=$name]"/>
- <xsl:when test="ancestor::interface/method[@name=$name]"/>
- <xsl:when test="ancestor::interface/property[@name=$name]"/>
- <xsl:otherwise>
- <xsl:message terminate="yes">
- <xsl:text>ERR: interface </xsl:text>
- <xsl:value-of select="ancestor::interface/@name"/>
- <xsl:text> has no signal/method/property called </xsl:text>
- <xsl:value-of select="$name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
-
- <a xmlns="http://www.w3.org/1999/xhtml" href="#{$prefix}{$name}">
- <xsl:value-of select="$name"/>
- </a>
- </xsl:template>
-
- <xsl:template match="*" mode="identity">
- <xsl:copy>
- <xsl:apply-templates mode="identity"/>
- </xsl:copy>
- </xsl:template>
-
- <xsl:template match="tp:docstring">
- <xsl:apply-templates mode="html"/>
- </xsl:template>
-
- <xsl:template match="tp:added">
- <p class="added" xmlns="http://www.w3.org/1999/xhtml">Added in
- version <xsl:value-of select="@version"/>.
- <xsl:apply-templates select="node()" mode="html"/></p>
- </xsl:template>
-
- <xsl:template match="tp:changed">
- <xsl:choose>
- <xsl:when test="node()">
- <p class="changed" xmlns="http://www.w3.org/1999/xhtml">Changed in
- version <xsl:value-of select="@version"/>:
- <xsl:apply-templates select="node()" mode="html"/></p>
- </xsl:when>
- <xsl:otherwise>
- <p class="changed">Changed in version
- <xsl:value-of select="@version"/></p>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:template>
-
- <xsl:template match="tp:deprecated">
- <p class="deprecated" xmlns="http://www.w3.org/1999/xhtml">Deprecated
- since version <xsl:value-of select="@version"/>.
- <xsl:apply-templates select="node()" mode="html"/></p>
- </xsl:template>
-
- <xsl:template match="tp:rationale" mode="html">
- <div xmlns="http://www.w3.org/1999/xhtml" class="rationale">
- <xsl:apply-templates select="node()" mode="html"/>
- </div>
- </xsl:template>
-
- <xsl:template match="tp:errors">
- <h1 xmlns="http://www.w3.org/1999/xhtml">Errors</h1>
- <xsl:apply-templates/>
- </xsl:template>
-
- <xsl:template match="tp:generic-types">
- <h1 xmlns="http://www.w3.org/1999/xhtml">Generic types</h1>
- <xsl:call-template name="do-types"/>
- </xsl:template>
-
- <xsl:template name="do-types">
- <xsl:if test="tp:simple-type">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Simple types</h2>
- <xsl:apply-templates select="tp:simple-type"/>
- </xsl:if>
-
- <xsl:if test="tp:enum">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Enumerated types:</h2>
- <xsl:apply-templates select="tp:enum"/>
- </xsl:if>
-
- <xsl:if test="tp:flags">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Sets of flags:</h2>
- <xsl:apply-templates select="tp:flags"/>
- </xsl:if>
-
- <xsl:if test="tp:struct">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Structure types</h2>
- <xsl:apply-templates select="tp:struct"/>
- </xsl:if>
-
- <xsl:if test="tp:mapping">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Mapping types</h2>
- <xsl:apply-templates select="tp:mapping"/>
- </xsl:if>
-
- <xsl:if test="tp:external-type">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Types defined elsewhere</h2>
- <dl><xsl:apply-templates select="tp:external-type"/></dl>
- </xsl:if>
- </xsl:template>
-
- <xsl:template match="tp:error">
- <h2 xmlns="http://www.w3.org/1999/xhtml"><a name="{concat(../@namespace, '.', translate(@name, ' ', ''))}"></a><xsl:value-of select="concat(../@namespace, '.', translate(@name, ' ', ''))"/></h2>
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </xsl:template>
-
- <xsl:template match="/tp:spec/tp:copyright">
- <div xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates mode="text"/>
- </div>
- </xsl:template>
- <xsl:template match="/tp:spec/tp:license">
- <div xmlns="http://www.w3.org/1999/xhtml" class="license">
- <xsl:apply-templates mode="html"/>
- </div>
- </xsl:template>
-
- <xsl:template match="tp:copyright"/>
- <xsl:template match="tp:license"/>
-
- <xsl:template match="interface">
- <h1 xmlns="http://www.w3.org/1999/xhtml"><a name="{@name}"></a><xsl:value-of select="@name"/></h1>
-
- <xsl:if test="@tp:causes-havoc">
- <p xmlns="http://www.w3.org/1999/xhtml" class="causes-havoc">
- This interface is <xsl:value-of select="@tp:causes-havoc"/>
- and is likely to cause havoc to your API/ABI if bindings are generated.
- Don't include it in libraries that care about compatibility.
- </p>
- </xsl:if>
-
- <xsl:if test="tp:requires">
- <p>Implementations of this interface must also implement:</p>
- <ul xmlns="http://www.w3.org/1999/xhtml">
- <xsl:for-each select="tp:requires">
- <li><code><a href="#{@interface}"><xsl:value-of select="@interface"/></a></code></li>
- </xsl:for-each>
- </ul>
- </xsl:if>
-
- <xsl:apply-templates select="tp:docstring" />
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
-
- <xsl:choose>
- <xsl:when test="method">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Methods:</h2>
- <xsl:apply-templates select="method"/>
- </xsl:when>
- <xsl:otherwise>
- <p xmlns="http://www.w3.org/1999/xhtml">Interface has no methods.</p>
- </xsl:otherwise>
- </xsl:choose>
-
- <xsl:choose>
- <xsl:when test="signal">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Signals:</h2>
- <xsl:apply-templates select="signal"/>
- </xsl:when>
- <xsl:otherwise>
- <p xmlns="http://www.w3.org/1999/xhtml">Interface has no signals.</p>
- </xsl:otherwise>
- </xsl:choose>
-
- <xsl:choose>
- <xsl:when test="tp:property">
- <h2 xmlns="http://www.w3.org/1999/xhtml">Telepathy Properties:</h2>
- <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the
- <a href="#org.freedesktop.Telepathy.Properties">Telepathy
- Properties</a> interface.</p>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:property"/>
- </dl>
- </xsl:when>
- <xsl:otherwise>
- <p xmlns="http://www.w3.org/1999/xhtml">Interface has no Telepathy
- properties.</p>
- </xsl:otherwise>
- </xsl:choose>
-
- <xsl:choose>
- <xsl:when test="property">
- <h2 xmlns="http://www.w3.org/1999/xhtml">D-Bus core Properties:</h2>
- <p xmlns="http://www.w3.org/1999/xhtml">Accessed using the
- org.freedesktop.DBus.Properties interface.</p>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="property"/>
- </dl>
- </xsl:when>
- <xsl:otherwise>
- <p xmlns="http://www.w3.org/1999/xhtml">Interface has no D-Bus core
- properties.</p>
- </xsl:otherwise>
- </xsl:choose>
-
- <xsl:call-template name="do-types"/>
-
- </xsl:template>
-
- <xsl:template match="tp:flags">
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a tp:flags type&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @type on tp:flags type</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <h3>
- <a name="type-{@name}">
- <xsl:value-of select="@name"/>
- </a>
- </h3>
- <xsl:apply-templates select="tp:docstring" />
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:variable name="value-prefix">
- <xsl:choose>
- <xsl:when test="@value-prefix">
- <xsl:value-of select="@value-prefix"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:for-each select="tp:flag">
- <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt>
- <xsl:choose>
- <xsl:when test="tp:docstring">
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:docstring" />
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </dd>
- </xsl:when>
- <xsl:otherwise>
- <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:for-each>
- </dl>
- </xsl:template>
-
- <xsl:template match="tp:enum">
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a tp:enum type&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @type on tp:enum type</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <h3 xmlns="http://www.w3.org/1999/xhtml">
- <a name="type-{@name}">
- <xsl:value-of select="@name"/>
- </a>
- </h3>
- <xsl:apply-templates select="tp:docstring" />
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:variable name="value-prefix">
- <xsl:choose>
- <xsl:when test="@value-prefix">
- <xsl:value-of select="@value-prefix"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="@name"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
- <xsl:for-each select="tp:enumvalue">
- <dt xmlns="http://www.w3.org/1999/xhtml"><code><xsl:value-of select="concat($value-prefix, '_', @suffix)"/> = <xsl:value-of select="@value"/></code></dt>
- <xsl:choose>
- <xsl:when test="tp:docstring">
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:docstring" />
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </dd>
- </xsl:when>
- <xsl:otherwise>
- <dd xmlns="http://www.w3.org/1999/xhtml">(Undocumented)</dd>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:for-each>
- </dl>
- </xsl:template>
-
- <xsl:template match="property">
-
- <xsl:if test="not(parent::interface)">
- <xsl:message terminate="yes">
- <xsl:text>ERR: property </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text> does not have an interface as parent&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a property of </xsl:text>
- <xsl:value-of select="../@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @type on property </xsl:text>
- <xsl:value-of select="concat(../@name, '.', @name)"/>
- <xsl:text>: '</xsl:text>
- <xsl:value-of select="@access"/>
- <xsl:text>'&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <dt xmlns="http://www.w3.org/1999/xhtml">
- <a name="{concat(../@name, '.', @name)}">
- <code><xsl:value-of select="@name"/></code>
- </a>
- <xsl:text> − </xsl:text>
- <code><xsl:value-of select="@type"/></code>
- <xsl:call-template name="parenthesized-tp-type"/>
- <xsl:text>, </xsl:text>
- <xsl:choose>
- <xsl:when test="@access = 'read'">
- <xsl:text>read-only</xsl:text>
- </xsl:when>
- <xsl:when test="@access = 'write'">
- <xsl:text>write-only</xsl:text>
- </xsl:when>
- <xsl:when test="@access = 'readwrite'">
- <xsl:text>read/write</xsl:text>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">
- <xsl:text>ERR: unknown or missing value for </xsl:text>
- <xsl:text>@access on property </xsl:text>
- <xsl:value-of select="concat(../@name, '.', @name)"/>
- <xsl:text>: '</xsl:text>
- <xsl:value-of select="@access"/>
- <xsl:text>'&#10;</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </dt>
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </dd>
- </xsl:template>
-
- <xsl:template match="tp:property">
- <dt xmlns="http://www.w3.org/1999/xhtml">
- <xsl:if test="@name">
- <code><xsl:value-of select="@name"/></code> −
- </xsl:if>
- <code><xsl:value-of select="@type"/></code>
- </dt>
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </dd>
- </xsl:template>
-
- <xsl:template match="tp:mapping">
- <div xmlns="http://www.w3.org/1999/xhtml" class="struct">
- <h3>
- <a name="type-{@name}">
- <xsl:value-of select="@name"/>
- </a> − a{
- <xsl:for-each select="tp:member">
- <xsl:value-of select="@type"/>
- <xsl:text>: </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:if test="position() != last()"> &#x2192; </xsl:if>
- </xsl:for-each>
- }
- </h3>
- <div class="docstring">
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:if test="string(@array-name) != ''">
- <p>In bindings that need a separate name, arrays of
- <xsl:value-of select="@name"/> should be called
- <xsl:value-of select="@array-name"/>.</p>
- </xsl:if>
- </div>
- <div>
- <h4>Members</h4>
- <dl>
- <xsl:apply-templates select="tp:member" mode="members-in-docstring"/>
- </dl>
- </div>
- </div>
- </xsl:template>
-
- <xsl:template match="tp:docstring" mode="in-index"/>
-
- <xsl:template match="tp:simple-type | tp:enum | tp:flags | tp:external-type"
- mode="in-index">
- − <xsl:value-of select="@type"/>
- </xsl:template>
-
- <xsl:template match="tp:simple-type">
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a tp:simple-type&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @type on tp:simple-type</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <div xmlns="http://www.w3.org/1999/xhtml" class="simple-type">
- <h3>
- <a name="type-{@name}">
- <xsl:value-of select="@name"/>
- </a> − <xsl:value-of select="@type"/>
- </h3>
- <div class="docstring">
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </div>
- </div>
- </xsl:template>
-
- <xsl:template match="tp:external-type">
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a tp:external-type&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @type on tp:external-type</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <div xmlns="http://www.w3.org/1999/xhtml" class="external-type">
- <dt>
- <a name="type-{@name}">
- <xsl:value-of select="@name"/>
- </a> − <xsl:value-of select="@type"/>
- </dt>
- <dd>Defined by: <xsl:value-of select="@from"/></dd>
- </div>
- </xsl:template>
-
- <xsl:template match="tp:struct" mode="in-index">
- − ( <xsl:for-each select="tp:member">
- <xsl:value-of select="@type"/>
- <xsl:if test="position() != last()">, </xsl:if>
- </xsl:for-each> )
- </xsl:template>
-
- <xsl:template match="tp:mapping" mode="in-index">
- − a{ <xsl:for-each select="tp:member">
- <xsl:value-of select="@type"/>
- <xsl:if test="position() != last()"> &#x2192; </xsl:if>
- </xsl:for-each> }
- </xsl:template>
-
- <xsl:template match="tp:struct">
- <div xmlns="http://www.w3.org/1999/xhtml" class="struct">
- <h3>
- <a name="type-{@name}">
- <xsl:value-of select="@name"/>
- </a> − (
- <xsl:for-each select="tp:member">
- <xsl:value-of select="@type"/>
- <xsl:text>: </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:if test="position() != last()">, </xsl:if>
- </xsl:for-each>
- )
- </h3>
- <div class="docstring">
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </div>
- <xsl:choose>
- <xsl:when test="string(@array-name) != ''">
- <p>In bindings that need a separate name, arrays of
- <xsl:value-of select="@name"/> should be called
- <xsl:value-of select="@array-name"/>.</p>
- </xsl:when>
- <xsl:otherwise>
- <p>Arrays of <xsl:value-of select="@name"/> don't generally
- make sense.</p>
- </xsl:otherwise>
- </xsl:choose>
- <div>
- <h4>Members</h4>
- <dl>
- <xsl:apply-templates select="tp:member" mode="members-in-docstring"/>
- </dl>
- </div>
- </div>
- </xsl:template>
-
- <xsl:template match="method">
-
- <xsl:if test="not(parent::interface)">
- <xsl:message terminate="yes">
- <xsl:text>ERR: method </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text> does not have an interface as parent&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a method of </xsl:text>
- <xsl:value-of select="../@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:for-each select="arg">
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: an arg of method </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has no type</xsl:text>
- </xsl:message>
- </xsl:if>
- <xsl:choose>
- <xsl:when test="@direction='in'">
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: an 'in' arg of method </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has no name</xsl:text>
- </xsl:message>
- </xsl:if>
- </xsl:when>
- <xsl:when test="@direction='out'">
- <!-- FIXME: This is commented out until someone with a lot of time
- on their hands goes through the spec adding names to all the "out"
- arguments
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="no">
- <xsl:text>INFO: an 'out' arg of method </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has no name</xsl:text>
- </xsl:message>
- </xsl:if>-->
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">
- <xsl:text>ERR: an arg of method </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has direction neither 'in' nor 'out'</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:for-each>
-
- <div xmlns="http://www.w3.org/1999/xhtml" class="method">
- <h3 xmlns="http://www.w3.org/1999/xhtml">
- <a name="{concat(../@name, concat('.', @name))}">
- <xsl:value-of select="@name"/>
- </a> (
- <xsl:for-each xmlns="" select="arg[@direction='in']">
- <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/>
- <xsl:if test="position() != last()">, </xsl:if>
- </xsl:for-each>
- ) &#x2192;
- <xsl:choose>
- <xsl:when test="arg[@direction='out']">
- <xsl:for-each xmlns="" select="arg[@direction='out']">
- <xsl:value-of select="@type"/>
- <xsl:if test="position() != last()">, </xsl:if>
- </xsl:for-each>
- </xsl:when>
- <xsl:otherwise>nothing</xsl:otherwise>
- </xsl:choose>
- </h3>
- <div xmlns="http://www.w3.org/1999/xhtml" class="docstring">
- <xsl:apply-templates select="tp:docstring" />
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </div>
-
- <xsl:if test="arg[@direction='in']">
- <div xmlns="http://www.w3.org/1999/xhtml">
- <h4>Parameters</h4>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="arg[@direction='in']"
- mode="parameters-in-docstring"/>
- </dl>
- </div>
- </xsl:if>
-
- <xsl:if test="arg[@direction='out']">
- <div xmlns="http://www.w3.org/1999/xhtml">
- <h4>Returns</h4>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="arg[@direction='out']"
- mode="returns-in-docstring"/>
- </dl>
- </div>
- </xsl:if>
-
- <xsl:if test="tp:possible-errors">
- <div xmlns="http://www.w3.org/1999/xhtml">
- <h4>Possible errors</h4>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:possible-errors/tp:error"/>
- </dl>
- </div>
- </xsl:if>
-
- </div>
- </xsl:template>
-
- <xsl:template name="tp-type">
- <xsl:param name="tp-type"/>
- <xsl:param name="type"/>
-
- <xsl:variable name="single-type">
- <xsl:choose>
- <xsl:when test="contains($tp-type, '[]')">
- <xsl:value-of select="substring-before($tp-type, '[]')"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:value-of select="$tp-type"/>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
-
- <xsl:variable name="type-of-tp-type">
- <xsl:if test="contains($tp-type, '[]')">
- <!-- one 'a', plus one for each [ after the [], and delete all ] -->
- <xsl:value-of select="concat('a',
- translate(substring-after($tp-type, '[]'), '[]', 'a'))"/>
- </xsl:if>
-
- <xsl:choose>
- <xsl:when test="//tp:simple-type[@name=$single-type]">
- <xsl:value-of select="string(//tp:simple-type[@name=$single-type]/@type)"/>
- </xsl:when>
- <xsl:when test="//tp:struct[@name=$single-type]">
- <xsl:text>(</xsl:text>
- <xsl:for-each select="//tp:struct[@name=$single-type]/tp:member">
- <xsl:value-of select="@type"/>
- </xsl:for-each>
- <xsl:text>)</xsl:text>
- </xsl:when>
- <xsl:when test="//tp:enum[@name=$single-type]">
- <xsl:value-of select="string(//tp:enum[@name=$single-type]/@type)"/>
- </xsl:when>
- <xsl:when test="//tp:flags[@name=$single-type]">
- <xsl:value-of select="string(//tp:flags[@name=$single-type]/@type)"/>
- </xsl:when>
- <xsl:when test="//tp:mapping[@name=$single-type]">
- <xsl:text>a{</xsl:text>
- <xsl:for-each select="//tp:mapping[@name=$single-type]/tp:member">
- <xsl:value-of select="@type"/>
- </xsl:for-each>
- <xsl:text>}</xsl:text>
- </xsl:when>
- <xsl:when test="//tp:external-type[@name=$single-type]">
- <xsl:value-of select="string(//tp:external-type[@name=$single-type]/@type)"/>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">
- <xsl:text>ERR: Unable to find type '</xsl:text>
- <xsl:value-of select="$tp-type"/>
- <xsl:text>'&#10;</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:variable>
-
- <xsl:if test="string($type) != '' and
- string($type-of-tp-type) != string($type)">
- <xsl:message terminate="yes">
- <xsl:text>ERR: tp:type '</xsl:text>
- <xsl:value-of select="$tp-type"/>
- <xsl:text>' has D-Bus type '</xsl:text>
- <xsl:value-of select="$type-of-tp-type"/>
- <xsl:text>' but has been used with type='</xsl:text>
- <xsl:value-of select="$type"/>
- <xsl:text>'&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <a href="#type-{$single-type}"><xsl:value-of select="$tp-type"/></a>
-
- </xsl:template>
-
- <xsl:template name="parenthesized-tp-type">
- <xsl:if test="@tp:type">
- <xsl:text> (</xsl:text>
- <xsl:call-template name="tp-type">
- <xsl:with-param name="tp-type" select="@tp:type"/>
- <xsl:with-param name="type" select="@type"/>
- </xsl:call-template>
- <xsl:text>)</xsl:text>
- </xsl:if>
- </xsl:template>
-
- <xsl:template match="tp:member" mode="members-in-docstring">
- <dt xmlns="http://www.w3.org/1999/xhtml">
- <code><xsl:value-of select="@name"/></code> −
- <code><xsl:value-of select="@type"/></code>
- <xsl:call-template name="parenthesized-tp-type"/>
- </dt>
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:choose>
- <xsl:when test="tp:docstring">
- <xsl:apply-templates select="tp:docstring" />
- </xsl:when>
- <xsl:otherwise>
- <em>(undocumented)</em>
- </xsl:otherwise>
- </xsl:choose>
- </dd>
- </xsl:template>
-
- <xsl:template match="arg" mode="parameters-in-docstring">
- <dt xmlns="http://www.w3.org/1999/xhtml">
- <code><xsl:value-of select="@name"/></code> −
- <code><xsl:value-of select="@type"/></code>
- <xsl:call-template name="parenthesized-tp-type"/>
- </dt>
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:docstring" />
- </dd>
- </xsl:template>
-
- <xsl:template match="arg" mode="returns-in-docstring">
- <dt xmlns="http://www.w3.org/1999/xhtml">
- <xsl:if test="@name">
- <code><xsl:value-of select="@name"/></code> −
- </xsl:if>
- <code><xsl:value-of select="@type"/></code>
- <xsl:call-template name="parenthesized-tp-type"/>
- </dt>
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="tp:docstring"/>
- </dd>
- </xsl:template>
-
- <xsl:template match="tp:possible-errors/tp:error">
- <dt xmlns="http://www.w3.org/1999/xhtml">
- <code><xsl:value-of select="@name"/></code>
- </dt>
- <dd xmlns="http://www.w3.org/1999/xhtml">
- <xsl:variable name="name" select="@name"/>
- <xsl:choose>
- <xsl:when test="tp:docstring">
- <xsl:apply-templates select="tp:docstring"/>
- </xsl:when>
- <xsl:when test="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring">
- <xsl:apply-templates select="//tp:errors/tp:error[concat(../@namespace, '.', translate(@name, ' ', ''))=$name]/tp:docstring"/> <em xmlns="http://www.w3.org/1999/xhtml">(generic description)</em>
- </xsl:when>
- <xsl:otherwise>
- (Undocumented.)
- </xsl:otherwise>
- </xsl:choose>
- </dd>
- </xsl:template>
-
- <xsl:template match="signal">
-
- <xsl:if test="not(parent::interface)">
- <xsl:message terminate="yes">
- <xsl:text>ERR: signal </xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text> does not have an interface as parent&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: missing @name on a signal of </xsl:text>
- <xsl:value-of select="../@name"/>
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
-
- <xsl:for-each select="arg">
- <xsl:if test="not(@type) or @type = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: an arg of signal </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has no type</xsl:text>
- </xsl:message>
- </xsl:if>
- <xsl:if test="not(@name) or @name = ''">
- <xsl:message terminate="yes">
- <xsl:text>ERR: an arg of signal </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has no name</xsl:text>
- </xsl:message>
- </xsl:if>
- <xsl:choose>
- <xsl:when test="not(@direction)"/>
- <xsl:when test="@direction='in'">
- <xsl:message terminate="no">
- <xsl:text>INFO: an arg of signal </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has unnecessary direction 'in'</xsl:text>
- </xsl:message>
- </xsl:when>
- <xsl:otherwise>
- <xsl:message terminate="yes">
- <xsl:text>ERR: an arg of signal </xsl:text>
- <xsl:value-of select="concat(../../@name, '.', ../@name)"/>
- <xsl:text> has direction other than 'in'</xsl:text>
- </xsl:message>
- </xsl:otherwise>
- </xsl:choose>
- </xsl:for-each>
-
- <div xmlns="http://www.w3.org/1999/xhtml" class="signal">
- <h3 xmlns="http://www.w3.org/1999/xhtml">
- <a name="{concat(../@name, concat('.', @name))}">
- <xsl:value-of select="@name"/>
- </a> (
- <xsl:for-each xmlns="" select="arg">
- <xsl:value-of select="@type"/>: <xsl:value-of select="@name"/>
- <xsl:if test="position() != last()">, </xsl:if>
- </xsl:for-each>
- )</h3>
-
- <div xmlns="http://www.w3.org/1999/xhtml" class="docstring">
- <xsl:apply-templates select="tp:docstring"/>
- <xsl:apply-templates select="tp:added"/>
- <xsl:apply-templates select="tp:changed"/>
- <xsl:apply-templates select="tp:deprecated"/>
- </div>
-
- <xsl:if test="arg">
- <div xmlns="http://www.w3.org/1999/xhtml">
- <h4>Parameters</h4>
- <dl xmlns="http://www.w3.org/1999/xhtml">
- <xsl:apply-templates select="arg" mode="parameters-in-docstring"/>
- </dl>
- </div>
- </xsl:if>
- </div>
- </xsl:template>
-
- <xsl:output method="xml" indent="no" encoding="ascii"
- omit-xml-declaration="yes"
- doctype-system="http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"
- doctype-public="-//W3C//DTD XHTML 1.0 Strict//EN" />
-
- <xsl:template match="/tp:spec">
- <html xmlns="http://www.w3.org/1999/xhtml">
- <head>
- <title>
- <xsl:value-of select="tp:title"/>
- <xsl:if test="tp:version">
- <xsl:text> version </xsl:text>
- <xsl:value-of select="tp:version"/>
- </xsl:if>
- </title>
- <style type="text/css">
-
- body {
- font-family: sans-serif;
- margin: 2em;
- height: 100%;
- font-size: 1.2em;
- }
- h1 {
- padding-top: 5px;
- padding-bottom: 5px;
- font-size: 1.6em;
- background: #dadae2;
- }
- h2 {
- font-size: 1.3em;
- }
- h3 {
- font-size: 1.2em;
- }
- a:link, a:visited, a:link:hover, a:visited:hover {
- font-weight: bold;
- }
- .topbox {
- padding-top: 10px;
- padding-left: 10px;
- border-bottom: black solid 1px;
- padding-bottom: 10px;
- background: #dadae2;
- font-size: 2em;
- font-weight: bold;
- color: #5c5c5c;
- }
- .topnavbox {
- padding-left: 10px;
- padding-top: 5px;
- padding-bottom: 5px;
- background: #abacba;
- border-bottom: black solid 1px;
- font-size: 1.2em;
- }
- .topnavbox a{
- color: black;
- font-weight: normal;
- }
- .sidebar {
- float: left;
- /* width:9em;
- border-right:#abacba solid 1px;
- border-left: #abacba solid 1px;
- height:100%; */
- border: #abacba solid 1px;
- padding-left: 10px;
- margin-left: 10px;
- padding-right: 10px;
- margin-right: 10px;
- color: #5d5d5d;
- background: #dadae2;
- }
- .sidebar a {
- text-decoration: none;
- border-bottom: #e29625 dotted 1px;
- color: #e29625;
- font-weight: normal;
- }
- .sidebar h1 {
- font-size: 1.2em;
- color: black;
- }
- .sidebar ul {
- padding-left: 25px;
- padding-bottom: 10px;
- border-bottom: #abacba solid 1px;
- }
- .sidebar li {
- padding-top: 2px;
- padding-bottom: 2px;
- }
- .sidebar h2 {
- font-style:italic;
- font-size: 0.81em;
- padding-left: 5px;
- padding-right: 5px;
- font-weight: normal;
- }
- .date {
- font-size: 0.6em;
- float: right;
- font-style: italic;
- }
- .method, .signal, .property {
- margin-left: 1em;
- margin-right: 4em;
- }
- .rationale {
- font-style: italic;
- border-left: 0.25em solid #808080;
- padding-left: 0.5em;
- }
-
- .added {
- color: #006600;
- background: #ffffff;
- }
- .deprecated {
- color: #ff0000;
- background: #ffffff;
- }
- table, tr, td, th {
- border: 1px solid #666;
- }
-
- </style>
- </head>
- <body>
- <h1 class="topbox">
- <xsl:value-of select="tp:title" />
- </h1>
- <xsl:if test="tp:version">
- <h2>Version <xsl:value-of select="string(tp:version)"/></h2>
- </xsl:if>
- <xsl:apply-templates select="tp:copyright"/>
- <xsl:apply-templates select="tp:license"/>
- <xsl:apply-templates select="tp:docstring"/>
-
- <h2>Interfaces</h2>
- <ul>
- <xsl:for-each select="//node/interface">
- <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li>
- </xsl:for-each>
- </ul>
-
- <xsl:apply-templates select="//node"/>
- <xsl:apply-templates select="tp:generic-types"/>
- <xsl:apply-templates select="tp:errors"/>
-
- <h1>Index</h1>
- <h2>Index of interfaces</h2>
- <ul>
- <xsl:for-each select="//node/interface">
- <li><code><a href="#{@name}"><xsl:value-of select="@name"/></a></code></li>
- </xsl:for-each>
- </ul>
- <h2>Index of types</h2>
- <ul>
- <xsl:for-each select="//tp:simple-type | //tp:enum | //tp:flags | //tp:mapping | //tp:struct | //tp:external-type">
- <xsl:sort select="@name"/>
- <li>
- <code>
- <a href="#type-{@name}">
- <xsl:value-of select="@name"/>
- </a>
- </code>
- <xsl:apply-templates mode="in-index" select="."/>
- </li>
- </xsl:for-each>
- </ul>
- </body>
- </html>
- </xsl:template>
-
- <xsl:template match="node">
- <xsl:apply-templates />
- </xsl:template>
-
- <xsl:template match="text()">
- <xsl:if test="normalize-space(.) != ''">
- <xsl:message terminate="yes">
- <xsl:text>Stray text: {{{</xsl:text>
- <xsl:value-of select="." />
- <xsl:text>}}}&#10;</xsl:text>
- </xsl:message>
- </xsl:if>
- </xsl:template>
-
- <xsl:template match="*">
- <xsl:message terminate="yes">
- <xsl:text>Unrecognised element: {</xsl:text>
- <xsl:value-of select="namespace-uri(.)" />
- <xsl:text>}</xsl:text>
- <xsl:value-of select="local-name(.)" />
- <xsl:text>&#10;</xsl:text>
- </xsl:message>
- </xsl:template>
-</xsl:stylesheet>
-
-<!-- vim:set sw=2 sts=2 et: -->
diff --git a/tools/glib-blocking-client-gen.py b/tools/glib-blocking-client-gen.py
deleted file mode 100644
index c20dcd4a..00000000
--- a/tools/glib-blocking-client-gen.py
+++ /dev/null
@@ -1,1014 +0,0 @@
-#!/usr/bin/python
-
-# glib-client-gen.py: "I Can't Believe It's Not dbus-binding-tool"
-#
-# Generate GLib client wrappers from the Telepathy specification.
-# The master copy of this program is in the telepathy-glib repository -
-# please make any changes there.
-#
-# Copyright (C) 2006-2008 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# 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
-
-import sys
-import os.path
-import xml.dom.minidom
-from getopt import gnu_getopt
-
-from libglibcodegen import Signature, type_to_gtype, cmp_by_name, \
- camelcase_to_lower, get_docstring
-
-
-NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-
-class Generator(object):
-
- def __init__(self, dom, prefix, basename, opts):
- self.dom = dom
- self.__header = []
- self.__body = []
-
- self.prefix_lc = prefix.lower()
- self.prefix_uc = prefix.upper()
- self.prefix_mc = prefix.replace('_', '')
- self.basename = basename
- self.group = opts.get('--group', None)
- self.iface_quark_prefix = opts.get('--iface-quark-prefix', None)
- self.proxy_cls = opts.get('--subclass', 'TpProxy') + ' *'
- self.proxy_arg = opts.get('--subclass', 'void') + ' *'
- self.proxy_assert = opts.get('--subclass-assert', 'TP_IS_PROXY')
- self.proxy_doc = ('A #%s or subclass'
- % opts.get('--subclass', 'TpProxy'))
- if self.proxy_arg == 'void *':
- self.proxy_arg = 'gpointer '
-
- def h(self, s):
- self.__header.append(s)
-
- def b(self, s):
- self.__body.append(s)
-
- def get_iface_quark(self):
- assert self.iface_dbus is not None
- assert self.iface_uc is not None
- if self.iface_quark_prefix is None:
- return 'g_quark_from_static_string (\"%s\")' % self.iface_dbus
- else:
- return '%s_%s' % (self.iface_quark_prefix, self.iface_uc)
-
- def do_signal(self, iface, signal):
- iface_lc = iface.lower()
-
- member = signal.getAttribute('name')
- member_lc = camelcase_to_lower(member)
- member_uc = member_lc.upper()
-
- arg_count = 0
- args = []
- out_args = []
-
- for arg in signal.getElementsByTagName('arg'):
- name = arg.getAttribute('name')
- type = arg.getAttribute('type')
- tp_type = arg.getAttribute('tp:type')
-
- if not name:
- name = 'arg%u' % arg_count
- arg_count += 1
- else:
- name = 'arg_%s' % name
-
- info = type_to_gtype(type)
- args.append((name, info, tp_type, arg))
-
- callback_name = ('%s_%s_signal_callback_%s'
- % (self.prefix_lc, iface_lc, member_lc))
- collect_name = ('_%s_%s_collect_args_of_%s'
- % (self.prefix_lc, iface_lc, member_lc))
- invoke_name = ('_%s_%s_invoke_callback_for_%s'
- % (self.prefix_lc, iface_lc, member_lc))
-
- # Example:
- #
- # typedef void (*tp_cli_connection_signal_callback_new_channel)
- # (TpConnection *proxy, const gchar *arg_object_path,
- # const gchar *arg_channel_type, guint arg_handle_type,
- # guint arg_handle, gboolean arg_suppress_handler,
- # gpointer user_data, GObject *weak_object);
-
- self.b('/**')
- self.b(' * %s:' % callback_name)
- self.b(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
- % (self.prefix_lc, iface_lc, member_lc))
- self.b(' * was called')
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' * @%s: <![CDATA[%s]]>' % (name,
- get_docstring(elt) or '(Undocumented)'))
-
- self.b(' * @user_data: User-supplied data')
- self.b(' * @weak_object: User-supplied weakly referenced object')
- self.b(' *')
- self.b(' * Represents the signature of a callback for the signal %s.'
- % member)
- self.b(' */')
- self.h('typedef void (*%s) (%sproxy,'
- % (callback_name, self.proxy_cls))
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
-
- self.h(' gpointer user_data, GObject *weak_object);')
-
- if args:
- self.b('static void')
- self.b('%s (DBusGProxy *proxy,' % collect_name)
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s%s%s,' % (const, ctype, name))
-
- self.b(' TpProxySignalConnection *sc)')
- self.b('{')
- self.b(' GValueArray *args = g_value_array_new (%d);' % len(args))
- self.b(' GValue blank = { 0 };')
- self.b(' guint i;')
- self.b('')
- self.b(' g_value_init (&blank, G_TYPE_INT);')
- self.b('')
- self.b(' for (i = 0; i < %d; i++)' % len(args))
- self.b(' g_value_array_append (args, &blank);')
- self.b('')
-
- for i, arg in enumerate(args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' g_value_unset (args->values + %d);' % i)
- self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
-
- if gtype == 'G_TYPE_STRING':
- self.b(' g_value_set_string (args->values + %d, %s);'
- % (i, name))
- elif marshaller == 'BOXED':
- self.b(' g_value_set_boxed (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_set_uchar (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_set_boolean (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_set_int (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_set_uint (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_set_int (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_set_uint (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_set_double (args->values + %d, %s);'
- % (i, name))
- else:
- assert False, ("Don't know how to put %s in a GValue"
- % gtype)
- self.b('')
-
- self.b(' tp_proxy_signal_connection_v0_take_results (sc, args);')
- self.b('}')
-
- self.b('static void')
- self.b('%s (TpProxy *tpproxy,' % invoke_name)
- self.b(' GError *error,')
- self.b(' GValueArray *args,')
- self.b(' GCallback generic_callback,')
- self.b(' gpointer user_data,')
- self.b(' GObject *weak_object)')
- self.b('{')
- self.b(' %s callback =' % callback_name)
- self.b(' (%s) generic_callback;' % callback_name)
- self.b('')
- self.b(' if (callback != NULL)')
- self.b(' callback (g_object_ref (tpproxy),')
-
- # FIXME: factor out into a function
- for i, arg in enumerate(args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
-
- self.b(' user_data,')
- self.b(' weak_object);')
- self.b('')
-
- if len(args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b('')
-
- self.b(' g_object_unref (tpproxy);')
- self.b('}')
-
- # Example:
- #
- # TpProxySignalConnection *
- # tp_cli_connection_connect_to_new_channel
- # (TpConnection *proxy,
- # tp_cli_connection_signal_callback_new_channel callback,
- # gpointer user_data,
- # GDestroyNotify destroy);
- #
- # destroy is invoked when the signal becomes disconnected. This
- # is either because the signal has been disconnected explicitly
- # by the user, because the TpProxy has become invalid and
- # emitted the 'invalidated' signal, or because the weakly referenced
- # object has gone away.
-
- self.b('/**')
- self.b(' * %s_%s_connect_to_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: %s' % self.proxy_doc)
- self.b(' * @callback: Callback to be called when the signal is')
- self.b(' * received')
- self.b(' * @user_data: User-supplied data for the callback')
- self.b(' * @destroy: Destructor for the user-supplied data, which')
- self.b(' * will be called when this signal is disconnected, or')
- self.b(' * before this function returns %NULL')
- self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
- self.b(' * if it is destroyed, this callback will automatically be')
- self.b(' * disconnected')
- self.b(' * @error: If not %NULL, used to raise an error if %NULL is')
- self.b(' * returned')
- self.b(' *')
- self.b(' * Connect a handler to the signal %s.' % member)
- self.b(' *')
- self.b(' * <![CDATA[%s]]>'
- % (get_docstring(signal) or '(Undocumented)'))
- self.b(' *')
- self.b(' * Returns: a #TpProxySignalConnection containing all of the')
- self.b(' * above, which can be used to disconnect the signal; or')
- self.b(' * %NULL if the proxy does not have the desired interface')
- self.b(' * or has become invalid.')
- self.b(' */')
- self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.h(' %s callback,' % callback_name)
- self.h(' gpointer user_data,')
- self.h(' GDestroyNotify destroy,')
- self.h(' GObject *weak_object,')
- self.h(' GError **error);')
-
- self.b('TpProxySignalConnection *')
- self.b('%s_%s_connect_to_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.b(' %s callback,' % callback_name)
- self.b(' gpointer user_data,')
- self.b(' GDestroyNotify destroy,')
- self.b(' GObject *weak_object,')
- self.b(' GError **error)')
- self.b('{')
- self.b(' GType expected_types[%d] = {' % (len(args) + 1))
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s,' % gtype)
-
- self.b(' G_TYPE_INVALID };')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), NULL);'
- % self.proxy_assert)
- self.b(' g_return_val_if_fail (callback != NULL, NULL);')
- self.b('')
- self.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
- self.b(' %s, \"%s\",' % (self.get_iface_quark(), member))
- self.b(' expected_types,')
-
- if args:
- self.b(' G_CALLBACK (%s),' % collect_name)
- else:
- self.b(' NULL, /* no args => no collector function */')
-
- self.b(' %s,' % invoke_name)
- self.b(' G_CALLBACK (callback), user_data, destroy,')
- self.b(' weak_object, error);')
- self.b('}')
- self.b('')
-
- self.h('')
-
- def do_method(self, iface, method):
- iface_lc = iface.lower()
-
- member = method.getAttribute('name')
- member_lc = camelcase_to_lower(member)
- member_uc = member_lc.upper()
-
- in_count = 0
- ret_count = 0
- in_args = []
- out_args = []
-
- for arg in method.getElementsByTagName('arg'):
- name = arg.getAttribute('name')
- direction = arg.getAttribute('direction')
- type = arg.getAttribute('type')
- tp_type = arg.getAttribute('tp:type')
-
- if direction != 'out':
- if not name:
- name = 'in%u' % in_count
- in_count += 1
- else:
- name = 'in_%s' % name
- else:
- if not name:
- name = 'out%u' % ret_count
- ret_count += 1
- else:
- name = 'out_%s' % name
-
- info = type_to_gtype(type)
- if direction != 'out':
- in_args.append((name, info, tp_type, arg))
- else:
- out_args.append((name, info, tp_type, arg))
-
- # Async reply callback type
-
- # Example:
- # void (*tp_cli_properties_interface_callback_for_get_properties)
- # (TpProxy *proxy,
- # const GPtrArray *out0,
- # const GError *error,
- # gpointer user_data,
- # GObject *weak_object);
-
- self.b('/**')
- self.b(' * %s_%s_callback_for_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: the proxy on which the call was made')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' * @%s: Used to return an \'out\' argument if @error is '
- '%%NULL: <![CDATA[%s]]>'
- % (name, get_docstring(elt) or '(Undocumented)'))
-
- self.b(' * @error: %NULL on success, or an error on failure')
- self.b(' * @user_data: user-supplied data')
- self.b(' * @weak_object: user-supplied object')
- self.b(' *')
- self.b(' * Signature of the callback called when a %s method call'
- % member)
- self.b(' * succeeds or fails.')
- self.b(' */')
-
- callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc,
- member_lc)
-
- self.h('typedef void (*%s) (%sproxy,'
- % (callback_name, self.proxy_cls))
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
-
- self.h(' const GError *error, gpointer user_data,')
- self.h(' GObject *weak_object);')
- self.h('')
-
- # Async callback implementation
-
- invoke_callback = '_%s_%s_invoke_callback_%s' % (self.prefix_lc,
- iface_lc,
- member_lc)
-
- collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc,
- iface_lc,
- member_lc)
-
- # The callback called by dbus-glib; this ends the call and collects
- # the results into a GValueArray.
- self.b('static void')
- self.b('%s (DBusGProxy *proxy,' % collect_callback)
- self.b(' DBusGProxyCall *call,')
- self.b(' gpointer user_data)')
- self.b('{')
- self.b(' GError *error = NULL;')
-
- if len(out_args) > 0:
- self.b(' GValueArray *args;')
- self.b(' GValue blank = { 0 };')
- self.b(' guint i;')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s%s;' % (ctype, name))
-
- self.b('')
- self.b(' dbus_g_proxy_end_call (proxy, call, &error,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s, &%s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID);')
-
- if len(out_args) == 0:
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,'
- 'NULL);')
- else:
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,')
- self.b(' NULL);')
- self.b(' return;')
- self.b(' }')
- self.b('')
- self.b(' args = g_value_array_new (%d);' % len(out_args))
- self.b(' g_value_init (&blank, G_TYPE_INT);')
- self.b('')
- self.b(' for (i = 0; i < %d; i++)' % len(out_args))
- self.b(' g_value_array_append (args, &blank);')
-
- for i, arg in enumerate(out_args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b('')
- self.b(' g_value_unset (args->values + %d);' % i)
- self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
-
- if gtype == 'G_TYPE_STRING':
- self.b(' g_value_take_string (args->values + %d, %s);'
- % (i, name))
- elif marshaller == 'BOXED':
- self.b(' g_value_take_boxed (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_set_uchar (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_set_boolean (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_set_int (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_set_uint (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_set_int (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_set_uint (args->values + %d, %s);'
- % (i, name))
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_set_double (args->values + %d, %s);'
- % (i, name))
- else:
- assert False, ("Don't know how to put %s in a GValue"
- % gtype)
-
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, '
- 'NULL, args);')
-
- self.b('}')
-
- self.b('static void')
- self.b('%s (TpProxy *self,' % invoke_callback)
- self.b(' GError *error,')
- self.b(' GValueArray *args,')
- self.b(' GCallback generic_callback,')
- self.b(' gpointer user_data,')
- self.b(' GObject *weak_object)')
- self.b('{')
- self.b(' %s callback = (%s) generic_callback;'
- % (callback_name, callback_name))
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' callback ((%s) self,' % self.proxy_cls)
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if marshaller == 'BOXED' or pointer:
- self.b(' NULL,')
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' 0.0,')
- else:
- self.b(' 0,')
-
- self.b(' error, user_data, weak_object);')
- self.b(' g_error_free (error);')
- self.b(' return;')
- self.b(' }')
-
- self.b(' callback ((%s) self,' % self.proxy_cls)
-
- # FIXME: factor out into a function
- for i, arg in enumerate(out_args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
-
- self.b(' error, user_data, weak_object);')
- self.b('')
-
- if len(out_args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
-
- self.b('}')
- self.b('')
-
- # Async stub
-
- # Example:
- # TpProxyPendingCall *
- # tp_cli_properties_interface_call_get_properties
- # (gpointer proxy,
- # gint timeout_ms,
- # const GArray *in_properties,
- # tp_cli_properties_interface_callback_for_get_properties callback,
- # gpointer user_data,
- # GDestroyNotify *destructor);
-
- self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.h(' gint timeout_ms,')
-
- self.b('/**')
- self.b(' * %s_%s_call_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: the #TpProxy')
- self.b(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
- self.b(' * default')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' * @%s: Used to pass an \'in\' argument: <![CDATA[%s]]>'
- % (name, get_docstring(elt) or '(Undocumented)'))
-
- self.b(' * @callback: called when the method call succeeds or fails')
- self.b(' * @user_data: user-supplied data passed to the callback')
- self.b(' * @destroy: called with the user_data as argument, after the')
- self.b(' * call has succeeded, failed or been cancelled')
- self.b(' * @weak_object: A #GObject which will be weakly referenced; ')
- self.b(' * if it is destroyed, this callback will automatically be')
- self.b(' * disconnected')
- self.b(' *')
- self.b(' * Start a %s method call.' % member)
- self.b(' *')
- self.b(' * <![CDATA[%s]]>'
- % (get_docstring(method) or '(Undocumented)'))
- self.b(' *')
- self.b(' * Returns: a #TpProxyPendingCall representing the call in')
- self.b(' * progress. It is borrowed from the object, and will become')
- self.b(' * invalid when the callback is called, the call is')
- self.b(' * cancelled or the #TpProxy becomes invalid.')
- self.b(' */')
- self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.b(' gint timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
- self.b(' %s%s%s,' % (const, ctype, name))
-
- self.h(' %s callback,' % callback_name)
- self.h(' gpointer user_data,')
- self.h(' GDestroyNotify destroy,')
- self.h(' GObject *weak_object);')
- self.h('')
-
- self.b(' %s callback,' % callback_name)
- self.b(' gpointer user_data,')
- self.b(' GDestroyNotify destroy,')
- self.b(' GObject *weak_object)')
- self.b('{')
- self.b(' GError *error = NULL;')
- self.b(' GQuark interface = %s;' % self.get_iface_quark())
- self.b(' DBusGProxy *iface;')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), NULL);'
- % self.proxy_assert)
- self.b('')
- self.b(' iface = tp_proxy_borrow_interface_by_id (')
- self.b(' (TpProxy *) proxy,')
- self.b(' interface, &error);')
- self.b('')
- self.b(' if (iface == NULL)')
- self.b(' {')
- self.b(' if (callback != NULL)')
- self.b(' callback (proxy,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if pointer:
- self.b(' NULL,')
- else:
- self.b(' 0,')
-
- self.b(' error, user_data, weak_object);')
- self.b(' g_error_free (error);')
- self.b(' return NULL;')
- self.b(' }')
- self.b('')
- self.b(' if (callback == NULL)')
- self.b(' {')
- self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member)
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s, %s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID);')
- self.b(' return NULL;')
- self.b(' }')
- self.b(' else')
- self.b(' {')
- self.b(' TpProxyPendingCall *data;')
- self.b('')
- self.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
- self.b(' interface, "%s", iface,' % member)
- self.b(' %s,' % invoke_callback)
- self.b(' G_CALLBACK (callback), user_data, destroy,')
- self.b(' weak_object, FALSE);')
- self.b(' tp_proxy_pending_call_v0_take_pending_call (data,')
- self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
- self.b(' "%s",' % member)
- self.b(' %s,' % collect_callback)
- self.b(' data,')
- self.b(' tp_proxy_pending_call_v0_completed,')
- self.b(' timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s, %s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID));')
- self.b('')
- self.b(' return data;')
- self.b(' }')
- self.b('}')
- self.b('')
-
- # Non reentrant blocking calls
- # Example:
- # gboolean tp_cli_properties_interface_do_get_properties
- # (gpointer proxy,
- # gint timeout_ms,
- # const GArray *in_properties,
- # GPtrArray **out0,
- # GError **error);
-
- self.h('gboolean %s_%s_do_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.h(' gint timeout_ms,')
-
- self.b('/**')
- self.b(' * %s_%s_do_%s:' % (self.prefix_lc, iface_lc, member_lc))
- self.b(' * @proxy: %s' % self.proxy_doc)
- self.b(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' * @%s: Used to pass an \'in\' argument: <![CDATA[%s]]>'
- % (name, get_docstring(elt) or '(Undocumented)'))
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' * @%s: Used to return an \'out\' argument if %%TRUE is '
- 'returned: <![CDATA[%s]]>'
- % (name, get_docstring(elt) or '(Undocumented)'))
-
- self.b(' * @error: If not %NULL, used to return errors if %FALSE ')
- self.b(' * is returned')
- self.b(' *')
- self.b(' * Call the method %s and block' % member)
- self.b(' * until it returns.')
- self.b(' *')
- self.b(' * <![CDATA[%s]]>'
- % (get_docstring(method) or '(Undocumented)'))
- self.b(' *')
- self.b(' * Returns: TRUE on success, FALSE and sets @error on error')
- self.b(' */')
- self.b('gboolean\n%s_%s_do_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.b(' gint timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
- self.b(' %s%s%s,' % (const, ctype, name))
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.h(' %s*%s,' % (ctype, name))
- self.b(' %s*%s,' % (ctype, name))
-
- self.h(' GError **error);')
- self.h('')
-
- self.b(' GError **error)')
- self.b('{')
- self.b(' DBusGProxy *iface;')
- self.b(' GQuark interface = %s;' % self.get_iface_quark())
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %si_%s;' % (ctype, name))
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), FALSE);'
- % self.proxy_assert)
- self.b('')
- self.b(' iface = tp_proxy_borrow_interface_by_id')
- self.b(' ((TpProxy *) proxy, interface, error);')
- self.b('')
- self.b(' if (iface == NULL)')
- self.b(' return FALSE;')
- self.b('')
- self.b(' if (dbus_g_proxy_call_with_timeout (iface,')
- self.b(' "%s",' % member)
- self.b(' timeout_ms,')
- self.b(' error,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s, %s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s, &i_%s,' % (gtype, name))
- self.b(' G_TYPE_INVALID))')
- self.b(' {')
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' *%s = i_%s;' % (name, name))
- self.b(' return TRUE;')
- self.b(' }')
- self.b(' else')
- self.b(' return FALSE;')
- self.b('}')
- self.b('')
-
- # leave a gap for the end of the method
- self.b('')
- self.h('')
-
- def do_signal_add(self, signal):
- marshaller_items = []
- gtypes = []
-
- for i in signal.getElementsByTagName('arg'):
- name = i.getAttribute('name')
- type = i.getAttribute('type')
- info = type_to_gtype(type)
- # type, GType, STRING, is a pointer
- gtypes.append(info[1])
-
- self.b(' dbus_g_proxy_add_signal (proxy, "%s",'
- % signal.getAttribute('name'))
- for gtype in gtypes:
- self.b(' %s,' % gtype)
- self.b(' G_TYPE_INVALID);')
-
- def do_interface(self, node):
- ifaces = node.getElementsByTagName('interface')
- assert len(ifaces) == 1
- iface = ifaces[0]
- name = node.getAttribute('name').replace('/', '')
-
- self.iface = name
- self.iface_lc = name.lower()
- self.iface_uc = name.upper()
- self.iface_mc = name.replace('_', '')
- self.iface_dbus = iface.getAttribute('name')
-
- signals = node.getElementsByTagName('signal')
- methods = node.getElementsByTagName('method')
-
- self.b('static inline void')
- self.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
- % (self.prefix_lc, name.lower()))
- self.b('{')
-
- for signal in signals:
- self.do_signal_add(signal)
-
- self.b('}')
- self.b('')
- self.b('')
-
- for signal in signals:
- self.do_signal(name, signal)
-
- for method in methods:
- self.do_method(name, method)
-
- self.iface_dbus = None
-
- def __call__(self):
-
- self.h('G_BEGIN_DECLS')
- self.h('')
-
- self.b('/* We don\'t want gtkdoc scanning this file, it\'ll get')
- self.b(' * confused by seeing function definitions, so mark it as: */')
- self.b('/*<private_header>*/')
- self.b('')
-
- nodes = self.dom.getElementsByTagName('node')
- nodes.sort(cmp_by_name)
-
- for node in nodes:
- self.do_interface(node)
-
- if self.group is not None:
-
- self.b('/*')
- self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group))
- self.b(' * @self: the #TpProxy')
- self.b(' * @quark: a quark whose string value is the interface')
- self.b(' * name whose signals should be added')
- self.b(' * @proxy: the D-Bus proxy to which to add the signals')
- self.b(' * @unused: not used for anything')
- self.b(' *')
- self.b(' * Tell dbus-glib that @proxy has the signatures of all')
- self.b(' * signals on the given interface, if it\'s one we')
- self.b(' * support.')
- self.b(' *')
- self.b(' * This function should be used as a signal handler for')
- self.b(' * #TpProxy::interface-added.')
- self.b(' */')
- self.b('static void')
- self.b('%s_%s_add_signals (TpProxy *self,'
- % (self.prefix_lc, self.group))
- self.b(' guint quark,')
- self.b(' DBusGProxy *proxy,')
- self.b(' gpointer unused)')
-
- self.b('{')
-
- for node in nodes:
- iface = node.getElementsByTagName('interface')[0]
- self.iface_dbus = iface.getAttribute('name')
- name = node.getAttribute('name').replace('/', '').lower()
- self.iface_uc = name.upper()
- self.b(' if (quark == %s)' % self.get_iface_quark())
- self.b(' %s_add_signals_for_%s (proxy);'
- % (self.prefix_lc, name))
-
- self.b('}')
- self.b('')
-
- self.h('G_END_DECLS')
- self.h('')
-
- open(self.basename + '.h', 'w').write('\n'.join(self.__header))
- open(self.basename + '-body.h', 'w').write('\n'.join(self.__body))
-
-
-def types_to_gtypes(types):
- return [type_to_gtype(t)[1] for t in types]
-
-
-if __name__ == '__main__':
- options, argv = gnu_getopt(sys.argv[1:], '',
- ['group=', 'subclass=', 'subclass-assert=',
- 'iface-quark-prefix='])
-
- opts = {}
-
- for option, value in options:
- opts[option] = value
-
- dom = xml.dom.minidom.parse(argv[0])
-
- Generator(dom, argv[1], argv[2], opts)()
diff --git a/tools/glib-client-gen.py b/tools/glib-client-gen.py
deleted file mode 100644
index b7edbc0d..00000000
--- a/tools/glib-client-gen.py
+++ /dev/null
@@ -1,1217 +0,0 @@
-#!/usr/bin/python
-
-# glib-client-gen.py: "I Can't Believe It's Not dbus-binding-tool"
-#
-# Generate GLib client wrappers from the Telepathy specification.
-# The master copy of this program is in the telepathy-glib repository -
-# please make any changes there.
-#
-# Copyright (C) 2006-2008 Collabora Ltd. <http://www.collabora.co.uk/>
-#
-# 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
-
-import sys
-import os.path
-import xml.dom.minidom
-from getopt import gnu_getopt
-
-from libtpcodegen import file_set_contents, key_by_name, u
-from libglibcodegen import (Signature, type_to_gtype,
- get_docstring, xml_escape, get_deprecated, copy_into_gvalue,
- move_into_gvalue)
-
-NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-
-class Generator(object):
-
- def __init__(self, dom, prefix, basename, opts):
- self.dom = dom
- self.__header = []
- self.__body = []
- self.__docs = []
-
- self.prefix_lc = prefix.lower()
- self.prefix_uc = prefix.upper()
- self.prefix_mc = prefix.replace('_', '')
- self.basename = basename
- self.group = opts.get('--group', None)
- self.iface_quark_prefix = opts.get('--iface-quark-prefix', None)
- self.tp_proxy_api = tuple(map(int,
- opts.get('--tp-proxy-api', '0').split('.')))
- self.proxy_cls = opts.get('--subclass', 'TpProxy') + ' *'
- self.proxy_arg = opts.get('--subclass', 'void') + ' *'
- self.proxy_assert = opts.get('--subclass-assert', 'TP_IS_PROXY')
- self.proxy_doc = ('A #%s or subclass'
- % opts.get('--subclass', 'TpProxy'))
- if self.proxy_arg == 'void *':
- self.proxy_arg = 'gpointer '
-
- self.reentrant_symbols = set()
- try:
- filename = opts['--generate-reentrant']
- with open(filename, 'r') as f:
- for line in f.readlines():
- self.reentrant_symbols.add(line.strip())
- except KeyError:
- pass
-
- self.deprecate_reentrant = opts.get('--deprecate-reentrant', None)
- self.deprecation_attribute = opts.get('--deprecation-attribute',
- 'G_GNUC_DEPRECATED')
-
- self.guard = opts.get('--guard', None)
-
- def h(self, s):
- self.__header.append(s)
-
- def b(self, s):
- self.__body.append(s)
-
- def d(self, s):
- self.__docs.append(s)
-
- def get_iface_quark(self):
- assert self.iface_dbus is not None
- assert self.iface_uc is not None
- if self.iface_quark_prefix is None:
- return 'g_quark_from_static_string (\"%s\")' % self.iface_dbus
- else:
- return '%s_%s' % (self.iface_quark_prefix, self.iface_uc)
-
- def do_signal(self, iface, signal):
- iface_lc = iface.lower()
-
- member = signal.getAttribute('name')
- member_lc = signal.getAttribute('tp:name-for-bindings')
- if member != member_lc.replace('_', ''):
- raise AssertionError('Signal %s tp:name-for-bindings (%s) does '
- 'not match' % (member, member_lc))
- member_lc = member_lc.lower()
- member_uc = member_lc.upper()
-
- arg_count = 0
- args = []
- out_args = []
-
- for arg in signal.getElementsByTagName('arg'):
- name = arg.getAttribute('name')
- type = arg.getAttribute('type')
- tp_type = arg.getAttribute('tp:type')
-
- if not name:
- name = 'arg%u' % arg_count
- arg_count += 1
- else:
- name = 'arg_%s' % name
-
- info = type_to_gtype(type)
- args.append((name, info, tp_type, arg))
-
- callback_name = ('%s_%s_signal_callback_%s'
- % (self.prefix_lc, iface_lc, member_lc))
- collect_name = ('_%s_%s_collect_args_of_%s'
- % (self.prefix_lc, iface_lc, member_lc))
- invoke_name = ('_%s_%s_invoke_callback_for_%s'
- % (self.prefix_lc, iface_lc, member_lc))
-
- # Example:
- #
- # typedef void (*tp_cli_connection_signal_callback_new_channel)
- # (TpConnection *proxy, const gchar *arg_object_path,
- # const gchar *arg_channel_type, guint arg_handle_type,
- # guint arg_handle, gboolean arg_suppress_handler,
- # gpointer user_data, GObject *weak_object);
-
- self.d('/**')
- self.d(' * %s:' % callback_name)
- self.d(' * @proxy: The proxy on which %s_%s_connect_to_%s ()'
- % (self.prefix_lc, iface_lc, member_lc))
- self.d(' * was called')
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- docs = get_docstring(elt) or '(Undocumented)'
-
- if ctype == 'guint ' and tp_type != '':
- docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
-
- self.d(' * @%s: %s' % (name, xml_escape(docs)))
-
- self.d(' * @user_data: User-supplied data')
- self.d(' * @weak_object: User-supplied weakly referenced object')
- self.d(' *')
- self.d(' * Represents the signature of a callback for the signal %s.'
- % member)
- self.d(' */')
- self.d('')
-
- self.h('typedef void (*%s) (%sproxy,'
- % (callback_name, self.proxy_cls))
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
-
- self.h(' gpointer user_data, GObject *weak_object);')
-
- if args:
- self.b('static void')
- self.b('%s (DBusGProxy *proxy G_GNUC_UNUSED,' % collect_name)
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s%s%s,' % (const, ctype, name))
-
- self.b(' TpProxySignalConnection *sc)')
- self.b('{')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' GValueArray *args = g_value_array_new (%d);' % len(args))
- self.b(' GValue blank = { 0 };')
- self.b(' guint i;')
- self.b('')
- self.b(' g_value_init (&blank, G_TYPE_INT);')
- self.b('')
- self.b(' for (i = 0; i < %d; i++)' % len(args))
- self.b(' g_value_array_append (args, &blank);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
- self.b('')
-
- for i, arg in enumerate(args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' g_value_unset (args->values + %d);' % i)
- self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
-
- self.b(' ' + copy_into_gvalue('args->values + %d' % i,
- gtype, marshaller, name))
- self.b('')
-
- self.b(' tp_proxy_signal_connection_v0_take_results (sc, args);')
- self.b('}')
-
- self.b('static void')
- self.b('%s (TpProxy *tpproxy,' % invoke_name)
- self.b(' GError *error G_GNUC_UNUSED,')
- self.b(' GValueArray *args,')
- self.b(' GCallback generic_callback,')
- self.b(' gpointer user_data,')
- self.b(' GObject *weak_object)')
- self.b('{')
- self.b(' %s callback =' % callback_name)
- self.b(' (%s) generic_callback;' % callback_name)
- self.b('')
- self.b(' if (callback != NULL)')
- self.b(' callback (g_object_ref (tpproxy),')
-
- # FIXME: factor out into a function
- for i, arg in enumerate(args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
-
- self.b(' user_data,')
- self.b(' weak_object);')
- self.b('')
-
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- if len(args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b('')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
-
- self.b(' g_object_unref (tpproxy);')
- self.b('}')
-
- # Example:
- #
- # TpProxySignalConnection *
- # tp_cli_connection_connect_to_new_channel
- # (TpConnection *proxy,
- # tp_cli_connection_signal_callback_new_channel callback,
- # gpointer user_data,
- # GDestroyNotify destroy);
- #
- # destroy is invoked when the signal becomes disconnected. This
- # is either because the signal has been disconnected explicitly
- # by the user, because the TpProxy has become invalid and
- # emitted the 'invalidated' signal, or because the weakly referenced
- # object has gone away.
-
- self.d('/**')
- self.d(' * %s_%s_connect_to_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
- self.d(' * @proxy: %s' % self.proxy_doc)
- self.d(' * @callback: Callback to be called when the signal is')
- self.d(' * received')
- self.d(' * @user_data: User-supplied data for the callback')
- self.d(' * @destroy: Destructor for the user-supplied data, which')
- self.d(' * will be called when this signal is disconnected, or')
- self.d(' * before this function returns %NULL')
- self.d(' * @weak_object: A #GObject which will be weakly referenced; ')
- self.d(' * if it is destroyed, this callback will automatically be')
- self.d(' * disconnected')
- self.d(' * @error: If not %NULL, used to raise an error if %NULL is')
- self.d(' * returned')
- self.d(' *')
- self.d(' * Connect a handler to the signal %s.' % member)
- self.d(' *')
- self.d(' * %s' % xml_escape(get_docstring(signal) or '(Undocumented)'))
- self.d(' *')
- self.d(' * Returns: a #TpProxySignalConnection containing all of the')
- self.d(' * above, which can be used to disconnect the signal; or')
- self.d(' * %NULL if the proxy does not have the desired interface')
- self.d(' * or has become invalid.')
- self.d(' */')
- self.d('')
-
- self.h('TpProxySignalConnection *%s_%s_connect_to_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.h(' %s callback,' % callback_name)
- self.h(' gpointer user_data,')
- self.h(' GDestroyNotify destroy,')
- self.h(' GObject *weak_object,')
- self.h(' GError **error);')
- self.h('')
-
- self.b('TpProxySignalConnection *')
- self.b('%s_%s_connect_to_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.b(' %s callback,' % callback_name)
- self.b(' gpointer user_data,')
- self.b(' GDestroyNotify destroy,')
- self.b(' GObject *weak_object,')
- self.b(' GError **error)')
- self.b('{')
- self.b(' GType expected_types[%d] = {' % (len(args) + 1))
-
- for arg in args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s,' % gtype)
-
- self.b(' G_TYPE_INVALID };')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), NULL);'
- % self.proxy_assert)
- self.b(' g_return_val_if_fail (callback != NULL, NULL);')
- self.b('')
- self.b(' return tp_proxy_signal_connection_v0_new ((TpProxy *) proxy,')
- self.b(' %s, \"%s\",' % (self.get_iface_quark(), member))
- self.b(' expected_types,')
-
- if args:
- self.b(' G_CALLBACK (%s),' % collect_name)
- else:
- self.b(' NULL, /* no args => no collector function */')
-
- self.b(' %s,' % invoke_name)
- self.b(' G_CALLBACK (callback), user_data, destroy,')
- self.b(' weak_object, error);')
- self.b('}')
- self.b('')
-
- def do_method(self, iface, method):
- iface_lc = iface.lower()
-
- member = method.getAttribute('name')
- member_lc = method.getAttribute('tp:name-for-bindings')
- if member != member_lc.replace('_', ''):
- raise AssertionError('Method %s tp:name-for-bindings (%s) does '
- 'not match' % (member, member_lc))
- member_lc = member_lc.lower()
- member_uc = member_lc.upper()
-
- in_count = 0
- ret_count = 0
- in_args = []
- out_args = []
-
- for arg in method.getElementsByTagName('arg'):
- name = arg.getAttribute('name')
- direction = arg.getAttribute('direction')
- type = arg.getAttribute('type')
- tp_type = arg.getAttribute('tp:type')
-
- if direction != 'out':
- if not name:
- name = 'in%u' % in_count
- in_count += 1
- else:
- name = 'in_%s' % name
- else:
- if not name:
- name = 'out%u' % ret_count
- ret_count += 1
- else:
- name = 'out_%s' % name
-
- info = type_to_gtype(type)
- if direction != 'out':
- in_args.append((name, info, tp_type, arg))
- else:
- out_args.append((name, info, tp_type, arg))
-
- # Async reply callback type
-
- # Example:
- # void (*tp_cli_properties_interface_callback_for_get_properties)
- # (TpProxy *proxy,
- # const GPtrArray *out0,
- # const GError *error,
- # gpointer user_data,
- # GObject *weak_object);
-
- self.d('/**')
- self.d(' * %s_%s_callback_for_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
- self.d(' * @proxy: the proxy on which the call was made')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- docs = xml_escape(get_docstring(elt) or '(Undocumented)')
-
- if ctype == 'guint ' and tp_type != '':
- docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
-
- self.d(' * @%s: Used to return an \'out\' argument if @error is '
- '%%NULL: %s'
- % (name, docs))
-
- self.d(' * @error: %NULL on success, or an error on failure')
- self.d(' * @user_data: user-supplied data')
- self.d(' * @weak_object: user-supplied object')
- self.d(' *')
- self.d(' * Signature of the callback called when a %s method call'
- % member)
- self.d(' * succeeds or fails.')
-
- deprecated = method.getElementsByTagName('tp:deprecated')
- if deprecated:
- d = deprecated[0]
- self.d(' *')
- self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
-
- self.d(' */')
- self.d('')
-
- callback_name = '%s_%s_callback_for_%s' % (self.prefix_lc, iface_lc,
- member_lc)
-
- self.h('typedef void (*%s) (%sproxy,'
- % (callback_name, self.proxy_cls))
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
-
- self.h(' const GError *error, gpointer user_data,')
- self.h(' GObject *weak_object);')
- self.h('')
-
- # Async callback implementation
-
- invoke_callback = '_%s_%s_invoke_callback_%s' % (self.prefix_lc,
- iface_lc,
- member_lc)
-
- collect_callback = '_%s_%s_collect_callback_%s' % (self.prefix_lc,
- iface_lc,
- member_lc)
-
- # The callback called by dbus-glib; this ends the call and collects
- # the results into a GValueArray.
- self.b('static void')
- self.b('%s (DBusGProxy *proxy,' % collect_callback)
- self.b(' DBusGProxyCall *call,')
- self.b(' gpointer user_data)')
- self.b('{')
- self.b(' GError *error = NULL;')
-
- if len(out_args) > 0:
- self.b(' GValueArray *args;')
- self.b(' GValue blank = { 0 };')
- self.b(' guint i;')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- # "We handle variants specially; the caller is expected to
- # have already allocated storage for them". Thanks,
- # dbus-glib...
- if gtype == 'G_TYPE_VALUE':
- self.b(' GValue *%s = g_new0 (GValue, 1);' % name)
- else:
- self.b(' %s%s;' % (ctype, name))
-
- self.b('')
- self.b(' dbus_g_proxy_end_call (proxy, call, &error,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if gtype == 'G_TYPE_VALUE':
- self.b(' %s, %s,' % (gtype, name))
- else:
- self.b(' %s, &%s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID);')
-
- if len(out_args) == 0:
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,'
- 'NULL);')
- else:
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, error,')
- self.b(' NULL);')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
- if gtype == 'G_TYPE_VALUE':
- self.b(' g_free (%s);' % name)
-
- self.b(' return;')
- self.b(' }')
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' args = g_value_array_new (%d);' % len(out_args))
- self.b(' g_value_init (&blank, G_TYPE_INT);')
- self.b('')
- self.b(' for (i = 0; i < %d; i++)' % len(out_args))
- self.b(' g_value_array_append (args, &blank);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
-
- for i, arg in enumerate(out_args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b('')
- self.b(' g_value_unset (args->values + %d);' % i)
- self.b(' g_value_init (args->values + %d, %s);' % (i, gtype))
-
- self.b(' ' + move_into_gvalue('args->values + %d' % i,
- gtype, marshaller, name))
-
- self.b(' tp_proxy_pending_call_v0_take_results (user_data, '
- 'NULL, args);')
-
- self.b('}')
-
- self.b('static void')
- self.b('%s (TpProxy *self,' % invoke_callback)
- self.b(' GError *error,')
- self.b(' GValueArray *args,')
- self.b(' GCallback generic_callback,')
- self.b(' gpointer user_data,')
- self.b(' GObject *weak_object)')
- self.b('{')
- self.b(' %s callback = (%s) generic_callback;'
- % (callback_name, callback_name))
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' callback ((%s) self,' % self.proxy_cls)
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if marshaller == 'BOXED' or pointer:
- self.b(' NULL,')
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' 0.0,')
- else:
- self.b(' 0,')
-
- self.b(' error, user_data, weak_object);')
- self.b(' g_error_free (error);')
- self.b(' return;')
- self.b(' }')
-
- self.b(' callback ((%s) self,' % self.proxy_cls)
-
- # FIXME: factor out into a function
- for i, arg in enumerate(out_args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if marshaller == 'BOXED':
- self.b(' g_value_get_boxed (args->values + %d),' % i)
- elif gtype == 'G_TYPE_STRING':
- self.b(' g_value_get_string (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UCHAR':
- self.b(' g_value_get_uchar (args->values + %d),' % i)
- elif gtype == 'G_TYPE_BOOLEAN':
- self.b(' g_value_get_boolean (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT':
- self.b(' g_value_get_uint (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT':
- self.b(' g_value_get_int (args->values + %d),' % i)
- elif gtype == 'G_TYPE_UINT64':
- self.b(' g_value_get_uint64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_INT64':
- self.b(' g_value_get_int64 (args->values + %d),' % i)
- elif gtype == 'G_TYPE_DOUBLE':
- self.b(' g_value_get_double (args->values + %d),' % i)
- else:
- assert False, "Don't know how to get %s from a GValue" % gtype
-
- self.b(' error, user_data, weak_object);')
- self.b('')
-
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- if len(out_args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
-
- self.b('}')
- self.b('')
-
- # Async stub
-
- # Example:
- # TpProxyPendingCall *
- # tp_cli_properties_interface_call_get_properties
- # (gpointer proxy,
- # gint timeout_ms,
- # const GArray *in_properties,
- # tp_cli_properties_interface_callback_for_get_properties callback,
- # gpointer user_data,
- # GDestroyNotify *destructor);
-
- self.h('TpProxyPendingCall *%s_%s_call_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.h(' gint timeout_ms,')
-
- self.d('/**')
- self.d(' * %s_%s_call_%s:'
- % (self.prefix_lc, iface_lc, member_lc))
- self.d(' * @proxy: the #TpProxy')
- self.d(' * @timeout_ms: the timeout in milliseconds, or -1 to use the')
- self.d(' * default')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- docs = xml_escape(get_docstring(elt) or '(Undocumented)')
-
- if ctype == 'guint ' and tp_type != '':
- docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
-
- self.d(' * @%s: Used to pass an \'in\' argument: %s'
- % (name, docs))
-
- self.d(' * @callback: called when the method call succeeds or fails;')
- self.d(' * may be %NULL to make a "fire and forget" call with no ')
- self.d(' * reply tracking')
- self.d(' * @user_data: user-supplied data passed to the callback;')
- self.d(' * must be %NULL if @callback is %NULL')
- self.d(' * @destroy: called with the user_data as argument, after the')
- self.d(' * call has succeeded, failed or been cancelled;')
- self.d(' * must be %NULL if @callback is %NULL')
- self.d(' * @weak_object: If not %NULL, a #GObject which will be ')
- self.d(' * weakly referenced; if it is destroyed, this call ')
- self.d(' * will automatically be cancelled. Must be %NULL if ')
- self.d(' * @callback is %NULL')
- self.d(' *')
- self.d(' * Start a %s method call.' % member)
- self.d(' *')
- self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
- self.d(' *')
- self.d(' * Returns: a #TpProxyPendingCall representing the call in')
- self.d(' * progress. It is borrowed from the object, and will become')
- self.d(' * invalid when the callback is called, the call is')
- self.d(' * cancelled or the #TpProxy becomes invalid.')
-
- deprecated = method.getElementsByTagName('tp:deprecated')
- if deprecated:
- d = deprecated[0]
- self.d(' *')
- self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
-
- self.d(' */')
- self.d('')
-
- self.b('TpProxyPendingCall *\n%s_%s_call_%s (%sproxy,'
- % (self.prefix_lc, iface_lc, member_lc, self.proxy_arg))
- self.b(' gint timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
- self.b(' %s%s%s,' % (const, ctype, name))
-
- self.h(' %s callback,' % callback_name)
- self.h(' gpointer user_data,')
- self.h(' GDestroyNotify destroy,')
- self.h(' GObject *weak_object);')
- self.h('')
-
- self.b(' %s callback,' % callback_name)
- self.b(' gpointer user_data,')
- self.b(' GDestroyNotify destroy,')
- self.b(' GObject *weak_object)')
- self.b('{')
- self.b(' GError *error = NULL;')
- self.b(' GQuark interface = %s;' % self.get_iface_quark())
- self.b(' DBusGProxy *iface;')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), NULL);'
- % self.proxy_assert)
- self.b(' g_return_val_if_fail (callback != NULL || '
- 'user_data == NULL, NULL);')
- self.b(' g_return_val_if_fail (callback != NULL || '
- 'destroy == NULL, NULL);')
- self.b(' g_return_val_if_fail (callback != NULL || '
- 'weak_object == NULL, NULL);')
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' iface = tp_proxy_borrow_interface_by_id (')
- self.b(' (TpProxy *) proxy,')
- self.b(' interface, &error);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
- self.b('')
- self.b(' if (iface == NULL)')
- self.b(' {')
- self.b(' if (callback != NULL)')
- self.b(' callback (proxy,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- if pointer:
- self.b(' NULL,')
- else:
- self.b(' 0,')
-
- self.b(' error, user_data, weak_object);')
- self.b('')
- self.b(' if (destroy != NULL)')
- self.b(' destroy (user_data);')
- self.b('')
- self.b(' g_error_free (error);')
- self.b(' return NULL;')
- self.b(' }')
- self.b('')
- self.b(' if (callback == NULL)')
- self.b(' {')
- self.b(' dbus_g_proxy_call_no_reply (iface, "%s",' % member)
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s, %s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID);')
- self.b(' return NULL;')
- self.b(' }')
- self.b(' else')
- self.b(' {')
- self.b(' TpProxyPendingCall *data;')
- self.b('')
- self.b(' data = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
- self.b(' interface, "%s", iface,' % member)
- self.b(' %s,' % invoke_callback)
- self.b(' G_CALLBACK (callback), user_data, destroy,')
- self.b(' weak_object, FALSE);')
- self.b(' tp_proxy_pending_call_v0_take_pending_call (data,')
- self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
- self.b(' "%s",' % member)
- self.b(' %s,' % collect_callback)
- self.b(' data,')
- self.b(' tp_proxy_pending_call_v0_completed,')
- self.b(' timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s, %s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID));')
- self.b('')
- self.b(' return data;')
- self.b(' }')
- self.b('}')
- self.b('')
-
- self.do_method_reentrant(method, iface_lc, member, member_lc,
- in_args, out_args, collect_callback)
-
- # leave a gap for the end of the method
- self.d('')
- self.b('')
- self.h('')
-
- def do_method_reentrant(self, method, iface_lc, member, member_lc, in_args,
- out_args, collect_callback):
- # Reentrant blocking calls
- # Example:
- # gboolean tp_cli_properties_interface_run_get_properties
- # (gpointer proxy,
- # gint timeout_ms,
- # const GArray *in_properties,
- # GPtrArray **out0,
- # GError **error,
- # GMainLoop **loop);
-
- run_method_name = '%s_%s_run_%s' % (self.prefix_lc, iface_lc, member_lc)
- if run_method_name not in self.reentrant_symbols:
- return
-
- self.b('typedef struct {')
- self.b(' GMainLoop *loop;')
- self.b(' GError **error;')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' %s*%s;' % (ctype, name))
-
- self.b(' unsigned success:1;')
- self.b(' unsigned completed:1;')
- self.b('} _%s_%s_run_state_%s;'
- % (self.prefix_lc, iface_lc, member_lc))
-
- reentrant_invoke = '_%s_%s_finish_running_%s' % (self.prefix_lc,
- iface_lc,
- member_lc)
-
- self.b('static void')
- self.b('%s (TpProxy *self G_GNUC_UNUSED,' % reentrant_invoke)
- self.b(' GError *error,')
- self.b(' GValueArray *args,')
- self.b(' GCallback unused G_GNUC_UNUSED,')
- self.b(' gpointer user_data G_GNUC_UNUSED,')
- self.b(' GObject *unused2 G_GNUC_UNUSED)')
- self.b('{')
- self.b(' _%s_%s_run_state_%s *state = user_data;'
- % (self.prefix_lc, iface_lc, member_lc))
- self.b('')
- self.b(' state->success = (error == NULL);')
- self.b(' state->completed = TRUE;')
- self.b(' g_main_loop_quit (state->loop);')
- self.b('')
- self.b(' if (error != NULL)')
- self.b(' {')
- self.b(' if (state->error != NULL)')
- self.b(' *state->error = error;')
- self.b(' else')
- self.b(' g_error_free (error);')
- self.b('')
- self.b(' return;')
- self.b(' }')
- self.b('')
-
- for i, arg in enumerate(out_args):
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.b(' if (state->%s != NULL)' % name)
- if marshaller == 'BOXED':
- self.b(' *state->%s = g_value_dup_boxed ('
- 'args->values + %d);' % (name, i))
- elif marshaller == 'STRING':
- self.b(' *state->%s = g_value_dup_string '
- '(args->values + %d);' % (name, i))
- elif marshaller in ('UCHAR', 'BOOLEAN', 'INT', 'UINT',
- 'INT64', 'UINT64', 'DOUBLE'):
- self.b(' *state->%s = g_value_get_%s (args->values + %d);'
- % (name, marshaller.lower(), i))
- else:
- assert False, "Don't know how to copy %s" % gtype
-
- self.b('')
-
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- if len(out_args) > 0:
- self.b(' g_value_array_free (args);')
- else:
- self.b(' if (args != NULL)')
- self.b(' g_value_array_free (args);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
-
- self.b('}')
- self.b('')
-
- if self.deprecate_reentrant:
- self.h('#ifndef %s' % self.deprecate_reentrant)
-
- self.h('gboolean %s (%sproxy,'
- % (run_method_name, self.proxy_arg))
- self.h(' gint timeout_ms,')
-
- self.d('/**')
- self.d(' * %s:' % run_method_name)
- self.d(' * @proxy: %s' % self.proxy_doc)
- self.d(' * @timeout_ms: Timeout in milliseconds, or -1 for default')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- docs = xml_escape(get_docstring(elt) or '(Undocumented)')
-
- if ctype == 'guint ' and tp_type != '':
- docs += ' (#%s)' % ('Tp' + tp_type.replace('_', ''))
-
- self.d(' * @%s: Used to pass an \'in\' argument: %s'
- % (name, docs))
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.d(' * @%s: Used to return an \'out\' argument if %%TRUE is '
- 'returned: %s'
- % (name, xml_escape(get_docstring(elt) or '(Undocumented)')))
-
- self.d(' * @error: If not %NULL, used to return errors if %FALSE ')
- self.d(' * is returned')
- self.d(' * @loop: If not %NULL, set before re-entering ')
- self.d(' * the main loop, to point to a #GMainLoop ')
- self.d(' * which can be used to cancel this call with ')
- self.d(' * g_main_loop_quit(), causing a return of ')
- self.d(' * %FALSE with @error set to %TP_DBUS_ERROR_CANCELLED')
- self.d(' *')
- self.d(' * Call the method %s and run the main loop' % member)
- self.d(' * until it returns. Before calling this method, you must')
- self.d(' * add a reference to any borrowed objects you need to keep,')
- self.d(' * and generally ensure that everything is in a consistent')
- self.d(' * state.')
- self.d(' *')
- self.d(' * %s' % xml_escape(get_docstring(method) or '(Undocumented)'))
- self.d(' *')
- self.d(' * Returns: TRUE on success, FALSE and sets @error on error')
-
- deprecated = method.getElementsByTagName('tp:deprecated')
- if deprecated:
- d = deprecated[0]
- self.d(' *')
- self.d(' * Deprecated: %s' % xml_escape(get_deprecated(d)))
-
- self.d(' */')
- self.d('')
-
- self.b('gboolean\n%s (%sproxy,'
- % (run_method_name, self.proxy_arg))
- self.b(' gint timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.h(' %s%s%s,' % (const, ctype, name))
- self.b(' %s%s%s,' % (const, ctype, name))
-
- for arg in out_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- self.h(' %s*%s,' % (ctype, name))
- self.b(' %s*%s,' % (ctype, name))
-
- self.h(' GError **error,')
-
- if self.deprecate_reentrant:
- self.h(' GMainLoop **loop) %s;' % self.deprecation_attribute)
- self.h('#endif /* not %s */' % self.deprecate_reentrant)
- else:
- self.h(' GMainLoop **loop);')
-
- self.h('')
-
- self.b(' GError **error,')
- self.b(' GMainLoop **loop)')
- self.b('{')
- self.b(' DBusGProxy *iface;')
- self.b(' GQuark interface = %s;' % self.get_iface_quark())
- self.b(' TpProxyPendingCall *pc;')
- self.b(' _%s_%s_run_state_%s state = {'
- % (self.prefix_lc, iface_lc, member_lc))
- self.b(' NULL /* loop */, error,')
-
- for arg in out_args:
- name, info, tp_type, elt = arg
-
- self.b(' %s,' % name)
-
- self.b(' FALSE /* completed */, FALSE /* success */ };')
- self.b('')
- self.b(' g_return_val_if_fail (%s (proxy), FALSE);'
- % self.proxy_assert)
- self.b('')
- self.b(' G_GNUC_BEGIN_IGNORE_DEPRECATIONS')
- self.b(' iface = tp_proxy_borrow_interface_by_id')
- self.b(' ((TpProxy *) proxy, interface, error);')
- self.b(' G_GNUC_END_IGNORE_DEPRECATIONS')
- self.b('')
- self.b(' if (iface == NULL)')
- self.b(' return FALSE;')
- self.b('')
- self.b(' state.loop = g_main_loop_new (NULL, FALSE);')
- self.b('')
- self.b(' pc = tp_proxy_pending_call_v0_new ((TpProxy *) proxy,')
- self.b(' interface, "%s", iface,' % member)
- self.b(' %s,' % reentrant_invoke)
- self.b(' NULL, &state, NULL, NULL, TRUE);')
- self.b('')
- self.b(' if (loop != NULL)')
- self.b(' *loop = state.loop;')
- self.b('')
- self.b(' tp_proxy_pending_call_v0_take_pending_call (pc,')
- self.b(' dbus_g_proxy_begin_call_with_timeout (iface,')
- self.b(' "%s",' % member)
- self.b(' %s,' % collect_callback)
- self.b(' pc,')
- self.b(' tp_proxy_pending_call_v0_completed,')
- self.b(' timeout_ms,')
-
- for arg in in_args:
- name, info, tp_type, elt = arg
- ctype, gtype, marshaller, pointer = info
-
- const = pointer and 'const ' or ''
-
- self.b(' %s, %s,' % (gtype, name))
-
- self.b(' G_TYPE_INVALID));')
- self.b('')
- self.b(' if (!state.completed)')
- self.b(' g_main_loop_run (state.loop);')
- self.b('')
- self.b(' if (!state.completed)')
- self.b(' tp_proxy_pending_call_cancel (pc);')
- self.b('')
- self.b(' if (loop != NULL)')
- self.b(' *loop = NULL;')
- self.b('')
- self.b(' g_main_loop_unref (state.loop);')
- self.b('')
- self.b(' return state.success;')
- self.b('}')
- self.b('')
-
- def do_signal_add(self, signal):
- marshaller_items = []
- gtypes = []
-
- for i in signal.getElementsByTagName('arg'):
- name = i.getAttribute('name')
- type = i.getAttribute('type')
- info = type_to_gtype(type)
- # type, GType, STRING, is a pointer
- gtypes.append(info[1])
-
- self.b(' dbus_g_proxy_add_signal (proxy, "%s",'
- % signal.getAttribute('name'))
- for gtype in gtypes:
- self.b(' %s,' % gtype)
- self.b(' G_TYPE_INVALID);')
-
- def do_interface(self, node):
- ifaces = node.getElementsByTagName('interface')
- assert len(ifaces) == 1
- iface = ifaces[0]
- name = node.getAttribute('name').replace('/', '')
-
- self.iface = name
- self.iface_lc = name.lower()
- self.iface_uc = name.upper()
- self.iface_mc = name.replace('_', '')
- self.iface_dbus = iface.getAttribute('name')
-
- signals = node.getElementsByTagName('signal')
- methods = node.getElementsByTagName('method')
-
- if signals:
- self.b('static inline void')
- self.b('%s_add_signals_for_%s (DBusGProxy *proxy)'
- % (self.prefix_lc, name.lower()))
- self.b('{')
-
- if self.tp_proxy_api >= (0, 7, 6):
- self.b(' if (!tp_proxy_dbus_g_proxy_claim_for_signal_adding '
- '(proxy))')
- self.b(' return;')
-
- for signal in signals:
- self.do_signal_add(signal)
-
- self.b('}')
- self.b('')
- self.b('')
-
- for signal in signals:
- self.do_signal(name, signal)
-
- for method in methods:
- self.do_method(name, method)
-
- self.iface_dbus = None
-
- def __call__(self):
-
- if self.guard is not None:
- self.h('#ifndef %s' % self.guard)
- self.h('#define %s' % self.guard)
- self.h('')
-
- self.h('G_BEGIN_DECLS')
- self.h('')
-
- self.b('/* We don\'t want gtkdoc scanning this file, it\'ll get')
- self.b(' * confused by seeing function definitions, so mark it as: */')
- self.b('/*<private_header>*/')
- self.b('')
-
- nodes = self.dom.getElementsByTagName('node')
- nodes.sort(key=key_by_name)
-
- for node in nodes:
- self.do_interface(node)
-
- if self.group is not None:
-
- self.b('/*')
- self.b(' * %s_%s_add_signals:' % (self.prefix_lc, self.group))
- self.b(' * @self: the #TpProxy')
- self.b(' * @quark: a quark whose string value is the interface')
- self.b(' * name whose signals should be added')
- self.b(' * @proxy: the D-Bus proxy to which to add the signals')
- self.b(' * @unused: not used for anything')
- self.b(' *')
- self.b(' * Tell dbus-glib that @proxy has the signatures of all')
- self.b(' * signals on the given interface, if it\'s one we')
- self.b(' * support.')
- self.b(' *')
- self.b(' * This function should be used as a signal handler for')
- self.b(' * #TpProxy::interface-added.')
- self.b(' */')
- self.b('static void')
- self.b('%s_%s_add_signals (TpProxy *self G_GNUC_UNUSED,'
- % (self.prefix_lc, self.group))
- self.b(' guint quark,')
- self.b(' DBusGProxy *proxy,')
- self.b(' gpointer unused G_GNUC_UNUSED)')
-
- self.b('{')
-
- for node in nodes:
- iface = node.getElementsByTagName('interface')[0]
- self.iface_dbus = iface.getAttribute('name')
- signals = node.getElementsByTagName('signal')
- if not signals:
- continue
- name = node.getAttribute('name').replace('/', '').lower()
- self.iface_uc = name.upper()
- self.b(' if (quark == %s)' % self.get_iface_quark())
- self.b(' %s_add_signals_for_%s (proxy);'
- % (self.prefix_lc, name))
-
- self.b('}')
- self.b('')
-
- self.h('G_END_DECLS')
- self.h('')
-
- if self.guard is not None:
- self.h('#endif /* defined (%s) */' % self.guard)
- self.h('')
-
- file_set_contents(self.basename + '.h', u('\n').join(self.__header).encode('utf-8'))
- file_set_contents(self.basename + '-body.h', u('\n').join(self.__body).encode('utf-8'))
- file_set_contents(self.basename + '-gtk-doc.h', u('\n').join(self.__docs).encode('utf-8'))
-
-def types_to_gtypes(types):
- return [type_to_gtype(t)[1] for t in types]
-
-
-if __name__ == '__main__':
- options, argv = gnu_getopt(sys.argv[1:], '',
- ['group=', 'subclass=', 'subclass-assert=',
- 'iface-quark-prefix=', 'tp-proxy-api=',
- 'generate-reentrant=', 'deprecate-reentrant=',
- 'deprecation-attribute=', 'guard='])
-
- opts = {}
-
- for option, value in options:
- opts[option] = value
-
- dom = xml.dom.minidom.parse(argv[0])
-
- Generator(dom, argv[1], argv[2], opts)()
diff --git a/tools/glib-client-marshaller-gen.py b/tools/glib-client-marshaller-gen.py
deleted file mode 100644
index cd9823bd..00000000
--- a/tools/glib-client-marshaller-gen.py
+++ /dev/null
@@ -1,60 +0,0 @@
-#!/usr/bin/python
-
-import sys
-import xml.dom.minidom
-from string import ascii_letters, digits
-
-
-from libglibcodegen import signal_to_marshal_name
-
-
-NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-
-class Generator(object):
-
- def __init__(self, dom, prefix):
- self.dom = dom
- self.marshallers = {}
- self.prefix = prefix
-
- def do_signal(self, signal):
- marshaller = signal_to_marshal_name(signal, self.prefix)
-
- assert '__' in marshaller
- rhs = marshaller.split('__', 1)[1].split('_')
-
- self.marshallers[marshaller] = rhs
-
- def __call__(self):
- signals = self.dom.getElementsByTagName('signal')
-
- for signal in signals:
- self.do_signal(signal)
-
- print('void')
- print('%s_register_dbus_glib_marshallers (void)' % self.prefix)
- print('{')
-
- all = list(self.marshallers.keys())
- all.sort()
- for marshaller in all:
- rhs = self.marshallers[marshaller]
-
- print(' dbus_g_object_register_marshaller (')
- print(' g_cclosure_marshal_generic,')
- print(' G_TYPE_NONE, /* return */')
- for type in rhs:
- print(' G_TYPE_%s,' % type.replace('VOID', 'NONE'))
- print(' G_TYPE_INVALID);')
-
- print('}')
-
-
-def types_to_gtypes(types):
- return [type_to_gtype(t)[1] for t in types]
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
- dom = xml.dom.minidom.parse(argv[0])
-
- Generator(dom, argv[1])()
diff --git a/tools/glib-ginterface-gen.py b/tools/glib-ginterface-gen.py
deleted file mode 100644
index c0ce20dd..00000000
--- a/tools/glib-ginterface-gen.py
+++ /dev/null
@@ -1,832 +0,0 @@
-#!/usr/bin/python
-
-# glib-ginterface-gen.py: service-side interface generator
-#
-# Generate dbus-glib 0.x service GInterfaces from the Telepathy specification.
-# The master copy of this program is in the telepathy-glib repository -
-# please make any changes there.
-#
-# Copyright (C) 2006, 2007 Collabora Limited
-#
-# 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
-
-import sys
-import os.path
-import xml.dom.minidom
-
-from libtpcodegen import file_set_contents, key_by_name, u
-from libglibcodegen import Signature, type_to_gtype, \
- NS_TP, dbus_gutils_wincaps_to_uscore
-
-
-NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-
-def get_emits_changed(node):
- try:
- return [
- annotation.getAttribute('value')
- for annotation in node.getElementsByTagName('annotation')
- if annotation.getAttribute('name') == 'org.freedesktop.DBus.Property.EmitsChangedSignal'
- ][0]
- except IndexError:
- return None
-
-class Generator(object):
-
- def __init__(self, dom, prefix, basename, signal_marshal_prefix,
- headers, end_headers, not_implemented_func,
- allow_havoc):
- self.dom = dom
- self.__header = []
- self.__body = []
- self.__docs = []
-
- assert prefix.endswith('_')
- assert not signal_marshal_prefix.endswith('_')
-
- # The main_prefix, sub_prefix thing is to get:
- # FOO_ -> (FOO_, _)
- # FOO_SVC_ -> (FOO_, _SVC_)
- # but
- # FOO_BAR/ -> (FOO_BAR_, _)
- # FOO_BAR/SVC_ -> (FOO_BAR_, _SVC_)
-
- if '/' in prefix:
- main_prefix, sub_prefix = prefix.upper().split('/', 1)
- prefix = prefix.replace('/', '_')
- else:
- main_prefix, sub_prefix = prefix.upper().split('_', 1)
-
- self.MAIN_PREFIX_ = main_prefix + '_'
- self._SUB_PREFIX_ = '_' + sub_prefix
-
- self.Prefix_ = prefix
- self.Prefix = prefix.replace('_', '')
- self.prefix_ = prefix.lower()
- self.PREFIX_ = prefix.upper()
-
- self.basename = basename
- self.signal_marshal_prefix = signal_marshal_prefix
- self.headers = headers
- self.end_headers = end_headers
- self.not_implemented_func = not_implemented_func
- self.allow_havoc = allow_havoc
-
- def h(self, s):
- self.__header.append(s)
-
- def b(self, s):
- self.__body.append(s)
-
- def d(self, s):
- self.__docs.append(s)
-
- def do_node(self, node):
- node_name = node.getAttribute('name').replace('/', '')
- node_name_mixed = self.node_name_mixed = node_name.replace('_', '')
- node_name_lc = self.node_name_lc = node_name.lower()
- node_name_uc = self.node_name_uc = node_name.upper()
-
- interfaces = node.getElementsByTagName('interface')
- assert len(interfaces) == 1, interfaces
- interface = interfaces[0]
- self.iface_name = interface.getAttribute('name')
-
- tmp = interface.getAttribute('tp:implement-service')
- if tmp == "no":
- return
-
- tmp = interface.getAttribute('tp:causes-havoc')
- if tmp and not self.allow_havoc:
- raise AssertionError('%s is %s' % (self.iface_name, tmp))
-
- iface_emits_changed = get_emits_changed(interface)
-
- self.b('static const DBusGObjectInfo _%s%s_object_info;'
- % (self.prefix_, node_name_lc))
- self.b('')
-
- methods = interface.getElementsByTagName('method')
- signals = interface.getElementsByTagName('signal')
- properties = interface.getElementsByTagName('property')
- # Don't put properties in dbus-glib glue
- glue_properties = []
-
- self.b('struct _%s%sClass {' % (self.Prefix, node_name_mixed))
- self.b(' GTypeInterface parent_class;')
- for method in methods:
- self.b(' %s %s;' % self.get_method_impl_names(method))
- self.b('};')
- self.b('')
-
- if signals:
- self.b('enum {')
- for signal in signals:
- self.b(' %s,' % self.get_signal_const_entry(signal))
- self.b(' N_%s_SIGNALS' % node_name_uc)
- self.b('};')
- self.b('static guint %s_signals[N_%s_SIGNALS] = {0};'
- % (node_name_lc, node_name_uc))
- self.b('')
-
- self.b('static void %s%s_base_init (gpointer klass);'
- % (self.prefix_, node_name_lc))
- self.b('')
-
- self.b('GType')
- self.b('%s%s_get_type (void)'
- % (self.prefix_, node_name_lc))
- self.b('{')
- self.b(' static GType type = 0;')
- self.b('')
- self.b(' if (G_UNLIKELY (type == 0))')
- self.b(' {')
- self.b(' static const GTypeInfo info = {')
- self.b(' sizeof (%s%sClass),' % (self.Prefix, node_name_mixed))
- self.b(' %s%s_base_init, /* base_init */'
- % (self.prefix_, node_name_lc))
- self.b(' NULL, /* base_finalize */')
- self.b(' NULL, /* class_init */')
- self.b(' NULL, /* class_finalize */')
- self.b(' NULL, /* class_data */')
- self.b(' 0,')
- self.b(' 0, /* n_preallocs */')
- self.b(' NULL /* instance_init */')
- self.b(' };')
- self.b('')
- self.b(' type = g_type_register_static (G_TYPE_INTERFACE,')
- self.b(' "%s%s", &info, 0);' % (self.Prefix, node_name_mixed))
- self.b(' }')
- self.b('')
- self.b(' return type;')
- self.b('}')
- self.b('')
-
- self.d('/**')
- self.d(' * %s%s:' % (self.Prefix, node_name_mixed))
- self.d(' *')
- self.d(' * Dummy typedef representing any implementation of this '
- 'interface.')
- self.d(' */')
-
- self.h('typedef struct _%s%s %s%s;'
- % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed))
- self.h('')
-
- self.d('/**')
- self.d(' * %s%sClass:' % (self.Prefix, node_name_mixed))
- self.d(' *')
- self.d(' * The class of %s%s.' % (self.Prefix, node_name_mixed))
-
- if methods:
- self.d(' *')
- self.d(' * In a full implementation of this interface (i.e. all')
- self.d(' * methods implemented), the interface initialization')
- self.d(' * function used in G_IMPLEMENT_INTERFACE() would')
- self.d(' * typically look like this:')
- self.d(' *')
- self.d(' * <programlisting>')
- self.d(' * static void')
- self.d(' * implement_%s (gpointer klass,' % self.node_name_lc)
- self.d(' * gpointer unused G_GNUC_UNUSED)')
- self.d(' * {')
- self.d(' * #define IMPLEMENT(x) %s%s_implement_&num;&num;x (\\'
- % (self.prefix_, self.node_name_lc))
- self.d(' * klass, my_object_&num;&num;x)')
-
- for method in methods:
- class_member_name = method.getAttribute('tp:name-for-bindings')
- class_member_name = class_member_name.lower()
- self.d(' * IMPLEMENT (%s);' % class_member_name)
-
- self.d(' * #undef IMPLEMENT')
- self.d(' * }')
- self.d(' * </programlisting>')
- else:
- self.d(' * This interface has no D-Bus methods, so an')
- self.d(' * implementation can typically pass %NULL to')
- self.d(' * G_IMPLEMENT_INTERFACE() as the interface')
- self.d(' * initialization function.')
-
- self.d(' */')
- self.d('')
-
- self.h('typedef struct _%s%sClass %s%sClass;'
- % (self.Prefix, node_name_mixed, self.Prefix, node_name_mixed))
- self.h('')
- self.h('GType %s%s_get_type (void);'
- % (self.prefix_, node_name_lc))
-
- gtype = self.current_gtype = \
- self.MAIN_PREFIX_ + 'TYPE' + self._SUB_PREFIX_ + node_name_uc
- classname = self.Prefix + node_name_mixed
-
- self.h('#define %s \\\n (%s%s_get_type ())'
- % (gtype, self.prefix_, node_name_lc))
- self.h('#define %s%s(obj) \\\n'
- ' (G_TYPE_CHECK_INSTANCE_CAST((obj), %s, %s))'
- % (self.PREFIX_, node_name_uc, gtype, classname))
- self.h('#define %sIS%s%s(obj) \\\n'
- ' (G_TYPE_CHECK_INSTANCE_TYPE((obj), %s))'
- % (self.MAIN_PREFIX_, self._SUB_PREFIX_, node_name_uc, gtype))
- self.h('#define %s%s_GET_CLASS(obj) \\\n'
- ' (G_TYPE_INSTANCE_GET_INTERFACE((obj), %s, %sClass))'
- % (self.PREFIX_, node_name_uc, gtype, classname))
- self.h('')
- self.h('')
-
- base_init_code = []
-
- for method in methods:
- self.do_method(method)
-
- for signal in signals:
- base_init_code.extend(self.do_signal(signal))
-
- self.b('static inline void')
- self.b('%s%s_base_init_once (gpointer klass G_GNUC_UNUSED)'
- % (self.prefix_, node_name_lc))
- self.b('{')
-
- if properties:
- self.b(' static TpDBusPropertiesMixinPropInfo properties[%d] = {'
- % (len(properties) + 1))
-
- for m in properties:
- access = m.getAttribute('access')
- assert access in ('read', 'write', 'readwrite')
-
- if access == 'read':
- flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_READ'
- elif access == 'write':
- flags = 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE'
- else:
- flags = ('TP_DBUS_PROPERTIES_MIXIN_FLAG_READ | '
- 'TP_DBUS_PROPERTIES_MIXIN_FLAG_WRITE')
-
- prop_emits_changed = get_emits_changed(m)
-
- if prop_emits_changed is None:
- prop_emits_changed = iface_emits_changed
-
- if prop_emits_changed == 'true':
- flags += ' | TP_DBUS_PROPERTIES_MIXIN_FLAG_EMITS_CHANGED'
- elif prop_emits_changed == 'invalidates':
- flags += ' | TP_DBUS_PROPERTIES_MIXIN_FLAG_EMITS_INVALIDATED'
-
- self.b(' { 0, %s, "%s", 0, NULL, NULL }, /* %s */'
- % (flags, m.getAttribute('type'), m.getAttribute('name')))
-
- self.b(' { 0, 0, NULL, 0, NULL, NULL }')
- self.b(' };')
- self.b(' static TpDBusPropertiesMixinIfaceInfo interface =')
- self.b(' { 0, properties, NULL, NULL };')
- self.b('')
-
-
- self.b(' dbus_g_object_type_install_info (%s%s_get_type (),'
- % (self.prefix_, node_name_lc))
- self.b(' &_%s%s_object_info);'
- % (self.prefix_, node_name_lc))
- self.b('')
-
- if properties:
- self.b(' interface.dbus_interface = g_quark_from_static_string '
- '("%s");' % self.iface_name)
-
- for i, m in enumerate(properties):
- self.b(' properties[%d].name = g_quark_from_static_string ("%s");'
- % (i, m.getAttribute('name')))
- self.b(' properties[%d].type = %s;'
- % (i, type_to_gtype(m.getAttribute('type'))[1]))
-
- self.b(' tp_svc_interface_set_dbus_properties_info (%s, &interface);'
- % self.current_gtype)
-
- self.b('')
-
- for s in base_init_code:
- self.b(s)
- self.b('}')
-
- self.b('static void')
- self.b('%s%s_base_init (gpointer klass)'
- % (self.prefix_, node_name_lc))
- self.b('{')
- self.b(' static gboolean initialized = FALSE;')
- self.b('')
- self.b(' if (!initialized)')
- self.b(' {')
- self.b(' initialized = TRUE;')
- self.b(' %s%s_base_init_once (klass);'
- % (self.prefix_, node_name_lc))
- self.b(' }')
- # insert anything we need to do per implementation here
- self.b('}')
-
- self.h('')
-
- self.b('static const DBusGMethodInfo _%s%s_methods[] = {'
- % (self.prefix_, node_name_lc))
-
- method_blob, offsets = self.get_method_glue(methods)
-
- for method, offset in zip(methods, offsets):
- self.do_method_glue(method, offset)
-
- if len(methods) == 0:
- # empty arrays are a gcc extension, so put in a dummy member
- self.b(" { NULL, NULL, 0 }")
-
- self.b('};')
- self.b('')
-
- self.b('static const DBusGObjectInfo _%s%s_object_info = {'
- % (self.prefix_, node_name_lc))
- self.b(' 0,') # version
- self.b(' _%s%s_methods,' % (self.prefix_, node_name_lc))
- self.b(' %d,' % len(methods))
- self.b('"' + method_blob.replace('\0', '\\0') + '",')
- self.b('"' + self.get_signal_glue(signals).replace('\0', '\\0') + '",')
- self.b('"' +
- self.get_property_glue(glue_properties).replace('\0', '\\0') +
- '",')
- self.b('};')
- self.b('')
-
- self.node_name_mixed = None
- self.node_name_lc = None
- self.node_name_uc = None
-
- def get_method_glue(self, methods):
- info = []
- offsets = []
-
- for method in methods:
- offsets.append(len(''.join(info)))
-
- info.append(self.iface_name + '\0')
- info.append(method.getAttribute('name') + '\0')
-
- info.append('A\0') # async
-
- counter = 0
- for arg in method.getElementsByTagName('arg'):
- out = arg.getAttribute('direction') == 'out'
-
- name = arg.getAttribute('name')
- if not name:
- assert out
- name = 'arg%u' % counter
- counter += 1
-
- info.append(name + '\0')
-
- if out:
- info.append('O\0')
- else:
- info.append('I\0')
-
- if out:
- info.append('F\0') # not const
- info.append('N\0') # not error or return
- info.append(arg.getAttribute('type') + '\0')
-
- info.append('\0')
-
- return ''.join(info) + '\0', offsets
-
- def do_method_glue(self, method, offset):
- lc_name = method.getAttribute('tp:name-for-bindings')
- if method.getAttribute('name') != lc_name.replace('_', ''):
- raise AssertionError('Method %s tp:name-for-bindings (%s) does '
- 'not match' % (method.getAttribute('name'), lc_name))
- lc_name = lc_name.lower()
-
- marshaller = 'g_cclosure_marshal_generic'
- wrapper = self.prefix_ + self.node_name_lc + '_' + lc_name
-
- self.b(" { (GCallback) %s, %s, %d }," % (wrapper, marshaller, offset))
-
- def get_signal_glue(self, signals):
- info = []
-
- for signal in signals:
- info.append(self.iface_name)
- info.append(signal.getAttribute('name'))
-
- return '\0'.join(info) + '\0\0'
-
- # the implementation can be the same
- get_property_glue = get_signal_glue
-
- def get_method_impl_names(self, method):
- dbus_method_name = method.getAttribute('name')
-
- class_member_name = method.getAttribute('tp:name-for-bindings')
- if dbus_method_name != class_member_name.replace('_', ''):
- raise AssertionError('Method %s tp:name-for-bindings (%s) does '
- 'not match' % (dbus_method_name, class_member_name))
- class_member_name = class_member_name.lower()
-
- stub_name = (self.prefix_ + self.node_name_lc + '_' +
- class_member_name)
- return (stub_name + '_impl', class_member_name + '_cb')
-
- def do_method(self, method):
- assert self.node_name_mixed is not None
-
- in_class = []
-
- # Examples refer to Thing.DoStuff (su) -> ii
-
- # DoStuff
- dbus_method_name = method.getAttribute('name')
- # do_stuff
- class_member_name = method.getAttribute('tp:name-for-bindings')
- if dbus_method_name != class_member_name.replace('_', ''):
- raise AssertionError('Method %s tp:name-for-bindings (%s) does '
- 'not match' % (dbus_method_name, class_member_name))
- class_member_name = class_member_name.lower()
-
- # void tp_svc_thing_do_stuff (TpSvcThing *, const char *, guint,
- # DBusGMethodInvocation *);
- stub_name = (self.prefix_ + self.node_name_lc + '_' +
- class_member_name)
- # typedef void (*tp_svc_thing_do_stuff_impl) (TpSvcThing *,
- # const char *, guint, DBusGMethodInvocation);
- impl_name = stub_name + '_impl'
- # void tp_svc_thing_return_from_do_stuff (DBusGMethodInvocation *,
- # gint, gint);
- ret_name = (self.prefix_ + self.node_name_lc + '_return_from_' +
- class_member_name)
-
- # Gather arguments
- in_args = []
- out_args = []
- for i in method.getElementsByTagName('arg'):
- name = i.getAttribute('name')
- direction = i.getAttribute('direction') or 'in'
- dtype = i.getAttribute('type')
-
- assert direction in ('in', 'out')
-
- if name:
- name = direction + '_' + name
- elif direction == 'in':
- name = direction + str(len(in_args))
- else:
- name = direction + str(len(out_args))
-
- ctype, gtype, marshaller, pointer = type_to_gtype(dtype)
-
- if pointer:
- ctype = 'const ' + ctype
-
- struct = (ctype, name)
-
- if direction == 'in':
- in_args.append(struct)
- else:
- out_args.append(struct)
-
- # Implementation type declaration (in header, docs separated)
- self.d('/**')
- self.d(' * %s:' % impl_name)
- self.d(' * @self: The object implementing this interface')
- for (ctype, name) in in_args:
- self.d(' * @%s: %s (FIXME, generate documentation)'
- % (name, ctype))
- self.d(' * @context: Used to return values or throw an error')
- self.d(' *')
- self.d(' * The signature of an implementation of the D-Bus method')
- self.d(' * %s on interface %s.' % (dbus_method_name, self.iface_name))
- self.d(' */')
-
- self.h('typedef void (*%s) (%s%s *self,'
- % (impl_name, self.Prefix, self.node_name_mixed))
- for (ctype, name) in in_args:
- self.h(' %s%s,' % (ctype, name))
- self.h(' DBusGMethodInvocation *context);')
-
- # Class member (in class definition)
- in_class.append(' %s %s;' % (impl_name, class_member_name))
-
- # Stub definition (in body only - it's static)
- self.b('static void')
- self.b('%s (%s%s *self,'
- % (stub_name, self.Prefix, self.node_name_mixed))
- for (ctype, name) in in_args:
- self.b(' %s%s,' % (ctype, name))
- self.b(' DBusGMethodInvocation *context)')
- self.b('{')
- self.b(' %s impl = (%s%s_GET_CLASS (self)->%s_cb);'
- % (impl_name, self.PREFIX_, self.node_name_uc, class_member_name))
- self.b('')
- self.b(' if (impl != NULL)')
- tmp = ['self'] + [name for (ctype, name) in in_args] + ['context']
- self.b(' {')
- self.b(' (impl) (%s);' % ',\n '.join(tmp))
- self.b(' }')
- self.b(' else')
- self.b(' {')
- if self.not_implemented_func:
- self.b(' %s (context);' % self.not_implemented_func)
- else:
- self.b(' GError e = { DBUS_GERROR, ')
- self.b(' DBUS_GERROR_UNKNOWN_METHOD,')
- self.b(' "Method not implemented" };')
- self.b('')
- self.b(' dbus_g_method_return_error (context, &e);')
- self.b(' }')
- self.b('}')
- self.b('')
-
- # Implementation registration (in both header and body)
- self.h('void %s%s_implement_%s (%s%sClass *klass, %s impl);'
- % (self.prefix_, self.node_name_lc, class_member_name,
- self.Prefix, self.node_name_mixed, impl_name))
-
- self.d('/**')
- self.d(' * %s%s_implement_%s:'
- % (self.prefix_, self.node_name_lc, class_member_name))
- self.d(' * @klass: A class whose instances implement this interface')
- self.d(' * @impl: A callback used to implement the %s D-Bus method'
- % dbus_method_name)
- self.d(' *')
- self.d(' * Register an implementation for the %s method in the vtable'
- % dbus_method_name)
- self.d(' * of an implementation of this interface. To be called from')
- self.d(' * the interface init function.')
- self.d(' */')
-
- self.b('void')
- self.b('%s%s_implement_%s (%s%sClass *klass, %s impl)'
- % (self.prefix_, self.node_name_lc, class_member_name,
- self.Prefix, self.node_name_mixed, impl_name))
- self.b('{')
- self.b(' klass->%s_cb = impl;' % class_member_name)
- self.b('}')
- self.b('')
-
- # Return convenience function (static inline, in header)
- self.d('/**')
- self.d(' * %s:' % ret_name)
- self.d(' * @context: The D-Bus method invocation context')
- for (ctype, name) in out_args:
- self.d(' * @%s: %s (FIXME, generate documentation)'
- % (name, ctype))
- self.d(' *')
- self.d(' * Return successfully by calling dbus_g_method_return().')
- self.d(' * This inline function exists only to provide type-safety.')
- self.d(' */')
- self.d('')
-
- tmp = (['DBusGMethodInvocation *context'] +
- [ctype + name for (ctype, name) in out_args])
- self.h('static inline')
- self.h('/* this comment is to stop gtkdoc realising this is static */')
- self.h(('void %s (' % ret_name) + (',\n '.join(tmp)) + ');')
- self.h('static inline void')
- self.h(('%s (' % ret_name) + (',\n '.join(tmp)) + ')')
- self.h('{')
- tmp = ['context'] + [name for (ctype, name) in out_args]
- self.h(' dbus_g_method_return (' + ',\n '.join(tmp) + ');')
- self.h('}')
- self.h('')
-
- return in_class
-
- def get_signal_const_entry(self, signal):
- assert self.node_name_uc is not None
- return ('SIGNAL_%s_%s'
- % (self.node_name_uc, signal.getAttribute('name')))
-
- def do_signal(self, signal):
- assert self.node_name_mixed is not None
-
- in_base_init = []
-
- # for signal: Thing::StuffHappened (s, u)
- # we want to emit:
- # void tp_svc_thing_emit_stuff_happened (gpointer instance,
- # const char *arg0, guint arg1);
-
- dbus_name = signal.getAttribute('name')
-
- ugly_name = signal.getAttribute('tp:name-for-bindings')
- if dbus_name != ugly_name.replace('_', ''):
- raise AssertionError('Signal %s tp:name-for-bindings (%s) does '
- 'not match' % (dbus_name, ugly_name))
-
- stub_name = (self.prefix_ + self.node_name_lc + '_emit_' +
- ugly_name.lower())
-
- const_name = self.get_signal_const_entry(signal)
-
- # Gather arguments
- args = []
- for i in signal.getElementsByTagName('arg'):
- name = i.getAttribute('name')
- dtype = i.getAttribute('type')
- tp_type = i.getAttribute('tp:type')
-
- if name:
- name = 'arg_' + name
- else:
- name = 'arg' + str(len(args))
-
- ctype, gtype, marshaller, pointer = type_to_gtype(dtype)
-
- if pointer:
- ctype = 'const ' + ctype
-
- struct = (ctype, name, gtype)
- args.append(struct)
-
- tmp = (['gpointer instance'] +
- [ctype + name for (ctype, name, gtype) in args])
-
- self.h(('void %s (' % stub_name) + (',\n '.join(tmp)) + ');')
-
- # FIXME: emit docs
-
- self.d('/**')
- self.d(' * %s:' % stub_name)
- self.d(' * @instance: The object implementing this interface')
- for (ctype, name, gtype) in args:
- self.d(' * @%s: %s (FIXME, generate documentation)'
- % (name, ctype))
- self.d(' *')
- self.d(' * Type-safe wrapper around g_signal_emit to emit the')
- self.d(' * %s signal on interface %s.'
- % (dbus_name, self.iface_name))
- self.d(' */')
-
- self.b('void')
- self.b(('%s (' % stub_name) + (',\n '.join(tmp)) + ')')
- self.b('{')
- self.b(' g_assert (instance != NULL);')
- self.b(' g_assert (G_TYPE_CHECK_INSTANCE_TYPE (instance, %s));'
- % (self.current_gtype))
- tmp = (['instance', '%s_signals[%s]' % (self.node_name_lc, const_name),
- '0'] + [name for (ctype, name, gtype) in args])
- self.b(' g_signal_emit (' + ',\n '.join(tmp) + ');')
- self.b('}')
- self.b('')
-
- signal_name = dbus_gutils_wincaps_to_uscore(dbus_name).replace('_',
- '-')
-
- self.d('/**')
- self.d(' * %s%s::%s:'
- % (self.Prefix, self.node_name_mixed, signal_name))
- self.d(' * @self: an object')
- for (ctype, name, gtype) in args:
- self.d(' * @%s: %s (FIXME, generate documentation)'
- % (name, ctype))
- self.d(' *')
- self.d(' * The %s D-Bus signal is emitted whenever '
- 'this GObject signal is.' % dbus_name)
- self.d(' */')
- self.d('')
-
- in_base_init.append(' %s_signals[%s] ='
- % (self.node_name_lc, const_name))
- in_base_init.append(' g_signal_new ("%s",' % signal_name)
- in_base_init.append(' G_OBJECT_CLASS_TYPE (klass),')
- in_base_init.append(' G_SIGNAL_RUN_LAST|G_SIGNAL_DETAILED,')
- in_base_init.append(' 0,')
- in_base_init.append(' NULL, NULL,')
- in_base_init.append(' g_cclosure_marshal_generic,')
- in_base_init.append(' G_TYPE_NONE,')
- tmp = ['%d' % len(args)] + [gtype for (ctype, name, gtype) in args]
- in_base_init.append(' %s);' % ',\n '.join(tmp))
- in_base_init.append('')
-
- return in_base_init
-
- def have_properties(self, nodes):
- for node in nodes:
- interface = node.getElementsByTagName('interface')[0]
- if interface.getElementsByTagName('property'):
- return True
- return False
-
- def __call__(self):
- nodes = self.dom.getElementsByTagName('node')
- nodes.sort(key=key_by_name)
-
- self.h('#include <glib-object.h>')
- self.h('#include <dbus/dbus-glib.h>')
-
- for header in self.headers:
- self.h('#include %s' % header)
- self.h('')
-
- self.h('')
- self.h('G_BEGIN_DECLS')
- self.h('')
-
- self.b('#include "%s.h"' % self.basename)
- self.b('')
-
- for node in nodes:
- self.do_node(node)
-
- self.h('')
- self.h('G_END_DECLS')
-
- self.b('')
- for header in self.end_headers:
- self.b('#include %s' % header)
-
- self.h('')
- self.b('')
- file_set_contents(self.basename + '.h', u('\n').join(self.__header).encode('utf-8'))
- file_set_contents(self.basename + '.c', u('\n').join(self.__body).encode('utf-8'))
- file_set_contents(self.basename + '-gtk-doc.h', u('\n').join(self.__docs).encode('utf-8'))
-
-def cmdline_error():
- print("""\
-usage:
- gen-ginterface [OPTIONS] xmlfile Prefix_
-options:
- --include='<header.h>' (may be repeated)
- --include='"header.h"' (ditto)
- --include-end='"header.h"' (ditto)
- Include extra headers in the generated .c file
- --signal-marshal-prefix='prefix'
- Use the given prefix on generated signal marshallers (default is
- prefix.lower()).
- --filename='BASENAME'
- Set the basename for the output files (default is prefix.lower()
- + 'ginterfaces')
- --not-implemented-func='symbol'
- Set action when methods not implemented in the interface vtable are
- called. symbol must have signature
- void symbol (DBusGMethodInvocation *context)
- and return some sort of "not implemented" error via
- dbus_g_method_return_error (context, ...)
-""")
- sys.exit(1)
-
-
-if __name__ == '__main__':
- from getopt import gnu_getopt
-
- options, argv = gnu_getopt(sys.argv[1:], '',
- ['filename=', 'signal-marshal-prefix=',
- 'include=', 'include-end=',
- 'allow-unstable',
- 'not-implemented-func='])
-
- try:
- prefix = argv[1]
- except IndexError:
- cmdline_error()
-
- basename = prefix.lower() + 'ginterfaces'
- signal_marshal_prefix = prefix.lower().rstrip('_')
- headers = []
- end_headers = []
- not_implemented_func = ''
- allow_havoc = False
-
- for option, value in options:
- if option == '--filename':
- basename = value
- elif option == '--signal-marshal-prefix':
- signal_marshal_prefix = value
- elif option == '--include':
- if value[0] not in '<"':
- value = '"%s"' % value
- headers.append(value)
- elif option == '--include-end':
- if value[0] not in '<"':
- value = '"%s"' % value
- end_headers.append(value)
- elif option == '--not-implemented-func':
- not_implemented_func = value
- elif option == '--allow-unstable':
- allow_havoc = True
-
- try:
- dom = xml.dom.minidom.parse(argv[0])
- except IndexError:
- cmdline_error()
-
- Generator(dom, prefix, basename, signal_marshal_prefix, headers,
- end_headers, not_implemented_func, allow_havoc)()
diff --git a/tools/glib-gtypes-generator.py b/tools/glib-gtypes-generator.py
deleted file mode 100644
index 1477bd37..00000000
--- a/tools/glib-gtypes-generator.py
+++ /dev/null
@@ -1,304 +0,0 @@
-#!/usr/bin/python
-
-# Generate GLib GInterfaces from the Telepathy specification.
-# The master copy of this program is in the telepathy-glib repository -
-# please make any changes there.
-#
-# Copyright (C) 2006, 2007 Collabora Limited
-#
-# 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
-
-import sys
-import xml.dom.minidom
-
-from libtpcodegen import file_set_contents, u
-from libglibcodegen import escape_as_identifier, \
- get_docstring, \
- NS_TP, \
- Signature, \
- type_to_gtype, \
- xml_escape
-
-
-def types_to_gtypes(types):
- return [type_to_gtype(t)[1] for t in types]
-
-
-class GTypesGenerator(object):
- def __init__(self, dom, output, mixed_case_prefix):
- self.dom = dom
- self.Prefix = mixed_case_prefix
- self.PREFIX_ = self.Prefix.upper() + '_'
- self.prefix_ = self.Prefix.lower() + '_'
-
- self.header = []
- self.body = []
- self.docs = []
- self.output = output
-
- for f in (self.header, self.body, self.docs):
- f.append('/* Auto-generated, do not edit.\n *\n'
- ' * This file may be distributed under the same terms\n'
- ' * as the specification from which it was generated.\n'
- ' */\n\n')
-
- # keys are e.g. 'sv', values are the key escaped
- self.need_mappings = {}
- # keys are the contents of the struct (e.g. 'sssu'), values are the
- # key escaped
- self.need_structs = {}
- # keys are the contents of the struct (e.g. 'sssu'), values are the
- # key escaped
- self.need_struct_arrays = {}
-
- # keys are the contents of the array (unlike need_struct_arrays!),
- # values are the key escaped
- self.need_other_arrays = {}
-
- def h(self, code):
- self.header.append(code)
-
- def c(self, code):
- self.body.append(code)
-
- def d(self, code):
- self.docs.append(code)
-
- def do_mapping_header(self, mapping):
- members = mapping.getElementsByTagNameNS(NS_TP, 'member')
- assert len(members) == 2
-
- impl_sig = ''.join([elt.getAttribute('type')
- for elt in members])
-
- esc_impl_sig = escape_as_identifier(impl_sig)
-
- name = (self.PREFIX_ + 'HASH_TYPE_' +
- mapping.getAttribute('name').upper())
- impl = self.prefix_ + 'type_dbus_hash_' + esc_impl_sig
-
- docstring = get_docstring(mapping) or '(Undocumented)'
-
- self.d('/**\n * %s:\n *\n' % name.strip())
- self.d(' * %s\n' % xml_escape(docstring))
- self.d(' *\n')
- self.d(' * This macro expands to a call to a function\n')
- self.d(' * that returns the #GType of a #GHashTable\n')
- self.d(' * appropriate for representing a D-Bus\n')
- self.d(' * dictionary of signature\n')
- self.d(' * <literal>a{%s}</literal>.\n' % impl_sig)
- self.d(' *\n')
-
- key, value = members
-
- self.d(' * Keys (D-Bus type <literal>%s</literal>,\n'
- % key.getAttribute('type'))
- tp_type = key.getAttributeNS(NS_TP, 'type')
- if tp_type:
- self.d(' * type <literal>%s</literal>,\n' % tp_type)
- self.d(' * named <literal>%s</literal>):\n'
- % key.getAttribute('name'))
- docstring = get_docstring(key) or '(Undocumented)'
- self.d(' * %s\n' % xml_escape(docstring))
- self.d(' *\n')
-
- self.d(' * Values (D-Bus type <literal>%s</literal>,\n'
- % value.getAttribute('type'))
- tp_type = value.getAttributeNS(NS_TP, 'type')
- if tp_type:
- self.d(' * type <literal>%s</literal>,\n' % tp_type)
- self.d(' * named <literal>%s</literal>):\n'
- % value.getAttribute('name'))
- docstring = get_docstring(value) or '(Undocumented)'
- self.d(' * %s\n' % xml_escape(docstring))
- self.d(' *\n')
-
- self.d(' */\n')
-
- self.h('#define %s (%s ())\n\n' % (name, impl))
- self.need_mappings[impl_sig] = esc_impl_sig
-
- array_name = mapping.getAttribute('array-name')
- if array_name:
- gtype_name = self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper()
- contents_sig = 'a{' + impl_sig + '}'
- esc_contents_sig = escape_as_identifier(contents_sig)
- impl = self.prefix_ + 'type_dbus_array_of_' + esc_contents_sig
- self.d('/**\n * %s:\n\n' % gtype_name)
- self.d(' * Expands to a call to a function\n')
- self.d(' * that returns the #GType of a #GPtrArray\n')
- self.d(' * of #%s.\n' % name)
- self.d(' */\n\n')
-
- self.h('#define %s (%s ())\n\n' % (gtype_name, impl))
- self.need_other_arrays[contents_sig] = esc_contents_sig
-
- def do_struct_header(self, struct):
- members = struct.getElementsByTagNameNS(NS_TP, 'member')
- impl_sig = ''.join([elt.getAttribute('type') for elt in members])
- esc_impl_sig = escape_as_identifier(impl_sig)
-
- name = (self.PREFIX_ + 'STRUCT_TYPE_' +
- struct.getAttribute('name').upper())
- impl = self.prefix_ + 'type_dbus_struct_' + esc_impl_sig
- docstring = struct.getElementsByTagNameNS(NS_TP, 'docstring')
- if docstring:
- docstring = docstring[0].toprettyxml()
- if docstring.startswith('<tp:docstring>'):
- docstring = docstring[14:]
- if docstring.endswith('</tp:docstring>\n'):
- docstring = docstring[:-16]
- if docstring.strip() in ('<tp:docstring/>', ''):
- docstring = '(Undocumented)'
- else:
- docstring = '(Undocumented)'
- self.d('/**\n * %s:\n\n' % name)
- self.d(' * %s\n' % xml_escape(docstring))
- self.d(' *\n')
- self.d(' * This macro expands to a call to a function\n')
- self.d(' * that returns the #GType of a #GValueArray\n')
- self.d(' * appropriate for representing a D-Bus struct\n')
- self.d(' * with signature <literal>(%s)</literal>.\n'
- % impl_sig)
- self.d(' *\n')
-
- for i, member in enumerate(members):
- self.d(' * Member %d (D-Bus type '
- '<literal>%s</literal>,\n'
- % (i, member.getAttribute('type')))
- tp_type = member.getAttributeNS(NS_TP, 'type')
- if tp_type:
- self.d(' * type <literal>%s</literal>,\n' % tp_type)
- self.d(' * named <literal>%s</literal>):\n'
- % member.getAttribute('name'))
- docstring = get_docstring(member) or '(Undocumented)'
- self.d(' * %s\n' % xml_escape(docstring))
- self.d(' *\n')
-
- self.d(' */\n\n')
-
- self.h('#define %s (%s ())\n\n' % (name, impl))
-
- array_name = struct.getAttribute('array-name')
- if array_name != '':
- array_name = (self.PREFIX_ + 'ARRAY_TYPE_' + array_name.upper())
- impl = self.prefix_ + 'type_dbus_array_' + esc_impl_sig
- self.d('/**\n * %s:\n\n' % array_name)
- self.d(' * Expands to a call to a function\n')
- self.d(' * that returns the #GType of a #GPtrArray\n')
- self.d(' * of #%s.\n' % name)
- self.d(' */\n\n')
-
- self.h('#define %s (%s ())\n\n' % (array_name, impl))
- self.need_struct_arrays[impl_sig] = esc_impl_sig
-
- self.need_structs[impl_sig] = esc_impl_sig
-
- def __call__(self):
- mappings = self.dom.getElementsByTagNameNS(NS_TP, 'mapping')
- structs = self.dom.getElementsByTagNameNS(NS_TP, 'struct')
-
- for mapping in mappings:
- self.do_mapping_header(mapping)
-
- for sig in self.need_mappings:
- self.h('GType %stype_dbus_hash_%s (void);\n\n' %
- (self.prefix_, self.need_mappings[sig]))
- self.c('GType\n%stype_dbus_hash_%s (void)\n{\n' %
- (self.prefix_, self.need_mappings[sig]))
- self.c(' static GType t = 0;\n\n')
- self.c(' if (G_UNLIKELY (t == 0))\n')
- # FIXME: translate sig into two GTypes
- items = tuple(Signature(sig))
- gtypes = types_to_gtypes(items)
- self.c(' t = dbus_g_type_get_map ("GHashTable", '
- '%s, %s);\n' % (gtypes[0], gtypes[1]))
- self.c(' return t;\n')
- self.c('}\n\n')
-
- for struct in structs:
- self.do_struct_header(struct)
-
- for sig in self.need_structs:
- self.h('GType %stype_dbus_struct_%s (void);\n\n' %
- (self.prefix_, self.need_structs[sig]))
- self.c('GType\n%stype_dbus_struct_%s (void)\n{\n' %
- (self.prefix_, self.need_structs[sig]))
- self.c(' static GType t = 0;\n\n')
- self.c(' if (G_UNLIKELY (t == 0))\n')
- self.c(' t = dbus_g_type_get_struct ("GValueArray",\n')
- items = tuple(Signature(sig))
- gtypes = types_to_gtypes(items)
- for gtype in gtypes:
- self.c(' %s,\n' % gtype)
- self.c(' G_TYPE_INVALID);\n')
- self.c(' return t;\n')
- self.c('}\n\n')
-
- for sig in self.need_struct_arrays:
- self.h('GType %stype_dbus_array_%s (void);\n\n' %
- (self.prefix_, self.need_struct_arrays[sig]))
- self.c('GType\n%stype_dbus_array_%s (void)\n{\n' %
- (self.prefix_, self.need_struct_arrays[sig]))
- self.c(' static GType t = 0;\n\n')
- self.c(' if (G_UNLIKELY (t == 0))\n')
- self.c(' t = dbus_g_type_get_collection ("GPtrArray", '
- '%stype_dbus_struct_%s ());\n' %
- (self.prefix_, self.need_struct_arrays[sig]))
- self.c(' return t;\n')
- self.c('}\n\n')
-
- for sig in self.need_other_arrays:
- self.h('GType %stype_dbus_array_of_%s (void);\n\n' %
- (self.prefix_, self.need_other_arrays[sig]))
- self.c('GType\n%stype_dbus_array_of_%s (void)\n{\n' %
- (self.prefix_, self.need_other_arrays[sig]))
- self.c(' static GType t = 0;\n\n')
- self.c(' if (G_UNLIKELY (t == 0))\n')
-
- if sig[:2] == 'a{' and sig[-1:] == '}':
- # array of mappings
- self.c(' t = dbus_g_type_get_collection ('
- '"GPtrArray", '
- '%stype_dbus_hash_%s ());\n' %
- (self.prefix_, escape_as_identifier(sig[2:-1])))
- elif sig[:2] == 'a(' and sig[-1:] == ')':
- # array of arrays of struct
- self.c(' t = dbus_g_type_get_collection ('
- '"GPtrArray", '
- '%stype_dbus_array_%s ());\n' %
- (self.prefix_, escape_as_identifier(sig[2:-1])))
- elif sig[:1] == 'a':
- # array of arrays of non-struct
- self.c(' t = dbus_g_type_get_collection ('
- '"GPtrArray", '
- '%stype_dbus_array_of_%s ());\n' %
- (self.prefix_, escape_as_identifier(sig[1:])))
- else:
- raise AssertionError("array of '%s' not supported" % sig)
-
- self.c(' return t;\n')
- self.c('}\n\n')
-
- file_set_contents(self.output + '.h', u('').join(self.header).encode('utf-8'))
- file_set_contents(self.output + '-body.h', u('').join(self.body).encode('utf-8'))
- file_set_contents(self.output + '-gtk-doc.h', u('').join(self.docs).encode('utf-8'))
-
-if __name__ == '__main__':
- argv = sys.argv[1:]
-
- dom = xml.dom.minidom.parse(argv[0])
-
- GTypesGenerator(dom, argv[1], argv[2])()
diff --git a/tools/glib-interfaces-body-generator.xsl b/tools/glib-interfaces-body-generator.xsl
deleted file mode 100644
index caff8917..00000000
--- a/tools/glib-interfaces-body-generator.xsl
+++ /dev/null
@@ -1,47 +0,0 @@
-<!-- Stylesheet to extract C interface names from the Telepathy spec.
-The master copy of this stylesheet is in telepathy-glib - please make any
-changes there.
-
-Copyright (C) 2006, 2007 Collabora Limited
-
-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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
--->
-
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- exclude-result-prefixes="tp">
-
- <xsl:import href="c-interfaces-generator.xsl"/>
-
- <xsl:template match="interface">
- <xsl:text>GQuark&#10;</xsl:text>
- <xsl:value-of select="$prefix"/>
- <xsl:text>_iface_quark_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($upper, '/'), $lower)"/>
- <xsl:text> (void)&#10;{&#10;</xsl:text>
- <xsl:text> static GQuark quark = 0;&#10;&#10;</xsl:text>
- <xsl:text> if (G_UNLIKELY (quark == 0))&#10;</xsl:text>
- <xsl:text> {&#10;</xsl:text>
- <xsl:text> quark = g_quark_from_static_string ("</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>");&#10;</xsl:text>
- <xsl:text> }&#10;&#10;</xsl:text>
- <xsl:text> return quark;&#10;</xsl:text>
- <xsl:text>}&#10;&#10;</xsl:text>
- </xsl:template>
-
-</xsl:stylesheet>
-
-<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/glib-interfaces-generator.xsl b/tools/glib-interfaces-generator.xsl
deleted file mode 100644
index e703c407..00000000
--- a/tools/glib-interfaces-generator.xsl
+++ /dev/null
@@ -1,55 +0,0 @@
-<!-- Stylesheet to extract C interface names from the Telepathy spec.
-The master copy of this stylesheet is in telepathy-glib - please make any
-changes there.
-
-Copyright (C) 2006, 2007 Collabora Limited
-
-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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
--->
-
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- exclude-result-prefixes="tp">
-
- <xsl:import href="c-interfaces-generator.xsl"/>
-
- <xsl:template match="interface">
- <xsl:apply-imports/>
-
- <xsl:text>/**&#10; * </xsl:text>
- <xsl:value-of select="$PREFIX"/>
- <xsl:text>_IFACE_QUARK_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($lower, '/'), $upper)"/>
- <xsl:text>:&#10; * &#10; * Expands to a call to a function that </xsl:text>
- <xsl:text>returns a quark for the interface name "</xsl:text>
- <xsl:value-of select="@name"/>
- <xsl:text>"&#10; */&#10;#define </xsl:text>
- <xsl:value-of select="$PREFIX"/>
- <xsl:text>_IFACE_QUARK_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($lower, '/'), $upper)"/>
- <xsl:text> \&#10; (</xsl:text>
- <xsl:value-of select="$prefix"/>
- <xsl:text>_iface_quark_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($upper, '/'), $lower)"/>
- <xsl:text> ())&#10;&#10;GQuark </xsl:text>
- <xsl:value-of select="$prefix"/>
- <xsl:text>_iface_quark_</xsl:text>
- <xsl:value-of select="translate(../@name, concat($upper, '/'), $lower)"/>
- <xsl:text> (void);&#10;&#10;</xsl:text>
- </xsl:template>
-
-</xsl:stylesheet>
-
-<!-- vim:set sw=2 sts=2 et noai noci: -->
diff --git a/tools/identity.xsl b/tools/identity.xsl
deleted file mode 100644
index 6630f84d..00000000
--- a/tools/identity.xsl
+++ /dev/null
@@ -1,7 +0,0 @@
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
- <xsl:template match="@*|node()">
- <xsl:copy>
- <xsl:apply-templates select="@*|node()"/>
- </xsl:copy>
- </xsl:template>
-</xsl:stylesheet>
diff --git a/tools/lcov.am b/tools/lcov.am
index a5feb727..298e0914 100644
--- a/tools/lcov.am
+++ b/tools/lcov.am
@@ -8,7 +8,7 @@ lcov-report:
--remove @top_builddir@/lcov.info.tmp \
'doc/reference/*/*-scan.c'
rm @top_builddir@/lcov.info.tmp
- $(mkdir_p) @top_builddir@/lcov.html
+ $(MKDIR_P) @top_builddir@/lcov.html
git_commit=`GIT_DIR=@top_srcdir@/.git git log -1 --pretty=format:%h 2>/dev/null`;\
genhtml --title "@PACKAGE_STRING@ $$git_commit" \
--output-directory @top_builddir@/lcov.html lcov.info
diff --git a/tools/libglibcodegen.py b/tools/libglibcodegen.py
deleted file mode 100644
index 5c76f07d..00000000
--- a/tools/libglibcodegen.py
+++ /dev/null
@@ -1,216 +0,0 @@
-"""Library code for GLib/D-Bus-related code generation.
-
-The master copy of this library is in the telepathy-glib repository -
-please make any changes there.
-"""
-
-# Copyright (C) 2006-2008 Collabora Limited
-#
-# 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
-
-
-from libtpcodegen import NS_TP, \
- Signature, \
- cmp_by_name, \
- escape_as_identifier, \
- get_by_path, \
- get_descendant_text, \
- get_docstring, \
- xml_escape, \
- get_deprecated
-
-def dbus_gutils_wincaps_to_uscore(s):
- """Bug-for-bug compatible Python port of _dbus_gutils_wincaps_to_uscore
- which gets sequences of capital letters wrong in the same way.
- (e.g. in Telepathy, SendDTMF -> send_dt_mf)
- """
- ret = ''
- for c in s:
- if c >= 'A' and c <= 'Z':
- length = len(ret)
- if length > 0 and (length < 2 or ret[length-2] != '_'):
- ret += '_'
- ret += c.lower()
- else:
- ret += c
- return ret
-
-
-def signal_to_marshal_type(signal):
- """
- return a list of strings indicating the marshalling type for this signal.
- """
-
- mtype=[]
- for i in signal.getElementsByTagName("arg"):
- name =i.getAttribute("name")
- type = i.getAttribute("type")
- mtype.append(type_to_gtype(type)[2])
-
- return mtype
-
-
-_glib_marshallers = ['VOID', 'BOOLEAN', 'CHAR', 'UCHAR', 'INT',
- 'STRING', 'UINT', 'LONG', 'ULONG', 'ENUM', 'FLAGS', 'FLOAT',
- 'DOUBLE', 'STRING', 'PARAM', 'BOXED', 'POINTER', 'OBJECT',
- 'UINT_POINTER']
-
-
-def signal_to_marshal_name(signal, prefix):
-
- mtype = signal_to_marshal_type(signal)
- if len(mtype):
- name = '_'.join(mtype)
- else:
- name = 'VOID'
-
- if name in _glib_marshallers:
- return 'g_cclosure_marshal_VOID__' + name
- else:
- return prefix + '_marshal_VOID__' + name
-
-
-def method_to_glue_marshal_name(method, prefix):
-
- mtype = []
- for i in method.getElementsByTagName("arg"):
- if i.getAttribute("direction") != "out":
- type = i.getAttribute("type")
- mtype.append(type_to_gtype(type)[2])
-
- mtype.append('POINTER')
-
- name = '_'.join(mtype)
-
- if name in _glib_marshallers:
- return 'g_cclosure_marshal_VOID__' + name
- else:
- return prefix + '_marshal_VOID__' + name
-
-
-def type_to_gtype(s):
- if s == 'y': #byte
- return ("guchar ", "G_TYPE_UCHAR","UCHAR", False)
- elif s == 'b': #boolean
- return ("gboolean ", "G_TYPE_BOOLEAN","BOOLEAN", False)
- elif s == 'n': #int16
- return ("gint ", "G_TYPE_INT","INT", False)
- elif s == 'q': #uint16
- return ("guint ", "G_TYPE_UINT","UINT", False)
- elif s == 'i': #int32
- return ("gint ", "G_TYPE_INT","INT", False)
- elif s == 'u': #uint32
- return ("guint ", "G_TYPE_UINT","UINT", False)
- elif s == 'x': #int64
- return ("gint64 ", "G_TYPE_INT64","INT64", False)
- elif s == 't': #uint64
- return ("guint64 ", "G_TYPE_UINT64","UINT64", False)
- elif s == 'd': #double
- return ("gdouble ", "G_TYPE_DOUBLE","DOUBLE", False)
- elif s == 's': #string
- return ("gchar *", "G_TYPE_STRING", "STRING", True)
- elif s == 'g': #signature - FIXME
- return ("gchar *", "DBUS_TYPE_G_SIGNATURE", "STRING", True)
- elif s == 'o': #object path
- return ("gchar *", "DBUS_TYPE_G_OBJECT_PATH", "BOXED", True)
- elif s == 'v': #variant
- return ("GValue *", "G_TYPE_VALUE", "BOXED", True)
- elif s == 'as': #array of strings
- return ("gchar **", "G_TYPE_STRV", "BOXED", True)
- elif s == 'ay': #byte array
- return ("GArray *",
- "dbus_g_type_get_collection (\"GArray\", G_TYPE_UCHAR)", "BOXED",
- True)
- elif s == 'au': #uint array
- return ("GArray *", "DBUS_TYPE_G_UINT_ARRAY", "BOXED", True)
- elif s == 'ai': #int array
- return ("GArray *", "DBUS_TYPE_G_INT_ARRAY", "BOXED", True)
- elif s == 'ax': #int64 array
- return ("GArray *", "DBUS_TYPE_G_INT64_ARRAY", "BOXED", True)
- elif s == 'at': #uint64 array
- return ("GArray *", "DBUS_TYPE_G_UINT64_ARRAY", "BOXED", True)
- elif s == 'ad': #double array
- return ("GArray *", "DBUS_TYPE_G_DOUBLE_ARRAY", "BOXED", True)
- elif s == 'ab': #boolean array
- return ("GArray *", "DBUS_TYPE_G_BOOLEAN_ARRAY", "BOXED", True)
- elif s == 'ao': #object path array
- return ("GPtrArray *",
- 'dbus_g_type_get_collection ("GPtrArray",'
- ' DBUS_TYPE_G_OBJECT_PATH)',
- "BOXED", True)
- elif s == 'a{ss}': #hash table of string to string
- return ("GHashTable *", "DBUS_TYPE_G_STRING_STRING_HASHTABLE", "BOXED", False)
- elif s[:2] == 'a{': #some arbitrary hash tables
- if s[2] not in ('y', 'b', 'n', 'q', 'i', 'u', 's', 'o', 'g'):
- raise Exception("can't index a hashtable off non-basic type " + s)
- first = type_to_gtype(s[2])
- second = type_to_gtype(s[3:-1])
- return ("GHashTable *", "(dbus_g_type_get_map (\"GHashTable\", " + first[1] + ", " + second[1] + "))", "BOXED", False)
- elif s[:2] in ('a(', 'aa'): # array of structs or arrays, recurse
- gtype = type_to_gtype(s[1:])[1]
- return ("GPtrArray *", "(dbus_g_type_get_collection (\"GPtrArray\", "+gtype+"))", "BOXED", True)
- elif s[:1] == '(': #struct
- gtype = "(dbus_g_type_get_struct (\"GValueArray\", "
- for subsig in Signature(s[1:-1]):
- gtype = gtype + type_to_gtype(subsig)[1] + ", "
- gtype = gtype + "G_TYPE_INVALID))"
- return ("GValueArray *", gtype, "BOXED", True)
-
- # we just don't know ..
- raise Exception("don't know the GType for " + s)
-
-def move_into_gvalue(gvaluep, gtype, marshaller, name):
- if gtype == 'G_TYPE_STRING':
- return 'g_value_take_string (%s, %s);' % (gvaluep, name)
- elif marshaller == 'BOXED':
- return 'g_value_take_boxed (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_UCHAR':
- return 'g_value_set_uchar (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_BOOLEAN':
- return 'g_value_set_boolean (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_INT':
- return 'g_value_set_int (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_UINT':
- return 'g_value_set_uint (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_INT64':
- return 'g_value_set_int (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_UINT64':
- return 'g_value_set_uint64 (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_DOUBLE':
- return 'g_value_set_double (%s, %s);' % (gvaluep, name)
- else:
- raise AssertionError("Don't know how to put %s in a GValue" % gtype)
-
-def copy_into_gvalue(gvaluep, gtype, marshaller, name):
- if gtype == 'G_TYPE_STRING':
- return 'g_value_set_string (%s, %s);' % (gvaluep, name)
- elif marshaller == 'BOXED':
- return 'g_value_set_boxed (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_UCHAR':
- return 'g_value_set_uchar (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_BOOLEAN':
- return 'g_value_set_boolean (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_INT':
- return 'g_value_set_int (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_UINT':
- return 'g_value_set_uint (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_INT64':
- return 'g_value_set_int (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_UINT64':
- return 'g_value_set_uint64 (%s, %s);' % (gvaluep, name)
- elif gtype == 'G_TYPE_DOUBLE':
- return 'g_value_set_double (%s, %s);' % (gvaluep, name)
- else:
- raise AssertionError("Don't know how to put %s in a GValue" % gtype)
diff --git a/tools/libtpcodegen.py b/tools/libtpcodegen.py
deleted file mode 100644
index 99de6634..00000000
--- a/tools/libtpcodegen.py
+++ /dev/null
@@ -1,247 +0,0 @@
-"""Library code for language-independent D-Bus-related code generation.
-
-The master copy of this library is in the telepathy-glib repository -
-please make any changes there.
-"""
-
-# Copyright (C) 2006-2008 Collabora Limited
-#
-# 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
-
-import os
-import sys
-from string import ascii_letters, digits
-
-
-NS_TP = "http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
-
-_ASCII_ALNUM = ascii_letters + digits
-
-if sys.version_info[0] >= 3:
- def u(s):
- """Return s, which must be a str literal with no non-ASCII characters.
- This is like a more restricted form of the Python 2 u'' syntax.
- """
- return s.encode('ascii').decode('ascii')
-else:
- def u(s):
- """Return a Unicode version of s, which must be a str literal
- (a bytestring) in which each byte is an ASCII character.
- This is like a more restricted form of the u'' syntax.
- """
- return s.decode('ascii')
-
-def file_set_contents(filename, contents):
- try:
- os.remove(filename)
- except OSError:
- pass
- try:
- os.remove(filename + '.tmp')
- except OSError:
- pass
-
- open(filename + '.tmp', 'wb').write(contents)
- os.rename(filename + '.tmp', filename)
-
-def cmp_by_name(node1, node2):
- return cmp(node1.getAttributeNode("name").nodeValue,
- node2.getAttributeNode("name").nodeValue)
-
-def key_by_name(node):
- return node.getAttributeNode("name").nodeValue
-
-def escape_as_identifier(identifier):
- """Escape the given string to be a valid D-Bus object path or service
- name component, using a reversible encoding to ensure uniqueness.
-
- The reversible encoding is as follows:
-
- * The empty string becomes '_'
- * Otherwise, each non-alphanumeric character is replaced by '_' plus
- two lower-case hex digits; the same replacement is carried out on
- the first character, if it's a digit
- """
- # '' -> '_'
- if not identifier:
- return '_'
-
- # A bit of a fast path for strings which are already OK.
- # We deliberately omit '_' because, for reversibility, that must also
- # be escaped.
- if (identifier.strip(_ASCII_ALNUM) == '' and
- identifier[0] in ascii_letters):
- return identifier
-
- # The first character may not be a digit
- if identifier[0] not in ascii_letters:
- ret = ['_%02x' % ord(identifier[0])]
- else:
- ret = [identifier[0]]
-
- # Subsequent characters may be digits or ASCII letters
- for c in identifier[1:]:
- if c in _ASCII_ALNUM:
- ret.append(c)
- else:
- ret.append('_%02x' % ord(c))
-
- return ''.join(ret)
-
-
-def get_by_path(element, path):
- branches = path.split('/')
- branch = branches[0]
-
- # Is the current branch an attribute, if so, return the attribute value
- if branch[0] == '@':
- return element.getAttribute(branch[1:])
-
- # Find matching children for the branch
- children = []
- if branch == '..':
- children.append(element.parentNode)
- else:
- for x in element.childNodes:
- if x.localName == branch:
- children.append(x)
-
- ret = []
- # If this is not the last path element, recursively gather results from
- # children
- if len(branches) > 1:
- for x in children:
- add = get_by_path(x, '/'.join(branches[1:]))
- if isinstance(add, list):
- ret += add
- else:
- return add
- else:
- ret = children
-
- return ret
-
-
-def get_docstring(element):
- docstring = None
- for x in element.childNodes:
- if x.namespaceURI == NS_TP and x.localName == 'docstring':
- docstring = x
- if docstring is not None:
- docstring = docstring.toxml().replace('\n', ' ').strip()
- if docstring.startswith('<tp:docstring>'):
- docstring = docstring[14:].lstrip()
- if docstring.endswith('</tp:docstring>'):
- docstring = docstring[:-15].rstrip()
- if docstring in ('<tp:docstring/>', ''):
- docstring = ''
- return docstring
-
-def get_deprecated(element):
- text = []
- for x in element.childNodes:
- if hasattr(x, 'data'):
- text.append(x.data.replace('\n', ' ').strip())
- else:
- # This caters for tp:dbus-ref elements, but little else.
- if x.childNodes and hasattr(x.childNodes[0], 'data'):
- text.append(x.childNodes[0].data.replace('\n', ' ').strip())
- return ' '.join(text)
-
-def get_descendant_text(element_or_elements):
- if not element_or_elements:
- return ''
- if isinstance(element_or_elements, list):
- return ''.join(map(get_descendant_text, element_or_elements))
- parts = []
- for x in element_or_elements.childNodes:
- if x.nodeType == x.TEXT_NODE:
- parts.append(x.nodeValue)
- elif x.nodeType == x.ELEMENT_NODE:
- parts.append(get_descendant_text(x))
- else:
- pass
- return ''.join(parts)
-
-
-class _SignatureIter:
- """Iterator over a D-Bus signature. Copied from dbus-python 0.71 so we
- can run genginterface in a limited environment with only Python
- (like Scratchbox).
- """
- def __init__(self, string):
- self.remaining = string
-
- def next(self):
- return self.__next__()
-
- def __next__(self):
- if self.remaining == '':
- raise StopIteration
-
- signature = self.remaining
- block_depth = 0
- block_type = None
- end = len(signature)
-
- for marker in range(0, end):
- cur_sig = signature[marker]
-
- if cur_sig == 'a':
- pass
- elif cur_sig == '{' or cur_sig == '(':
- if block_type == None:
- block_type = cur_sig
-
- if block_type == cur_sig:
- block_depth = block_depth + 1
-
- elif cur_sig == '}':
- if block_type == '{':
- block_depth = block_depth - 1
-
- if block_depth == 0:
- end = marker
- break
-
- elif cur_sig == ')':
- if block_type == '(':
- block_depth = block_depth - 1
-
- if block_depth == 0:
- end = marker
- break
-
- else:
- if block_depth == 0:
- end = marker
- break
-
- end = end + 1
- self.remaining = signature[end:]
- return Signature(signature[0:end])
-
-
-class Signature(str):
- """A string, iteration over which is by D-Bus single complete types
- rather than characters.
- """
- def __iter__(self):
- return _SignatureIter(self)
-
-
-def xml_escape(s):
- s = s.replace('&', '&amp;').replace("'", '&apos;').replace('"', '&quot;')
- return s.replace('<', '&lt;').replace('>', '&gt;')
diff --git a/tools/spec-to-introspect.xsl b/tools/spec-to-introspect.xsl
deleted file mode 100644
index 992efc73..00000000
--- a/tools/spec-to-introspect.xsl
+++ /dev/null
@@ -1,26 +0,0 @@
-<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
- xmlns:mc="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- exclude-result-prefixes="mc">
-
- <xsl:template match="*">
- <xsl:copy>
- <xsl:for-each select="@*">
- <xsl:if test="not(starts-with(name(), 'mc:'))">
- <xsl:copy/>
- </xsl:if>
- </xsl:for-each>
- <xsl:apply-templates/>
- </xsl:copy>
- </xsl:template>
-
- <xsl:template match="mc:*"/>
- <xsl:template match="text()"/>
-
- <xsl:output method="xml" indent="yes" encoding="UTF-8"
- omit-xml-declaration="no"
- doctype-system="http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd"
- doctype-public="-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" />
-
-</xsl:stylesheet>
-
-<!-- vim:set sw=2 sts=2 et: -->
diff --git a/util/Makefile.am b/util/Makefile.am
index f506dd22..4a5a6016 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -37,7 +37,7 @@ Android.mk: Makefile.am
-:EXECUTABLE mc-tool -:TAGS eng debug \
-:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
-:SOURCES $(mc_tool_SOURCES) \
- -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) $(INCLUDES) \
+ -:CFLAGS $(DEFS) $(CFLAGS) $(DEFAULT_INCLUDES) \
$(AM_CFLAGS) \
-:CPPFLAGS $(CPPFLAGS) $(AM_CPPFLAGS) \
-:LDFLAGS $(LDADD) \
diff --git a/xml/Account_Interface_Conditions.xml b/xml/Account_Interface_Conditions.xml
deleted file mode 100644
index eb384826..00000000
--- a/xml/Account_Interface_Conditions.xml
+++ /dev/null
@@ -1,99 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Account_Interface_Conditions" xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
-<p>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.</p>
-
-<p>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 Street, Fifth Floor, Boston, MA 02110-1301, USA.</p>
- </tp:license>
- <interface name="com.nokia.Account.Interface.Conditions">
- <tp:requires interface="org.freedesktop.Telepathy.Account"/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The Conditions interface specifies under what conditions an account
- can be put online. When the conditions are met and the
- ConnectAutomatically property on the account is set to True, then the
- account will automatically try to connect. On the other hand, if the
- conditions are not met, the account won't attempt to connect, not even if
- requested so.</p>
-
- <tp:rationale>
- <p>The main goal is to bind accounts to connectivity: most TCP and UDP
- based protocols require a network route to be present, while link-local
- does not; some protocol might be specifically designed to work only over
- bluetooth, in which case we don't want to attempt a connection if
- bluetooth is not available. Then, some accounts might work only in certain
- VPNs.</p>
-
- <p>There is also the case of user preferences: one might want to activate
- a certain account only when he is at home (in that case, he could set a
- rule on the network ESSID) or when he is not at work (this requires the
- possibility of negating rules).</p>
-
- <p>The proposed format of a rule is (name, value), where name is a string
- (which is typically a connectivity parameter, such as "ip-address",
- "vpn-name", "essid", maybe prefixed with some namespacing convention)
- and value is the value the parameter must assume for the rule to be met.
- The value, it will be specified as a string, but we want to be
- able to specify multiple alternatives (for instance a rule might be
- "connect if ESSID is HOME or WORK"), as well as negative matches. The
- proposed syntax is simple yet expressive enough.</p>
-
- </tp:rationale>
-
- <p>Conditions consists of a list of rules, which take the form of a
- struct <code>(name, value)</code>, where:</p>
- <ul>
- <li><code>name</code> is a string which names the rule</li>
- <li><code>value</code> is the value</li>
- </ul>
- </tp:docstring>
-
- <property name="Condition" type="a{ss}" tp:type="String_String_Map"
- access="readwrite">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The condition is a list of rules, consisting of a name and of a value,
- both strings.
- The syntax for the value is:</p>
- <code>
- value ::= [logic] (":" singlevalue | "[" listvalue)<br />
- logic ::= ("!" | &lt;possibly other operators&gt;)<br />
- singlevalue ::= &lt;possibly any ASCII string&gt;<br />
- listvalue ::= separator list<br />
- separator ::= &lt;any non-blank ASCII character&gt;<br />
- list ::= singlevaluenonsep (separator singlevaluenonsep)*<br />
- singlevaluenonsep ::= &lt;ASCII string not containing the separator character&gt;<br />
- </code>
-
- <p>Some examples of values:</p>
- <code>
- :my_essid_name<br />
- !:my_essid_name<br />
- [,my_essid_name,his_essid_name<br />
- ![,my_essid_name,his_essid_name<br />
- </code>
-
- <tp:rationale>
- <p>
- Questions:</p>
- <ul>
- <li>Should it be a(ss) or a{ss}?</li>
- <li>Should we specify namespacing rules for the name?</li>
- <li>Should we allow wildcards in the values?</li>
- </ul>
- </tp:rationale>
- </tp:docstring>
- </property>
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/xml/Account_Interface_External_Password_Storage.xml b/xml/Account_Interface_External_Password_Storage.xml
deleted file mode 100644
index 5bd1bfce..00000000
--- a/xml/Account_Interface_External_Password_Storage.xml
+++ /dev/null
@@ -1,58 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Account_Interface_External_Password_Storage"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-
- <tp:copyright>Copyright © 2011 Collabora Ltd.</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Account.Interface.ExternalPasswordStorage.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.21.10">(draft 1)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.Account"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>An interface for Accounts whose passwords are stored externally and
- SHOULD NOT be stored by either the
- <tp:dbus-ref namespace="ofdT">AccountManager</tp:dbus-ref> nor any
- <tp:dbus-ref namespace="ofdT.Channel.Type">ServerAuthentication</tp:dbus-ref>
- handler.</p>
-
- <p>This interface SHOULD only appear on accounts for which the
- related Connection Manager implements
- <tp:dbus-ref namespace="ofdT">ConnectionManager.Interface.AccountStorage.DRAFT</tp:dbus-ref>.</p>
- </tp:docstring>
-
- <method name="ForgetPassword" tp:name-for-bindings="Forget_Password">
- <tp:docstring>
- Clears any saved password associated with this account.
- </tp:docstring>
- </method>
-
- <property name="PasswordSaved"
- tp:name-for-bindings="Password_Saved"
- type="b" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Indicates whether the account has a saved password or not.</p>
-
- <p>Change notification for this property is provided by the
- standard D-Bus <code>PropertiesChanged</code> signal.</p>
- </tp:docstring>
- </property>
-
- </interface>
-</node>
diff --git a/xml/Account_Interface_Hidden.xml b/xml/Account_Interface_Hidden.xml
deleted file mode 100644
index cb001917..00000000
--- a/xml/Account_Interface_Hidden.xml
+++ /dev/null
@@ -1,65 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Account_Interface_Hidden"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-
- <tp:copyright>Copyright © 2010 Collabora Ltd.</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.Account.Interface.Hidden.DRAFT1"
- tp:causes-havoc="outrageous">
- <tp:added version="0.21.10">(draft 1)</tp:added>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>An interface for flagging certain accounts as hidden, so that they do
- not appear in the account manager's standard lists of accounts.
- Accounts whose <tp:member-ref>Hidden</tp:member-ref> property is
- <code>True</code> are intended for non-interactive use (by
- non-user-visible services), and appear on the <tp:dbus-ref
- namespace='ofdT'>AccountManager.Interface.Hidden.DRAFT1</tp:dbus-ref>
- interface; in all other respects, they behave like any other
- account.</p>
-
- <tp:rationale>
- <p>XMPP, in particular, is increasingly used for purposes other than
- instant messaging and VoIP. For instance, extensions exist for
- inter-device bookmark synchronization.</p>
-
- <p>While obviously these services could re-use connections intended for
- instant messaging, in some cases you might want to use a different
- account. (Perhaps your bookmark sync provider is not your IM
- provider.) This API allows such auxiliary accounts to exist in
- Telepathy, while not being displayed in standard user interfaces for
- IM, VoIP, and friends.</p>
- </tp:rationale>
- </tp:docstring>
-
- <property name="Hidden" tp:name-for-bindings="Hidden"
- type="b" access="read" tp:immutable='aye'>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>If <code>True</code>, this account is intended for non-interactive
- use, and thus should not be presented to the user. It will not appear
- in properties and signals on the main <tp:dbus-ref
- namespace='ofdT'>AccountManager</tp:dbus-ref> interface; instead, it
- will show up on <tp:dbus-ref
- namespace='ofdT'>AccountManager.Interface.Hidden.DRAFT1</tp:dbus-ref>.</p>
- </tp:docstring>
- </property>
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/xml/Account_Manager_Interface_Hidden.xml b/xml/Account_Manager_Interface_Hidden.xml
deleted file mode 100644
index 284eb642..00000000
--- a/xml/Account_Manager_Interface_Hidden.xml
+++ /dev/null
@@ -1,100 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Account_Manager_Interface_Hidden"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
- <tp:copyright>Copyright © 2010 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright © 2010 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
-<p>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.</p>
-
-<p>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.</p>
-
-<p>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 Street, Fifth Floor, Boston, MA 02110-1301, USA.
-</p>
- </tp:license>
- <interface
- name="org.freedesktop.Telepathy.AccountManager.Interface.Hidden.DRAFT1"
- tp:causes-havoc='kind of sketchy'>
- <tp:requires interface='org.freedesktop.Telepathy.AccountManager'/>
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>This interface lists accounts whose <tp:dbus-ref
- namespace='ofdT.Account.Interface.Hidden.DRAFT1'>Hidden</tp:dbus-ref>
- property is <code>True</code>.</p>
- </tp:docstring>
- <tp:added version="0.21.10">first draft</tp:added>
-
- <property name="ValidHiddenAccounts" type="ao" access="read"
- tp:name-for-bindings="Valid_Hidden_Accounts">
- <tp:docstring>
- A list of valid (complete, usable) <tp:dbus-ref
- namespace="org.freedesktop.Telepathy">Account</tp:dbus-ref>s intended
- exclusively for noninteractive applications. These accounts are not
- included in <tp:dbus-ref
- namespace='ofdT'>AccountManager.ValidAccounts</tp:dbus-ref>. Change
- notification is via
- <tp:member-ref>HiddenAccountValidityChanged</tp:member-ref>.
- </tp:docstring>
- </property>
-
- <property name="InvalidHiddenAccounts" type="ao" access="read"
- tp:name-for-bindings="Invalid_Hidden_Accounts">
- <tp:docstring>
- A list of incomplete or otherwise unusable <tp:dbus-ref
- namespace="org.freedesktop.Telepathy">Account</tp:dbus-ref>s intended
- exclusively for noninteractive applications. Change notification is via
- <tp:member-ref>HiddenAccountValidityChanged</tp:member-ref>.
- </tp:docstring>
- </property>
-
- <signal name="HiddenAccountRemoved"
- tp:name-for-bindings="Hidden_Account_Removed">
- <tp:docstring>
- The given account has been removed from
- <tp:member-ref>ValidHiddenAccounts</tp:member-ref> or
- <tp:member-ref>InvalidHiddenAccounts</tp:member-ref>.
- </tp:docstring>
-
- <arg name="Account" type="o">
- <tp:docstring>
- An Account, which must not be used any more.
- </tp:docstring>
- </arg>
- </signal>
-
- <signal name="HiddenAccountValidityChanged"
- tp:name-for-bindings="Hidden_Account_Validity_Changed">
- <tp:docstring>
- The validity of the given account has changed. New magic
- accounts are also indicated by this signal, as an account validity
- change (usually to True) on an account that did not previously exist.
-
- <tp:rationale>
- This is effectively change notification for the valid and invalid
- accounts lists.
- </tp:rationale>
- </tp:docstring>
-
- <arg name="Account" type="o">
- <tp:docstring>
- An <tp:dbus-ref
- namespace="org.freedesktop.Telepathy">Account</tp:dbus-ref>.
- </tp:docstring>
- </arg>
-
- <arg name="Valid" type="b">
- <tp:docstring>
- True if the account is now valid.
- </tp:docstring>
- </arg>
- </signal>
-
- </interface>
-</node>
-<!-- vim:set sw=2 sts=2 et ft=xml: -->
diff --git a/xml/Channel_Dispatcher_Interface_Messages_DRAFT.xml b/xml/Channel_Dispatcher_Interface_Messages_DRAFT.xml
deleted file mode 100644
index 61a398b7..00000000
--- a/xml/Channel_Dispatcher_Interface_Messages_DRAFT.xml
+++ /dev/null
@@ -1,57 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Channel_Dispatcher_Interface_Messages_Draft"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-
- <tp:copyright>Copyright (C) 2011 Collabora Ltd.</tp:copyright>
- <tp:copyright>Copyright (C) 2011 Nokia Corporation</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA 02110-1301,
- USA.</p>
- </tp:license>
-
- <interface
- name="org.freedesktop.Telepathy.ChannelDispatcher.Interface.Messages.DRAFT"
- tp:causes-havoc="not yet final">
-
- <tp:requires interface="org.freedesktop.Telepathy.ChannelDispatcher"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>
- This interface allows DBus clients to use the ChannelDispatcher to
- send one-off text messages to a contact, identified by account and
- target ID, without requiring the caller to handle channels or be
- the primary message UI.
- </p>
-
- <tp:rationale>
- <p>
- This enables entities other than the main UI to send messages
- to contacts.
- </p>
- </tp:rationale>
- </tp:docstring>
-
- <method name="SendMessage" tp:name-for-bindings="Send_Message">
- <arg direction="in" name="Account" type="o"/>
- <arg direction="in" name="TargetID" type="s"/>
- <arg direction="in" name="Message" type="aa{sv}"
- tp:type="Message_Part[]"/>
- <arg direction="in" name="Flags" type="u"/>
- <arg direction="out" name="Token" type="s"/>
- </method>
-
- </interface>
-</node>
-
diff --git a/xml/Connection_Manager_Interface_Account_Storage.xml b/xml/Connection_Manager_Interface_Account_Storage.xml
deleted file mode 100644
index 2f4f4bf7..00000000
--- a/xml/Connection_Manager_Interface_Account_Storage.xml
+++ /dev/null
@@ -1,120 +0,0 @@
-<?xml version="1.0" ?>
-<node name="/Connection_Manager_Interface_Account_Storage"
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-
- <tp:copyright>Copyright © 2011 Collabora Ltd.</tp:copyright>
- <tp:license xmlns="http://www.w3.org/1999/xhtml">
- <p>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.</p>
-
- <p>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.</p>
-
- <p>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 Street, Fifth Floor, Boston, MA
- 02110-1301, USA.</p>
- </tp:license>
-
- <interface name="org.freedesktop.Telepathy.ConnectionManager.Interface.AccountStorage.DRAFT"
- tp:causes-havoc="experimental">
- <tp:added version="0.21.10">(draft 1)</tp:added>
- <tp:requires interface="org.freedesktop.Telepathy.ConnectionManager"/>
-
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>An interface for connection managers that store account details
- internally. At the moment this consists only of storing an account's
- credentials, but other functionality may be added in the future.</p>
-
- <p><tp:dbus-ref namespace="ofdT">Account</tp:dbus-ref> objects
- representing accounts on a connection manager that implements this
- interface should implement the
- <tp:dbus-ref namespace="ofdT.Account.Interface">ExternalPasswordStorage.DRAFT</tp:dbus-ref>
- interface.</p>
- </tp:docstring>
-
- <tp:flags name="Account_Flags" value-prefix="Account_Flag" type="u">
- <tp:docstring>
- A set of flags representing the status of the Account stored in the
- Connection Manager.
- </tp:docstring>
-
- <tp:flag suffix="Credentials_Stored" value="1">
- <tp:docstring>
- The associated account has its authentication credentials (password)
- stored in the connection manager
- </tp:docstring>
- </tp:flag>
- </tp:flags>
-
- <tp:mapping name="Account_Flags_Map" array-name="Account_Flags_Map_List">
- <tp:docstring>A mapping from Account_Ids to account flags.
- </tp:docstring>
- <tp:member type="s" name="Account_Id"/>
- <tp:member type="u" tp:type="Account_Flags" name="Flags"/>
- </tp:mapping>
-
- <property name="Accounts"
- tp:name-for-bindings="Accounts"
- type="a{su}" tp:type="Account_Flags_Map" access="read">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The set of Accounts stored in this Connection Manager, and flags
- indicating their status.</p>
-
- <p>Change notification for this property is provided by the standard
- D-Bus <code>PropertiesChanged</code> signal.</p>
- </tp:docstring>
- </property>
-
- <method name="ForgetCredentials" tp:name-for-bindings="Forget_Credentials">
- <tp:docstring>
- Clears any saved credentials associated with the specified Account_Id.
- Any other saved data related to the account will be unaffected.
- </tp:docstring>
-
- <arg direction="in" name="Account_Id"
- type="s">
- <tp:docstring>
- An account id as returned from
- <tp:dbus-ref namespace="ofdT">Protocol.IdentifyAccount</tp:dbus-ref>.
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument">
- <tp:docstring>
- The account id is invalid.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- <method name="RemoveAccount" tp:name-for-bindings="Remove_Account">
- <tp:docstring>
- Completely removes all data associated with an account from the
- connection manager's internal storage.
- </tp:docstring>
-
- <arg direction="in" name="Account_Id"
- type="s">
- <tp:docstring>
- An account id as returned from
- <tp:dbus-ref namespace="ofdT">Protocol.IdentifyAccount</tp:dbus-ref>.
- </tp:docstring>
- </arg>
-
- <tp:possible-errors>
- <tp:error name="org.freedesktop.Telepathy.Error.InvalidArgument">
- <tp:docstring>
- The account id is invalid.
- </tp:docstring>
- </tp:error>
- </tp:possible-errors>
- </method>
-
- </interface>
-</node>
diff --git a/xml/Makefile.am b/xml/Makefile.am
deleted file mode 100644
index 50ef1d51..00000000
--- a/xml/Makefile.am
+++ /dev/null
@@ -1,33 +0,0 @@
-tools_dir = $(top_srcdir)/tools
-
-XSLTFLAGS = --nonet --novalid
-DROP_NAMESPACE = sed -e 's@xmlns:tp="http://telepathy\.freedesktop\.org/wiki/DbusSpec.extensions-v0"@@g'
-DROP_TPTYPE = sed -e 's@tp:type="[^"]*"@@g'
-
-SPECS = \
- Account_Manager_Interface_Hidden.xml \
- Account_Interface_Conditions.xml \
- Account_Interface_External_Password_Storage.xml \
- Account_Interface_Hidden.xml \
- Connection_Manager_Interface_Account_Storage.xml \
- Channel_Dispatcher_Interface_Messages_DRAFT.xml
-
-
-SPECS_GEN = ${SPECS:%.xml=_gen/introspect-%.xml}
-
-all-local: $(SPECS_GEN)
-
-_gen/introspect-%.xml: %.xml $(tools_dir)/spec-to-introspect.xsl
- $(AM_V_at)$(mkdir_p) _gen
- $(AM_V_GEN)$(XSLTPROC) $(XSLTFLAGS) $(tools_dir)/spec-to-introspect.xsl $< \
- | $(DROP_NAMESPACE) > $@
-
-clean-local:
- rm -f $(SPECS_GEN)
-
-EXTRA_DIST = \
- all.xml \
- nmc5.xml \
- generic-types.xml \
- telepathy-types.xml \
- $(SPECS)
diff --git a/xml/all.xml b/xml/all.xml
deleted file mode 100644
index cb7661f9..00000000
--- a/xml/all.xml
+++ /dev/null
@@ -1,35 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright>
-
-<xi:include href="nmc5.xml"/>
-
-<tp:generic-types>
- <tp:external-type name="Connection_Status" type="u"
- from="Telepathy specification (Connection)"/>
- <tp:external-type name="Connection_Status_Reason" type="u"
- from="Telepathy specification (Connection)"/>
- <tp:external-type name="Connection_Presence_Type" type="u"
- from="Telepathy specification (Connection)"/>
- <tp:external-type name="Connection_Manager_Name" type="s"
- from="Telepathy specification (ConnectionManager)"/>
- <tp:external-type name="Contact_Handle" type="u"
- from="Telepathy specification (Connection)"/>
- <tp:external-type name="Protocol" type="s"
- from="Telepathy specification (ConnectionManager)"/>
- <tp:external-type name="Simple_Presence" type="(uss)"
- from="Telepathy specification (SimplePresence)"/>
- <tp:external-type name="Conn_Mgr_Param_Flags" type="u"
- from="Telepathy specification (ConnectionManager)"/>
- <tp:external-type name="Requestable_Channel_Class" type="(a{sv}as)"
- from="Telepathy specification (Requests)"/>
- <tp:external-type name="Handler_Capability_Token" type="s"
- from="Telepathy specification (Handler)"/>
-</tp:generic-types>
-
-<xi:include href="generic-types.xml"/>
-<xi:include href="telepathy-types.xml"/>
-
-</tp:spec>
diff --git a/xml/generic-types.xml b/xml/generic-types.xml
deleted file mode 100644
index 5b0d6ab9..00000000
--- a/xml/generic-types.xml
+++ /dev/null
@@ -1,214 +0,0 @@
-<tp:generic-types
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-
- <tp:simple-type name="Unix_Timestamp" type="u">
- <tp:docstring>An unsigned 32-bit integer representing time as the number
- of seconds elapsed since the Unix epoch
- (1970-01-01T00:00:00Z)</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="Unix_Timestamp64" type="x">
- <tp:docstring>An signed 64-bit integer representing time as the number
- of seconds elapsed since the Unix epoch
- (1970-01-01T00:00:00Z); negative for times before the epoch</tp:docstring>
-
- <tp:rationale>The Text interface is the only user of Unix_Timestamp so
- far, and we'd like to be Y2038 compatible in future
- interfaces.</tp:rationale>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Bus_Name" type="s"
- array-name="DBus_Bus_Name_List">
- <tp:docstring>A string representing a D-Bus bus name - either a well-known
- name like "org.freedesktop.Telepathy.MissionControl" or a unique name
- like ":1.123"</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Well_Known_Name" type="s"
- array-name="DBus_Well_Known_Name_List">
- <tp:docstring>A string representing a D-Bus well-known
- name like "org.freedesktop.Telepathy.MissionControl".</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Unique_Name" type="s"
- array-name="DBus_Unique_Name_List">
- <tp:docstring>A string representing a D-Bus unique name, such as
- ":1.123"</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Interface" type="s"
- array-name="DBus_Interface_List">
- <tp:docstring>An ASCII string representing a D-Bus interface - two or more
- elements separated by dots, where each element is a non-empty
- string of ASCII letters, digits and underscores, not starting with
- a digit. The maximum total length is 255 characters. For example,
- "org.freedesktop.DBus.Peer".</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Error_Name" type="s">
- <tp:docstring>An ASCII string representing a D-Bus error. This is
- syntactically the same as a <tp:type>DBus_Interface</tp:type>, but the
- meaning is different.</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Signature" type="s">
- <tp:docstring>A string representing a D-Bus signature
- (the 'g' type isn't used because of poor interoperability, particularly
- with dbus-glib)</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Member" type="s">
- <tp:docstring>An ASCII string representing a D-Bus method, signal
- or property name - a non-empty string of ASCII letters, digits and
- underscores, not starting with a digit, with a maximum length of 255
- characters. For example, "Ping".</tp:docstring>
- </tp:simple-type>
-
- <tp:simple-type name="DBus_Qualified_Member" type="s"
- array-name="DBus_Qualified_Member_List">
- <tp:docstring>A string representing the full name of a D-Bus method,
- signal or property, consisting of a DBus_Interface, followed by
- a dot, followed by a DBus_Member. For example,
- "org.freedesktop.DBus.Peer.Ping".</tp:docstring>
- </tp:simple-type>
-
- <tp:mapping name="Qualified_Property_Value_Map"
- array-name="Qualified_Property_Value_Map_List">
- <tp:docstring>A mapping from strings representing D-Bus
- properties (by their namespaced names) to their values.</tp:docstring>
- <tp:member type="s" name="Key" tp:type="DBus_Qualified_Member">
- <tp:docstring>
- A D-Bus interface name, followed by a dot and a D-Bus property name.
- </tp:docstring>
- </tp:member>
- <tp:member type="v" name="Value">
- <tp:docstring>
- The value of the property.
- </tp:docstring>
- </tp:member>
- </tp:mapping>
-
- <tp:mapping name="String_Variant_Map" array-name="String_Variant_Map_List">
- <tp:docstring>A mapping from strings to variants representing extra
- key-value pairs.</tp:docstring>
- <tp:member type="s" name="Key"/>
- <tp:member type="v" name="Value"/>
- </tp:mapping>
-
- <tp:mapping name="String_String_Map" array-name="String_String_Map_List">
- <tp:docstring>A mapping from strings to strings representing extra
- key-value pairs.</tp:docstring>
- <tp:member type="s" name="Key"/>
- <tp:member type="s" name="Value"/>
- </tp:mapping>
-
- <tp:struct name="Socket_Address_IP" array-name="Socket_Address_IP_List">
- <tp:docstring>An IP address and port.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>Either a dotted-quad IPv4 address literal as for
- <tp:type>Socket_Address_IPv4</tp:type>, or an RFC2373 IPv6 address
- as for <tp:type>Socket_Address_IPv6</tp:type>.
- </tp:docstring>
- </tp:member>
- <tp:member type="q" name="Port">
- <tp:docstring>The TCP or UDP port number.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:struct name="Socket_Address_IPv4">
- <tp:docstring>An IPv4 address and port.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>A dotted-quad IPv4 address literal: four ASCII decimal
- numbers, each between 0 and 255 inclusive, e.g.
- "192.168.0.1".</tp:docstring>
- </tp:member>
- <tp:member type="q" name="Port">
- <tp:docstring>The TCP or UDP port number.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:struct name="Socket_Address_IPv6">
- <tp:docstring>An IPv6 address and port.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>An IPv6 address literal as specified by RFC2373
- section 2.2, e.g. "2001:DB8::8:800:200C:4171".</tp:docstring>
- </tp:member>
- <tp:member type="q" name="Port">
- <tp:docstring>The TCP or UDP port number.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:struct name="Socket_Netmask_IPv4">
- <tp:docstring>An IPv4 network or subnet.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>A dotted-quad IPv4 address literal: four ASCII decimal
- numbers, each between 0 and 255 inclusive, e.g.
- "192.168.0.1".</tp:docstring>
- </tp:member>
- <tp:member type="y" name="Prefix_Length">
- <tp:docstring>The number of leading bits of the address that must
- match, for this netmask to be considered to match an
- address.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:struct name="Socket_Netmask_IPv6">
- <tp:docstring>An IPv6 network or subnet.</tp:docstring>
- <tp:member type="s" name="Address">
- <tp:docstring>An IPv6 address literal as specified by RFC2373
- section 2.2, e.g. "2001:DB8::8:800:200C:4171".</tp:docstring>
- </tp:member>
- <tp:member type="y" name="Prefix_Length">
- <tp:docstring>The number of leading bits of the address that must
- match, for this netmask to be considered to match an
- address.</tp:docstring>
- </tp:member>
- </tp:struct>
-
- <tp:simple-type name="User_Action_Timestamp" type="x">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>The time at which an user action occurred. This type has the 2
- following special values:</p>
-
- <p>0: the action doesn't involve any user action. Clients
- SHOULD avoid stealing focus when presenting the channel.</p>
-
- <p>MAX_INT64: clients SHOULD behave as though the user action happened
- at the current time, e.g. a client MAY request that its window gains
- focus.
- </p>
-
- <tp:rationale>
- <p>This can be used by clients that can't know the X server time like
- command line applications for example.</p>
- </tp:rationale>
-
- <p>For all the other values it corresponds to the time of the user
- action. Clients SHOULD use this for focus-stealing prevention,
- if applicable.
- Note that the time is dependant on the local
- environment and so is not necessarily a wall-clock time.
- For example in an X environment it's expected to be the X timestamp
- of events.
- This corresponds to the _NET_WM_USER_TIME property in
- <a href="http://standards.freedesktop.org/wm-spec/wm-spec-latest.html">EWMH</a>.</p>
- </tp:docstring>
- </tp:simple-type>
-
- <tp:mapping name="Object_Immutable_Properties_Map"
- array-name="Object_Immutable_Properties_Map_List">
- <tp:docstring>A mapping from object path to the immutable properties of
- the object.</tp:docstring>
- <tp:member type="o" name="Path">
- <tp:docstring>
- The object path of an object
- </tp:docstring>
- </tp:member>
- <tp:member type="a{sv}" name="Immutable_Properties" tp:type="Qualified_Property_Value_Map">
- <tp:docstring>
- The immutable properties of the object
- </tp:docstring>
- </tp:member>
- </tp:mapping>
-
-</tp:generic-types>
diff --git a/xml/nmc5.xml b/xml/nmc5.xml
deleted file mode 100644
index 130fd3f3..00000000
--- a/xml/nmc5.xml
+++ /dev/null
@@ -1,14 +0,0 @@
-<tp:spec
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0"
- xmlns:xi="http://www.w3.org/2001/XInclude">
-
-<tp:copyright>Copyright (C) 2008 Nokia Corporation</tp:copyright>
-
-<xi:include href="Account_Interface_Conditions.xml"/>
-<xi:include href="Account_Interface_External_Password_Storage.xml"/>
-<xi:include href="Account_Interface_Hidden.xml"/>
-<xi:include href="Account_Manager_Interface_Hidden.xml"/>
-
-<xi:include href="Connection_Manager_Interface_Account_Storage.xml"/>
-
-</tp:spec>
diff --git a/xml/telepathy-types.xml b/xml/telepathy-types.xml
deleted file mode 100644
index 8225aa03..00000000
--- a/xml/telepathy-types.xml
+++ /dev/null
@@ -1,96 +0,0 @@
-<tp:telepathy-types
- xmlns:tp="http://telepathy.freedesktop.org/wiki/DbusSpec#extensions-v0">
-
- <tp:mapping name="Channel_Class" array-name="Channel_Class_List">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Mapping representing a class of channels that can be requested
- from a connection manager, can be handled by a user interface,
- are supported by a contact, etc.</p>
-
- <p>Classes of channel are identified by the fixed values of
- a subset of their properties.</p>
-
- <p>Channel classes SHOULD always include the keys
- <tp:dbus-ref>org.freedesktop.Telepathy.Channel.ChannelType</tp:dbus-ref>
- and
- <tp:dbus-ref>org.freedesktop.Telepathy.Channel.TargetHandleType</tp:dbus-ref>.
- </p>
- </tp:docstring>
-
- <tp:member type="s" name="Key" tp:type="DBus_Qualified_Member">
- <tp:docstring>
- A D-Bus interface name, followed by a dot and a D-Bus property name.
- </tp:docstring>
- </tp:member>
-
- <tp:member type="v" name="Value">
- <tp:docstring>
- The value of the property.
- </tp:docstring>
- </tp:member>
- </tp:mapping>
-
- <tp:struct name="Channel_Details" array-name="Channel_Details_List">
- <tp:added version="0.17.11">(as stable API)</tp:added>
-
- <tp:docstring>
- Enough details of a channel that clients can work out how to dispatch
- or handle it.
- </tp:docstring>
-
- <tp:member name="Channel" type="o">
- <tp:docstring>
- The object path of the channel.
- </tp:docstring>
- </tp:member>
-
- <tp:member name="Properties" type="a{sv}"
- tp:type="Qualified_Property_Value_Map">
- <tp:docstring xmlns="http://www.w3.org/1999/xhtml">
- <p>Properties of the channel.</p>
-
- <p>Connection managers MUST NOT include properties in this mapping
- if their values can change. Clients MUST ignore properties
- that appear in this mapping if their values can change.</p>
-
- <tp:rationale>
- <p>If properties that could change were included, the following
- race condition would be likely to exist in some cases:</p>
-
- <ul>
- <li>NewChannels or Get("Channels") includes a property P with
- value V1</li>
- <li>Client creates a proxy object for the channel</li>
- <li>The value of P changes to V2</li>
- <li>Client connects to PChanged signal</li>
- <li>Client should call Get("P") or GetAll here, to avoid the
- race, but client's author has forgotten to do so</li>
- <li>Proxy object thinks P == V1, but actually P == V2</li>
- </ul>
-
- <p>We've taken the opportunity to make the API encourage the
- client author to get it right. Where possible, we intend that
- properties whose value will be used in channel dispatching
- or other "early" processing will be defined so that they are
- immutable (can never change).</p>
- </tp:rationale>
-
- <p>Each dictionary MUST contain the keys
- <tp:dbus-ref>org.freedesktop.Telepathy.Channel.ChannelType</tp:dbus-ref>,
- <tp:dbus-ref>org.freedesktop.Telepathy.Channel.TargetHandleType</tp:dbus-ref>,
- <tp:dbus-ref>org.freedesktop.Telepathy.Channel.TargetHandle</tp:dbus-ref>
- and
- <tp:dbus-ref>org.freedesktop.Telepathy.Channel.TargetID</tp:dbus-ref>.
- </p>
- <!-- FIXME: maybe also Requested, InitiatorHandle,
- InitiatorID once they leave the FUTURE pseudo-interface -->
-
- <tp:rationale>
- <p>We expect these to be crucial to the channel-dispatching
- process.</p>
- </tp:rationale>
- </tp:docstring>
- </tp:member>
- </tp:struct>
-
-</tp:telepathy-types>