[epiphany/wip/sync: 3/22] lib: Replace ephy-form-auth-data with ephy-password-manager
- From: Gabriel Ivașcu <gabrielivascu src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [epiphany/wip/sync: 3/22] lib: Replace ephy-form-auth-data with ephy-password-manager
- Date: Sat, 10 Jun 2017 17:30:06 +0000 (UTC)
commit 25ecbff59dcafd77ec6ae1de3f9641f7b1b3746d
Author: Gabriel Ivascu <ivascu gabriel59 gmail com>
Date: Sat Apr 29 17:18:56 2017 +0300
lib: Replace ephy-form-auth-data with ephy-password-manager
embed/ephy-web-view.c | 1 -
embed/web-extension/ephy-web-extension.c | 168 ++++-----
lib/ephy-form-auth-data.c | 403 ---------------------
lib/ephy-form-auth-data.h | 76 ----
lib/ephy-password-manager.c | 483 ++++++++++++++++++++++++++
lib/ephy-password-manager.h | 77 ++++
lib/ephy-password-record.c | 236 +++++++++++++
lib/ephy-password-record.h | 45 +++
lib/meson.build | 3 +-
po/POTFILES.in | 2 +-
src/clear-data-dialog.c | 1 -
src/ephy-shell.c | 20 +
src/ephy-shell.h | 3 +
src/passwords-dialog.c | 172 +++------
src/passwords-dialog.h | 4 +-
src/prefs-dialog.c | 4 +-
src/profile-migrator/ephy-profile-migrator.c | 18 +-
src/resources/gtk/passwords-dialog.ui | 2 +-
18 files changed, 1010 insertions(+), 708 deletions(-)
---
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index 1d9eb2f..4129100 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -33,7 +33,6 @@
#include "ephy-favicon-helpers.h"
#include "ephy-file-helpers.h"
#include "ephy-file-monitor.h"
-#include "ephy-form-auth-data.h"
#include "ephy-history-service.h"
#include "ephy-lib-type-builtins.h"
#include "ephy-permissions-manager.h"
diff --git a/embed/web-extension/ephy-web-extension.c b/embed/web-extension/ephy-web-extension.c
index edde1f3..b628358 100644
--- a/embed/web-extension/ephy-web-extension.c
+++ b/embed/web-extension/ephy-web-extension.c
@@ -26,7 +26,7 @@
#include "ephy-debug.h"
#include "ephy-embed-form-auth.h"
#include "ephy-file-helpers.h"
-#include "ephy-form-auth-data.h"
+#include "ephy-password-manager.h"
#include "ephy-permissions-manager.h"
#include "ephy-prefs.h"
#include "ephy-settings.h"
@@ -51,7 +51,7 @@ struct _EphyWebExtension {
GDBusConnection *dbus_connection;
GArray *page_created_signals_pending;
- EphyFormAuthDataCache *form_auth_data_cache;
+ EphyPasswordManager *password_manager;
GHashTable *form_auth_data_save_requests;
EphyWebOverviewModel *overview_model;
EphyPermissionsManager *permissions_manager;
@@ -283,19 +283,12 @@ store_password (EphyEmbedFormAuth *form_auth)
uri = ephy_embed_form_auth_get_uri (form_auth);
uri_str = soup_uri_to_string (uri, FALSE);
- ephy_form_auth_data_store (uri_str,
- username_field_name,
- password_field_name,
- username_field_value,
- password_field_value,
- NULL, NULL);
-
- /* Update internal caching */
- ephy_form_auth_data_cache_add (extension->form_auth_data_cache,
- uri_str,
- username_field_name,
- password_field_name,
- username_field_value);
+ ephy_password_manager_save (extension->password_manager,
+ uri_str,
+ username_field_name,
+ password_field_name,
+ username_field_value,
+ password_field_value);
g_free (uri_str);
g_free (username_field_name);
@@ -368,9 +361,8 @@ out:
}
static void
-should_store_cb (const char *username,
- const char *password,
- gpointer user_data)
+should_store_cb (GSList *records,
+ gpointer user_data)
{
EphyEmbedFormAuth *form_auth = EPHY_EMBED_FORM_AUTH (user_data);
EphyWebExtension *web_extension;
@@ -407,9 +399,12 @@ should_store_cb (const char *username,
if (password_field_value == NULL || strlen (password_field_value) == 0)
goto out;
- if (password) {
+ if (records && records->data) {
+ EphyPasswordRecord *record = EPHY_PASSWORD_RECORD (records->data);
WebKitDOMNode *username_node;
char *username_field_value = NULL;
+ const char *username = ephy_password_record_get_username (record);
+ const char *password = ephy_password_record_get_password (record);
username_node = ephy_embed_form_auth_get_username_node (form_auth);
if (username_node)
@@ -440,6 +435,8 @@ out:
if (origin != NULL)
g_free (origin);
g_free (uri_string);
+ g_object_unref (form_auth);
+ g_slist_free_full (records, g_object_unref);
}
static gboolean
@@ -447,6 +444,7 @@ form_submitted_cb (WebKitDOMHTMLFormElement *dom_form,
WebKitDOMEvent *dom_event,
WebKitWebPage *web_page)
{
+ EphyWebExtension *extension = ephy_web_extension_get ();
EphyEmbedFormAuth *form_auth;
SoupURI *uri;
WebKitDOMNode *username_node = NULL;
@@ -475,13 +473,13 @@ form_submitted_cb (WebKitDOMHTMLFormElement *dom_form,
g_object_get (password_node, "name", &password_field_name, NULL);
uri_str = soup_uri_to_string (uri, FALSE);
- ephy_form_auth_data_query (uri_str,
- username_field_name,
- password_field_name,
- username_field_value,
- should_store_cb,
- form_auth,
- (GDestroyNotify)g_object_unref);
+ ephy_password_manager_query (extension->password_manager,
+ uri_str,
+ username_field_name,
+ password_field_name,
+ username_field_value,
+ should_store_cb,
+ form_auth);
g_free (username_field_name);
g_free (username_field_value);
@@ -492,19 +490,22 @@ form_submitted_cb (WebKitDOMHTMLFormElement *dom_form,
}
static void
-fill_form_cb (const char *username,
- const char *password,
- gpointer user_data)
+fill_form_cb (GSList *records,
+ gpointer user_data)
{
EphyEmbedFormAuth *form_auth = EPHY_EMBED_FORM_AUTH (user_data);
WebKitDOMHTMLInputElement *username_node;
WebKitDOMHTMLInputElement *password_node;
+ const char *username;
+ const char *password;
- if (username == NULL && password == NULL) {
+ if (!(records && records->data)) {
LOG ("No result");
return;
}
+ username = ephy_password_record_get_username (EPHY_PASSWORD_RECORD (records->data));
+ password = ephy_password_record_get_password (EPHY_PASSWORD_RECORD (records->data));
username_node = WEBKIT_DOM_HTML_INPUT_ELEMENT (ephy_embed_form_auth_get_username_node (form_auth));
password_node = WEBKIT_DOM_HTML_INPUT_ELEMENT (ephy_embed_form_auth_get_password_node (form_auth));
@@ -517,44 +518,20 @@ fill_form_cb (const char *username,
}
webkit_dom_html_input_element_set_auto_filled (password_node, TRUE);
webkit_dom_html_input_element_set_editing_value (password_node, password);
-}
-
-static gint
-ephy_form_auth_data_compare (EphyFormAuthData *form_data,
- EphyEmbedFormAuth *form_auth)
-{
- WebKitDOMNode *username_node;
- WebKitDOMNode *password_node;
- char *username_field_name = NULL;
- char *password_field_name = NULL;
- gboolean retval;
-
- username_node = ephy_embed_form_auth_get_username_node (form_auth);
- if (username_node)
- g_object_get (username_node, "name", &username_field_name, NULL);
- password_node = ephy_embed_form_auth_get_password_node (form_auth);
- if (password_node)
- g_object_get (password_node, "name", &password_field_name, NULL);
-
- retval = g_strcmp0 (username_field_name, form_data->form_username) == 0 &&
- g_strcmp0 (password_field_name, form_data->form_password) == 0;
-
- g_free (username_field_name);
- g_free (password_field_name);
- return retval ? 0 : 1;
+ g_slist_free_full (records, g_object_unref);
}
static void
pre_fill_form (EphyEmbedFormAuth *form_auth)
{
- GSList *form_auth_data_list;
- GSList *l;
- EphyFormAuthData *form_data;
SoupURI *uri;
char *uri_str;
- char *username;
+ char *username = NULL;
+ char *username_field_name = NULL;
+ char *password_field_name = NULL;
WebKitDOMNode *username_node;
+ WebKitDOMNode *password_node;
EphyWebExtension *extension;
uri = ephy_embed_form_auth_get_uri (form_auth);
@@ -563,34 +540,31 @@ pre_fill_form (EphyEmbedFormAuth *form_auth)
extension = ephy_web_extension_get ();
uri_str = soup_uri_to_string (uri, FALSE);
- form_auth_data_list = ephy_form_auth_data_cache_get_list (extension->form_auth_data_cache, uri_str);
- l = g_slist_find_custom (form_auth_data_list, form_auth, (GCompareFunc)ephy_form_auth_data_compare);
- if (!l) {
- g_free (uri_str);
- return;
- }
-
- form_data = (EphyFormAuthData *)l->data;
username_node = ephy_embed_form_auth_get_username_node (form_auth);
- if (username_node)
+ if (username_node) {
+ g_object_get (username_node, "name", &username_field_name, NULL);
g_object_get (username_node, "value", &username, NULL);
- else
- username = NULL;
+ }
+ password_node = ephy_embed_form_auth_get_password_node (form_auth);
+ if (password_node)
+ g_object_get (password_node, "name", &password_field_name, NULL);
/* The username node is empty, so pre-fill with the default. */
if (username != NULL && g_str_equal (username, ""))
g_clear_pointer (&username, g_free);
- ephy_form_auth_data_query (uri_str,
- form_data->form_username,
- form_data->form_password,
- username,
- fill_form_cb,
- g_object_ref (form_auth),
- (GDestroyNotify)g_object_unref);
+ ephy_password_manager_query (extension->password_manager,
+ uri_str,
+ username_field_name,
+ password_field_name,
+ username,
+ fill_form_cb,
+ form_auth);
- g_free (username);
g_free (uri_str);
+ g_free (username);
+ g_free (username_field_name);
+ g_free (password_field_name);
}
static void
@@ -757,7 +731,7 @@ show_user_choices (WebKitDOMDocument *document,
WebKitDOMElement *main_div;
WebKitDOMElement *ul;
GSList *iter;
- GSList *auth_data_list;
+ GSList *password_records_list;
gboolean username_node_ever_edited;
double x, y;
double input_width;
@@ -803,30 +777,32 @@ show_user_choices (WebKitDOMDocument *document,
"padding: 0;",
NULL);
- auth_data_list = (GSList *)g_object_get_data (G_OBJECT (username_node),
- "ephy-auth-data-list");
+ password_records_list = (GSList *)g_object_get_data (G_OBJECT (username_node),
+ "ephy-password-records-list");
username_node_ever_edited =
GPOINTER_TO_INT (g_object_get_data (G_OBJECT (username_node),
"ephy-user-ever-edited"));
- for (iter = auth_data_list; iter; iter = iter->next) {
- EphyFormAuthData *data;
+ for (iter = password_records_list; iter; iter = iter->next) {
+ EphyPasswordRecord *record;
WebKitDOMElement *li;
WebKitDOMElement *anchor;
char *child_style;
+ const char *record_username;
gboolean is_selected;
- data = (EphyFormAuthData *)iter->data;
+ record = EPHY_PASSWORD_RECORD (iter->data);
+ record_username = ephy_password_record_get_username (record);
/* Filter out the available names that do not match, but show all options in
* case we have been triggered by something other than the user editing the
* input.
*/
- if (username_node_ever_edited && !g_str_has_prefix (data->username, username))
+ if (username_node_ever_edited && !g_str_has_prefix (record_username, username))
continue;
- is_selected = !g_strcmp0 (username, data->username);
+ is_selected = !g_strcmp0 (username, record_username);
li = webkit_dom_document_create_element (document, "li", NULL);
webkit_dom_element_set_attribute (li, "tabindex", "-1", NULL);
@@ -858,7 +834,7 @@ show_user_choices (WebKitDOMDocument *document,
username_node);
webkit_dom_node_set_text_content (WEBKIT_DOM_NODE (anchor),
- data->username,
+ record_username,
NULL);
}
@@ -1125,14 +1101,14 @@ web_page_form_controls_associated (WebKitWebPage *web_page,
web_page);
}
- if (!extension->form_auth_data_cache ||
+ if (!extension->password_manager ||
!g_settings_get_boolean (EPHY_SETTINGS_WEB, EPHY_PREFS_WEB_REMEMBER_PASSWORDS))
continue;
/* We have a field that may be the user, and one for a password. */
if (ephy_web_dom_utils_find_form_auth_elements (form, &username_node, &password_node)) {
EphyEmbedFormAuth *form_auth;
- GSList *auth_data_list;
+ GSList *password_records_list;
const char *uri;
LOG ("Hooking and pre-filling a form");
@@ -1150,11 +1126,11 @@ web_page_form_controls_associated (WebKitWebPage *web_page,
/* Plug in the user autocomplete */
uri = webkit_web_page_get_uri (web_page);
- auth_data_list = ephy_form_auth_data_cache_get_list (extension->form_auth_data_cache, uri);
+ password_records_list = ephy_password_manager_get_cached_by_uri (extension->password_manager, uri);
- if (auth_data_list && auth_data_list->next && username_node) {
+ if (password_records_list && password_records_list->next && username_node) {
LOG ("More than 1 password saved, hooking menu for choosing which on focus");
- g_object_set_data (G_OBJECT (username_node), "ephy-auth-data-list", auth_data_list);
+ g_object_set_data (G_OBJECT (username_node), "ephy-password-records-list", password_records_list);
g_object_set_data (G_OBJECT (username_node), "ephy-form-auth", form_auth);
g_object_set_data (G_OBJECT (username_node), "ephy-document", document);
webkit_dom_event_target_add_event_listener (WEBKIT_DOM_EVENT_TARGET (username_node), "input",
@@ -1173,7 +1149,7 @@ web_page_form_controls_associated (WebKitWebPage *web_page,
G_CALLBACK (username_node_changed_cb), FALSE,
web_page);
} else
- LOG ("No items or a single item in auth_data_list, not hooking menu for choosing.");
+ LOG ("No items or a single item in password_records_list, not hooking menu for choosing.");
pre_fill_form (form_auth);
@@ -1476,9 +1452,7 @@ ephy_web_extension_dispose (GObject *object)
g_clear_object (&extension->uri_tester);
g_clear_object (&extension->overview_model);
g_clear_object (&extension->permissions_manager);
-
- g_clear_pointer (&extension->form_auth_data_cache,
- ephy_form_auth_data_cache_free);
+ g_clear_object (&extension->password_manager);
if (extension->form_auth_data_save_requests) {
g_hash_table_destroy (extension->form_auth_data_save_requests);
@@ -1589,7 +1563,7 @@ ephy_web_extension_initialize (EphyWebExtension *extension,
extension->extension = g_object_ref (wk_extension);
if (!is_private_profile)
- extension->form_auth_data_cache = ephy_form_auth_data_cache_new ();
+ extension->password_manager = ephy_password_manager_new ();
extension->permissions_manager = ephy_permissions_manager_new ();
diff --git a/lib/ephy-password-manager.c b/lib/ephy-password-manager.c
new file mode 100644
index 0000000..2337755
--- /dev/null
+++ b/lib/ephy-password-manager.c
@@ -0,0 +1,483 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "ephy-password-manager.h"
+
+#include "ephy-debug.h"
+#include "ephy-uri-helpers.h"
+
+#include <glib/gi18n.h>
+
+const SecretSchema *
+ephy_password_manager_get_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;
+}
+
+struct _EphyPasswordManager {
+ GObject parent_instance;
+
+ GSList *records;
+};
+
+G_DEFINE_TYPE (EphyPasswordManager, ephy_password_manager, G_TYPE_OBJECT)
+
+typedef struct {
+ EphyPasswordManagerQueryCallback callback;
+ gpointer user_data;
+} QueryAsyncData;
+
+static QueryAsyncData *
+query_async_data_new (EphyPasswordManagerQueryCallback callback,
+ gpointer user_data)
+{
+ QueryAsyncData *data;
+
+ data = g_slice_new (QueryAsyncData);
+ data->callback = callback;
+ data->user_data = user_data;
+
+ return data;
+}
+
+static void
+query_async_data_free (QueryAsyncData *data)
+{
+ g_slice_free (QueryAsyncData, data);
+}
+
+static void
+ephy_password_manager_dispose (GObject *object)
+{
+ EphyPasswordManager *self = EPHY_PASSWORD_MANAGER (object);
+
+ g_slist_free_full (self->records, g_object_unref);
+ self->records = NULL;
+
+ G_OBJECT_CLASS (ephy_password_manager_parent_class)->dispose (object);
+}
+
+static void
+ephy_password_manager_class_init (EphyPasswordManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->dispose = ephy_password_manager_dispose;
+}
+
+static void
+secret_service_search_all_cb (SecretService *service,
+ GAsyncResult *result,
+ EphyPasswordManager *self)
+{
+ GList *matches = NULL;
+ GError *error = NULL;
+
+ matches = secret_service_search_finish (service, result, &error);
+ if (error) {
+ g_warning ("Failed to search secrets in password schema: %s", error->message);
+ g_error_free (error);
+ return;
+ }
+
+ for (GList *l = matches; l && l->data; l = l->next) {
+ SecretItem *item = (SecretItem *)l->data;
+ SecretValue *value = secret_item_get_secret (item);
+ GHashTable *attributes = secret_item_get_attributes (item);
+ const char *uri = g_hash_table_lookup (attributes, URI_KEY);
+ const char *form_username = g_hash_table_lookup (attributes, FORM_USERNAME_KEY);
+ const char *form_password = g_hash_table_lookup (attributes, FORM_PASSWORD_KEY);
+ const char *username = g_hash_table_lookup (attributes, USERNAME_KEY);
+ const char *password = secret_value_get (value, NULL);
+ EphyPasswordRecord *record;
+
+ LOG ("Loading password record for uri=%s, form_username=%s, form_password=%s, username=%s",
+ uri, form_username, form_password, username);
+
+ record = ephy_password_record_new (uri, form_username, form_password, username, password);
+ self->records = g_slist_prepend (self->records, record);
+
+ secret_value_unref (value);
+ g_hash_table_unref (attributes);
+ }
+
+ g_list_free_full (matches, g_object_unref);
+}
+
+static void
+ephy_password_manager_load_passwords (EphyPasswordManager *self)
+{
+ GHashTable *attributes;
+
+ g_assert (EPHY_IS_PASSWORD_MANAGER (self));
+
+ attributes = secret_attributes_build (EPHY_FORM_PASSWORD_SCHEMA, NULL);
+ secret_service_search (NULL,
+ EPHY_FORM_PASSWORD_SCHEMA,
+ attributes,
+ SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
+ NULL,
+ (GAsyncReadyCallback)secret_service_search_all_cb,
+ self);
+
+ g_hash_table_unref (attributes);
+}
+
+static void
+ephy_password_manager_init (EphyPasswordManager *self)
+{
+ ephy_password_manager_load_passwords (self);
+}
+
+EphyPasswordManager *
+ephy_password_manager_new (void)
+{
+ return EPHY_PASSWORD_MANAGER (g_object_new (EPHY_TYPE_PASSWORD_MANAGER, NULL));
+}
+
+GSList *
+ephy_password_manager_get_cached_by_uri (EphyPasswordManager *self,
+ const char *uri)
+{
+ GSList *list = NULL;
+ char *origin;
+
+ g_return_val_if_fail (EPHY_IS_PASSWORD_MANAGER (self), NULL);
+ g_return_val_if_fail (uri, NULL);
+
+ origin = ephy_uri_to_security_origin (uri);
+
+ for (GSList *l = self->records; l && l->data; l = l->next) {
+ EphyPasswordRecord *record = EPHY_PASSWORD_RECORD (l->data);
+
+ if (!g_strcmp0 (origin, ephy_password_record_get_origin (record)))
+ list = g_slist_prepend (list, record);
+ }
+
+ g_free (origin);
+
+ return list;
+}
+
+static EphyPasswordRecord *
+ephy_password_manager_get_cached (EphyPasswordManager *self,
+ const char *origin,
+ const char *form_username,
+ const char *form_password,
+ const char *username)
+{
+ g_assert (EPHY_IS_PASSWORD_MANAGER (self));
+
+ for (GSList *l = self->records; l && l->data; l = l->next) {
+ EphyPasswordRecord *record = EPHY_PASSWORD_RECORD (l->data);
+
+ if (!g_strcmp0 (origin, ephy_password_record_get_origin (record)) &&
+ !g_strcmp0 (form_username, ephy_password_record_get_form_username (record)) &&
+ !g_strcmp0 (form_password, ephy_password_record_get_form_password (record)) &&
+ !g_strcmp0 (username, ephy_password_record_get_username (record)))
+ return record;
+ }
+
+ return NULL;
+}
+
+void
+ephy_password_manager_save (EphyPasswordManager *self,
+ const char *uri,
+ const char *form_username,
+ const char *form_password,
+ const char *username,
+ const char *password)
+{
+ EphyPasswordRecord *record = NULL;
+ char *origin;
+
+ g_return_if_fail (EPHY_IS_PASSWORD_MANAGER (self));
+ g_return_if_fail (uri);
+ g_return_if_fail (password);
+ g_return_if_fail (!form_username || username);
+ g_return_if_fail (!form_password || password);
+
+ origin = ephy_uri_to_security_origin (uri);
+
+ /* Check if there is an existing record for the given parameters.
+ * If there is, don't create a new record, only update password. */
+ record = ephy_password_manager_get_cached (self, origin,
+ form_username, form_password,
+ username);
+ if (record) {
+ ephy_password_record_set_password (record, password);
+ } else {
+ record = ephy_password_record_new (origin, form_username, form_password,
+ username, password);
+ self->records = g_slist_prepend (self->records, record);
+ }
+
+ /* Add/overwrite the password in the secret schema. */
+ ephy_password_manager_store (origin,
+ form_username, form_password,
+ username, password,
+ NULL, NULL);
+
+ g_free (origin);
+}
+
+static GHashTable *
+get_attributes_table (const char *uri,
+ const char *form_username,
+ const char *form_password,
+ const char *username)
+{
+ GHashTable *attributes = secret_attributes_build (EPHY_FORM_PASSWORD_SCHEMA, NULL);
+
+ if (uri)
+ g_hash_table_insert (attributes, g_strdup (URI_KEY), ephy_uri_to_security_origin (uri));
+ if (username)
+ g_hash_table_insert (attributes, g_strdup (USERNAME_KEY), g_strdup (username));
+ if (form_username)
+ g_hash_table_insert (attributes, g_strdup (FORM_USERNAME_KEY), g_strdup (form_username));
+ if (form_password)
+ g_hash_table_insert (attributes, g_strdup (FORM_PASSWORD_KEY), g_strdup (form_password));
+
+ return attributes;
+}
+
+static void
+secret_service_search_cb (SecretService *service,
+ GAsyncResult *result,
+ QueryAsyncData *data)
+{
+ GList *matches = NULL;
+ GSList *records = NULL;
+ GError *error = NULL;
+
+ matches = secret_service_search_finish (service, result, &error);
+ if (error) {
+ g_warning ("Failed to search secrets in password schema: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ for (GList *l = matches; l && l->data; l = l->next) {
+ SecretItem *item = (SecretItem *)l->data;
+ GHashTable *attributes = secret_item_get_attributes (item);
+ SecretValue *value = secret_item_get_secret (item);
+ const char *origin = g_hash_table_lookup (attributes, URI_KEY);
+ const char *form_username = g_hash_table_lookup (attributes, FORM_USERNAME_KEY);
+ const char *form_password = g_hash_table_lookup (attributes, FORM_PASSWORD_KEY);
+ const char *username = g_hash_table_lookup (attributes, USERNAME_KEY);
+ const char *password = secret_value_get (value, NULL);
+ EphyPasswordRecord *record;
+
+ LOG ("Query found password record for (%s, %s, %s, %s)",
+ origin, form_username, form_password, username);
+
+ record = ephy_password_record_new (origin, form_username, form_password, username, password);
+ records = g_slist_prepend (records, record);
+
+ secret_value_unref (value);
+ g_hash_table_unref (attributes);
+ }
+
+out:
+ if (data->callback)
+ data->callback (records, data->user_data);
+ query_async_data_free (data);
+ g_list_free_full (matches, g_object_unref);
+}
+
+void
+ephy_password_manager_query (EphyPasswordManager *self,
+ const char *uri,
+ const char *form_username,
+ const char *form_password,
+ const char *username,
+ EphyPasswordManagerQueryCallback callback,
+ gpointer user_data)
+{
+ QueryAsyncData *data;
+ GHashTable *attributes;
+
+ g_return_if_fail (EPHY_IS_PASSWORD_MANAGER (self));
+
+ LOG ("Querying password records for uri=%s, form_username=%s, form_password=%s, username=%s",
+ uri, form_username, form_password, username);
+
+ attributes = get_attributes_table (uri, form_username, form_password, username);
+ data = query_async_data_new (callback, user_data);
+
+ secret_service_search (NULL,
+ EPHY_FORM_PASSWORD_SCHEMA,
+ attributes,
+ SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
+ NULL,
+ (GAsyncReadyCallback)secret_service_search_cb,
+ data);
+
+ g_hash_table_unref (attributes);
+}
+
+static void
+secret_service_store_cb (SecretService *service,
+ GAsyncResult *result,
+ GTask *task)
+{
+ GError *error = NULL;
+
+ secret_service_store_finish (service, result, &error);
+ if (error)
+ g_task_return_error (task, error);
+ else
+ g_task_return_boolean (task, TRUE);
+
+ g_object_unref (task);
+}
+
+void
+ephy_password_manager_store (const char *uri,
+ const char *form_username,
+ const char *form_password,
+ const char *username,
+ const char *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ SecretValue *value;
+ GHashTable *attributes;
+ GTask *task;
+ char *origin;
+ char *label;
+
+ g_return_if_fail (uri);
+ g_return_if_fail (password);
+ g_return_if_fail (!form_username || username);
+ g_return_if_fail (!form_password || password);
+
+ task = g_task_new (NULL, NULL, callback, user_data);
+ value = secret_value_new (password, -1, "text/plain");
+ attributes = get_attributes_table (uri, form_username, form_password, username);
+ origin = ephy_uri_to_security_origin (uri);
+
+ if (username) {
+ /* Translators: The first %s is the username and the second one is the
+ * security origin where this is happening. Example: gnome gmail com and
+ * https://mail.google.com. */
+ label = g_strdup_printf (_("Password for %s in a form in %s"), username, origin);
+ } else {
+ /* Translators: The %s is the security origin where this is happening.
+ * Example: https://mail.google.com. */
+ label = g_strdup_printf (_("Password in a form in %s"), origin);
+ }
+
+ LOG ("Storing password record for uri=%s, form_username=%s, form_password=%s, username=%s",
+ uri, form_username, form_password, username);
+
+ secret_service_store (NULL, EPHY_FORM_PASSWORD_SCHEMA,
+ attributes, NULL, label, value, NULL,
+ (GAsyncReadyCallback)secret_service_store_cb,
+ g_object_ref (task));
+
+ g_free (label);
+ g_free (origin);
+ secret_value_unref (value);
+ g_hash_table_unref (attributes);
+ g_object_unref (task);
+}
+
+gboolean
+ephy_password_manager_store_finish (GAsyncResult *result,
+ GError **error)
+{
+ g_return_val_if_fail (!error || !(*error), FALSE);
+ g_return_val_if_fail (g_task_is_valid (result, NULL), FALSE);
+
+ return g_task_propagate_boolean (G_TASK (result), error);
+}
+
+static void
+secret_service_clear_cb (SecretService *service,
+ GAsyncResult *result,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ secret_service_clear_finish (service, result, &error);
+ if (error) {
+ g_warning ("Failed to clear secrets from password schema: %s", error->message);
+ g_error_free (error);
+ }
+}
+
+void
+ephy_password_manager_forget (EphyPasswordManager *self,
+ const char *origin,
+ const char *form_username,
+ const char *form_password,
+ const char *username)
+{
+ EphyPasswordRecord *record;
+ GHashTable *attributes;
+
+ g_return_if_fail (EPHY_IS_PASSWORD_MANAGER (self));
+ g_return_if_fail (origin);
+ g_return_if_fail (form_password);
+ g_return_if_fail (!form_username || username);
+
+ attributes = get_attributes_table (origin, form_username, form_password, username);
+ secret_service_clear (NULL, EPHY_FORM_PASSWORD_SCHEMA, attributes, NULL,
+ (GAsyncReadyCallback)secret_service_clear_cb, NULL);
+
+ /* If record is in cache, delete it. */
+ record = ephy_password_manager_get_cached (self, origin,
+ form_username, form_password,
+ username);
+ if (record) {
+ self->records = g_slist_remove (self->records, record);
+ g_object_unref (record);
+ }
+}
+
+void
+ephy_password_manager_forget_all (EphyPasswordManager *self)
+{
+ GHashTable *attributes;
+
+ g_return_if_fail (EPHY_IS_PASSWORD_MANAGER (self));
+
+ attributes = secret_attributes_build (EPHY_FORM_PASSWORD_SCHEMA, NULL);
+ secret_service_clear (NULL, EPHY_FORM_PASSWORD_SCHEMA, attributes, NULL,
+ (GAsyncReadyCallback)secret_service_clear_cb, NULL);
+
+ g_slist_free_full (self->records, g_object_unref);
+ self->records = NULL;
+
+ g_hash_table_unref (attributes);
+}
diff --git a/lib/ephy-password-manager.h b/lib/ephy-password-manager.h
new file mode 100644
index 0000000..aa967aa
--- /dev/null
+++ b/lib/ephy-password-manager.h
@@ -0,0 +1,77 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include "ephy-password-record.h"
+
+#include <glib-object.h>
+#include <libsecret/secret.h>
+
+G_BEGIN_DECLS
+
+const SecretSchema *ephy_password_manager_get_password_schema (void) G_GNUC_CONST;
+
+#define URI_KEY "uri"
+#define FORM_USERNAME_KEY "form_username"
+#define FORM_PASSWORD_KEY "form_password"
+#define USERNAME_KEY "username"
+
+#define EPHY_FORM_PASSWORD_SCHEMA ephy_password_manager_get_password_schema ()
+
+#define EPHY_TYPE_PASSWORD_MANAGER (ephy_password_manager_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyPasswordManager, ephy_password_manager, EPHY, PASSWORD_MANAGER, GObject)
+
+typedef void (*EphyPasswordManagerQueryCallback) (GSList *records, gpointer user_data);
+
+EphyPasswordManager *ephy_password_manager_new (void);
+GSList *ephy_password_manager_get_cached_by_uri (EphyPasswordManager *self,
+ const char *uri);
+void ephy_password_manager_save (EphyPasswordManager *self,
+ const char *uri,
+ const char *form_username,
+ const char *form_password,
+ const char *username,
+ const char *password);
+void ephy_password_manager_query (EphyPasswordManager *self,
+ const char *uri,
+ const char
*form_username,
+ const char
*form_password,
+ const char *username,
+ EphyPasswordManagerQueryCallback callback,
+ gpointer user_data);
+void ephy_password_manager_store (const char *uri,
+ const char *form_username,
+ const char *form_password,
+ const char *username,
+ const char *password,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean ephy_password_manager_store_finish (GAsyncResult *result,
+ GError **error);
+void ephy_password_manager_forget (EphyPasswordManager *self,
+ const char *origin,
+ const char *form_username,
+ const char *form_password,
+ const char *username);
+void ephy_password_manager_forget_all (EphyPasswordManager *self);
+
+G_END_DECLS
diff --git a/lib/ephy-password-record.c b/lib/ephy-password-record.c
new file mode 100644
index 0000000..1d3852f
--- /dev/null
+++ b/lib/ephy-password-record.c
@@ -0,0 +1,236 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include "ephy-password-record.h"
+
+struct _EphyPasswordRecord {
+ GObject parent_instance;
+
+ char *origin;
+ char *form_username;
+ char *form_password;
+ char *username;
+ char *password;
+};
+
+G_DEFINE_TYPE (EphyPasswordRecord, ephy_password_record, G_TYPE_OBJECT)
+
+enum {
+ PROP_0,
+ PROP_ORIGIN,
+ PROP_FORM_USERNAME,
+ PROP_FORM_PASSWORD,
+ PROP_USERNAME,
+ PROP_PASSWORD,
+ LAST_PROP,
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+ephy_password_record_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ EphyPasswordRecord *self = EPHY_PASSWORD_RECORD (object);
+
+ switch (prop_id) {
+ case PROP_ORIGIN:
+ g_free (self->origin);
+ self->origin = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_FORM_USERNAME:
+ g_free (self->form_username);
+ self->form_username = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_FORM_PASSWORD:
+ g_free (self->form_password);
+ self->form_password = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_USERNAME:
+ g_free (self->username);
+ self->username = g_strdup (g_value_get_string (value));
+ break;
+ case PROP_PASSWORD:
+ ephy_password_record_set_password (self, g_value_get_string (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_password_record_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ EphyPasswordRecord *self = EPHY_PASSWORD_RECORD (object);
+
+ switch (prop_id) {
+ case PROP_ORIGIN:
+ g_value_set_string (value, ephy_password_record_get_origin (self));
+ break;
+ case PROP_FORM_USERNAME:
+ g_value_set_string (value, ephy_password_record_get_form_username (self));
+ break;
+ case PROP_FORM_PASSWORD:
+ g_value_set_string (value, ephy_password_record_get_form_password (self));
+ break;
+ case PROP_USERNAME:
+ g_value_set_string (value, ephy_password_record_get_username (self));
+ break;
+ case PROP_PASSWORD:
+ g_value_set_string (value, ephy_password_record_get_password (self));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+ephy_password_record_dispose (GObject *object)
+{
+ EphyPasswordRecord *self = EPHY_PASSWORD_RECORD (object);
+
+ g_clear_pointer (&self->origin, g_free);
+ g_clear_pointer (&self->form_username, g_free);
+ g_clear_pointer (&self->form_password, g_free);
+ g_clear_pointer (&self->username, g_free);
+ g_clear_pointer (&self->password, g_free);
+
+ G_OBJECT_CLASS (ephy_password_record_parent_class)->dispose (object);
+}
+
+static void
+ephy_password_record_class_init (EphyPasswordRecordClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->set_property = ephy_password_record_set_property;
+ object_class->get_property = ephy_password_record_get_property;
+ object_class->dispose = ephy_password_record_dispose;
+
+ obj_properties[PROP_ORIGIN] =
+ g_param_spec_string ("origin",
+ "Origin",
+ "Origin url that password is applicable at",
+ "Default origin",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_FORM_USERNAME] =
+ g_param_spec_string ("form-username",
+ "Form username",
+ "HTML field name of the username",
+ "Default form username",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_FORM_PASSWORD] =
+ g_param_spec_string ("form-password",
+ "Form password",
+ "HTML field name of the password",
+ "Default form password",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_USERNAME] =
+ g_param_spec_string ("username",
+ "Username",
+ "Username to log in as",
+ "Default username",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+ obj_properties[PROP_PASSWORD] =
+ g_param_spec_string ("password",
+ "Password",
+ "Password for the username",
+ "Default password",
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+}
+
+static void
+ephy_password_record_init (EphyPasswordRecord *self)
+{
+}
+
+EphyPasswordRecord *
+ephy_password_record_new (const char *origin,
+ const char *form_username,
+ const char *form_password,
+ const char *username,
+ const char *password)
+{
+ return EPHY_PASSWORD_RECORD (g_object_new (EPHY_TYPE_PASSWORD_RECORD,
+ "origin", origin,
+ "form-username", form_username,
+ "form-password", form_password,
+ "username", username,
+ "password", password,
+ NULL));
+}
+
+const char *
+ephy_password_record_get_origin (EphyPasswordRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_PASSWORD_RECORD (self), NULL);
+
+ return self->origin;
+}
+
+const char *
+ephy_password_record_get_form_username (EphyPasswordRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_PASSWORD_RECORD (self), NULL);
+
+ return self->form_username;
+}
+
+const char *
+ephy_password_record_get_form_password (EphyPasswordRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_PASSWORD_RECORD (self), NULL);
+
+ return self->form_password;
+}
+
+const char *
+ephy_password_record_get_username (EphyPasswordRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_PASSWORD_RECORD (self), NULL);
+
+ return self->username;
+}
+
+const char *
+ephy_password_record_get_password (EphyPasswordRecord *self)
+{
+ g_return_val_if_fail (EPHY_IS_PASSWORD_RECORD (self), NULL);
+
+ return self->password;
+}
+
+void
+ephy_password_record_set_password (EphyPasswordRecord *self,
+ const char *password)
+{
+ g_return_if_fail (EPHY_IS_PASSWORD_RECORD (self));
+
+ g_free (self->password);
+ self->password = g_strdup (password);
+}
diff --git a/lib/ephy-password-record.h b/lib/ephy-password-record.h
new file mode 100644
index 0000000..2dcd128
--- /dev/null
+++ b/lib/ephy-password-record.h
@@ -0,0 +1,45 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ * Copyright © 2017 Gabriel Ivascu <ivascu gabriel59 gmail com>
+ *
+ * This file is part of Epiphany.
+ *
+ * Epiphany is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Epiphany is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Epiphany. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#pragma once
+
+#include <glib-object.h>
+#include <libsecret/secret.h>
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_PASSWORD_RECORD (ephy_password_record_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyPasswordRecord, ephy_password_record, EPHY, PASSWORD_RECORD, GObject)
+
+EphyPasswordRecord *ephy_password_record_new (const char *origin,
+ const char *form_username,
+ const char *form_passwords,
+ const char *username,
+ const char *password);
+const char *ephy_password_record_get_origin (EphyPasswordRecord *self);
+const char *ephy_password_record_get_form_username (EphyPasswordRecord *self);
+const char *ephy_password_record_get_form_password (EphyPasswordRecord *self);
+const char *ephy_password_record_get_username (EphyPasswordRecord *self);
+const char *ephy_password_record_get_password (EphyPasswordRecord *self);
+void ephy_password_record_set_password (EphyPasswordRecord *self,
+ const char *password);
+
+G_END_DECLS
diff --git a/lib/meson.build b/lib/meson.build
index 78ce8fa..6e88051 100644
--- a/lib/meson.build
+++ b/lib/meson.build
@@ -20,9 +20,10 @@ libephymisc_sources = [
'ephy-favicon-helpers.c',
'ephy-file-helpers.c',
'ephy-filters-manager.c',
- 'ephy-form-auth-data.c',
'ephy-gui.c',
'ephy-langs.c',
+ 'ephy-password-manager.c',
+ 'ephy-password-record.c',
'ephy-permissions-manager.c',
'ephy-profile-utils.c',
'ephy-search-engine-manager.c',
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 62bdad5..04ee4ee 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -12,9 +12,9 @@ embed/ephy-encodings.c
embed/ephy-find-toolbar.c
embed/ephy-web-view.c
lib/ephy-file-helpers.c
-lib/ephy-form-auth-data.c
lib/ephy-gui.c
lib/ephy-langs.c
+lib/ephy-password-manager.c
lib/ephy-string.c
lib/ephy-time-helpers.c
lib/ephy-zoom.h
diff --git a/src/clear-data-dialog.c b/src/clear-data-dialog.c
index ec532ae..4934e71 100644
--- a/src/clear-data-dialog.c
+++ b/src/clear-data-dialog.c
@@ -26,7 +26,6 @@
#include <string.h>
#include <webkit2/webkit2.h>
-#include "ephy-form-auth-data.h"
#include "ephy-history-service.h"
#include "ephy-embed-shell.h"
diff --git a/src/ephy-shell.c b/src/ephy-shell.c
index 4801cfd..6f917a5 100644
--- a/src/ephy-shell.c
+++ b/src/ephy-shell.c
@@ -56,6 +56,7 @@ struct _EphyShell {
GList *windows;
GObject *lockdown;
EphyBookmarksManager *bookmarks_manager;
+ EphyPasswordManager *password_manager;
GNetworkMonitor *network_monitor;
GtkWidget *history_dialog;
GObject *prefs_dialog;
@@ -345,6 +346,8 @@ ephy_shell_startup (GApplication *application)
G_BINDING_SYNC_CREATE);
}
+ ephy_shell->password_manager = ephy_password_manager_new ();
+
/* Create the sync service and register synchronizable managers. */
ephy_shell->sync_service = ephy_sync_service_new ();
if (g_settings_get_boolean (EPHY_SETTINGS_SYNC, EPHY_PREFS_SYNC_BOOKMARKS_ENABLED))
@@ -618,6 +621,7 @@ ephy_shell_dispose (GObject *object)
g_clear_object (&shell->network_monitor);
g_clear_object (&shell->sync_service);
g_clear_object (&shell->bookmarks_manager);
+ g_clear_object (&shell->password_manager);
g_slist_free_full (shell->open_uris_idle_ids, remove_open_uris_idle_cb);
shell->open_uris_idle_ids = NULL;
@@ -805,6 +809,22 @@ ephy_shell_get_bookmarks_manager (EphyShell *shell)
}
/**
+ * ephy_shell_get_password_manager:
+ * @shell: the #EphyShell
+ *
+ * Returns the passwords manager.
+ *
+ * Return value: (transfer none): An #EphyPasswordManager.
+ */
+EphyPasswordManager *
+ephy_shell_get_password_manager (EphyShell *shell)
+{
+ g_return_val_if_fail (EPHY_IS_SHELL (shell), NULL);
+
+ return shell->password_manager;
+}
+
+/**
* ephy_shell_get_net_monitor:
*
* Return value: (transfer none):
diff --git a/src/ephy-shell.h b/src/ephy-shell.h
index bd79449..6734d82 100644
--- a/src/ephy-shell.h
+++ b/src/ephy-shell.h
@@ -25,6 +25,7 @@
#include "ephy-bookmarks-manager.h"
#include "ephy-embed-shell.h"
#include "ephy-embed.h"
+#include "ephy-password-manager.h"
#include "ephy-session.h"
#include "ephy-sync-service.h"
#include "ephy-window.h"
@@ -102,6 +103,8 @@ GNetworkMonitor *ephy_shell_get_net_monitor (EphyShell *shell);
EphyBookmarksManager *ephy_shell_get_bookmarks_manager (EphyShell *shell);
+EphyPasswordManager *ephy_shell_get_password_manager (EphyShell *shell);
+
EphySyncService *ephy_shell_get_sync_service (EphyShell *shell);
GtkWidget *ephy_shell_get_history_dialog (EphyShell *shell);
diff --git a/src/passwords-dialog.c b/src/passwords-dialog.c
index fcdaafa..2f0637f 100644
--- a/src/passwords-dialog.c
+++ b/src/passwords-dialog.c
@@ -27,7 +27,6 @@
#define SECRET_API_SUBJECT_TO_CHANGE
#include <libsecret/secret.h>
-#include "ephy-form-auth-data.h"
#include "ephy-uri-helpers.h"
#include "passwords-dialog.h"
@@ -39,14 +38,11 @@ typedef enum {
COL_PASSWORDS_DATA,
} PasswordsDialogColumn;
-#define URI_KEY "uri"
-#define FORM_USERNAME_KEY "form_username"
-#define FORM_PASSWORD_KEY "form_password"
-#define USERNAME_KEY "username"
-
struct _EphyPasswordsDialog {
GtkDialog parent_instance;
+ EphyPasswordManager *manager;
+ GSList *records;
GtkWidget *passwords_treeview;
GtkTreeSelection *tree_selection;
GtkWidget *liststore;
@@ -59,8 +55,6 @@ struct _EphyPasswordsDialog {
GActionGroup *action_group;
- SecretService *ss;
- GCancellable *ss_cancellable;
gboolean filled;
char *search_text;
@@ -83,31 +77,13 @@ ephy_passwords_dialog_dispose (GObject *object)
{
EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (object);
- if (dialog->ss_cancellable != NULL) {
- g_cancellable_cancel (dialog->ss_cancellable);
- g_clear_object (&(dialog->ss_cancellable));
- }
-
- g_clear_object (&(dialog->ss));
g_free (dialog->search_text);
dialog->search_text = NULL;
- G_OBJECT_CLASS (ephy_passwords_dialog_parent_class)->dispose (object);
-}
-
-static void
-secret_remove_ready_cb (GObject *source,
- GAsyncResult *res,
- EphyPasswordsDialog *dialog)
-{
- secret_item_delete_finish (SECRET_ITEM (source), res, NULL);
-}
+ g_slist_free_full (dialog->records, g_object_unref);
+ dialog->records = NULL;
-static void
-secret_remove (EphyPasswordsDialog *dialog,
- SecretItem *item)
-{
- secret_item_delete (item, NULL, (GAsyncReadyCallback)secret_remove_ready_cb, dialog);
+ G_OBJECT_CLASS (ephy_passwords_dialog_parent_class)->dispose (object);
}
static void
@@ -155,15 +131,21 @@ forget (GSimpleAction *action,
/* Removal */
for (r = rlist; r != NULL; r = r->next) {
GValue val = { 0, };
- SecretItem *item;
+ EphyPasswordRecord *record;
GtkTreeIter filter_iter;
GtkTreeIter child_iter;
path = gtk_tree_row_reference_get_path ((GtkTreeRowReference *)r->data);
gtk_tree_model_get_iter (model, &iter, path);
gtk_tree_model_get_value (model, &iter, COL_PASSWORDS_DATA, &val);
- item = g_value_get_object (&val);
- secret_remove (dialog, item);
+ record = g_value_get_object (&val);
+ ephy_password_manager_forget (dialog->manager,
+ ephy_password_record_get_origin (record),
+ ephy_password_record_get_form_username (record),
+ ephy_password_record_get_form_password (record),
+ ephy_password_record_get_username (record));
+ dialog->records = g_slist_remove (dialog->records, record);
+ g_object_unref (record);
g_value_unset (&val);
gtk_tree_model_sort_convert_iter_to_child_iter (GTK_TREE_MODEL_SORT (dialog->treemodelsort),
@@ -362,105 +344,53 @@ ephy_passwords_dialog_class_init (EphyPasswordsDialogClass *klass)
}
static void
-delete_all_passwords_ready_cb (GObject *source_object,
- GAsyncResult *res,
- EphyPasswordsDialog *dialog)
-{
- secret_service_clear_finish (dialog->ss, res, NULL);
- reload_model (dialog);
-}
-
-static void
forget_all (GSimpleAction *action,
GVariant *parameter,
gpointer user_data)
{
EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (user_data);
- GHashTable *attributes;
-
- attributes = secret_attributes_build (EPHY_FORM_PASSWORD_SCHEMA, NULL);
- secret_service_clear (dialog->ss,
- EPHY_FORM_PASSWORD_SCHEMA,
- attributes,
- dialog->ss_cancellable,
- (GAsyncReadyCallback)delete_all_passwords_ready_cb,
- dialog);
- g_hash_table_unref (attributes);
+
+ ephy_password_manager_forget_all (dialog->manager);
+ g_slist_free_full (dialog->records, g_object_unref);
+ dialog->records = NULL;
+
+ reload_model (dialog);
}
static void
-secrets_search_ready_cb (GObject *source_object,
- GAsyncResult *res,
- EphyPasswordsDialog *dialog)
+populate_model_cb (GSList *records,
+ gpointer user_data)
{
- GList *matches;
- GList *l;
-
- matches = secret_service_search_finish (dialog->ss, res, NULL);
-
- for (l = matches; l != NULL; l = l->next) {
- SecretItem *item = l->data;
- SecretValue *value = NULL;
- GHashTable *attributes = NULL;
- const char *username = NULL;
- const char *password = NULL;
- char *origin = NULL;
- GtkTreeIter iter;
+ EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (user_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);
- origin = ephy_uri_to_security_origin (g_hash_table_lookup (attributes, URI_KEY));
- if (origin == NULL) {
- g_hash_table_unref (attributes);
- continue;
- }
+ for (GSList *l = records; l && l->data; l = l->next) {
+ EphyPasswordRecord *record = EPHY_PASSWORD_RECORD (l->data);
+ GtkTreeIter iter;
gtk_list_store_insert_with_values (GTK_LIST_STORE (dialog->liststore),
&iter,
-1,
- COL_PASSWORDS_ORIGIN, origin,
- COL_PASSWORDS_USER, username,
- COL_PASSWORDS_PASSWORD, password,
+ COL_PASSWORDS_ORIGIN, ephy_password_record_get_origin (record),
+ COL_PASSWORDS_USER, ephy_password_record_get_username (record),
+ COL_PASSWORDS_PASSWORD, ephy_password_record_get_password (record),
COL_PASSWORDS_INVISIBLE, "●●●●●●●●",
- COL_PASSWORDS_DATA, item,
+ COL_PASSWORDS_DATA, record,
-1);
-
- g_free (origin);
- g_hash_table_unref (attributes);
}
- g_list_free_full (matches, g_object_unref);
+ dialog->records = records;
}
static void
populate_model (EphyPasswordsDialog *dialog)
{
- GHashTable *attributes;
-
+ g_assert (EPHY_IS_PASSWORDS_DIALOG (dialog));
g_assert (dialog->filled == FALSE);
- attributes = secret_attributes_build (EPHY_FORM_PASSWORD_SCHEMA, NULL);
-
- secret_service_search (dialog->ss,
- EPHY_FORM_PASSWORD_SCHEMA,
- attributes,
- SECRET_SEARCH_ALL | SECRET_SEARCH_UNLOCK | SECRET_SEARCH_LOAD_SECRETS,
- dialog->ss_cancellable,
- (GAsyncReadyCallback)secrets_search_ready_cb,
- dialog);
-
- g_hash_table_unref (attributes);
-}
-
-static void
-secrets_ready_cb (GObject *source_object,
- GAsyncResult *res,
- EphyPasswordsDialog *dialog)
-{
- dialog->ss = secret_service_get_finish (res, NULL);
- populate_model (dialog);
+ /* Ask for all password records. */
+ ephy_password_manager_query (dialog->manager,
+ NULL, NULL, NULL, NULL,
+ populate_model_cb, dialog);
}
static gboolean
@@ -511,6 +441,15 @@ create_action_group (EphyPasswordsDialog *dialog)
}
static void
+show_dialog_cb (GtkWidget *widget,
+ gpointer user_data)
+{
+ EphyPasswordsDialog *dialog = EPHY_PASSWORDS_DIALOG (widget);
+
+ populate_model (dialog);
+}
+
+static void
ephy_passwords_dialog_init (EphyPasswordsDialog *dialog)
{
gtk_widget_init_template (GTK_WIDGET (dialog));
@@ -520,22 +459,23 @@ ephy_passwords_dialog_init (EphyPasswordsDialog *dialog)
dialog,
NULL);
- dialog->ss_cancellable = g_cancellable_new ();
- secret_service_get (SECRET_SERVICE_OPEN_SESSION | SECRET_SERVICE_LOAD_COLLECTIONS,
- dialog->ss_cancellable,
- (GAsyncReadyCallback)secrets_ready_cb,
- dialog);
-
dialog->action_group = create_action_group (dialog);
gtk_widget_insert_action_group (GTK_WIDGET (dialog), "passwords", dialog->action_group);
update_selection_actions (G_ACTION_MAP (dialog->action_group), FALSE);
+
+ g_signal_connect (GTK_WIDGET (dialog), "show", G_CALLBACK (show_dialog_cb), NULL);
}
EphyPasswordsDialog *
-ephy_passwords_dialog_new (void)
+ephy_passwords_dialog_new (EphyPasswordManager *manager)
{
- return g_object_new (EPHY_TYPE_PASSWORDS_DIALOG,
- "use-header-bar", TRUE,
- NULL);
+ EphyPasswordsDialog *dialog;
+
+ dialog = EPHY_PASSWORDS_DIALOG (g_object_new (EPHY_TYPE_PASSWORDS_DIALOG,
+ "use-header-bar", TRUE,
+ NULL));
+ dialog->manager = manager;
+
+ return dialog;
}
diff --git a/src/passwords-dialog.h b/src/passwords-dialog.h
index 02a256d..eafbf2a 100644
--- a/src/passwords-dialog.h
+++ b/src/passwords-dialog.h
@@ -20,11 +20,13 @@
#pragma once
+#include "ephy-password-manager.h"
+
G_BEGIN_DECLS
#define EPHY_TYPE_PASSWORDS_DIALOG (ephy_passwords_dialog_get_type ())
G_DECLARE_FINAL_TYPE (EphyPasswordsDialog, ephy_passwords_dialog, EPHY, PASSWORDS_DIALOG, GtkDialog);
-EphyPasswordsDialog *ephy_passwords_dialog_new (void);
+EphyPasswordsDialog *ephy_passwords_dialog_new (EphyPasswordManager *manager);
G_END_DECLS
diff --git a/src/prefs-dialog.c b/src/prefs-dialog.c
index 5148a17..ddc44c2 100644
--- a/src/prefs-dialog.c
+++ b/src/prefs-dialog.c
@@ -533,8 +533,10 @@ on_manage_passwords_button_clicked (GtkWidget *button,
PrefsDialog *dialog)
{
EphyPasswordsDialog *passwords_dialog;
+ EphyPasswordManager *password_manager;
- passwords_dialog = ephy_passwords_dialog_new ();
+ password_manager = ephy_shell_get_password_manager (ephy_shell_get_default ());
+ passwords_dialog = ephy_passwords_dialog_new (password_manager);
gtk_window_set_transient_for (GTK_WINDOW (passwords_dialog), GTK_WINDOW (dialog));
gtk_window_set_modal (GTK_WINDOW (passwords_dialog), TRUE);
diff --git a/src/profile-migrator/ephy-profile-migrator.c b/src/profile-migrator/ephy-profile-migrator.c
index 91eb262..1f19ebf 100644
--- a/src/profile-migrator/ephy-profile-migrator.c
+++ b/src/profile-migrator/ephy-profile-migrator.c
@@ -34,8 +34,8 @@
#include "ephy-bookmarks-manager.h"
#include "ephy-debug.h"
#include "ephy-file-helpers.h"
-#include "ephy-form-auth-data.h"
#include "ephy-history-service.h"
+#include "ephy-password-manager.h"
#include "ephy-prefs.h"
#include "ephy-profile-utils.h"
#include "ephy-search-engine-manager.h"
@@ -285,7 +285,7 @@ store_form_auth_data_cb (GObject *object,
{
GError *error = NULL;
- if (ephy_form_auth_data_store_finish (res, &error) == FALSE) {
+ if (ephy_password_manager_store_finish (res, &error) == FALSE) {
g_warning ("Couldn't store a form password: %s", error->message);
g_error_free (error);
goto out;
@@ -348,13 +348,13 @@ load_collection_items_cb (SecretCollection *collection,
secret_item_load_secret_sync (item, NULL, NULL);
secret = secret_item_get_secret (item);
password = secret_value_get (secret, NULL);
- ephy_form_auth_data_store (actual_server,
- form_username,
- form_password,
- username,
- password,
- (GAsyncReadyCallback)store_form_auth_data_cb,
- g_hash_table_ref (attributes));
+ ephy_password_manager_store (actual_server,
+ form_username,
+ form_password,
+ username,
+ password,
+ (GAsyncReadyCallback)store_form_auth_data_cb,
+ g_hash_table_ref (attributes));
g_free (actual_server);
secret_value_unref (secret);
g_hash_table_unref (t);
diff --git a/src/resources/gtk/passwords-dialog.ui b/src/resources/gtk/passwords-dialog.ui
index 7c69985..dd9b1a2 100644
--- a/src/resources/gtk/passwords-dialog.ui
+++ b/src/resources/gtk/passwords-dialog.ui
@@ -12,7 +12,7 @@
<!-- column-name INVISIBLE -->
<column type="gchararray"/>
<!-- column-name DATA -->
- <column type="SecretItem"/>
+ <column type="EphyPasswordRecord"/>
</columns>
</object>
<object class="GtkTreeModelFilter" id="treemodelfilter">
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]