summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimon McVittie <simon.mcvittie@collabora.co.uk>2013-10-15 18:10:00 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2013-10-29 11:27:37 +0000
commit76e09aa96406ed8219769c497ba50b9c8ca56e9b (patch)
tree81d1382a15eb8f24a99608b25879ff07a442167a
parent62dda025c5961fc05705eccac7e753f730259f7b (diff)
Call IdentifyAccount to get new accounts' names
It's exposed through the plugin API so that exemplary plugins can use the same utility functions to decide how to name accounts for the ::created signal, if they want to. Reviewed-by: Guillaume Desmottes <guillaume.desmottes@collabora.co.uk> Bug: https://bugs.freedesktop.org/show_bug.cgi?id=34640
-rw-r--r--configure.ac4
-rw-r--r--mission-control-plugins/account.c42
-rw-r--r--mission-control-plugins/account.h11
-rw-r--r--mission-control-plugins/implementation.h11
-rw-r--r--src/mcd-account-manager.c136
-rw-r--r--src/mcd-storage.c78
-rw-r--r--tests/twisted/account-manager/create-with-properties.py5
7 files changed, 234 insertions, 53 deletions
diff --git a/configure.ac b/configure.ac
index fc78f6a1..99bcf130 100644
--- a/configure.ac
+++ b/configure.ac
@@ -220,7 +220,7 @@ AC_DEFINE([TP_SEAL_ENABLE], [], [Define to hide deprecated struct fields])
AC_DEFINE([TP_DISABLE_SINGLE_INCLUDE], [], [Avoid individual headers])
PKG_CHECK_MODULES([GLIB],
- [glib-2.0 >= 2.32, gobject-2.0, gmodule-no-export-2.0, gio-2.0])
+ [glib-2.0 >= 2.36, gobject-2.0, gmodule-no-export-2.0, gio-2.0])
PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0],
[
@@ -231,7 +231,7 @@ PKG_CHECK_MODULES([GIO_UNIX], [gio-unix-2.0],
[])
AC_DEFINE([GLIB_VERSION_MIN_REQUIRED], [GLIB_VERSION_2_30], [Ignore post 2.30 deprecations])
-AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_32], [Prevent post 2.32 APIs])
+AC_DEFINE([GLIB_VERSION_MAX_ALLOWED], [GLIB_VERSION_2_36], [Prevent post 2.36 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])
diff --git a/mission-control-plugins/account.c b/mission-control-plugins/account.c
index 62318d44..1744ef6a 100644
--- a/mission-control-plugins/account.c
+++ b/mission-control-plugins/account.c
@@ -290,6 +290,7 @@ mcp_account_manager_parameter_make_secret (const McpAccountManager *mcpa,
* 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.
@@ -308,6 +309,47 @@ mcp_account_manager_get_unique_name (McpAccountManager *mcpa,
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);
+}
+
+/**
+ * Returns: (transfer full): a newly allocated string, free with g_free()
+ */
+gchar *
+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->identify_account_async != NULL, NULL);
+ g_return_val_if_fail (iface->identify_account_finish != NULL, NULL);
+
+ return iface->identify_account_finish (mcpa, res, error);
+}
+
/**
* mcp_account_manager_escape_value_from_keyfile:
* @mcpa: a #McpAccountManager
diff --git a/mission-control-plugins/account.h b/mission-control-plugins/account.h
index a4763427..4015457b 100644
--- a/mission-control-plugins/account.h
+++ b/mission-control-plugins/account.h
@@ -101,6 +101,17 @@ gboolean mcp_account_manager_init_value_for_attribute (
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
#endif
diff --git a/mission-control-plugins/implementation.h b/mission-control-plugins/implementation.h
index 29d29377..2ad28938 100644
--- a/mission-control-plugins/implementation.h
+++ b/mission-control-plugins/implementation.h
@@ -128,6 +128,17 @@ struct _McpAccountManagerIface {
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/src/mcd-account-manager.c b/src/mcd-account-manager.c
index 0a19de1f..029c0c28 100644
--- a/src/mcd-account-manager.c
+++ b/src/mcd-account-manager.c
@@ -105,6 +105,9 @@ typedef struct
typedef struct
{
McdAccountManager *account_manager;
+ gchar *cm_name;
+ gchar *protocol_name;
+ gchar *display_name;
GHashTable *parameters;
GHashTable *properties;
McdGetAccountCb callback;
@@ -650,6 +653,10 @@ mcd_create_account_data_free (McdCreateAccountData *cad)
if (G_UNLIKELY (cad->error))
g_error_free (cad->error);
+ g_free (cad->cm_name);
+ g_free (cad->protocol_name);
+ g_free (cad->display_name);
+
g_slice_free (McdCreateAccountData, cad);
}
@@ -781,91 +788,120 @@ 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;
- McdAccount *account;
- gchar *unique_name = NULL;
+ McdStorage *storage = MCD_STORAGE (source_object);
+ McdCreateAccountData *cad = user_data;
const gchar *provider;
- GError *e = NULL;
- const gchar *id;
+ gchar *id;
+ gchar *unique_name;
+ McdAccount *account;
- 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,
+ provider = tp_asv_get_string (cad->properties,
TP_PROP_ACCOUNT_INTERFACE_STORAGE_STORAGE_PROVIDER);
- id = tp_asv_get_string (params, "account");
-
- if (id == NULL)
- id = "account";
-
unique_name = mcd_storage_create_account (storage, provider,
- manager, protocol, id,
- &e);
+ cad->cm_name, cad->protocol_name,
+ id, &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);
g_free (unique_name);
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_new (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->properties = (properties ? g_hash_table_ref (properties) : NULL);
+ cad->callback = callback;
+ cad->user_data = user_data;
+ cad->destroy = destroy;
+ cad->error = NULL;
+
+ 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
diff --git a/src/mcd-storage.c b/src/mcd-storage.c
index dfe972d3..d52e3456 100644
--- a/src/mcd-storage.c
+++ b/src/mcd-storage.c
@@ -611,6 +611,82 @@ unique_name (const McpAccountManager *ma,
return NULL;
}
+static void
+identify_account_cb (TpProxy *proxy,
+ const gchar *identification,
+ const GError *error,
+ gpointer task,
+ GObject *weak_object G_GNUC_UNUSED)
+{
+ if (error == NULL)
+ {
+ g_task_return_pointer (task, g_strdup (identification), g_free);
+ }
+ else if (g_error_matches (error, TP_ERROR, TP_ERROR_NOT_IMPLEMENTED) ||
+ g_error_matches (error, DBUS_GERROR, DBUS_GERROR_SERVICE_UNKNOWN))
+ {
+ g_task_return_pointer (task, g_strdup (g_task_get_task_data (task)),
+ g_free);
+ }
+ else
+ {
+ g_task_return_error (task, g_error_copy (error));
+ }
+}
+
+static gchar *
+identify_account_finish (McpAccountManager *mcpa,
+ GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (g_task_is_valid (result, mcpa), NULL);
+
+ return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+identify_account_async (McpAccountManager *mcpa,
+ const gchar *manager,
+ const gchar *protocol_name,
+ GVariant *parameters,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ McdStorage *self = MCD_STORAGE (mcpa);
+ GError *error = NULL;
+ TpProtocol *protocol;
+ GTask *task;
+ GValue value = G_VALUE_INIT;
+ const gchar *base;
+
+ task = g_task_new (self, cancellable, callback, user_data);
+
+ /* in case IdentifyAccount fails and we need to make something up */
+ if (!g_variant_lookup (parameters, "account", "&s", &base))
+ base = "account";
+
+ g_task_set_task_data (task, g_strdup (base), g_free);
+
+ protocol = tp_protocol_new (self->dbusd, manager, protocol_name,
+ NULL, &error);
+
+ if (protocol == NULL)
+ {
+ g_task_return_error (task, error);
+ g_object_unref (task);
+ return;
+ }
+
+ 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)
@@ -2062,6 +2138,8 @@ plugin_iface_init (McpAccountManagerIface *iface,
iface->is_secret = is_secret;
iface->make_secret = make_secret;
iface->unique_name = unique_name;
+ iface->identify_account_async = identify_account_async;
+ iface->identify_account_finish = identify_account_finish;
iface->list_keys = list_keys;
iface->escape_value_for_keyfile = mcpa_escape_value_for_keyfile;
iface->escape_variant_for_keyfile = mcpa_escape_variant_for_keyfile;
diff --git a/tests/twisted/account-manager/create-with-properties.py b/tests/twisted/account-manager/create-with-properties.py
index 8d02e2d5..fb276c48 100644
--- a/tests/twisted/account-manager/create-with-properties.py
+++ b/tests/twisted/account-manager/create-with-properties.py
@@ -50,7 +50,7 @@ def test(q, bus, mc):
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')
simulated_cm = SimulatedConnectionManager(q, bus)
@@ -94,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