From d90e8ec4d400097010c2dee7ad43747a5cb8e8cf Mon Sep 17 00:00:00 2001 From: Simon McVittie Date: Mon, 3 Feb 2014 20:22:32 +0000 Subject: [PATCH 1/3] Require account plugins to provide the ability to list parameters Bug: https://bugs.freedesktop.org/show_bug.cgi?id=71093 --- mission-control-plugins/account-storage.c | 103 ++++++++++++++++++++++++++++-- mission-control-plugins/account-storage.h | 13 ++++ src/mcd-account-manager-default.c | 57 +++++++++++++++++ src/mcd-storage.c | 48 ++++++++++++++ tests/twisted/dbus-account-plugin.c | 59 ++++++++++++++++- tests/twisted/mcp-account-diversion.c | 44 +++++++++++++ 6 files changed, 317 insertions(+), 7 deletions(-) diff --git a/mission-control-plugins/account-storage.c b/mission-control-plugins/account-storage.c index 288df07..d93d2c1 100644 --- a/mission-control-plugins/account-storage.c +++ b/mission-control-plugins/account-storage.c @@ -67,6 +67,8 @@ * iface->create = foo_plugin_create; * 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; * } @@ -205,6 +207,14 @@ default_set_parameter (McpAccountStorage *storage, return MCP_ACCOUNT_STORAGE_SET_RESULT_FAILED; } +static gchar ** +default_list_untyped_parameters (McpAccountStorage *storage, + McpAccountManager *am, + const gchar *account) +{ + return NULL; +} + static void class_init (gpointer klass, gpointer data) @@ -222,6 +232,7 @@ class_init (gpointer klass, 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) { @@ -258,8 +269,9 @@ class_init (gpointer klass, * or mcp_account_storage_get_parameter() will return the new value * when queried. * - * Note that mcp_account_manager_get_parameter() and - * mcp_account_manager_set_parameter() do not use the + * 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. * * Should not be fired until mcp_account_storage_ready() has been called @@ -475,7 +487,7 @@ mcp_account_storage_get_attribute (McpAccountStorage *storage, * @am: an #McpAccountManager instance * @account: the unique name of the account * @parameter: the name of a parameter, e.g. "require-encryption" - * @type: the expected type of @parameter, as a hint for + * @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 * @@ -489,6 +501,9 @@ mcp_account_storage_get_attribute (McpAccountStorage *storage, * 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 */ @@ -502,9 +517,12 @@ mcp_account_storage_get_parameter (McpAccountStorage *storage, { McpAccountStorageIface *iface = MCP_ACCOUNT_STORAGE_GET_IFACE (storage); - SDEBUG (storage, "%s.%s (type '%.*s')", account, parameter, - (int) g_variant_type_get_string_length (type), - g_variant_type_peek_string (type)); + 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_parameter != NULL, FALSE); @@ -513,6 +531,79 @@ mcp_account_storage_get_parameter (McpAccountStorage *storage, } /** + * mcp_account_storage_list_typed_parameters: + * @storage: an #McpAccountStorage instance + * @am: an #McpAccountManager instance + * @account: the unique name of the account + * + * List the names of all parameters whose corresponding types are known. + * + * Ideally, all parameters are typed parameters, 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 untyped parameters, + * returned by mcp_account_storage_list_untyped_parameters(). + * + * 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_list_untyped_parameters: + * @storage: an #McpAccountStorage instance + * @am: an #McpAccountManager instance + * @account: the unique name of the account + * + * List the names of all parameters whose types are unknown. + * The values are not listed, because interpreting the value + * correctly requires a type. + * + * See mcp_account_storage_list_typed_parameters() for more on + * typed vs. untyped parameters. + * + * The default implementation just returns %NULL, and is appropriate + * for "legacy-free" backends that store a type with every parameter. + * + * 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 + */ +gchar ** +mcp_account_storage_list_untyped_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_untyped_parameters != NULL, NULL); + + return iface->list_untyped_parameters (storage, am, account); +} + +/** * mcp_account_storage_set_attribute: * @storage: an #McpAccountStorage instance * @am: an #McpAccountManager instance diff --git a/mission-control-plugins/account-storage.h b/mission-control-plugins/account-storage.h index fd6daee..c1a1ece 100644 --- a/mission-control-plugins/account-storage.h +++ b/mission-control-plugins/account-storage.h @@ -155,6 +155,13 @@ struct _McpAccountStorageIface const gchar *parameter, GVariant *val, McpParameterFlags flags); + + gchar **(*list_typed_parameters) (McpAccountStorage *storage, + McpAccountManager *am, + const gchar *account); + gchar **(*list_untyped_parameters) (McpAccountStorage *storage, + McpAccountManager *am, + const gchar *account); }; /* virtual methods */ @@ -217,6 +224,12 @@ GVariant *mcp_account_storage_get_parameter (McpAccountStorage *storage, 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); McpAccountStorageSetResult mcp_account_storage_set_attribute ( McpAccountStorage *storage, diff --git a/src/mcd-account-manager-default.c b/src/mcd-account-manager-default.c index e9f2bf2..f4abd84 100644 --- a/src/mcd-account-manager-default.c +++ b/src/mcd-account-manager-default.c @@ -305,6 +305,9 @@ get_parameter (McpAccountStorage *self, 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) @@ -314,6 +317,58 @@ get_parameter (McpAccountStorage *self, 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 (McpAccountStorage *self, McpAccountManager *am, @@ -981,6 +1036,8 @@ account_storage_iface_init (McpAccountStorageIface *iface, 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; diff --git a/src/mcd-storage.c b/src/mcd-storage.c index 828d5a1..1db0717 100644 --- a/src/mcd-storage.c +++ b/src/mcd-storage.c @@ -1942,6 +1942,9 @@ mcd_storage_add_account_from_plugin (McdStorage *self, GError **error) { McpAccountStorage *other = g_hash_table_lookup (self->accounts, account); + McpAccountManager *api = (McpAccountManager *) self; + gchar **typed_parameters; + gchar **untyped_parameters; if (other != NULL) { @@ -1956,5 +1959,50 @@ mcd_storage_add_account_from_plugin (McdStorage *self, 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; } diff --git a/tests/twisted/dbus-account-plugin.c b/tests/twisted/dbus-account-plugin.c index 446a2ad..36f7891 100644 --- a/tests/twisted/dbus-account-plugin.c +++ b/tests/twisted/dbus-account-plugin.c @@ -1017,7 +1017,7 @@ test_dbus_account_plugin_get_parameter (McpAccountStorage *storage, { return g_variant_ref (v); } - else if (s != NULL) + else if (s != NULL && type != NULL) { return mcp_account_manager_unescape_variant_from_keyfile (am, s, type, NULL); @@ -1028,6 +1028,59 @@ test_dbus_account_plugin_get_parameter (McpAccountStorage *storage, } } +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_return_val_if_fail (self->active, NULL); + g_return_val_if_fail (account != NULL, NULL); + + arr = g_ptr_array_sized_new (g_hash_table_size (account->parameters) + 1); + + g_hash_table_iter_init (&iter, account->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 ** +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; + + g_return_val_if_fail (self->active, NULL); + g_return_val_if_fail (account != NULL, NULL); + + arr = g_ptr_array_sized_new ( + g_hash_table_size (account->untyped_parameters) + 1); + + g_hash_table_iter_init (&iter, account->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 McpAccountStorageSetResult test_dbus_account_plugin_set_attribute (McpAccountStorage *storage, McpAccountManager *am, @@ -1500,6 +1553,10 @@ account_storage_iface_init (McpAccountStorageIface *iface) 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; diff --git a/tests/twisted/mcp-account-diversion.c b/tests/twisted/mcp-account-diversion.c index 466d3ee..0e8bfbc 100644 --- a/tests/twisted/mcp-account-diversion.c +++ b/tests/twisted/mcp-account-diversion.c @@ -238,6 +238,11 @@ _get_parameter (McpAccountStorage *self, 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; + key = g_strdup_printf ("param-%s", parameter); v = g_key_file_get_value (adp->keyfile, account, key, NULL); g_free (key); @@ -250,6 +255,43 @@ _get_parameter (McpAccountStorage *self, 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_str_has_prefix (keys[i], "param-")) + g_ptr_array_add (arr, g_strdup (keys[i] + 6)); + } + + g_strfreev (keys); + g_ptr_array_add (arr, NULL); + return (gchar **) g_ptr_array_free (arr, FALSE); +} + static gboolean _commit (McpAccountStorage *self, McpAccountManager *am, const gchar *account_name); @@ -386,6 +428,8 @@ account_storage_iface_init (McpAccountStorageIface *iface, 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; -- 1.9.rc1