summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mission-control-plugins/account-storage.c18
-rw-r--r--mission-control-plugins/account-storage.h9
-rw-r--r--mission-control-plugins/account.c66
-rw-r--r--mission-control-plugins/account.h12
-rw-r--r--mission-control-plugins/implementation.h12
-rw-r--r--mission-control-plugins/mission-control-plugins.h9
-rw-r--r--src/mcd-account-conditions.c14
-rw-r--r--src/mcd-account-config.h3
-rw-r--r--src/mcd-account-manager.c15
-rw-r--r--src/mcd-account-priv.h1
-rw-r--r--src/mcd-account.c275
-rw-r--r--src/mcd-dbusprop.c3
-rw-r--r--src/mcd-dbusprop.h12
-rw-r--r--src/mcd-debug.h2
-rw-r--r--src/mcd-storage.c123
-rw-r--r--src/mcd-storage.h4
-rw-r--r--tests/Makefile.am9
-rw-r--r--tests/keyfile.c351
-rw-r--r--tests/twisted/account-manager/auto-connect.py20
-rw-r--r--tests/twisted/account-manager/avatar-persist.py5
-rw-r--r--tests/twisted/account-manager/avatar-refresh.py5
-rw-r--r--tests/twisted/account-manager/backend-makes-changes.py134
-rw-r--r--tests/twisted/account-storage/default-keyring-storage.py2
-rw-r--r--tests/twisted/dbus-account-plugin.c36
-rw-r--r--tests/twisted/dispatcher/create-at-startup.py4
-rw-r--r--util/mc-tool.c13
26 files changed, 957 insertions, 200 deletions
diff --git a/mission-control-plugins/account-storage.c b/mission-control-plugins/account-storage.c
index 92af6de3..7f7187f9 100644
--- a/mission-control-plugins/account-storage.c
+++ b/mission-control-plugins/account-storage.c
@@ -217,9 +217,15 @@ class_init (gpointer klass,
* 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.
*
+ * 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
*/
signals[ALTERED_ONE] = g_signal_new ("altered-one",
@@ -252,7 +258,7 @@ class_init (gpointer klass,
* 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
- * mcp_account_manager_set_value() first.
+ * a function like mcp_account_manager_set_value() first.
*
* Should not be fired until mcp_account_storage_ready() has been called
*
@@ -514,10 +520,16 @@ mcp_account_storage_priority (const McpAccountStorage *storage)
* like "DisplayName", or "param-" plus a parameter like "account"
*
* Get a value from the plugin's in-memory cache.
- * The plugin is expected to call mcp_account_manager_set_value(),
- * and if appropriate, mcp_account_manager_parameter_make_secret(),
+ * 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
diff --git a/mission-control-plugins/account-storage.h b/mission-control-plugins/account-storage.h
index a0054112..5b6c21c4 100644
--- a/mission-control-plugins/account-storage.h
+++ b/mission-control-plugins/account-storage.h
@@ -32,15 +32,6 @@ G_BEGIN_DECLS
#define MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_NORMAL 100
#define MCP_ACCOUNT_STORAGE_PLUGIN_PRIO_KEYRING 10000
-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;
-
/* API for plugins to implement */
typedef struct _McpAccountStorage McpAccountStorage;
typedef struct _McpAccountStorageIface McpAccountStorageIface;
diff --git a/mission-control-plugins/account.c b/mission-control-plugins/account.c
index 32f60332..e962857c 100644
--- a/mission-control-plugins/account.c
+++ b/mission-control-plugins/account.c
@@ -86,6 +86,9 @@ mcp_account_manager_get_type (void)
*
* 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,
@@ -102,6 +105,69 @@ mcp_account_manager_set_value (const McpAccountManager *mcpa,
}
/**
+ * 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
diff --git a/mission-control-plugins/account.h b/mission-control-plugins/account.h
index 4536ab18..69a33d56 100644
--- a/mission-control-plugins/account.h
+++ b/mission-control-plugins/account.h
@@ -50,6 +50,18 @@ void mcp_account_manager_set_value (const McpAccountManager *mcpa,
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);
diff --git a/mission-control-plugins/implementation.h b/mission-control-plugins/implementation.h
index eb857205..20c5fdf4 100644
--- a/mission-control-plugins/implementation.h
+++ b/mission-control-plugins/implementation.h
@@ -119,6 +119,18 @@ struct _McpAccountManagerIface {
gchar * (* escape_variant_for_keyfile) (const McpAccountManager *mcpa,
GVariant *variant);
+
+ 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);
};
G_END_DECLS
diff --git a/mission-control-plugins/mission-control-plugins.h b/mission-control-plugins/mission-control-plugins.h
index fe0d8afb..d875199c 100644
--- a/mission-control-plugins/mission-control-plugins.h
+++ b/mission-control-plugins/mission-control-plugins.h
@@ -25,6 +25,15 @@
#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_IN_MISSION_CONTROL_PLUGINS_H
#include <mission-control-plugins/account.h>
#include <mission-control-plugins/account-storage.h>
diff --git a/src/mcd-account-conditions.c b/src/mcd-account-conditions.c
index b36d6b1f..e40dccf9 100644
--- a/src/mcd-account-conditions.c
+++ b/src/mcd-account-conditions.c
@@ -53,8 +53,11 @@ store_condition (gpointer key, gpointer value, gpointer userdata)
}
static gboolean
-set_condition (TpSvcDBusProperties *self, const gchar *name,
- const GValue *value, GError **error)
+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);
@@ -95,9 +98,12 @@ set_condition (TpSvcDBusProperties *self, const gchar *name,
g_strfreev (keys);
- g_hash_table_foreach (conditions, store_condition, account);
+ if (!(flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE))
+ {
+ g_hash_table_foreach (conditions, store_condition, account);
- mcd_storage_commit (storage, account_name);
+ mcd_storage_commit (storage, account_name);
+ }
return TRUE;
}
diff --git a/src/mcd-account-config.h b/src/mcd-account-config.h
index 3124692e..fc7a9eae 100644
--- a/src/mcd-account-config.h
+++ b/src/mcd-account-config.h
@@ -39,6 +39,8 @@
#define MC_ACCOUNTS_KEY_NORMALIZED_NAME "NormalizedName"
#define MC_ACCOUNTS_KEY_AVATAR_TOKEN "avatar_token"
#define MC_ACCOUNTS_KEY_AVATAR_MIME "AvatarMime"
+#define MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE "AutomaticPresence"
+/* next two are obsoleted by MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE */
#define MC_ACCOUNTS_KEY_AUTO_PRESENCE_STATUS "AutomaticPresenceStatus"
#define MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE "AutomaticPresenceMessage"
#define MC_ACCOUNTS_KEY_ICON "Icon"
@@ -47,6 +49,7 @@
/* ... also "condition-*" reserved by mcd-account-conditions.c */
/* unsigned 32-bit integer, 'u' */
+/* obsoleted by MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE */
#define MC_ACCOUNTS_KEY_AUTO_PRESENCE_TYPE "AutomaticPresenceType"
/* boolean, 'b' */
diff --git a/src/mcd-account-manager.c b/src/mcd-account-manager.c
index e597eb1d..29482255 100644
--- a/src/mcd-account-manager.c
+++ b/src/mcd-account-manager.c
@@ -399,7 +399,8 @@ toggled_cb (GObject *plugin, const gchar *name, gboolean on, gpointer data)
return;
}
- _mcd_account_set_enabled (account, on, FALSE, &error);
+ _mcd_account_set_enabled (account, on, FALSE,
+ MCD_DBUS_PROP_SET_FLAG_NONE, &error);
if (error != NULL)
{
@@ -1225,7 +1226,8 @@ migrate_create_account_cb (McdAccountManager *account_manager,
if (error != NULL)
{
DEBUG ("Failed to create account: %s", error->message);
- _mcd_account_set_enabled (ctx->account, FALSE, TRUE, NULL);
+ _mcd_account_set_enabled (ctx->account, FALSE, TRUE,
+ MCD_DBUS_PROP_SET_FLAG_NONE, NULL);
migrate_ctx_free (ctx);
return;
}
@@ -1253,7 +1255,8 @@ migrate_butterfly_haze_ready (McdManager *manager,
if (error != NULL)
{
DEBUG ("Can't find Haze: %s", error->message);
- _mcd_account_set_enabled (ctx->account, FALSE, TRUE, NULL);
+ _mcd_account_set_enabled (ctx->account, FALSE, TRUE,
+ MCD_DBUS_PROP_SET_FLAG_NONE, NULL);
goto error;
}
@@ -1262,7 +1265,8 @@ migrate_butterfly_haze_ready (McdManager *manager,
"account", G_TYPE_STRING,
&v, NULL))
{
- _mcd_account_set_enabled (ctx->account, FALSE, TRUE, NULL);
+ _mcd_account_set_enabled (ctx->account, FALSE, TRUE,
+ MCD_DBUS_PROP_SET_FLAG_NONE, NULL);
goto error;
}
@@ -1349,7 +1353,8 @@ butterfly_account_loaded (McdAccount *account,
if (manager == NULL)
{
DEBUG ("Can't find Haze");
- _mcd_account_set_enabled (account, FALSE, TRUE, NULL);
+ _mcd_account_set_enabled (account, FALSE, TRUE,
+ MCD_DBUS_PROP_SET_FLAG_NONE, NULL);
goto error;
}
diff --git a/src/mcd-account-priv.h b/src/mcd-account-priv.h
index a00b398e..e80eb995 100644
--- a/src/mcd-account-priv.h
+++ b/src/mcd-account-priv.h
@@ -169,6 +169,7 @@ G_GNUC_INTERNAL void _mcd_account_set_changing_presence (McdAccount *self,
G_GNUC_INTERNAL gboolean _mcd_account_set_enabled (McdAccount *account,
gboolean enabled,
gboolean write_out,
+ McdDBusPropSetFlags flags,
GError **error);
G_GNUC_INTERNAL gboolean _mcd_account_presence_type_is_settable (
diff --git a/src/mcd-account.c b/src/mcd-account.c
index c7b941db..5faf104e 100644
--- a/src/mcd-account.c
+++ b/src/mcd-account.c
@@ -708,7 +708,8 @@ mcd_account_delete (McdAccount *account,
/* 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, &error))
+ if (!_mcd_account_set_enabled (account, FALSE, FALSE,
+ MCD_DBUS_PROP_SET_FLAG_NONE, &error))
{
g_warning ("could not disable account %s (%s)", name, error->message);
callback (account, error, user_data);
@@ -1012,8 +1013,11 @@ typedef enum {
* %SET_RESULT_ERROR on error
*/
static SetResult
-mcd_account_set_string_val (McdAccount *account, const gchar *key,
- const GValue *value, GError **error)
+mcd_account_set_string_val (McdAccount *account,
+ const gchar *key,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
+ GError **error)
{
McdAccountPrivate *priv = account->priv;
McdStorage *storage = priv->storage;
@@ -1034,11 +1038,19 @@ mcd_account_set_string_val (McdAccount *account, const gchar *key,
new_string = NULL;
}
- if (mcd_storage_set_string (storage, name, key, new_string)) {
+ if (flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE)
+ {
+ mcd_account_changed_property (account, key, value);
+ return SET_RESULT_CHANGED;
+ }
+ else if (mcd_storage_set_string (storage, name, key, new_string))
+ {
mcd_storage_commit (storage, name);
mcd_account_changed_property (account, key, value);
return SET_RESULT_CHANGED;
- } else {
+ }
+ else
+ {
return SET_RESULT_UNCHANGED;
}
}
@@ -1059,15 +1071,19 @@ mcd_account_get_string_val (McdAccount *account, const gchar *key,
}
static gboolean
-set_display_name (TpSvcDBusProperties *self, const gchar *name,
- const GValue *value, GError **error)
+set_display_name (TpSvcDBusProperties *self,
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
+ GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
McdAccountPrivate *priv = account->priv;
DEBUG ("called for %s", priv->unique_name);
return (mcd_account_set_string_val (account,
- MC_ACCOUNTS_KEY_DISPLAY_NAME, value, error) != SET_RESULT_ERROR);
+ MC_ACCOUNTS_KEY_DISPLAY_NAME, value, flags,
+ error) != SET_RESULT_ERROR);
}
static void
@@ -1079,7 +1095,10 @@ get_display_name (TpSvcDBusProperties *self, const gchar *name, GValue *value)
}
static gboolean
-set_icon (TpSvcDBusProperties *self, const gchar *name, const GValue *value,
+set_icon (TpSvcDBusProperties *self,
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -1087,7 +1106,7 @@ set_icon (TpSvcDBusProperties *self, const gchar *name, const GValue *value,
DEBUG ("called for %s", priv->unique_name);
return (mcd_account_set_string_val (account,
- MC_ACCOUNTS_KEY_ICON, value, error) != SET_RESULT_ERROR);
+ MC_ACCOUNTS_KEY_ICON, value, flags, error) != SET_RESULT_ERROR);
}
static void
@@ -1131,6 +1150,7 @@ gboolean
_mcd_account_set_enabled (McdAccount *account,
gboolean enabled,
gboolean write_out,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccountPrivate *priv = account->priv;
@@ -1159,11 +1179,14 @@ _mcd_account_set_enabled (McdAccount *account,
g_value_init (&value, G_TYPE_BOOLEAN);
g_value_set_boolean (&value, enabled);
- mcd_storage_set_attribute (priv->storage, name,
- MC_ACCOUNTS_KEY_ENABLED, &value);
+ if (!(flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE))
+ {
+ mcd_storage_set_attribute (priv->storage, name,
+ MC_ACCOUNTS_KEY_ENABLED, &value);
- if (write_out)
- mcd_storage_commit (priv->storage, name);
+ if (write_out)
+ mcd_storage_commit (priv->storage, name);
+ }
mcd_account_changed_property (account, "Enabled", &value);
@@ -1180,7 +1203,10 @@ _mcd_account_set_enabled (McdAccount *account,
}
static gboolean
-set_enabled (TpSvcDBusProperties *self, const gchar *name, const GValue *value,
+set_enabled (TpSvcDBusProperties *self,
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -1199,7 +1225,7 @@ set_enabled (TpSvcDBusProperties *self, const gchar *name, const GValue *value,
enabled = g_value_get_boolean (value);
- return _mcd_account_set_enabled (account, enabled, TRUE, error);
+ return _mcd_account_set_enabled (account, enabled, TRUE, flags, error);
}
static void
@@ -1214,7 +1240,9 @@ get_enabled (TpSvcDBusProperties *self, const gchar *name, GValue *value)
static gboolean
set_service (TpSvcDBusProperties *self, const gchar *name,
- const GValue *value, GError **error)
+ const GValue *value,
+ McdDBusPropSetFlags flags,
+ GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
SetResult ret = SET_RESULT_ERROR;
@@ -1240,7 +1268,7 @@ set_service (TpSvcDBusProperties *self, const gchar *name,
if (proceed)
{
ret = mcd_account_set_string_val (account, MC_ACCOUNTS_KEY_SERVICE,
- value, error);
+ value, flags, error);
}
else
{
@@ -1302,7 +1330,9 @@ mcd_account_send_nickname_to_connection (McdAccount *self,
static gboolean
set_nickname (TpSvcDBusProperties *self, const gchar *name,
- const GValue *value, GError **error)
+ const GValue *value,
+ McdDBusPropSetFlags flags,
+ GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
McdAccountPrivate *priv = account->priv;
@@ -1330,7 +1360,7 @@ set_nickname (TpSvcDBusProperties *self, const gchar *name,
}
ret = mcd_account_set_string_val (account, MC_ACCOUNTS_KEY_NICKNAME,
- value, error);
+ value, flags, error);
if (ret != SET_RESULT_ERROR)
{
@@ -1517,6 +1547,7 @@ mcd_account_send_avatar_to_connection (McdAccount *self,
static gboolean
set_avatar (TpSvcDBusProperties *self, const gchar *name, const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -1621,7 +1652,10 @@ _presence_type_is_online (TpConnectionPresenceType type)
static gboolean
set_automatic_presence (TpSvcDBusProperties *self,
- const gchar *name, const GValue *value, GError **error)
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
+ GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
McdAccountPrivate *priv = account->priv;
@@ -1658,29 +1692,12 @@ set_automatic_presence (TpSvcDBusProperties *self,
if (priv->auto_presence_type != type)
{
- GValue presence = G_VALUE_INIT;
-
- g_value_init (&presence, G_TYPE_INT);
- g_value_set_int (&presence, type);
-
- mcd_storage_set_attribute (priv->storage, account_name,
- MC_ACCOUNTS_KEY_AUTO_PRESENCE_TYPE,
- &presence);
priv->auto_presence_type = type;
changed = TRUE;
}
if (tp_strdiff (priv->auto_presence_status, status))
{
- const gchar *new_status = NULL;
-
- if (status != NULL && status[0] != 0)
- new_status = status;
-
- mcd_storage_set_string (priv->storage, account_name,
- MC_ACCOUNTS_KEY_AUTO_PRESENCE_STATUS,
- new_status);
-
g_free (priv->auto_presence_status);
priv->auto_presence_status = g_strdup (status);
changed = TRUE;
@@ -1688,23 +1705,16 @@ set_automatic_presence (TpSvcDBusProperties *self,
if (tp_strdiff (priv->auto_presence_message, message))
{
- const gchar *new_message = NULL;
-
- if (!tp_str_empty (message))
- new_message = message;
-
- mcd_storage_set_string (priv->storage, account_name,
- MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE,
- new_message);
-
g_free (priv->auto_presence_message);
priv->auto_presence_message = g_strdup (message);
changed = TRUE;
}
-
if (changed)
{
+ mcd_storage_set_attribute (priv->storage, account_name,
+ MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE,
+ value);
mcd_storage_commit (priv->storage, account_name);
mcd_account_changed_property (account, name, value);
}
@@ -1738,7 +1748,9 @@ get_automatic_presence (TpSvcDBusProperties *self,
static gboolean
set_connect_automatically (TpSvcDBusProperties *self,
- const gchar *name, const GValue *value,
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -1768,12 +1780,16 @@ set_connect_automatically (TpSvcDBusProperties *self,
if (priv->connect_automatically != connect_automatically)
{
const gchar *account_name = mcd_account_get_unique_name (account);
- mcd_storage_set_attribute (priv->storage, account_name,
- MC_ACCOUNTS_KEY_CONNECT_AUTOMATICALLY,
- value);
+
+ if (!(flags & MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE))
+ {
+ mcd_storage_set_attribute (priv->storage, account_name,
+ MC_ACCOUNTS_KEY_CONNECT_AUTOMATICALLY,
+ value);
+ mcd_storage_commit (priv->storage, account_name);
+ }
priv->connect_automatically = connect_automatically;
- mcd_storage_commit (priv->storage, account_name);
mcd_account_changed_property (account, name, value);
if (connect_automatically)
@@ -1880,7 +1896,9 @@ get_current_presence (TpSvcDBusProperties *self, const gchar *name,
static gboolean
set_requested_presence (TpSvcDBusProperties *self,
- const gchar *name, const GValue *value,
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -1973,6 +1991,7 @@ static gboolean
set_supersedes (TpSvcDBusProperties *svc,
const gchar *name,
const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *self = MCD_ACCOUNT (svc);
@@ -2048,6 +2067,7 @@ static gboolean
set_storage_provider (TpSvcDBusProperties *self,
const gchar *name,
const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -2192,6 +2212,7 @@ static gboolean
set_hidden (TpSvcDBusProperties *self,
const gchar *name,
const GValue *value,
+ McdDBusPropSetFlags flags,
GError **error)
{
McdAccount *account = MCD_ACCOUNT (self);
@@ -2478,6 +2499,31 @@ mcd_account_altered_by_plugin (McdAccount *account,
{
guint i = 0;
const McdDBusProp *prop = NULL;
+ GValue value = G_VALUE_INIT;
+ GError *error = NULL;
+
+ DEBUG ("%s", name);
+
+ if (tp_strdiff (name, "Parameters") &&
+ !mcd_storage_init_value_for_attribute (&value, name))
+ {
+ WARNING ("plugin wants to alter %s but I don't know what "
+ "type that ought to be", name);
+ return;
+ }
+
+ if (!tp_strdiff (name, "Parameters"))
+ {
+ get_parameters (TP_SVC_DBUS_PROPERTIES (account), name, &value);
+ }
+ else if (!mcd_storage_get_attribute (account->priv->storage,
+ account->priv->unique_name,
+ name, &value, &error))
+ {
+ WARNING ("cannot get new value of %s: %s", name, error->message);
+ g_error_free (error);
+ return;
+ }
/* find the property update handler */
for (; prop == NULL && account_properties[i].name != NULL; i++)
@@ -2490,32 +2536,34 @@ mcd_account_altered_by_plugin (McdAccount *account,
* then issue the change notification (DBus signals etc) for it */
if (prop != NULL)
{
- TpSvcDBusProperties *self = TP_SVC_DBUS_PROPERTIES (account);
-
- if (prop->getprop != NULL)
+ /* poke the value back into itself with the setter: this *
+ * extra round-trip may trigger extra actions like notifying *
+ * the connection manager of the change, even though our own *
+ * internal storage already has this value and needn't change */
+ if (prop->setprop != NULL)
{
- GValue value = G_VALUE_INIT;
-
- prop->getprop (self, name, &value);
-
- /* poke the value back into itself with the setter: this *
- * extra round-trip may trigger extra actions like notifying *
- * the connection manager of the change, even though our own *
- * internal storage already has this value and needn't change */
- if (prop->setprop != NULL)
- prop->setprop (self, prop->name, &value, NULL);
- else
- mcd_account_changed_property (account, prop->name, &value);
-
- g_value_unset (&value);
+ DEBUG ("Calling property setter for %s", name);
+ if (!prop->setprop (TP_SVC_DBUS_PROPERTIES (account),
+ prop->name, &value,
+ MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE,
+ &error))
+ {
+ WARNING ("Unable to set %s: %s", name, error->message);
+ g_error_free (error);
+ }
}
else
{
- DEBUG ("Valid DBus property %s with no get method was changed"
- " - cannot notify change since we cannot get its value",
- name);
+ DEBUG ("Emitting signal directly for %s", name);
+ mcd_account_changed_property (account, prop->name, &value);
}
}
+ else
+ {
+ DEBUG ("%s does not appear to be an Account property", name);
+ }
+
+ g_value_unset (&value);
}
}
@@ -3261,32 +3309,78 @@ mcd_account_setup (McdAccount *account)
priv->always_dispatch =
mcd_storage_get_boolean (storage, name, MC_ACCOUNTS_KEY_ALWAYS_DISPATCH);
- /* load the automatic presence */
- priv->auto_presence_type =
- mcd_storage_get_integer (storage, name,
- MC_ACCOUNTS_KEY_AUTO_PRESENCE_TYPE);
+ g_value_init (&value, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
+
+ g_free (priv->auto_presence_status);
+ g_free (priv->auto_presence_message);
- /* If invalid or something, force it to AVAILABLE - we want the auto
- * presence type to be an online status */
- if (!_presence_type_is_online (priv->auto_presence_type))
+ if (mcd_storage_get_attribute (storage, name,
+ MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE, &value,
+ NULL))
{
- priv->auto_presence_type = TP_CONNECTION_PRESENCE_TYPE_AVAILABLE;
- g_free (priv->auto_presence_status);
- priv->auto_presence_status = g_strdup ("available");
+ GValueArray *va = g_value_get_boxed (&value);
+
+ priv->auto_presence_type = g_value_get_uint (va->values + 0);
+ priv->auto_presence_status = g_value_dup_string (va->values + 1);
+ priv->auto_presence_message = g_value_dup_string (va->values + 2);
+
+ if (priv->auto_presence_status == NULL)
+ priv->auto_presence_status = g_strdup ("");
+ if (priv->auto_presence_message == NULL)
+ priv->auto_presence_message = g_strdup ("");
}
else
{
- g_free (priv->auto_presence_status);
+ /* try the old versions */
+ priv->auto_presence_type =
+ mcd_storage_get_integer (storage, name,
+ MC_ACCOUNTS_KEY_AUTO_PRESENCE_TYPE);
priv->auto_presence_status =
mcd_storage_dup_string (storage, name,
MC_ACCOUNTS_KEY_AUTO_PRESENCE_STATUS);
+ priv->auto_presence_message =
+ mcd_storage_dup_string (storage, name,
+ MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE);
+
+ if (priv->auto_presence_status == NULL)
+ priv->auto_presence_status = g_strdup ("");
+ if (priv->auto_presence_message == NULL)
+ priv->auto_presence_message = g_strdup ("");
+
+ /* migrate to a more sensible storage format */
+ g_value_take_boxed (&value, tp_value_array_build (3,
+ G_TYPE_UINT, (guint) priv->auto_presence_type,
+ G_TYPE_STRING, priv->auto_presence_status,
+ G_TYPE_STRING, priv->auto_presence_message,
+ G_TYPE_INVALID));
+
+ if (mcd_storage_set_attribute (storage, name,
+ MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE,
+ &value))
+ {
+ mcd_storage_set_attribute (storage, name,
+ MC_ACCOUNTS_KEY_AUTO_PRESENCE_TYPE,
+ NULL);
+ mcd_storage_set_attribute (storage, name,
+ MC_ACCOUNTS_KEY_AUTO_PRESENCE_STATUS,
+ NULL);
+ mcd_storage_set_attribute (storage, name,
+ MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE,
+ NULL);
+ mcd_storage_commit (storage, name);
+ }
}
- g_free (priv->auto_presence_message);
- priv->auto_presence_message =
- mcd_storage_dup_string (storage, name,
- MC_ACCOUNTS_KEY_AUTO_PRESENCE_MESSAGE);
+ /* If invalid or something, force it to AVAILABLE - we want the auto
+ * presence type to be an online status */
+ if (!_presence_type_is_online (priv->auto_presence_type))
+ {
+ priv->auto_presence_type = TP_CONNECTION_PRESENCE_TYPE_AVAILABLE;
+ g_free (priv->auto_presence_status);
+ priv->auto_presence_status = g_strdup ("available");
+ }
+ g_value_unset (&value);
g_value_init (&value, TP_ARRAY_TYPE_OBJECT_PATH_LIST);
if (priv->supersedes != NULL)
@@ -4193,7 +4287,8 @@ mcd_account_self_contact_notify_alias_cb (McdAccount *self,
g_value_init (&value, G_TYPE_STRING);
g_object_get_property (G_OBJECT (self_contact), "alias", &value);
- mcd_account_set_string_val (self, MC_ACCOUNTS_KEY_NICKNAME, &value, NULL);
+ mcd_account_set_string_val (self, MC_ACCOUNTS_KEY_NICKNAME, &value,
+ MCD_DBUS_PROP_SET_FLAG_NONE, NULL);
g_value_unset (&value);
}
diff --git a/src/mcd-dbusprop.c b/src/mcd-dbusprop.c
index f15bd85b..f0d64e58 100644
--- a/src/mcd-dbusprop.c
+++ b/src/mcd-dbusprop.c
@@ -181,7 +181,8 @@ mcd_dbusprop_set_property (TpSvcDBusProperties *self,
/* we pass property->name, because we know it's a static value and there
* will be no need to care about its lifetime */
- return property->setprop (self, property->name, value, error);
+ return property->setprop (self, property->name, value,
+ MCD_DBUS_PROP_SET_FLAG_NONE, error);
}
void
diff --git a/src/mcd-dbusprop.h b/src/mcd-dbusprop.h
index fa5091c2..509541a6 100644
--- a/src/mcd-dbusprop.h
+++ b/src/mcd-dbusprop.h
@@ -32,8 +32,16 @@
G_BEGIN_DECLS
-typedef gboolean (*mcd_setprop) (TpSvcDBusProperties *self, const gchar *name,
- const GValue *value, GError **error);
+typedef enum {
+ MCD_DBUS_PROP_SET_FLAG_NONE = 0,
+ MCD_DBUS_PROP_SET_FLAG_ALREADY_IN_STORAGE = 1
+} McdDBusPropSetFlags;
+
+typedef gboolean (*mcd_setprop) (TpSvcDBusProperties *self,
+ const gchar *name,
+ const GValue *value,
+ McdDBusPropSetFlags flags,
+ GError **error);
typedef void (*mcd_getprop) (TpSvcDBusProperties *self, const gchar *name,
GValue *value);
diff --git a/src/mcd-debug.h b/src/mcd-debug.h
index f9bd0227..f91e69d1 100644
--- a/src/mcd-debug.h
+++ b/src/mcd-debug.h
@@ -39,6 +39,8 @@ G_BEGIN_DECLS
#define DEBUGGING (_mcd_debug_get_level () > 0)
#define DEBUG(format, ...) \
mcd_debug ("%s: " format, G_STRFUNC, ##__VA_ARGS__)
+#define WARNING(format, ...) \
+ g_warning ("%s: " format, G_STRFUNC, ##__VA_ARGS__)
#else /* !defined ENABLE_DEBUG */
diff --git a/src/mcd-storage.c b/src/mcd-storage.c
index 5ca194c7..967228a2 100644
--- a/src/mcd-storage.c
+++ b/src/mcd-storage.c
@@ -29,6 +29,7 @@
#include "mcd-misc.h"
#include "plugin-loader.h"
+#include <errno.h>
#include <string.h>
#include <telepathy-glib/telepathy-glib.h>
@@ -299,6 +300,9 @@ static struct {
} known_attributes[] = {
/* Please keep this sorted by type, then by name. */
+ /* Structs */
+ { "(uss)", MC_ACCOUNTS_KEY_AUTOMATIC_PRESENCE },
+
/* Array of object path */
{ "ao", MC_ACCOUNTS_KEY_SUPERSEDES },
@@ -331,7 +335,7 @@ static struct {
{ NULL, NULL }
};
-static const gchar *
+const gchar *
mcd_storage_get_attribute_type (const gchar *attribute)
{
guint i;
@@ -349,7 +353,7 @@ mcd_storage_get_attribute_type (const gchar *attribute)
return NULL;
}
-static gboolean
+gboolean
mcd_storage_init_value_for_attribute (GValue *value,
const gchar *attribute)
{
@@ -387,6 +391,16 @@ mcd_storage_init_value_for_attribute (GValue *value,
}
}
break;
+
+ case '(':
+ {
+ if (!tp_strdiff (s, "(uss)"))
+ {
+ g_value_init (value, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
+ return TRUE;
+ }
+ }
+ break;
}
return FALSE;
@@ -401,6 +415,51 @@ mcpa_init_value_for_attribute (const McpAccountManager *mcpa,
}
static void
+mcpa_set_attribute (const McpAccountManager *ma,
+ const gchar *account,
+ const gchar *attribute,
+ GVariant *value,
+ McpAttributeFlags flags)
+{
+ McdStorage *self = MCD_STORAGE (ma);
+ McdStorageAccount *sa = ensure_account (self, account);
+
+ 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);
+ }
+}
+
+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);
+
+ g_hash_table_remove (sa->parameters, parameter);
+ g_hash_table_remove (sa->escaped_parameters, parameter);
+
+ if (value != NULL)
+ g_hash_table_insert (sa->parameters, g_strdup (parameter),
+ g_variant_ref_sink (value));
+
+ if (flags & MCP_PARAMETER_FLAG_SECRET)
+ {
+ DEBUG ("flagging %s parameter %s as secret", account, parameter);
+ g_hash_table_add (sa->secrets, g_strdup (parameter));
+ }
+}
+
+static void
set_value (const McpAccountManager *ma,
const gchar *account,
const gchar *key,
@@ -1239,6 +1298,48 @@ mcd_keyfile_get_value (GKeyFile *keyfile,
ret = TRUE;
}
}
+ else if (type == TP_STRUCT_TYPE_SIMPLE_PRESENCE)
+ {
+ gchar **v = g_key_file_get_string_list (keyfile, group,
+ key, NULL, error);
+
+ if (v == NULL)
+ {
+ /* error is already set, do nothing */
+ }
+ else if (g_strv_length (v) != 3)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "Invalid simple-presence structure stored in keyfile");
+ }
+ else
+ {
+ guint64 u;
+ gchar *endptr;
+
+ errno = 0;
+ u = g_ascii_strtoull (v[0], &endptr, 10);
+
+ if (errno != 0 || *endptr != '\0' || u > G_MAXUINT32)
+ {
+ g_set_error (error, TP_ERROR, TP_ERROR_NOT_AVAILABLE,
+ "Invalid presence type stored in keyfile: %s", v[0]);
+ }
+ 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;
+ }
+ }
+
+ g_strfreev (v);
+ }
else
{
gchar *message =
@@ -1695,6 +1796,22 @@ mcd_keyfile_set_value (GKeyFile *keyfile,
g_key_file_set_string_list (keyfile, name, key,
(const gchar * const *) arr->pdata, arr->len);
}
+ else if (G_VALUE_HOLDS (value, TP_STRUCT_TYPE_SIMPLE_PRESENCE))
+ {
+ guint 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,
+ &type,
+ &(strv[1]),
+ &(strv[2]));
+ g_snprintf (printf_buf, sizeof (printf_buf), "%u", type);
+ strv[0] = printf_buf;
+
+ g_key_file_set_string_list (keyfile, name, key, strv, 3);
+ }
else
{
g_warning ("Unexpected param type %s",
@@ -1956,6 +2073,8 @@ plugin_iface_init (McpAccountManagerIface *iface,
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;
diff --git a/src/mcd-storage.h b/src/mcd-storage.h
index a856b290..893a0af3 100644
--- a/src/mcd-storage.h
+++ b/src/mcd-storage.h
@@ -150,6 +150,10 @@ gboolean mcd_keyfile_unescape_value (const gchar *escaped,
GValue *value,
GError **error);
+const gchar *mcd_storage_get_attribute_type (const gchar *attribute);
+gboolean mcd_storage_init_value_for_attribute (GValue *value,
+ const gchar *attribute);
+
G_END_DECLS
#endif /* MCD_STORAGE_H */
diff --git a/tests/Makefile.am b/tests/Makefile.am
index 65e5ebc4..c02550f8 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
@@ -16,7 +16,11 @@ endif
SUBDIRS = . twisted
-TEST_EXECUTABLES = test-value-is-same
+TEST_EXECUTABLES = \
+ test-keyfile \
+ test-value-is-same \
+ $(NULL)
+
NON_TEST_EXECUTABLES = account-store tease-the-minotaur
if ENABLE_GNOME_KEYRING
@@ -32,6 +36,9 @@ TESTS = $(TEST_EXECUTABLES)
test_value_is_same_SOURCES = value-is-same.c
test_value_is_same_LDADD = $(top_builddir)/src/libmcd-convenience.la
+test_keyfile_SOURCES = keyfile.c
+test_keyfile_LDADD = $(top_builddir)/src/libmcd-convenience.la
+
tease_the_minotaur_SOURCES = tease-the-minotaur.c
tease_the_minotaur_LDADD = $(top_builddir)/src/libmcd-convenience.la
diff --git a/tests/keyfile.c b/tests/keyfile.c
new file mode 100644
index 00000000..df891ce5
--- /dev/null
+++ b/tests/keyfile.c
@@ -0,0 +1,351 @@
+/*
+ * Regression test for keyfile (un)escaping
+ *
+ * Copyright © 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
+ *
+ */
+
+#include "config.h"
+
+#include <telepathy-glib/telepathy-glib.h>
+#include <telepathy-glib/telepathy-glib-dbus.h>
+
+#include "mcd-storage.h"
+
+typedef enum {
+ FAILS = 1,
+ NOT_NORMALIZED = 2
+} Flags;
+
+#define SIMPLE_TEST(NAME, GTYPE, CMP, GET) \
+static void \
+test_ ## NAME (void) \
+{ \
+ guint i; \
+\
+ for (i = 0; NAME ## _tests[i].escaped != NULL; i++) \
+ { \
+ gboolean success; \
+ gchar *escaped; \
+ GValue unescaped = G_VALUE_INIT; \
+ GError *error = NULL; \
+\
+ g_value_init (&unescaped, GTYPE); \
+\
+ success = mcd_keyfile_unescape_value (NAME ## _tests[i].escaped, \
+ &unescaped, &error); \
+\
+ if (NAME ## _tests[i].flags & FAILS) \
+ { \
+ if (success || error == NULL) \
+ g_error ("Interpreting '%s' as %s was meant to fail", \
+ NAME ## _tests[i].escaped, g_type_name (GTYPE)); \
+\
+ g_error_free (error); \
+ } \
+ else \
+ { \
+ if (error != NULL) \
+ g_error ("Interpreting '%s' as %s was meant to succeed: %s", \
+ NAME ## _tests[i].escaped, g_type_name (GTYPE), error->message); \
+\
+ if (!success) \
+ g_error ("Interpreting '%s' as %s was meant to succeed", \
+ NAME ## _tests[i].escaped, g_type_name (GTYPE)); \
+\
+ g_assert (success); \
+ CMP (GET (&unescaped), ==, \
+ NAME ## _tests[i].unescaped); \
+\
+ escaped = mcd_keyfile_escape_value (&unescaped); \
+\
+ if (NAME ## _tests[i].flags & NOT_NORMALIZED) \
+ g_assert (escaped != NULL); \
+ else \
+ g_assert_cmpstr (escaped, ==, NAME ## _tests[i].escaped); \
+\
+ g_free (escaped); \
+ } \
+\
+ g_value_unset (&unescaped); \
+ } \
+}
+
+struct {
+ const gchar *escaped;
+ gint32 unescaped;
+ Flags flags;
+} int32_tests[] = {
+ { "-2147483649", 0, FAILS },
+ { "-2147483648", G_MININT32, 0 },
+ { "-2147483647", -2147483647, 0 },
+ { "-1", -1, 0 },
+ { "x", 0, FAILS },
+ { "0", 0, 0 },
+ { "000", 0, NOT_NORMALIZED },
+ { "1", 1, 0 },
+ { "001", 1, NOT_NORMALIZED },
+ { "042", 42, NOT_NORMALIZED },
+ { "2147483647", 2147483647, 0 },
+ { "2147483648", 2147483648, FAILS },
+ { NULL, 0, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ guint32 unescaped;
+ Flags flags;
+} uint32_tests[] = {
+ { "-1", 0, FAILS },
+ { "x", 0, FAILS },
+ { "0", 0, 0 },
+ { "000", 0, NOT_NORMALIZED },
+ { "1", 1, 0 },
+ { "001", 1, NOT_NORMALIZED },
+ { "042", 42, NOT_NORMALIZED },
+ { "2147483647", 2147483647, 0 },
+ { "2147483648", 2147483648u, 0 },
+ { "4294967295", 4294967295u, 0 },
+ { "4294967296", 0, FAILS },
+ { NULL, 0, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ gint64 unescaped;
+ Flags flags;
+} int64_tests[] = {
+#if 0
+ /* This actually "succeeds". tp_g_key_file_get_int64() and _uint64(),
+ * and the copy of them that was merged in GLib, don't detect overflow */
+ { "-9223372036854775809", 0, FAILS },
+#endif
+ { "-9223372036854775808", G_MININT64, 0 },
+ { "-1", -1, 0 },
+ { "0", 0, 0 },
+ { "1", 1, 0 },
+ { "9223372036854775807", G_GINT64_CONSTANT (9223372036854775807), 0 },
+#if 0
+ { "9223372036854775808", 0, FAILS },
+#endif
+ { "x", 0, FAILS },
+ { NULL, 0, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ guint64 unescaped;
+ Flags flags;
+} uint64_tests[] = {
+#if 0
+ { "-1", 0, FAILS },
+#endif
+ { "0", 0, 0 },
+ { "1", 1, 0 },
+ { "9223372036854775807", G_GUINT64_CONSTANT (9223372036854775807), 0 },
+ { "9223372036854775808", G_GUINT64_CONSTANT (9223372036854775808), 0 },
+ { "18446744073709551615", G_GUINT64_CONSTANT (18446744073709551615), 0 },
+#if 0
+ { "18446744073709551616", 0, FAILS },
+#endif
+ { "x", 0, FAILS },
+ { NULL, 0, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ guchar unescaped;
+ Flags flags;
+} byte_tests[] = {
+ { "-1", 0, FAILS },
+ { "x", 0, FAILS },
+ { "0", 0, 0 },
+ { "1", 1, 0 },
+ { "255", 255, 0 },
+ { "256", 0, FAILS },
+ { NULL, 0, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ gboolean unescaped;
+ Flags flags;
+} boolean_tests[] = {
+ { "true", TRUE, 0 },
+ { "false", FALSE, 0 },
+ { "0", FALSE, NOT_NORMALIZED },
+ { "1", TRUE, NOT_NORMALIZED },
+ { "2", 0, FAILS },
+ { "", 0, FAILS },
+ { NULL, 0, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ const gchar *unescaped;
+ Flags flags;
+} string_tests[] = {
+ { "lol", "lol", 0 },
+ { "\\s", " ", 0 },
+ { "\\s ", " ", NOT_NORMALIZED },
+ { "\\t", "\t", 0 },
+ { NULL, NULL, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ const gchar *unescaped;
+ Flags flags;
+} path_tests[] = {
+ { "/", "/", 0 },
+ { "/foo", "/foo", 0 },
+ { "x", NULL, FAILS },
+ { NULL, NULL, 0 }
+};
+
+struct {
+ const gchar *escaped;
+ double unescaped;
+ Flags flags;
+} double_tests[] = {
+ { "0", 0.0, 0 },
+ { "0.5", 0.5, 0 },
+ { "x", 0.0, FAILS },
+ { NULL, 0.0, 0 }
+};
+
+SIMPLE_TEST (int32, G_TYPE_INT, g_assert_cmpint, g_value_get_int)
+SIMPLE_TEST (uint32, G_TYPE_UINT, g_assert_cmpuint, g_value_get_uint)
+SIMPLE_TEST (int64, G_TYPE_INT64, g_assert_cmpint, g_value_get_int64)
+SIMPLE_TEST (uint64, G_TYPE_UINT64, g_assert_cmpuint, g_value_get_uint64)
+SIMPLE_TEST (byte, G_TYPE_UCHAR, g_assert_cmpuint, g_value_get_uchar)
+SIMPLE_TEST (boolean, G_TYPE_BOOLEAN, g_assert_cmpuint, g_value_get_boolean)
+SIMPLE_TEST (string, G_TYPE_STRING, g_assert_cmpstr, g_value_get_string)
+SIMPLE_TEST (path, DBUS_TYPE_G_OBJECT_PATH, g_assert_cmpstr, g_value_get_boxed)
+SIMPLE_TEST (double, G_TYPE_DOUBLE, g_assert_cmpfloat, g_value_get_double)
+
+static void
+test_strv (void)
+{
+ gboolean success;
+ gchar *escaped;
+ GValue unescaped = G_VALUE_INIT;
+ GError *error = NULL;
+ gchar **unescaped_strv;
+
+ g_value_init (&unescaped, G_TYPE_STRV);
+
+ success = mcd_keyfile_unescape_value ("x;\\t;z;", &unescaped, &error);
+
+ g_assert_no_error (error);
+ g_assert (success);
+ unescaped_strv = g_value_get_boxed (&unescaped);
+ g_assert_cmpstr (unescaped_strv[0], ==, "x");
+ g_assert_cmpstr (unescaped_strv[1], ==, "\t");
+ g_assert_cmpstr (unescaped_strv[2], ==, "z");
+ g_assert_cmpstr (unescaped_strv[3], ==, NULL);
+
+ escaped = mcd_keyfile_escape_value (&unescaped);
+ g_assert_cmpstr (escaped, ==, "x;\\t;z;");
+ g_free (escaped);
+
+ g_value_unset (&unescaped);
+}
+
+static void
+test_ao (void)
+{
+ gboolean success;
+ gchar *escaped;
+ GValue unescaped = G_VALUE_INIT;
+ GError *error = NULL;
+ GPtrArray *unescaped_pa;
+
+ g_value_init (&unescaped, TP_ARRAY_TYPE_OBJECT_PATH_LIST);
+
+ success = mcd_keyfile_unescape_value ("/x;/;", &unescaped, &error);
+
+ g_assert_no_error (error);
+ g_assert (success);
+ unescaped_pa = g_value_get_boxed (&unescaped);
+ g_assert_cmpuint (unescaped_pa->len, ==, 2);
+ g_assert_cmpstr (g_ptr_array_index (unescaped_pa, 0), ==, "/x");
+ g_assert_cmpstr (g_ptr_array_index (unescaped_pa, 1), ==, "/");
+
+ escaped = mcd_keyfile_escape_value (&unescaped);
+ g_assert_cmpstr (escaped, ==, "/x;/;");
+ g_free (escaped);
+
+ g_value_unset (&unescaped);
+}
+
+static void
+test_uss (void)
+{
+ gboolean success;
+ gchar *escaped;
+ GValue unescaped = G_VALUE_INIT;
+ GError *error = NULL;
+ GValueArray *unescaped_va;
+
+ g_value_init (&unescaped, TP_STRUCT_TYPE_SIMPLE_PRESENCE);
+
+ success = mcd_keyfile_unescape_value ("2;available;\\;;",
+ &unescaped, &error);
+
+ g_assert_no_error (error);
+ g_assert (success);
+ unescaped_va = g_value_get_boxed (&unescaped);
+ g_assert_cmpuint (g_value_get_uint (unescaped_va->values + 0), ==, 2);
+ g_assert_cmpstr (g_value_get_string (unescaped_va->values + 1), ==,
+ "available");
+ g_assert_cmpstr (g_value_get_string (unescaped_va->values + 2), ==,
+ ";");
+
+ escaped = mcd_keyfile_escape_value (&unescaped);
+ g_assert_cmpstr (escaped, ==, "2;available;\\;;");
+ g_free (escaped);
+
+ g_value_unset (&unescaped);
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ g_test_init (&argc, &argv, NULL);
+ g_test_bug_base ("http://bugs.freedesktop.org/show_bug.cgi?id=");
+
+ g_type_init ();
+
+ g_test_add_func ("/keyfile/int32", test_int32);
+ g_test_add_func ("/keyfile/uint32", test_uint32);
+ g_test_add_func ("/keyfile/int64", test_int64);
+ g_test_add_func ("/keyfile/uint64", test_uint64);
+ g_test_add_func ("/keyfile/string", test_string);
+ g_test_add_func ("/keyfile/byte", test_byte);
+ g_test_add_func ("/keyfile/boolean", test_boolean);
+ g_test_add_func ("/keyfile/double", test_double);
+ g_test_add_func ("/keyfile/path", test_path);
+
+ g_test_add_func ("/keyfile/strv", test_strv);
+ g_test_add_func ("/keyfile/ao", test_ao);
+ g_test_add_func ("/keyfile/uss", test_uss);
+
+ return g_test_run ();
+}
diff --git a/tests/twisted/account-manager/auto-connect.py b/tests/twisted/account-manager/auto-connect.py
index d6269835..a623902c 100644
--- a/tests/twisted/account-manager/auto-connect.py
+++ b/tests/twisted/account-manager/auto-connect.py
@@ -51,6 +51,7 @@ def preseed(q, bus, fake_accounts_service):
'NormalizedName': 'jc.denton@unatco.int',
'Enabled': True,
'ConnectAutomatically': True,
+ # These are in the old format. They'll be combined shortly.
'AutomaticPresenceType': dbus.UInt32(2),
'AutomaticPresenceStatus': 'available',
'AutomaticPresenceMessage': 'My vision is augmented',
@@ -85,7 +86,24 @@ def test(q, bus, unused, **kwargs):
'password': r'\\ionstorm\\',
}
- mc = MC(q, bus)
+ mc = MC(q, bus, wait_for_names=False)
+ mc.wait_for_names(
+ # Migration step: the three separate attributes get combined
+ # (before the names are taken, so we need to expect it here)
+ EventPattern('dbus-method-call',
+ interface=cs.TEST_DBUS_ACCOUNT_SERVICE_IFACE,
+ method='UpdateAttributes',
+ predicate=(lambda e:
+ e.args[0] == account_id and
+ e.args[1] == {'AutomaticPresence':
+ (2, 'available', 'My vision is augmented')} and
+ e.args[2] == {'AutomaticPresence': 0} and # flags
+ set(e.args[3]) == set([ # no particular order
+ 'AutomaticPresenceType',
+ 'AutomaticPresenceStatus',
+ 'AutomaticPresenceMessage',
+ ])))
+ )
request_conn, prop_changed = q.expect_many(
EventPattern('dbus-method-call', method='RequestConnection',
diff --git a/tests/twisted/account-manager/avatar-persist.py b/tests/twisted/account-manager/avatar-persist.py
index f9c28c76..7dedb188 100644
--- a/tests/twisted/account-manager/avatar-persist.py
+++ b/tests/twisted/account-manager/avatar-persist.py
@@ -52,9 +52,8 @@ def preseed(q, bus, fake_accounts_service):
'NormalizedName': 'jc.denton@unatco.int',
'Enabled': True,
'ConnectAutomatically': True,
- 'AutomaticPresenceType': dbus.UInt32(2),
- 'AutomaticPresenceStatus': 'available',
- 'AutomaticPresenceMessage': 'My vision is augmented',
+ 'AutomaticPresence': (dbus.UInt32(2), 'available',
+ 'My vision is augmented'),
'Nickname': 'JC',
'AvatarMime': 'image/jpeg',
'avatar_token': 'Deus Ex',
diff --git a/tests/twisted/account-manager/avatar-refresh.py b/tests/twisted/account-manager/avatar-refresh.py
index a6cb9e18..817a623e 100644
--- a/tests/twisted/account-manager/avatar-refresh.py
+++ b/tests/twisted/account-manager/avatar-refresh.py
@@ -52,9 +52,8 @@ def preseed(q, bus, fake_accounts_service):
'NormalizedName': 'jc.denton@unatco.int',
'Enabled': True,
'ConnectAutomatically': True,
- 'AutomaticPresenceType': dbus.UInt32(2),
- 'AutomaticPresenceStatus': 'available',
- 'AutomaticPresenceMessage': 'My vision is augmented',
+ 'AutomaticPresence': (dbus.UInt32(2), 'available',
+ 'My vision is augmented'),
'Nickname': 'JC',
'AvatarMime': 'image/jpeg',
'avatar_token': 'Deus Ex',
diff --git a/tests/twisted/account-manager/backend-makes-changes.py b/tests/twisted/account-manager/backend-makes-changes.py
index d895dfb6..89eb4c1d 100644
--- a/tests/twisted/account-manager/backend-makes-changes.py
+++ b/tests/twisted/account-manager/backend-makes-changes.py
@@ -132,9 +132,8 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
args=[account_path,
cs.ACCOUNT_IFACE_ADDRESSING + '.URISchemes']),
)
- # FIXME: doesn't work
- #assertEquals(['xmpp'],
- # account.Properties.Get(cs.ACCOUNT_IFACE_ADDRESSING, 'URISchemes'))
+ assertEquals(['xmpp'],
+ account.Properties.Get(cs.ACCOUNT_IFACE_ADDRESSING, 'URISchemes'))
fake_accounts_service.update_attributes(account_tail,
{'ConnectAutomatically': True})
@@ -145,20 +144,19 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
args=[account_tail,
{'ConnectAutomatically': True},
{'ConnectAutomatically': 0}, []]),
- # FIXME: signal not actually emitted
- #EventPattern('dbus-signal',
- # path=account_path,
- # signal='AccountPropertyChanged',
- # interface=cs.ACCOUNT,
- # args=[{'ConnectAutomatically': True}]),
+ EventPattern('dbus-signal',
+ path=account_path,
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ predicate=(lambda e:
+ e.args[0].get('ConnectAutomatically') == True)),
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
signal='AttributeChanged',
args=[account_path, 'ConnectAutomatically']),
)
- # FIXME: doesn't work
- #assertEquals(True,
- # account.Properties.Get(cs.ACCOUNT, 'ConnectAutomatically'))
+ assertEquals(True,
+ account.Properties.Get(cs.ACCOUNT, 'ConnectAutomatically'))
fake_accounts_service.update_attributes(account_tail,
{'Supersedes': [cs.ACCOUNT_PATH_PREFIX + 'ac1/game/altair']})
@@ -174,63 +172,45 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
path=account_path,
signal='AccountPropertyChanged',
interface=cs.ACCOUNT,
- # FIXME: signal is emitted, but doesn't have the new value
- #args=[{'Supersedes':
- # [cs.ACCOUNT_PATH_PREFIX + 'ac1/game/altair']}],
- predicate=(lambda e: 'Supersedes' in e.args[0]),
+ args=[{'Supersedes':
+ [cs.ACCOUNT_PATH_PREFIX + 'ac1/game/altair']}],
),
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
signal='AttributeChanged',
args=[account_path, 'Supersedes']),
)
- # FIXME: doesn't work
- #assertEquals([cs.ACCOUNT_PATH_PREFIX + 'ac1/game/altair'],
- # account.Properties.Get(cs.ACCOUNT, 'Supersedes'))
+ assertEquals([cs.ACCOUNT_PATH_PREFIX + 'ac1/game/altair'],
+ account.Properties.Get(cs.ACCOUNT, 'Supersedes'))
fake_accounts_service.update_attributes(account_tail,
- {'AutomaticPresenceType': cs.PRESENCE_TYPE_HIDDEN,
- 'AutomaticPresenceStatus': 'hidden',
- 'AutomaticPresenceMessage': 'in a haystack or something'})
+ {'AutomaticPresence': (dbus.UInt32(cs.PRESENCE_TYPE_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,
- {'AutomaticPresenceType': cs.PRESENCE_TYPE_HIDDEN,
- 'AutomaticPresenceStatus': 'hidden',
- 'AutomaticPresenceMessage':
- 'in a haystack or something'},
- {'AutomaticPresenceType': 0,
- 'AutomaticPresenceStatus': 0,
- 'AutomaticPresenceMessage': 0},
+ {'AutomaticPresence': (cs.PRESENCE_TYPE_HIDDEN,
+ 'hidden',
+ 'in a haystack or something')},
+ {'AutomaticPresence': 0},
[]]),
- # FIXME: signal not actually emitted: the three parts don't get
- # combined correctly
- #EventPattern('dbus-signal',
- # path=account_path,
- # signal='AccountPropertyChanged',
- # interface=cs.ACCOUNT,
- # args=[{'AutomaticPresence':
- # (cs.PRESENCE_TYPE_HIDDEN, 'hidden',
- # 'in a haystack or something')}]),
EventPattern('dbus-signal',
- path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
- signal='AttributeChanged',
- args=[account_path, 'AutomaticPresenceType']),
- EventPattern('dbus-signal',
- path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
- signal='AttributeChanged',
- args=[account_path, 'AutomaticPresenceStatus']),
+ path=account_path,
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ args=[{'AutomaticPresence':
+ (cs.PRESENCE_TYPE_HIDDEN, 'hidden',
+ 'in a haystack or something')}]),
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
signal='AttributeChanged',
- args=[account_path, 'AutomaticPresenceMessage']),
+ args=[account_path, 'AutomaticPresence']),
)
- # FIXME: doesn't work
- #assertEquals((cs.PRESENCE_TYPE_HIDDEN, 'hidden',
- # 'in a haystack or something'),
- # account.Properties.Get(cs.ACCOUNT, 'AutomaticPresence'))
+ assertEquals((cs.PRESENCE_TYPE_HIDDEN, 'hidden',
+ 'in a haystack or something'),
+ account.Properties.Get(cs.ACCOUNT, 'AutomaticPresence'))
fake_accounts_service.update_attributes(account_tail, {
'DisplayName': 'Ezio\'s IM account'})
@@ -240,13 +220,11 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
signal='AttributesChanged',
args=[account_tail, {'DisplayName': 'Ezio\'s IM account'},
{'DisplayName': 0}, []]),
- # FIXME: signal not actually emitted. Service, Icon, Nickname
- # probably have the same bug.
- #EventPattern('dbus-signal',
- # path=account_path,
- # signal='AccountPropertyChanged',
- # interface=cs.ACCOUNT,
- # args=[{'DisplayName': 'Ezio\'s IM account'}]),
+ EventPattern('dbus-signal',
+ path=account_path,
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ args=[{'DisplayName': 'Ezio\'s IM account'}]),
EventPattern('dbus-signal',
path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
signal='AttributeChanged',
@@ -255,6 +233,48 @@ def test(q, bus, mc, fake_accounts_service=None, **kwargs):
assertEquals("Ezio's IM account",
account.Properties.Get(cs.ACCOUNT, 'DisplayName'))
+ fake_accounts_service.update_attributes(account_tail, {
+ 'Icon': 'im-machiavelli'})
+ q.expect_many(
+ EventPattern('dbus-signal',
+ path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
+ signal='AttributesChanged',
+ args=[account_tail, {'Icon': 'im-machiavelli'},
+ {'Icon': 0}, []]),
+ EventPattern('dbus-signal',
+ path=account_path,
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ args=[{'Icon': 'im-machiavelli'}]),
+ EventPattern('dbus-signal',
+ path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
+ signal='AttributeChanged',
+ args=[account_path, 'Icon']),
+ )
+ assertEquals('im-machiavelli',
+ account.Properties.Get(cs.ACCOUNT, 'Icon'))
+
+ fake_accounts_service.update_attributes(account_tail, {
+ 'Service': 'machiavelli-talk'})
+ q.expect_many(
+ EventPattern('dbus-signal',
+ path=cs.TEST_DBUS_ACCOUNT_SERVICE_PATH,
+ signal='AttributesChanged',
+ args=[account_tail, {'Service': 'machiavelli-talk'},
+ {'Service': 0}, []]),
+ EventPattern('dbus-signal',
+ path=account_path,
+ signal='AccountPropertyChanged',
+ interface=cs.ACCOUNT,
+ args=[{'Service': 'machiavelli-talk'}]),
+ EventPattern('dbus-signal',
+ path=cs.TEST_DBUS_ACCOUNT_PLUGIN_PATH,
+ signal='AttributeChanged',
+ args=[account_path, 'Service']),
+ )
+ assertEquals('machiavelli-talk',
+ account.Properties.Get(cs.ACCOUNT, 'Service'))
+
fake_accounts_service.update_parameters(account_tail, {
'password': 'high profile'}, flags={'password': cs.PARAM_FLAG_SECRET})
q.expect_many(
diff --git a/tests/twisted/account-storage/default-keyring-storage.py b/tests/twisted/account-storage/default-keyring-storage.py
index 903df862..f41bc170 100644
--- a/tests/twisted/account-storage/default-keyring-storage.py
+++ b/tests/twisted/account-storage/default-keyring-storage.py
@@ -242,6 +242,7 @@ 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)
@@ -292,6 +293,7 @@ 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)
diff --git a/tests/twisted/dbus-account-plugin.c b/tests/twisted/dbus-account-plugin.c
index c7690fbc..16b1c9c0 100644
--- a/tests/twisted/dbus-account-plugin.c
+++ b/tests/twisted/dbus-account-plugin.c
@@ -428,19 +428,21 @@ test_dbus_account_plugin_process_attributes (TestDBusAccountPlugin *self,
(stored == NULL ||
!g_variant_equal (value, stored)))
{
- gchar *escaped = mcp_account_manager_escape_variant_for_keyfile (
- self->feedback, value);
+ gchar *repr = g_variant_print (value, TRUE);
+ guint32 flags;
- DEBUG ("%s changed to (escaped) %s, signalling MC",
- attr, escaped);
+ DEBUG ("%s changed to %s, signalling MC", attr, repr);
+ g_free (repr);
+
+ if (!g_variant_lookup (attr_flags, attr, "u", &flags))
+ flags = 0;
g_hash_table_insert (account->attributes,
g_strdup (attr), g_variant_ref (value));
- mcp_account_manager_set_value (self->feedback,
- account_name, attr, escaped);
+ 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);
- g_free (escaped);
g_dbus_connection_emit_signal (self->bus, NULL,
TEST_DBUS_ACCOUNT_PLUGIN_PATH, TEST_DBUS_ACCOUNT_PLUGIN_IFACE,
@@ -462,8 +464,8 @@ test_dbus_account_plugin_process_attributes (TestDBusAccountPlugin *self,
DEBUG ("%s deleted", attr);
g_hash_table_remove (account->attributes, attr);
- mcp_account_manager_set_value (self->feedback,
- account_name, attr, NULL);
+ 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);
@@ -538,17 +540,19 @@ test_dbus_account_plugin_process_parameters (TestDBusAccountPlugin *self,
(stored == NULL ||
!g_variant_equal (value, stored)))
{
+ guint32 flags;
+
+ if (!g_variant_lookup (param_flags, param, "u", &flags))
+ flags = 0;
+
g_hash_table_insert (account->parameters,
g_strdup (param), g_variant_ref (value));
- escaped = mcp_account_manager_escape_variant_for_keyfile (
- self->feedback, value);
key = g_strdup_printf ("param-%s", param);
- mcp_account_manager_set_value (self->feedback,
- account_name, key, escaped);
+ 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);
- g_free (escaped);
g_dbus_connection_emit_signal (self->bus, NULL,
TEST_DBUS_ACCOUNT_PLUGIN_PATH,
@@ -607,8 +611,8 @@ 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_value (self->feedback,
- account_name, key, NULL);
+ 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);
diff --git a/tests/twisted/dispatcher/create-at-startup.py b/tests/twisted/dispatcher/create-at-startup.py
index c3c2a173..e0d73722 100644
--- a/tests/twisted/dispatcher/create-at-startup.py
+++ b/tests/twisted/dispatcher/create-at-startup.py
@@ -49,9 +49,7 @@ def preseed(q, bus, fake_accounts_service):
'NormalizedName': 'jc.denton@unatco.int',
'Enabled': True,
'ConnectAutomatically': False,
- 'AutomaticPresenceType': dbus.UInt32(2),
- 'AutomaticPresenceStatus': 'available',
- 'AutomaticPresenceMessage': '',
+ 'AutomaticPresence': (dbus.UInt32(2), 'available', ''),
})
fake_accounts_service.update_parameters(account_id, untyped={
'account': 'jc.denton@unatco.int',
diff --git a/util/mc-tool.c b/util/mc-tool.c
index 1bd4c067..59a1a919 100644
--- a/util/mc-tool.c
+++ b/util/mc-tool.c
@@ -425,6 +425,7 @@ typedef enum {
GET_PARAM,
GET_STRING,
GET_BOOLEAN,
+ GET_PRESENCE,
GET_PRESENCE_TYPE,
GET_PRESENCE_STATUS,
GET_PRESENCE_MESSAGE
@@ -474,6 +475,8 @@ getter_list_init(void)
tp_account_get_connect_automatically);
getter_list_add("NormalizedName", GET_STRING, tp_account_get_normalized_name);
+ getter_list_add("AutomaticPresence",
+ GET_PRESENCE, tp_account_get_automatic_presence);
getter_list_add("AutomaticPresenceType",
GET_PRESENCE_TYPE, tp_account_get_automatic_presence);
getter_list_add("AutomaticPresenceStatus",
@@ -894,6 +897,16 @@ command_get (TpAccount *account)
else if (getter->type == GET_BOOLEAN) {
puts(getboolean(account) ? "true" : "false");
}
+ else if (getter->type == GET_PRESENCE)
+ {
+ struct presence presence;
+
+ presence.type = getpresence(account, &presence.status,
+ &presence.message);
+ printf ("(%u, \"%s\", \"%s\")\n", presence.type,
+ presence.status, presence.message);
+ free_presence (&presence);
+ }
else if (getter->type == GET_PRESENCE_TYPE ||
getter->type == GET_PRESENCE_STATUS ||
getter->type == GET_PRESENCE_MESSAGE) {