diff options
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | embed/ephy-web-view.c | 44 | ||||
-rw-r--r-- | lib/ephy-profile-migrator.c | 9 | ||||
-rw-r--r-- | lib/ephy-profile-utils.c | 211 | ||||
-rw-r--r-- | lib/ephy-profile-utils.h | 39 |
5 files changed, 216 insertions, 89 deletions
diff --git a/configure.ac b/configure.ac index 736cd8560..1f51c4c1d 100644 --- a/configure.ac +++ b/configure.ac @@ -87,6 +87,7 @@ WEBKIT_GTK_REQUIRED=1.11.5 LIBSOUP_REQUIRED=2.41.3 GNOME_DESKTOP_REQUIRED=2.91.2 GNOME_KEYRING_REQUIRED=2.26.0 +LIBSECRET_REQUIRED=0.14 GSETTINGS_DESKTOP_SCHEMAS_REQUIRED=0.0.1 LIBNOTIFY_REQUIRED=0.5.1 GCR_REQUIRED=3.5.5 @@ -127,6 +128,7 @@ PKG_CHECK_MODULES([DEPENDENCIES], [ libxslt >= $LIBXSLT_REQUIRED $WEBKIT_GTK_PC_NAME >= $WEBKIT_GTK_REQUIRED libsoup-2.4 >= $LIBSOUP_REQUIRED + libsecret-1 >= $LIBSECRET_REQUIRED gnome-desktop-3.0 >= $GNOME_DESKTOP_REQUIRED gnome-keyring-1 >= $GNOME_KEYRING_REQUIRED gsettings-desktop-schemas >= $GSETTINGS_DESKTOP_SCHEMAS_REQUIRED diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c index 3ddf2b56e..a69b3f9ee 100644 --- a/embed/ephy-web-view.c +++ b/embed/ephy-web-view.c @@ -49,7 +49,6 @@ #include <gio/gio.h> #include <glib/gi18n.h> #include <glib/gstdio.h> -#include <gnome-keyring.h> #include <gtk/gtk.h> #include <libsoup/soup.h> @@ -524,33 +523,23 @@ fill_data_free (gpointer data) } static void -fill_form_cb (GnomeKeyringResult retval, - GList *results, +fill_form_cb (const char *username, + const char *password, gpointer user_data) { FillData *fill_data = (FillData*)user_data; - GnomeKeyringNetworkPasswordData* keyring_data; - if (!results) { + if (username == NULL && password == NULL) { LOG ("No result"); return; } - /* FIXME: We use only the first result, for now; We need to do - * something smarter here */ - keyring_data = (GnomeKeyringNetworkPasswordData*)results->data; - - if (retval != GNOME_KEYRING_RESULT_OK) { - LOG ("Query failed."); - return; - } - - LOG ("Found: user %s pass (hidden)", keyring_data->user); + LOG ("Found: user %s pass (hidden)", username); g_object_set (fill_data->username_node, - "value", keyring_data->user, NULL); + "value", username, NULL); g_object_set (fill_data->password_node, - "value", keyring_data->password, NULL); + "value", password, NULL); } static void @@ -663,7 +652,8 @@ store_password (GtkInfoBar *info_bar, gint response_id, gpointer data) name_field_name, password_field_name, name_field_value, - password_field_value); + password_field_value, + NULL, NULL); /* Update internal caching */ host = ephy_string_get_host_name (uri); @@ -732,25 +722,23 @@ request_decision_on_storing (StorePasswordData *store_data) } static void -should_store_cb (GnomeKeyringResult retval, - GList *results, +should_store_cb (const char *username, + const char *password, gpointer user_data) { StorePasswordData *store_data = (StorePasswordData*)user_data; - GnomeKeyringNetworkPasswordData* keyring_data; - if (!results) { + if (username == NULL && password == NULL) { LOG ("No result on query; asking whether we should store."); request_decision_on_storing (store_data); return; } + /* FIXME: We use only the first result, for now; We need to do * something smarter here */ - keyring_data = (GnomeKeyringNetworkPasswordData*)results->data; - - if (g_str_equal (keyring_data->user, store_data->name_value) && - g_str_equal (keyring_data->password, store_data->password_value)) { + if (g_str_equal (username, store_data->name_value) && + g_str_equal (password, store_data->password_value)) { LOG ("User/password already stored. Not asking about storing."); store_password_data_free (store_data); return; @@ -800,7 +788,7 @@ form_submitted_cb (WebKitDOMHTMLFormElement *dom_form, _ephy_profile_utils_query_form_auth_data (store_data->uri, store_data->name_field, store_data->password_field, - should_store_cb, + (EphyQueryFormDataCallback)should_store_cb, store_data, NULL); @@ -847,7 +835,7 @@ pre_fill_form (WebKitDOMNode *username_node, _ephy_profile_utils_query_form_auth_data (uri_str, data->form_username, data->form_password, - fill_form_cb, + (EphyQueryFormDataCallback)fill_form_cb, fill_data, fill_data_free); g_free (uri_str); diff --git a/lib/ephy-profile-migrator.c b/lib/ephy-profile-migrator.c index 35d2f8dcf..43f36a781 100644 --- a/lib/ephy-profile-migrator.c +++ b/lib/ephy-profile-migrator.c @@ -298,10 +298,11 @@ parse_and_decrypt_signons (const char *signons, char *u = soup_uri_to_string (uri, FALSE); /* We skip the '*' at the beginning of form_password. */ _ephy_profile_utils_store_form_auth_data (u, - form_username, - form_password+1, - username, - password); + form_username, + form_password+1, + username, + password, + NULL, NULL); g_free (u); } else if (!handle_forms && realm && username && password && 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); } diff --git a/lib/ephy-profile-utils.h b/lib/ephy-profile-utils.h index 1e9d071db..7e22dd6f8 100644 --- a/lib/ephy-profile-utils.h +++ b/lib/ephy-profile-utils.h @@ -20,11 +20,15 @@ #ifndef EPHY_PROFILE_UTILS_H #define EPHY_PROFILE_UTILS_H +#define SECRET_API_SUBJECT_TO_CHANGE + #include <glib.h> -#include <gnome-keyring.h> +#include <libsecret/secret.h> +#define URI_KEY "uri" #define FORM_USERNAME_KEY "form_username" #define FORM_PASSWORD_KEY "form_password" +#define USERNAME_KEY "username" #define EPHY_PROFILE_MIGRATION_VERSION 8 @@ -38,18 +42,29 @@ gboolean ephy_profile_utils_set_migration_version (int version); gboolean ephy_profile_utils_do_migration (const char *profile_directory, int test_to_run, gboolean debug); -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); +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, + GAsyncReadyCallback callback, + gpointer userdata); + +gboolean _ephy_profile_utils_store_form_auth_data_finish (GAsyncResult *result, + GError **error); + +typedef void (*EphyQueryFormDataCallback) (const char *username, const char *password, gpointer user_data); void -_ephy_profile_utils_query_form_auth_data (const char *uri, - const char *form_username, - const char *form_password, - GnomeKeyringOperationGetListCallback callback, - gpointer data, - GDestroyNotify destroy_data); +_ephy_profile_utils_query_form_auth_data (const char *uri, + const char *form_username, + const char *form_password, + EphyQueryFormDataCallback callback, + gpointer data, + GDestroyNotify destroy_data); + +const SecretSchema *ephy_profile_get_form_password_schema (void) G_GNUC_CONST; + +#define EPHY_FORM_PASSWORD_SCHEMA ephy_profile_get_form_password_schema () #endif |