[epiphany] Store HTTP Auth passwords in password manager



commit e4ebf2b37dfc753e29967fd4c55606cf8197ae14
Author: Jan-Michael Brummer <jan brummer tabos org>
Date:   Sun May 3 11:48:01 2020 +0200

    Store HTTP Auth passwords in password manager
    
    Fixes: https://gitlab.gnome.org/GNOME/epiphany/-/issues/719

 embed/ephy-auth-dialog.c | 213 +++++++++++++++++++++++++++++++++++++++++++++++
 embed/ephy-auth-dialog.h |  36 ++++++++
 embed/ephy-web-view.c    |  13 ++-
 embed/meson.build        |   1 +
 4 files changed, 261 insertions(+), 2 deletions(-)
---
diff --git a/embed/ephy-auth-dialog.c b/embed/ephy-auth-dialog.c
new file mode 100644
index 000000000..78f758fa6
--- /dev/null
+++ b/embed/ephy-auth-dialog.c
@@ -0,0 +1,213 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2020 Jan-Michael Brummer <jan brummer tabos org>
+ *
+ *  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 <glib/gi18n.h>
+#include <webkit2/webkit2.h>
+
+#include "ephy-auth-dialog.h"
+
+struct _EphyAuthDialog {
+  GtkMessageDialog parent_instance;
+
+  WebKitAuthenticationRequest *request;
+
+  GtkWidget *username;
+  GtkWidget *password;
+  GtkWidget *remember;
+};
+
+G_DEFINE_TYPE (EphyAuthDialog, ephy_auth_dialog, GTK_TYPE_MESSAGE_DIALOG)
+
+enum {
+  PROP_0,
+  PROP_REQUEST,
+  LAST_PROP
+};
+
+static GParamSpec *obj_properties[LAST_PROP];
+
+static void
+ephy_auth_dialog_init (EphyAuthDialog *self)
+{
+}
+
+static void
+ephy_auth_dialog_set_property (GObject      *object,
+                               guint         prop_id,
+                               const GValue *value,
+                               GParamSpec   *pspec)
+{
+  EphyAuthDialog *dialog = EPHY_AUTH_DIALOG (object);
+
+  switch (prop_id) {
+    case PROP_REQUEST:
+      dialog->request = (WebKitAuthenticationRequest *)g_value_get_object (value);
+      break;
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+  }
+}
+
+static void
+ephy_auth_dialog_response_cb (GtkDialog *dialog,
+                              gint       response_id,
+                              gpointer   user_data)
+{
+  EphyAuthDialog *self = EPHY_AUTH_DIALOG (dialog);
+  EphyPasswordManager *manager = ephy_embed_shell_get_password_manager (EPHY_EMBED_SHELL 
(ephy_embed_shell_get_default ()));
+  WebKitCredential *credential = NULL;
+
+  if (response_id == GTK_RESPONSE_OK) {
+    credential = webkit_credential_new (gtk_entry_get_text (GTK_ENTRY (self->username)),
+                                        gtk_entry_get_text (GTK_ENTRY (self->password)),
+                                        WEBKIT_CREDENTIAL_PERSISTENCE_NONE);
+  }
+
+  webkit_authentication_request_authenticate (self->request, credential);
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->remember))) {
+    ephy_password_manager_save (manager,
+                                webkit_authentication_request_get_host (self->request),
+                                webkit_authentication_request_get_host (self->request),
+                                gtk_entry_get_text (GTK_ENTRY (self->username)),
+                                gtk_entry_get_text (GTK_ENTRY (self->password)),
+                                "",
+                                "",
+                                TRUE);
+  }
+
+  gtk_widget_destroy (GTK_WIDGET (self));
+}
+
+static void
+ephy_auth_dialog_constructed (GObject *object)
+{
+  EphyAuthDialog *self = EPHY_AUTH_DIALOG (object);
+  GtkWidget *content_area;
+  GtkWidget *content_grid;
+  GtkWidget *grid;
+  GtkWidget *label;
+  g_autofree char *realm_text = NULL;
+  const char *realm;
+  WebKitCredential *credential;
+
+  G_OBJECT_CLASS (ephy_auth_dialog_parent_class)->constructed (object);
+
+  gtk_dialog_add_button (GTK_DIALOG (self), _("_Cancel"), GTK_RESPONSE_CANCEL);
+  gtk_dialog_add_button (GTK_DIALOG (self), _("_Authenticate"), GTK_RESPONSE_OK);
+
+  credential = webkit_authentication_request_get_proposed_credential (self->request);
+
+  gtk_window_set_title (GTK_WINDOW (self), _("Authentication Required"));
+
+  content_grid = gtk_grid_new ();
+
+  grid = gtk_grid_new ();
+  gtk_grid_set_row_spacing (GTK_GRID (grid), 12);
+  gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+  gtk_grid_attach (GTK_GRID (content_grid), grid, 0, 0, 1, 1);
+
+  realm = webkit_authentication_request_get_realm (self->request);
+  if (realm && strlen (realm) > 0)
+    realm_text = g_strdup_printf ("\n%s \"%s\"", _("The site says:"), realm);
+
+  gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (self),
+                                            "%s %s:%d%s",
+                                            _("Authentication required by"),
+                                            webkit_authentication_request_get_host (self->request),
+                                            webkit_authentication_request_get_port (self->request),
+                                            realm_text ? realm_text : "");
+
+  label = gtk_label_new_with_mnemonic (_("_Username"));
+  gtk_label_set_xalign (GTK_LABEL (label), 1);
+  gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 0, 1, 1);
+
+  self->username = gtk_entry_new ();
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->username);
+  if (credential)
+    gtk_entry_set_text (GTK_ENTRY (self->username), webkit_credential_get_username (credential));
+
+  gtk_widget_set_hexpand (self->username, TRUE);
+  gtk_grid_attach (GTK_GRID (grid), self->username, 1, 0, 1, 1);
+
+  label = gtk_label_new_with_mnemonic (_("_Password"));
+  gtk_label_set_xalign (GTK_LABEL (label), 1);
+  gtk_style_context_add_class (gtk_widget_get_style_context (label), GTK_STYLE_CLASS_DIM_LABEL);
+  gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
+
+  self->password = gtk_entry_new ();
+  gtk_label_set_mnemonic_widget (GTK_LABEL (label), self->password);
+  if (credential)
+    gtk_entry_set_text (GTK_ENTRY (self->username), webkit_credential_get_password (credential));
+
+  gtk_entry_set_visibility (GTK_ENTRY (self->password), FALSE);
+  gtk_widget_set_hexpand (self->password, TRUE);
+  gtk_grid_attach (GTK_GRID (grid), self->password, 1, 1, 1, 1);
+
+  self->remember = gtk_check_button_new_with_mnemonic (_("_Remember password"));
+  gtk_label_set_line_wrap (GTK_LABEL (gtk_bin_get_child (GTK_BIN (self->remember))), TRUE);
+  gtk_grid_attach (GTK_GRID (grid), self->remember, 0, 2, 2, 1);
+
+  content_area = gtk_message_dialog_get_message_area (GTK_MESSAGE_DIALOG (self));
+  gtk_container_add (GTK_CONTAINER (content_area), content_grid);
+
+  gtk_window_set_position (GTK_WINDOW (self), GTK_WIN_POS_CENTER);
+  gtk_window_set_modal (GTK_WINDOW (self), TRUE);
+
+  g_signal_connect (self, "response", G_CALLBACK (ephy_auth_dialog_response_cb), NULL);
+}
+
+static void
+ephy_auth_dialog_finalize (GObject *object)
+{
+  EphyAuthDialog *self = EPHY_AUTH_DIALOG (object);
+
+  g_clear_object (&self->request);
+
+  G_OBJECT_CLASS (ephy_auth_dialog_parent_class)->finalize (object);
+}
+
+static void
+ephy_auth_dialog_class_init (EphyAuthDialogClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->constructed = ephy_auth_dialog_constructed;
+  object_class->finalize = ephy_auth_dialog_finalize;
+  object_class->set_property = ephy_auth_dialog_set_property;
+
+  obj_properties[PROP_REQUEST] =
+    g_param_spec_object ("request",
+                         "WebKitAuthenticationRequest",
+                         "WebKit Authentication Request",
+                         WEBKIT_TYPE_AUTHENTICATION_REQUEST,
+                         G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
+
+  g_object_class_install_properties (object_class, LAST_PROP, obj_properties);
+}
+
+GtkWidget *
+ephy_auth_dialog_new (WebKitAuthenticationRequest *request)
+{
+  g_assert (request != NULL);
+
+  return g_object_new (EPHY_TYPE_AUTH_DIALOG, "request", request, NULL);
+}
diff --git a/embed/ephy-auth-dialog.h b/embed/ephy-auth-dialog.h
new file mode 100644
index 000000000..546228baf
--- /dev/null
+++ b/embed/ephy-auth-dialog.h
@@ -0,0 +1,36 @@
+/* -*- Mode: C; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/*
+ *  Copyright © 2020 Jan-Michael Brummer <jan brummer tabos org>
+ *
+ *  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 <gtk/gtk.h>
+#define HANDY_USE_UNSTABLE_API
+#include <handy.h>
+
+#include "ephy-web-view.h"
+
+G_BEGIN_DECLS
+
+#define EPHY_TYPE_AUTH_DIALOG (ephy_auth_dialog_get_type ())
+
+G_DECLARE_FINAL_TYPE (EphyAuthDialog, ephy_auth_dialog, EPHY, AUTH_DIALOG, GtkMessageDialog)
+
+GtkWidget *ephy_auth_dialog_new           (WebKitAuthenticationRequest *request);
+
diff --git a/embed/ephy-web-view.c b/embed/ephy-web-view.c
index aa5316dff..8132ac011 100644
--- a/embed/ephy-web-view.c
+++ b/embed/ephy-web-view.c
@@ -23,6 +23,7 @@
 #include "ephy-web-view.h"
 
 #include "ephy-about-handler.h"
+#include "ephy-auth-dialog.h"
 #include "ephy-debug.h"
 #include "ephy-embed-container.h"
 #include "ephy-embed-prefs.h"
@@ -2355,12 +2356,14 @@ authenticate_cb (WebKitWebView               *web_view,
                  WebKitAuthenticationRequest *request,
                  gpointer                     user_data)
 {
+  GtkWidget *dialog;
+  GtkWindow *window;
   EphyWebView *ephy_web_view = EPHY_WEB_VIEW (web_view);
   g_autoptr (WebKitCredential) credential = NULL;
 
   credential = webkit_authentication_request_get_proposed_credential (request);
 
-  /* In case we have known credentials and it is the firs try, authenticate automatically */
+  /* In case we have known credentials and it is the first try, authenticate automatically */
   if (credential && !webkit_authentication_request_is_retry (request)) {
     webkit_authentication_request_authenticate (request, credential);
     return TRUE;
@@ -2368,7 +2371,13 @@ authenticate_cb (WebKitWebView               *web_view,
 
   ephy_web_view->in_auth_dialog = 1;
 
-  return FALSE;
+  dialog = ephy_auth_dialog_new (g_object_ref (request));
+  window = gtk_application_get_active_window (GTK_APPLICATION (g_application_get_default ()));
+  gtk_window_set_transient_for (GTK_WINDOW (dialog), window);
+
+  gtk_widget_show_all (dialog);
+
+  return TRUE;
 }
 
 typedef struct {
diff --git a/embed/meson.build b/embed/meson.build
index bab0617ca..917334c05 100644
--- a/embed/meson.build
+++ b/embed/meson.build
@@ -13,6 +13,7 @@ enums = gnome.mkenums_simple('ephy-embed-type-builtins',
 libephyembed_sources = [
   'contrib/gd-tagged-entry.c',
   'ephy-about-handler.c',
+  'ephy-auth-dialog.c',
   'ephy-downloads-manager.c',
   'ephy-download.c',
   'ephy-embed.c',


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