[epiphany/secret-migration: 1/6] ephy-profile-utils: migrate ephy_profile_utils_store/query_form_auth_data() to libsecret



commit 2ac54b4360973dce447c3cd1950750880cafc372
Author: Claudio Saavedra <csaavedra igalia com>
Date:   Tue Feb 19 13:16:55 2013 +0200

    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

 configure.ac                |    2 +
 embed/ephy-web-view.c       |   44 ++++------
 lib/ephy-profile-migrator.c |    9 +-
 lib/ephy-profile-utils.c    |  211 ++++++++++++++++++++++++++++++++++---------
 lib/ephy-profile-utils.h    |   39 ++++++---
 5 files changed, 216 insertions(+), 89 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 736cd85..f478391 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.6
 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 0973b5c..08924477 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -48,7 +48,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>
 
@@ -523,33 +522,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
@@ -662,7 +651,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);
@@ -731,25 +721,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;
@@ -799,7 +787,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);
 
@@ -846,7 +834,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 35d2f8d..43f36a7 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 2c685e0..5a8f1a3 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 1e9d071..7e22dd6 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


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]