diff options
author | Claudio Saavedra <csaavedra@igalia.com> | 2013-02-19 13:16:55 +0200 |
---|---|---|
committer | Claudio Saavedra <csaavedra@igalia.com> | 2013-03-05 08:15:23 +0200 |
commit | 1f50ff47f0ea156e43d8b0ef4977f0b5a2e6ce48 (patch) | |
tree | a8973325969bfe183bfccd38b21200ef5070ba9d /lib/ephy-profile-utils.c | |
parent | e9a3741f4039cfdb9b05ac2caf7cc642fa69b608 (diff) | |
download | epiphany-1f50ff47f0ea156e43d8b0ef4977f0b5a2e6ce48.tar.gz |
ephy-profile-utils: migrate ephy_profile_utils_store/query_form_auth_data() to libsecret
We add a new SecretSchema that is specific to epiphany and intended
solely to store passwords for webforms. This is a better approach than
hacking the server url in order to store the names of the forms in it.
These methods are only used by EphyWebView to store the passwords and
to retrieve the password when there is a cache match and by one of the
early stages of password migration in the profile-migrator. If only this
patch is applied, it is likely that only newly saved patchs will work
properly, but others will remain intact.
https://bugzilla.gnome.org/show_bug.cgi?id=679918
Diffstat (limited to 'lib/ephy-profile-utils.c')
-rw-r--r-- | lib/ephy-profile-utils.c | 211 |
1 files changed, 166 insertions, 45 deletions
diff --git a/lib/ephy-profile-utils.c b/lib/ephy-profile-utils.c index 2c685e05f..5a8f1a33b 100644 --- a/lib/ephy-profile-utils.c +++ b/lib/ephy-profile-utils.c @@ -25,10 +25,27 @@ #include "ephy-debug.h" #include "ephy-file-helpers.h" +#include <glib/gi18n.h> #include <libsoup/soup.h> #define PROFILE_MIGRATION_FILE ".migrated" +const SecretSchema* +ephy_profile_get_form_password_schema (void) +{ + static const SecretSchema schema = { + "org.epiphany.FormPassword", SECRET_SCHEMA_NONE, + { + { URI_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING }, + { FORM_USERNAME_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING }, + { FORM_PASSWORD_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING }, + { USERNAME_KEY, SECRET_SCHEMA_ATTRIBUTE_STRING }, + { "NULL", 0 }, + } + }; + return &schema; +} + int ephy_profile_utils_get_migration_version () { @@ -89,17 +106,7 @@ ephy_profile_utils_set_migration_version (int version) } static void -store_form_password_cb (GnomeKeyringResult result, - guint32 id, - gpointer data) -{ - /* FIXME: should we do anything if the operation failed? */ -} - -static void -normalize_and_prepare_uri (SoupURI *uri, - const char *form_username, - const char *form_password) +normalize_and_prepare_uri (SoupURI *uri) { g_return_if_fail (uri != NULL); @@ -110,26 +117,52 @@ normalize_and_prepare_uri (SoupURI *uri, soup_uri_set_scheme (uri, SOUP_URI_SCHEME_HTTP); soup_uri_set_path (uri, "/"); +} - /* Store the form login and password names encoded in the - * URL. A bit of an abuse of keyring, but oh well */ - soup_uri_set_query_from_fields (uri, - FORM_USERNAME_KEY, - form_username, - FORM_PASSWORD_KEY, - form_password, +static GHashTable * +ephy_profile_utils_get_attributes_table (const char *uri, + const char *field_username, + const char *field_password, + const char *username) +{ + return secret_attributes_build (EPHY_FORM_PASSWORD_SCHEMA, + URI_KEY, uri, + FORM_USERNAME_KEY, field_username, + FORM_PASSWORD_KEY, field_password, + username ? USERNAME_KEY : NULL, username, NULL); } +static void +store_form_password_cb (SecretService *service, + GAsyncResult *res, + GSimpleAsyncResult *async) +{ + GError *error = NULL; + + secret_service_store_finish (service, res, &error); + if (error != NULL) + g_simple_async_result_take_error (async, error); + + g_simple_async_result_complete (async); + g_object_unref (async); +} + void _ephy_profile_utils_store_form_auth_data (const char *uri, const char *form_username, const char *form_password, const char *username, - const char *password) + const char *password, + GAsyncReadyCallback callback, + gpointer userdata) { SoupURI *fake_uri; char *fake_uri_str; + SecretValue *value; + GHashTable *attributes; + char *label; + GSimpleAsyncResult *res; g_return_if_fail (uri); g_return_if_fail (form_username); @@ -138,38 +171,119 @@ _ephy_profile_utils_store_form_auth_data (const char *uri, g_return_if_fail (password); fake_uri = soup_uri_new (uri); + if (fake_uri == NULL) return; - normalize_and_prepare_uri (fake_uri, form_username, form_password); - fake_uri_str = soup_uri_to_string (fake_uri, FALSE); + res = g_simple_async_result_new (NULL, callback, userdata, + _ephy_profile_utils_store_form_auth_data); - gnome_keyring_set_network_password (NULL, - username, - NULL, - fake_uri_str, - NULL, - fake_uri->scheme, - NULL, - fake_uri->port, - password, - (GnomeKeyringOperationGetIntCallback)store_form_password_cb, - NULL, - NULL); + normalize_and_prepare_uri (fake_uri); + fake_uri_str = soup_uri_to_string (fake_uri, FALSE); + value = secret_value_new (password, -1, "text/plain"); + attributes = ephy_profile_utils_get_attributes_table (fake_uri_str, form_username, + form_password, username); + /* Translators: The first %s is the username and the second one is the + * hostname where this is happening. Example: gnome@gmail.com and + * mail.google.com. + */ + label = g_strdup_printf (_("Password for %s in a form in %s"), + username, fake_uri_str); + secret_service_store (NULL, EPHY_FORM_PASSWORD_SCHEMA, + attributes, NULL, label, value, + NULL, + (GAsyncReadyCallback)store_form_password_cb, + g_object_ref (res)); + + g_free (label); + secret_value_unref (value); + g_hash_table_unref (attributes); soup_uri_free (fake_uri); g_free (fake_uri_str); + g_object_unref (res); +} + + +gboolean +_ephy_profile_utils_store_form_auth_data_finish (GAsyncResult *result, + GError **error) +{ + g_return_val_if_fail (error == NULL || *error == NULL, FALSE); + g_return_val_if_fail (g_simple_async_result_is_valid (result, NULL, _ephy_profile_utils_store_form_auth_data), FALSE); + + return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error); +} + +typedef struct +{ + EphyQueryFormDataCallback callback; + gpointer data; + GDestroyNotify destroy_data; +} EphyProfileQueryClosure; + +static void +ephy_profile_query_closure_free (EphyProfileQueryClosure *closure) +{ + if (closure->destroy_data) + closure->destroy_data (closure->data); + + g_slice_free (EphyProfileQueryClosure, closure); +} + +static void +search_form_data_cb (SecretService *service, + GAsyncResult *res, + EphyProfileQueryClosure *closure) +{ + GList *results; + SecretItem *item; + const char* username = NULL, *password = NULL; + SecretValue *value = NULL; + GHashTable *attributes = NULL; + GError *error = NULL; + + results = secret_service_search_finish (service, res, &error); + if (error) { + g_warning ("Couldn't retrieve form data: %s", error->message); + g_error_free (error); + goto out; + } + + if (!results) + goto out; + + item = (SecretItem*)results->data; + attributes = secret_item_get_attributes (item); + username = g_hash_table_lookup (attributes, USERNAME_KEY); + value = secret_item_get_secret (item); + password = secret_value_get (value, NULL); + + g_list_free_full (results, (GDestroyNotify)g_object_unref); + +out: + if (closure->callback) + closure->callback (username, password, closure->data); + + if (value) + secret_value_unref (value); + if (attributes) + g_hash_table_unref (attributes); + + ephy_profile_query_closure_free (closure); } void _ephy_profile_utils_query_form_auth_data (const char *uri, const char *form_username, const char *form_password, - GnomeKeyringOperationGetListCallback callback, + EphyQueryFormDataCallback callback, gpointer data, GDestroyNotify destroy_data) { SoupURI *key; char *key_str; + EphyProfileQueryClosure *closure; + GHashTable *attributes; g_return_if_fail (uri); g_return_if_fail (form_username); @@ -178,21 +292,28 @@ _ephy_profile_utils_query_form_auth_data (const char *uri, key = soup_uri_new (uri); g_return_if_fail (key); - normalize_and_prepare_uri (key, form_username, form_password); + normalize_and_prepare_uri (key); key_str = soup_uri_to_string (key, FALSE); + attributes = ephy_profile_utils_get_attributes_table (key_str, form_username, + form_password, NULL); + + closure = g_slice_new0 (EphyProfileQueryClosure); + closure->callback = callback; + closure->data = data; + closure->destroy_data = destroy_data; + LOG ("Querying Keyring: %s", key_str); - gnome_keyring_find_network_password (NULL, - NULL, - key_str, - NULL, - NULL, - NULL, - 0, - callback, - data, - destroy_data); + + secret_service_search (NULL, + EPHY_FORM_PASSWORD_SCHEMA, + attributes, + SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS, + NULL, (GAsyncReadyCallback)search_form_data_cb, + closure); + + g_hash_table_unref (attributes); soup_uri_free (key); g_free (key_str); } |