]> www.fi.muni.cz Git - evince.git/commitdiff
Removed
authorCarlos Garcia Campos <carlosgc@gnome.org>
Mon, 1 Dec 2008 11:16:43 +0000 (11:16 +0000)
committerCarlos Garcia Campos <carlosgc@src.gnome.org>
Mon, 1 Dec 2008 11:16:43 +0000 (11:16 +0000)
2008-12-01  Carlos Garcia Campos  <carlosgc@gnome.org>

* configure.ac:
* shell/Makefile.am:
* shell/ev-keyring.[ch]:
* shell/ev-password.[ch]: Removed
* shell/ev-password-view.[ch]: (ev_password_view_finalize),
(ev_password_view_class_init), (ev_password_view_clicked_cb),
(ev_password_view_init), (ev_password_view_set_uri),
(ev_password_dialog_got_response),
(ev_password_dialog_remember_button_toggled),
(ev_password_dialog_entry_changed_cb),
(ev_password_dialog_entry_activated_cb),
(ev_password_view_ask_password), (ev_password_view_get_password),
(ev_password_view_get_password_save_flags),
(ev_password_view_new):
* shell/ev-window.c: (ev_window_password_view_unlock),
(ev_window_load_job_cb), (ev_window_close_dialogs),
(ev_window_init):

Rework the password view. When the password is in the keyring it's
used automatically without showing the password dialog and it's
only stored in the keyring when we are sure it's correct. The
password dialog has been reworked too, in order to make it
more hig compliant and consistent with the GTK+ dialog used in
gtkmountoperation. Fixes bug #562496.

svn path=/trunk/; revision=3281

ChangeLog
configure.ac
shell/Makefile.am
shell/ev-keyring.c [new file with mode: 0644]
shell/ev-keyring.h [new file with mode: 0644]
shell/ev-password-view.c
shell/ev-password-view.h
shell/ev-password.c [deleted file]
shell/ev-password.h [deleted file]
shell/ev-window.c

index 5e38e6043d31adcd18ba78170adbeab6c5a87daf..413f1dcfb61d231bee0ad19cdcf30daf88307188 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,30 @@
+2008-12-01  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+       * configure.ac:
+       * shell/Makefile.am:
+       * shell/ev-keyring.[ch]:
+       * shell/ev-password.[ch]: Removed
+       * shell/ev-password-view.[ch]: (ev_password_view_finalize),
+       (ev_password_view_class_init), (ev_password_view_clicked_cb),
+       (ev_password_view_init), (ev_password_view_set_uri),
+       (ev_password_dialog_got_response),
+       (ev_password_dialog_remember_button_toggled),
+       (ev_password_dialog_entry_changed_cb),
+       (ev_password_dialog_entry_activated_cb),
+       (ev_password_view_ask_password), (ev_password_view_get_password),
+       (ev_password_view_get_password_save_flags),
+       (ev_password_view_new):
+       * shell/ev-window.c: (ev_window_password_view_unlock),
+       (ev_window_load_job_cb), (ev_window_close_dialogs),
+       (ev_window_init):
+
+       Rework the password view. When the password is in the keyring it's
+       used automatically without showing the password dialog and it's  
+       only stored in the keyring when we are sure it's correct. The
+       password dialog has been reworked too, in order to make it
+       more hig compliant and consistent with the GTK+ dialog used in
+       gtkmountoperation. Fixes bug #562496. 
+       
 2008-11-29  Carlos Garcia Campos  <carlosgc@gnome.org>
 
        * backend/comics/comics-document.c: (comics_document_load):
index 3ddbdfe1da1166562b7c91720455b97eb247177a..a86f92fcb00b9b590a5b1f5a4cdcce8cbb2e8d31 100644 (file)
@@ -47,7 +47,7 @@ dnl Check dependencies
 DBUS_GLIB_REQUIRED=0.70
 GTK_REQUIRED=2.12.0
 GLIB_REQUIRED=2.15.6
-KEYRING_REQUIRED=0.4.0
+KEYRING_REQUIRED=2.22.0
 
 GNOME_ICON_THEME_REQUIRED=2.17.1
 LIBXML_REQUIRED=2.5.0
index b1dafd7a20f1e5e6da9f83770bf87a580b7eb2d1..1a1549427cab24e8e5957b7f8c677f91ceab2e0d 100644 (file)
@@ -38,6 +38,8 @@ evince_SOURCES=                               \
        ev-file-monitor.c               \
        ev-history.c                    \
        ev-history.h                    \
+       ev-keyring.h                    \
+       ev-keyring.c                    \
        ev-marshal.c                    \
        ev-marshal.h                    \
        $(DBUS_SOURCES)                 \
@@ -55,8 +57,6 @@ evince_SOURCES=                               \
        ev-page-action-widget.h         \
        ev-page-cache.h                 \
        ev-page-cache.c                 \
-       ev-password.h                   \
-       ev-password.c                   \
        ev-password-view.h              \
        ev-password-view.c              \
        ev-pixbuf-cache.c               \
diff --git a/shell/ev-keyring.c b/shell/ev-keyring.c
new file mode 100644 (file)
index 0000000..0199863
--- /dev/null
@@ -0,0 +1,116 @@
+/* ev-keyring.c
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "config.h"
+
+#include <glib/gi18n.h>
+
+#include "ev-keyring.h"
+
+#ifdef WITH_KEYRING
+#include <gnome-keyring.h>
+
+static const GnomeKeyringPasswordSchema doc_password_schema = {
+       GNOME_KEYRING_ITEM_GENERIC_SECRET,
+       {
+               { "type", GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
+               { "uri",  GNOME_KEYRING_ATTRIBUTE_TYPE_STRING },
+               { NULL, 0 }
+       }
+};
+const GnomeKeyringPasswordSchema *EV_DOCUMENT_PASSWORD_SCHEMA = &doc_password_schema;
+#endif /* WITH_KEYRING */
+
+gboolean
+ev_keyring_is_available (void)
+{
+#ifdef WITH_KEYRING
+       return gnome_keyring_is_available ();
+#else
+       return FALSE;
+#endif
+}
+
+gchar *
+ev_keyring_lookup_password (const gchar *uri)
+{
+       gchar             *retval = NULL;
+#ifdef WITH_KEYRING
+       GnomeKeyringResult result;
+       gchar             *password = NULL;
+       
+       g_return_val_if_fail (uri != NULL, NULL);
+
+       if (!gnome_keyring_is_available ())
+               return NULL;
+       
+       result = gnome_keyring_find_password_sync (EV_DOCUMENT_PASSWORD_SCHEMA,
+                                                  &password,
+                                                  "type", "document_password",
+                                                  "uri", uri,
+                                                  NULL);
+       if (result != GNOME_KEYRING_RESULT_OK || !password) {
+               if (password)
+                       gnome_keyring_free_password (password);
+               return NULL;
+       }
+
+       retval = g_strdup (password);
+       gnome_keyring_free_password (password);
+#endif /* WITH_KEYRING */
+       return retval;
+}
+
+gboolean
+ev_keyring_save_password (const gchar  *uri,
+                         const gchar  *password,
+                         GPasswordSave flags)
+{
+#ifdef WITH_KEYRING
+       GnomeKeyringResult result;
+       const gchar       *keyring;
+       gchar             *name;
+       gchar             *unescaped_uri;
+
+       g_return_val_if_fail (uri != NULL, FALSE);
+
+       if (!gnome_keyring_is_available ())
+               return FALSE;
+       
+       if (flags == G_PASSWORD_SAVE_NEVER)
+               return FALSE;
+
+       keyring = (flags == G_PASSWORD_SAVE_FOR_SESSION) ? "session" : NULL;
+       unescaped_uri = g_uri_unescape_string (uri, NULL);
+       name = g_strdup_printf (_("Password for document %s"), unescaped_uri);
+       g_free (unescaped_uri);
+       
+       result = gnome_keyring_store_password_sync (EV_DOCUMENT_PASSWORD_SCHEMA,
+                                                   keyring, name, password,
+                                                   "type", "document_password",
+                                                   "uri", uri,
+                                                   NULL);
+       g_free (name);
+
+       return (result == GNOME_KEYRING_RESULT_OK);
+#else
+       return FALSE;
+#endif /* WITH_KEYRING */
+}
diff --git a/shell/ev-keyring.h b/shell/ev-keyring.h
new file mode 100644 (file)
index 0000000..f51410e
--- /dev/null
@@ -0,0 +1,37 @@
+/* ev-keyring.h
+ *  this file is part of evince, a gnome document viewer
+ *
+ * Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
+ *
+ * Evince 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 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Evince 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 this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __EV_KEYRING_H__
+#define __EV_KEYRING_H__
+
+#include <glib.h>
+#include <gio/gio.h>
+
+G_BEGIN_DECLS
+
+gboolean ev_keyring_is_available    (void);
+gchar   *ev_keyring_lookup_password (const gchar  *uri);
+gboolean ev_keyring_save_password   (const gchar  *uri,
+                                    const gchar  *password,
+                                    GPasswordSave flags);
+
+G_END_DECLS
+
+#endif /* __EV_KEYRING_H__ */
index b53300d46c2bc49facdf34c70c400ee8ce0f289f..f7d0ca35ff6138b77086cb4d34cb15610758b6dd 100644 (file)
@@ -1,5 +1,6 @@
 /* this file is part of evince, a gnome document viewer
  *
+ *  Copyright (C) 2008 Carlos Garcia Campos <carlosgc@gnome.org>
  *  Copyright (C) 2005 Red Hat, Inc
  *
  * Evince is free software; you can redistribute it and/or modify it
@@ -24,8 +25,9 @@
 
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
+#include <gio/gio.h>
 
-#include "ev-marshal.h"
+#include "ev-keyring.h"
 #include "ev-password-view.h"
 
 enum {
@@ -33,7 +35,14 @@ enum {
        LAST_SIGNAL
 };
 struct _EvPasswordViewPrivate {
-       GtkWidget *label;
+       GtkWindow    *parent_window;
+       GtkWidget    *label;
+       GtkWidget    *password_entry;
+
+       gchar        *password;
+       GPasswordSave password_save;
+
+       GFile        *uri_file;
 };
 
 #define EV_PASSWORD_VIEW_GET_PRIVATE(object) \
@@ -44,6 +53,25 @@ static guint password_view_signals [LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE (EvPasswordView, ev_password_view, GTK_TYPE_VIEWPORT)
 
+static void
+ev_password_view_finalize (GObject *object)
+{
+       EvPasswordView *password_view = EV_PASSWORD_VIEW (object);
+
+       if (password_view->priv->password) {
+               g_free (password_view->priv->password);
+               password_view->priv->password = NULL;
+       }
+
+       password_view->priv->parent_window = NULL;
+
+       if (password_view->priv->uri_file) {
+               g_object_unref (password_view->priv->uri_file);
+               password_view->priv->uri_file = NULL;
+       }
+
+       G_OBJECT_CLASS (ev_password_view_parent_class)->finalize (object);
+}
 
 static void
 ev_password_view_class_init (EvPasswordViewClass *class)
@@ -54,23 +82,25 @@ ev_password_view_class_init (EvPasswordViewClass *class)
        g_object_class = G_OBJECT_CLASS (class);
        widget_class = GTK_WIDGET_CLASS (class);
 
-       password_view_signals [UNLOCK] =
+       password_view_signals[UNLOCK] =
                g_signal_new ("unlock",
                              G_TYPE_FROM_CLASS (g_object_class),
                              G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
                              G_STRUCT_OFFSET (EvPasswordViewClass, unlock),
                              NULL, NULL,
-                             ev_marshal_VOID__VOID,
+                             g_cclosure_marshal_VOID__VOID,
                              G_TYPE_NONE, 0);
 
        g_type_class_add_private (g_object_class, sizeof (EvPasswordViewPrivate));
+
+       g_object_class->finalize = ev_password_view_finalize;
 }
 
 static void
 ev_password_view_clicked_cb (GtkWidget      *button,
                             EvPasswordView *password_view)
 {
-       g_signal_emit (password_view, password_view_signals [UNLOCK], 0);
+       ev_password_view_ask_password (password_view);
 }
 
 static void
@@ -82,10 +112,12 @@ ev_password_view_init (EvPasswordView *password_view)
        GtkWidget *image;
        GtkWidget *button;
        GtkWidget *label;
-       gchar *markup;
+       gchar     *markup;
 
        password_view->priv = EV_PASSWORD_VIEW_GET_PRIVATE (password_view);
 
+       password_view->priv->password_save = G_PASSWORD_SAVE_NEVER;
+       
        gtk_widget_push_composite_child ();
 
        /* set ourselves up */
@@ -126,30 +158,274 @@ ev_password_view_init (EvPasswordView *password_view)
        gtk_widget_pop_composite_child ();
 }
 
-
 /* Public functions */
 void
-ev_password_view_set_file_name (EvPasswordView *password_view,
-                               const char     *file_name)
+ev_password_view_set_uri (EvPasswordView *password_view,
+                         const char     *uri)
 {
-       gchar *markup;
+       gchar *markup, *file_name;
+       GFile *file;
 
        g_return_if_fail (EV_IS_PASSWORD_VIEW (password_view));
-       g_return_if_fail (file_name != NULL);
-
-       markup = g_markup_printf_escaped ("<span size=\"x-large\" weight=\"bold\">%s</span>", file_name);
+       g_return_if_fail (uri != NULL);
+
+       file = g_file_new_for_uri (uri);
+       if (password_view->priv->uri_file &&
+           g_file_equal (file, password_view->priv->uri_file)) {
+               g_object_unref (file);
+               return;
+       }
+       if (password_view->priv->uri_file)
+               g_object_unref (password_view->priv->uri_file);
+       password_view->priv->uri_file = file;
+
+       file_name = g_file_get_basename (password_view->priv->uri_file);
+       markup = g_markup_printf_escaped ("<span size=\"x-large\" weight=\"bold\">%s</span>",
+                                         file_name);
+       g_free (file_name);
 
        gtk_label_set_markup (GTK_LABEL (password_view->priv->label), markup);
+       g_free (markup);
+}
+
+static void
+ev_password_dialog_got_response (GtkDialog      *dialog,
+                                gint            response_id,
+                                EvPasswordView *password_view)
+{
+       gtk_widget_set_sensitive (GTK_WIDGET (password_view), TRUE);
+       
+       if (response_id == GTK_RESPONSE_OK) {
+               g_free (password_view->priv->password);
+               password_view->priv->password =
+                       g_strdup (gtk_entry_get_text (GTK_ENTRY (password_view->priv->password_entry)));
+               
+               g_signal_emit (password_view, password_view_signals[UNLOCK], 0);
+       }
+       
+       gtk_widget_destroy (GTK_WIDGET (dialog));
+}
+
+static void
+ev_password_dialog_remember_button_toggled (GtkToggleButton *button,
+                                           EvPasswordView  *password_view)
+{
+       if (gtk_toggle_button_get_active (button)) {
+               gpointer data;
+               
+               data = g_object_get_data (G_OBJECT (button), "password-save");
+               password_view->priv->password_save = GPOINTER_TO_INT (data);
+       }
+}
+
+static void
+ev_password_dialog_entry_changed_cb (GtkEditable *editable,
+                                    GtkDialog   *dialog)
+{
+       const char *text;
+
+       text = gtk_entry_get_text (GTK_ENTRY (editable));
+
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), GTK_RESPONSE_OK,
+                                          (text != NULL && *text != '\0'));
+}
+
+static void
+ev_password_dialog_entry_activated_cb (GtkEntry  *entry,
+                                      GtkDialog *dialog)
+{
+       gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
+}
+
+void
+ev_password_view_ask_password (EvPasswordView *password_view)
+{
+       GtkDialog *dialog;
+       GtkWidget *entry_container;
+       GtkWidget *hbox, *main_vbox, *vbox, *icon;
+       GtkWidget *table;
+       GtkWidget *label;
+       gchar     *format, *markup, *file_name;
+
+       gtk_widget_set_sensitive (GTK_WIDGET (password_view), FALSE);
+       
+       dialog = GTK_DIALOG (gtk_dialog_new ());
+       
+       /* Set the dialog up with HIG properties */
+       gtk_dialog_set_has_separator (dialog, FALSE);
+       gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
+       gtk_box_set_spacing (GTK_BOX (dialog->vbox), 2); /* 2 * 5 + 2 = 12 */
+       gtk_container_set_border_width (GTK_CONTAINER (dialog->action_area), 5);
+       gtk_box_set_spacing (GTK_BOX (dialog->action_area), 6);
+
+       gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password"));
+       gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
+       gtk_window_set_icon_name (GTK_WINDOW (dialog), GTK_STOCK_DIALOG_AUTHENTICATION);
+       gtk_window_set_transient_for (GTK_WINDOW (dialog), password_view->priv->parent_window);
+       gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
+
+       gtk_dialog_add_buttons (dialog,
+                               GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                               _("_Unlock Document"), GTK_RESPONSE_OK,
+                               NULL);
+       gtk_dialog_set_default_response (dialog, GTK_RESPONSE_OK);
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog),
+                                          GTK_RESPONSE_OK, FALSE);
+       gtk_dialog_set_alternative_button_order (dialog,
+                                                GTK_RESPONSE_OK,
+                                                GTK_RESPONSE_CANCEL,
+                                                -1);
+       
+       /* Build contents */
+       hbox = gtk_hbox_new (FALSE, 12);
+       gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
+       gtk_box_pack_start (GTK_BOX (dialog->vbox), hbox, TRUE, TRUE, 0);
+       gtk_widget_show (hbox);
+
+       icon = gtk_image_new_from_stock (GTK_STOCK_DIALOG_AUTHENTICATION,
+                                        GTK_ICON_SIZE_DIALOG);
+
+       gtk_misc_set_alignment (GTK_MISC (icon), 0.5, 0.0);
+       gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
+       gtk_widget_show (icon);
+
+       main_vbox = gtk_vbox_new (FALSE, 18);
+       gtk_box_pack_start (GTK_BOX (hbox), main_vbox, TRUE, TRUE, 0);
+       gtk_widget_show (main_vbox);
 
+       label = gtk_label_new (NULL);
+       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+       gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
+       file_name = g_file_get_basename (password_view->priv->uri_file);
+       format = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n%s",
+                                 _("Password required"),
+                                 _("The document “%s” is locked and requires a password before it can be opened."));
+       markup = g_markup_printf_escaped (format, file_name);
+       gtk_label_set_markup (GTK_LABEL (label), markup);
+       g_free (format);
        g_free (markup);
+       g_free (file_name);
+       gtk_box_pack_start (GTK_BOX (main_vbox), label,
+                           FALSE, FALSE, 0);
+       gtk_widget_show (label);
+
+       vbox = gtk_vbox_new (FALSE, 6);
+       gtk_box_pack_start (GTK_BOX (main_vbox), vbox, FALSE, FALSE, 0);
+       gtk_widget_show (vbox);
+
+       /* The table that holds the entries */
+       entry_container = gtk_alignment_new (0.0, 0.0, 1.0, 1.0);
+
+       gtk_alignment_set_padding (GTK_ALIGNMENT (entry_container),
+                                  0, 0, 0, 0);
+       
+       gtk_box_pack_start (GTK_BOX (vbox), entry_container,
+                           FALSE, FALSE, 0);
+       gtk_widget_show (entry_container);
+
+       table = gtk_table_new (1, 2, FALSE);
+       gtk_table_set_col_spacings (GTK_TABLE (table), 12);
+       gtk_table_set_row_spacings (GTK_TABLE (table), 6);
+       gtk_container_add (GTK_CONTAINER (entry_container), table);
+       gtk_widget_show (table);
+
+       label = gtk_label_new_with_mnemonic (_("_Password:"));
+       gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+
+       password_view->priv->password_entry = gtk_entry_new ();
+       gtk_entry_set_visibility (GTK_ENTRY (password_view->priv->password_entry), FALSE);
+       g_signal_connect (password_view->priv->password_entry, "changed",
+                         G_CALLBACK (ev_password_dialog_entry_changed_cb),
+                         dialog);
+       g_signal_connect (password_view->priv->password_entry, "activate",
+                         G_CALLBACK (ev_password_dialog_entry_activated_cb),
+                         dialog);
+       gtk_table_attach (GTK_TABLE (table), label,
+                         0, 1, 0, 1,
+                         GTK_FILL, GTK_EXPAND | GTK_FILL, 0, 0);       
+       gtk_widget_show (label);
+
+       gtk_table_attach_defaults (GTK_TABLE (table), password_view->priv->password_entry,
+                                  1, 2, 0, 1);
+       gtk_widget_show (password_view->priv->password_entry);
+       
+       gtk_label_set_mnemonic_widget (GTK_LABEL (label),
+                                      password_view->priv->password_entry);
+
+       if (ev_keyring_is_available ()) {
+               GtkWidget  *choice;
+               GtkWidget  *remember_box;
+               GSList     *group;
+
+               remember_box = gtk_vbox_new (FALSE, 6);
+               gtk_box_pack_start (GTK_BOX (vbox), remember_box,
+                                   FALSE, FALSE, 0);
+               gtk_widget_show (remember_box);
+
+               choice = gtk_radio_button_new_with_mnemonic (NULL, _("Forget password _immediately"));
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
+                                             password_view->priv->password_save == G_PASSWORD_SAVE_NEVER);
+               g_object_set_data (G_OBJECT (choice), "password-save",
+                                  GINT_TO_POINTER (G_PASSWORD_SAVE_NEVER));
+               g_signal_connect (choice, "toggled",
+                                 G_CALLBACK (ev_password_dialog_remember_button_toggled),
+                                 password_view);
+               gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
+               gtk_widget_show (choice);
+
+               group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
+               choice = gtk_radio_button_new_with_mnemonic (group, _("Remember password until you _logout"));
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
+                                             password_view->priv->password_save == G_PASSWORD_SAVE_FOR_SESSION);
+               g_object_set_data (G_OBJECT (choice), "password-save",
+                                  GINT_TO_POINTER (G_PASSWORD_SAVE_FOR_SESSION));
+               g_signal_connect (choice, "toggled",
+                                 G_CALLBACK (ev_password_dialog_remember_button_toggled),
+                                 password_view);
+               gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
+               gtk_widget_show (choice);
+
+               group = gtk_radio_button_get_group (GTK_RADIO_BUTTON (choice));
+               choice = gtk_radio_button_new_with_mnemonic (group, _("Remember _forever"));
+               gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (choice),
+                                             password_view->priv->password_save == G_PASSWORD_SAVE_PERMANENTLY);
+               g_object_set_data (G_OBJECT (choice), "password-save",
+                                  GINT_TO_POINTER (G_PASSWORD_SAVE_PERMANENTLY));
+               g_signal_connect (choice, "toggled",
+                                 G_CALLBACK (ev_password_dialog_remember_button_toggled),
+                                 password_view);
+               gtk_box_pack_start (GTK_BOX (remember_box), choice, FALSE, FALSE, 0);
+               gtk_widget_show (choice);
+       }
+
+       g_signal_connect (G_OBJECT (dialog), "response",
+                         G_CALLBACK (ev_password_dialog_got_response),
+                         password_view);
+       
+       gtk_widget_show (GTK_WIDGET (dialog));
+}
+
+const gchar *
+ev_password_view_get_password (EvPasswordView *password_view)
+{
+       return password_view->priv->password;
+}
+
+GPasswordSave
+ev_password_view_get_password_save_flags (EvPasswordView *password_view)
+{
+       return password_view->priv->password_save;
 }
 
 GtkWidget *
-ev_password_view_new (void)
+ev_password_view_new (GtkWindow *parent)
 {
-       GtkWidget *retval;
+       EvPasswordView *retval;
+
+       retval = EV_PASSWORD_VIEW (g_object_new (EV_TYPE_PASSWORD_VIEW, NULL));
 
-       retval = (GtkWidget *) g_object_new (EV_TYPE_PASSWORD_VIEW, NULL);
+       retval->priv->parent_window = parent;
 
-       return retval;
+       return GTK_WIDGET (retval);
 }
+
index d59d62b4834ffed621c6b48ad739da9023b845e2..7f2670b22d0361ab568d73140ddd55917abf9d80 100644 (file)
@@ -21,6 +21,7 @@
 #define __EV_PASSWORD_VIEW_H__
 
 #include <gtk/gtk.h>
+#include <gio/gio.h>
 
 G_BEGIN_DECLS
 
@@ -34,6 +35,7 @@ typedef struct _EvPasswordViewPrivate EvPasswordViewPrivate;
 
 struct _EvPasswordView {
        GtkViewport parent_instance;
+       
        EvPasswordViewPrivate *priv;
 };
 
@@ -44,11 +46,13 @@ struct _EvPasswordViewClass {
        void (*unlock) (EvPasswordView  *self);
 };
 
-GType     ev_password_view_get_type      (void) G_GNUC_CONST;
-GtkWidget *ev_password_view_new           (void);
-void       ev_password_view_set_file_name (EvPasswordView *password_view,
-                                          const char     *file_name);
-
+GType        ev_password_view_get_type                (void) G_GNUC_CONST;
+GtkWidget    *ev_password_view_new                     (GtkWindow      *parent);
+void          ev_password_view_set_uri                 (EvPasswordView *password_view,
+                                                       const char     *uri);
+void          ev_password_view_ask_password            (EvPasswordView *password_view);
+const gchar  *ev_password_view_get_password            (EvPasswordView *password_view);
+GPasswordSave ev_password_view_get_password_save_flags (EvPasswordView *password_view);
 
 G_END_DECLS
 
diff --git a/shell/ev-password.c b/shell/ev-password.c
deleted file mode 100644 (file)
index a191b9f..0000000
+++ /dev/null
@@ -1,350 +0,0 @@
-/* this file is part of evince, a gnome document viewer
- *
- *  Copyright (C) 2005 Red Hat, Inc
- *
- * Evince 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 2 of the License, or
- * (at your option) any later version.
- *
- * Evince 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gi18n.h>
-#include <gio/gio.h>
-#include <gtk/gtk.h>
-#include <glade/glade.h>
-
-#ifdef WITH_KEYRING
-#include <gnome-keyring.h>
-#else
-#define gnome_keyring_is_available()   FALSE
-#endif
-
-#include "ev-password.h"
-
-enum {
-       PROP_0,
-       PROP_URI,
-};
-
-struct _EvPasswordDialogPrivate {
-       
-       gchar *uri;
-    
-       GtkWidget *bad_label;
-       GtkWidget *label;
-       GtkWidget *entry;
-       GtkWidget *check_default;
-       GtkWidget *check_session;
-};
-
-#define EV_PASSWORD_DIALOG_GET_PRIVATE(object) \
-       (G_TYPE_INSTANCE_GET_PRIVATE ((object), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogPrivate));
-
-G_DEFINE_TYPE (EvPasswordDialog, ev_password_dialog, GTK_TYPE_DIALOG)
-
-
-static void ev_password_dialog_entry_changed_cb   (GtkEditable *editable,
-                                                  EvPasswordDialog *dialog);
-static void ev_password_dialog_entry_activated_cb (GtkEntry *entry,
-                                                  EvPasswordDialog *dialog);
-static void ev_password_set_bad_password_label    (EvPasswordDialog *dialog,
-                                                  gchar     *message);
-static void ev_password_search_in_keyring         (EvPasswordDialog *dialog, 
-                                                  const gchar *uri);
-
-static void
-ev_password_dialog_set_property (GObject      *object,
-                                guint         prop_id,
-                                const GValue *value,
-                                GParamSpec   *pspec)
-{
-       EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (object);
-       char *format;
-       char *markup;
-       char *base_name;
-       GFile *file;
-
-       switch (prop_id) {
-       case PROP_URI:
-               dialog->priv->uri = g_strdup (g_value_get_string (value));
-               
-               file = g_file_new_for_uri (dialog->priv->uri);
-
-               base_name = g_file_get_basename (file);
-               format = g_strdup_printf ("<span size=\"larger\" weight=\"bold\">%s</span>\n\n%s",
-                                         _("Password required"),
-                                         _("The document “%s” is locked and requires a password before it can be opened."));
-               markup = g_markup_printf_escaped (format, base_name);
-
-               gtk_label_set_markup (GTK_LABEL (dialog->priv->label), markup);
-
-               g_free (base_name);
-               g_free (format);
-               g_free (markup);
-               g_object_unref (file);
-
-               ev_password_search_in_keyring (dialog, dialog->priv->uri);
-               break;
-       default:
-               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
-               break;
-       }
-}
-
-static void
-ev_password_dialog_finalize (GObject *object)
-{
-       EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (object);
-
-       if (dialog->priv->uri) {
-               g_free (dialog->priv->uri);
-               dialog->priv->uri = NULL;
-       }
-
-       G_OBJECT_CLASS (ev_password_dialog_parent_class)->finalize (object);
-}
-
-
-static void
-ev_password_dialog_class_init (EvPasswordDialogClass *class)
-{
-       GObjectClass *g_object_class;
-       GtkWidgetClass *widget_class;
-
-       g_object_class = G_OBJECT_CLASS (class);
-       widget_class = GTK_WIDGET_CLASS (class);
-
-       g_type_class_add_private (g_object_class, sizeof (EvPasswordDialogPrivate));
-
-       g_object_class->set_property = ev_password_dialog_set_property;
-       g_object_class->finalize = ev_password_dialog_finalize;
-       
-       g_object_class_install_property (g_object_class,
-                                        PROP_URI,
-                                        g_param_spec_string ("uri",
-                                                             "Document URI",
-                                                             "Encrypted document URI",
-                                                             NULL,
-                                                             G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY));
-}
-
-
-static void
-ev_password_dialog_init (EvPasswordDialog *dialog)
-{
-       GtkWidget *hbox;
-       const char *glade_file = DATADIR "/evince-password.glade";
-       GladeXML *xml;
-
-       dialog->priv = EV_PASSWORD_DIALOG_GET_PRIVATE (dialog);
-               
-       gtk_window_set_title (GTK_WINDOW (dialog), _("Enter password"));
-       gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
-       gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
-       gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
-       gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 12);
-
-       gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL,
-                              GTK_RESPONSE_CANCEL);
-       gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK,
-                              GTK_RESPONSE_OK);
-
-       xml = glade_xml_new (glade_file, "hbox-contents", NULL);
-       g_assert (xml);
-       
-       hbox = glade_xml_get_widget (xml, "hbox-contents");
-       gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
-
-       dialog->priv->bad_label = glade_xml_get_widget (xml, "bad_password_label");
-       dialog->priv->check_default = glade_xml_get_widget (xml, "savesession_checkbutton");
-       dialog->priv->check_session = glade_xml_get_widget (xml, "savekeyring_checkbutton");
-       dialog->priv->entry = glade_xml_get_widget (xml, "password_entry");
-       dialog->priv->label = glade_xml_get_widget (xml, "password_label");
-
-       g_signal_connect (dialog->priv->entry, "changed", G_CALLBACK (ev_password_dialog_entry_changed_cb), dialog);
-       g_signal_connect (dialog->priv->entry, "activate", G_CALLBACK (ev_password_dialog_entry_activated_cb), dialog);
-
-       ev_password_set_bad_password_label (dialog, " ");
-
-       if (!gnome_keyring_is_available ()) {
-               gtk_widget_hide (dialog->priv->check_default);
-               gtk_widget_hide (dialog->priv->check_session);
-       }
-
-       g_object_unref (xml);
-}
-
-static void
-ev_password_set_bad_password_label (EvPasswordDialog *dialog,
-                                   gchar     *message)
-{
-       gchar *markup;
-
-       markup = g_strdup_printf ("<span color=\"red\" size=\"smaller\">%s</span>",
-                                 message);
-       gtk_label_set_markup (GTK_LABEL (dialog->priv->bad_label), markup);
-       g_free (markup);
-}
-
-static void
-ev_password_dialog_entry_changed_cb (GtkEditable *editable,
-                                    EvPasswordDialog *dialog)
-{
-       const char *text;
-
-       text = gtk_entry_get_text (GTK_ENTRY (editable));
-
-       if (text == NULL || *text == '\0')
-               gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 
-                                                  GTK_RESPONSE_OK, FALSE);
-       else
-               gtk_dialog_set_response_sensitive (GTK_DIALOG (dialog), 
-                                                  GTK_RESPONSE_OK, TRUE);
-
-       ev_password_set_bad_password_label (dialog, " ");
-}
-
-static void
-ev_password_dialog_entry_activated_cb (GtkEntry *entry,
-                                      EvPasswordDialog *dialog)
-{
-       gtk_dialog_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
-}
-
-#ifdef WITH_KEYRING
-static void
-ev_password_item_created_callback (GnomeKeyringResult result,
-                                  guint32            val,
-                                  gpointer           data)
-{
-       /* Nothing yet */
-       return;
-}
-#endif
-
-void
-ev_password_dialog_save_password (EvPasswordDialog *dialog)
-{
-#ifdef WITH_KEYRING
-       GnomeKeyringAttributeList *attributes;
-       GnomeKeyringAttribute attribute;
-       gchar *name;
-       gchar *unescaped_uri;
-
-       attributes = gnome_keyring_attribute_list_new ();
-
-       attribute.name = g_strdup ("type");
-       attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
-       attribute.value.string = g_strdup ("document_password");
-       g_array_append_val (attributes, attribute);
-       attribute.name = g_strdup ("uri");
-       attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
-       attribute.value.string = g_strdup (dialog->priv->uri);
-       g_array_append_val (attributes, attribute);
-       
-       unescaped_uri = g_uri_unescape_string (dialog->priv->uri, NULL);
-       name = g_strdup_printf (_("Password for document %s"), unescaped_uri);  
-
-       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_default))) {
-               gnome_keyring_item_create (NULL,
-                                          GNOME_KEYRING_ITEM_GENERIC_SECRET,
-                                          name,
-                                          attributes,
-                                          ev_password_dialog_get_password (dialog),
-                                          TRUE, ev_password_item_created_callback, 
-                                          NULL, NULL);
-       }
-
-       if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->priv->check_session))) {
-               gnome_keyring_item_create ("session",
-                                          GNOME_KEYRING_ITEM_GENERIC_SECRET,
-                                          name,
-                                          attributes,
-                                          ev_password_dialog_get_password (dialog),
-                                          TRUE, ev_password_item_created_callback, 
-                                          NULL, NULL);
-       }
-       
-       gnome_keyring_attribute_list_free (attributes);
-       g_free (name);
-       g_free (unescaped_uri);
-
-#endif /* WITH_KEYRING */
-       return;
-}
-
-#ifdef WITH_KEYRING
-static void 
-ev_password_keyring_found_cb (GnomeKeyringResult result,
-                             GList             *list,
-                             gpointer           data)
-
-{
-       GnomeKeyringFound *found;
-       EvPasswordDialog *dialog = EV_PASSWORD_DIALOG (data);
-
-       if (result != GNOME_KEYRING_RESULT_OK || list == NULL) 
-                   return;
-
-       found = list->data;
-       gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), found->secret);
-}                        
-#endif /* WITH_KEYRING */
-
-static void
-ev_password_search_in_keyring (EvPasswordDialog *dialog, const gchar *uri)
-{
-#ifdef WITH_KEYRING
-       GnomeKeyringAttributeList *attributes;
-       GnomeKeyringAttribute attribute;
-       
-       attributes = gnome_keyring_attribute_list_new ();
-
-       attribute.name = g_strdup ("type");
-       attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
-       attribute.value.string = g_strdup ("document_password");
-       g_array_append_val (attributes, attribute);
-       attribute.name = g_strdup ("uri");
-       attribute.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
-       attribute.value.string = g_strdup (uri);
-       g_array_append_val (attributes, attribute);
-         
-       gnome_keyring_find_items  (GNOME_KEYRING_ITEM_GENERIC_SECRET,
-                                  attributes,
-                                  ev_password_keyring_found_cb,
-                                  g_object_ref (dialog),
-                                  g_object_unref);
-       gnome_keyring_attribute_list_free (attributes);
-#endif /* WITH_KEYRING */
-       return;
-}
-
-const char *
-ev_password_dialog_get_password (EvPasswordDialog *dialog)
-{
-       return gtk_entry_get_text (GTK_ENTRY (dialog->priv->entry));
-}
-
-void
-ev_password_dialog_set_bad_pass (EvPasswordDialog *dialog)
-{
-       gtk_entry_set_text (GTK_ENTRY (dialog->priv->entry), "");
-       ev_password_set_bad_password_label (dialog, _("Incorrect password"));
-}
-
-
diff --git a/shell/ev-password.h b/shell/ev-password.h
deleted file mode 100644 (file)
index d092cca..0000000
+++ /dev/null
@@ -1,58 +0,0 @@
-/* this file is part of evince, a gnome document viewer
- *
- *  Copyright (C) 2005 Red Hat, Inc
- *
- * Evince 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 2 of the License, or
- * (at your option) any later version.
- *
- * Evince 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 this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
- */
-
-#ifndef __EV_PASSWORD_H__
-#define __EV_PASSWORD_H__
-
-#include <gtk/gtk.h>
-
-G_BEGIN_DECLS
-
-#define EV_TYPE_PASSWORD_DIALOG            (ev_password_dialog_get_type ())
-#define EV_PASSWORD_DIALOG(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialog))
-#define EV_PASSWORD_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogClass))
-#define EV_IS_PASSWORD_DIALOG(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), EV_TYPE_PASSWORD_DIALOG))
-#define EV_IS_PASSWORD_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), EV_TYPE_PASSWORD_DIALOG))
-#define EV_PASSWORD_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), EV_TYPE_PASSWORD_DIALOG, EvPasswordDialogClass))
-
-typedef struct _EvPasswordDialog EvPasswordDialog;
-typedef struct _EvPasswordDialogClass EvPasswordDialogClass;
-typedef struct _EvPasswordDialogPrivate EvPasswordDialogPrivate;
-
-struct _EvPasswordDialog 
-{
-  GtkDialog parent_instance;
-
-  EvPasswordDialogPrivate* priv;
-};
-
-struct _EvPasswordDialogClass 
-{
-  GtkDialogClass parent_class;
-};
-
-GType       ev_password_dialog_get_type      (void) G_GNUC_CONST;
-
-const char *ev_password_dialog_get_password  (EvPasswordDialog *dialog);
-void        ev_password_dialog_set_bad_pass  (EvPasswordDialog *dialog);
-void       ev_password_dialog_save_password (EvPasswordDialog *dialog);
-
-G_END_DECLS
-
-#endif /* __EV_PASSWORD_H__ */
index 47ce4c77a5c4824893b4b1ee0cb64cf0727fb63a..c570de7f01cfcb417033fda19c28a0d4a008fed0 100644 (file)
@@ -73,7 +73,6 @@
 #include "ev-navigation-action.h"
 #include "ev-open-recent-action.h"
 #include "ev-page-action.h"
-#include "ev-password.h"
 #include "ev-password-view.h"
 #include "ev-properties-dialog.h"
 #include "ev-sidebar-attachments.h"
@@ -84,6 +83,7 @@
 #include "ev-sidebar-layers.h"
 #include "ev-stock-icons.h"
 #include "ev-utils.h"
+#include "ev-keyring.h"
 #include "ev-view.h"
 #include "ev-window.h"
 #include "ev-window-title.h"
@@ -135,7 +135,6 @@ struct _EvWindowPrivate {
        /* Dialogs */
        GtkWidget *properties;
        GtkWidget *print_dialog;
-       GtkWidget *password_dialog;
 
        /* UI Builders */
        GtkActionGroup   *action_group;
@@ -1256,57 +1255,15 @@ ev_window_document_changed (EvWindow *ev_window,
 }
 
 static void
-password_dialog_response (GtkWidget *password_dialog,
-                         gint       response_id,
-                         EvWindow  *ev_window)
-{
-       if (response_id == GTK_RESPONSE_OK) {
-               ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job),
-                                         ev_password_dialog_get_password (EV_PASSWORD_DIALOG (password_dialog)));
-
-               ev_password_dialog_save_password (EV_PASSWORD_DIALOG (password_dialog));
-
-               ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_DOCUMENT);
-               ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
-               
-               gtk_widget_destroy (password_dialog);
-                       
-               return;
-       }
-
-       gtk_widget_set_sensitive (ev_window->priv->password_view, TRUE);
-       gtk_widget_destroy (password_dialog);
-}
-
-/* Called either by ev_window_load_job_cb or by the "unlock" callback on the
- * password_view page.  It assumes that ev_window->priv->password_* has been set
- * correctly.  These are cleared by password_dialog_response() */
-
-static void
-ev_window_popup_password_dialog (EvWindow *ev_window)
+ev_window_password_view_unlock (EvWindow *ev_window)
 {
+       const gchar *password;
+       
        g_assert (ev_window->priv->load_job);
 
-       gtk_widget_set_sensitive (ev_window->priv->password_view, FALSE);
-
-       ev_window_title_set_uri (ev_window->priv->title, ev_window->priv->uri);
-       ev_window_title_set_type (ev_window->priv->title, EV_WINDOW_TITLE_PASSWORD);
-
-       if (ev_window->priv->password_dialog == NULL) {
-               ev_window->priv->password_dialog =
-                       g_object_new (EV_TYPE_PASSWORD_DIALOG, "uri", ev_window->priv->uri, NULL);
-               gtk_window_set_transient_for (GTK_WINDOW (ev_window->priv->password_dialog), GTK_WINDOW (ev_window));
-
-               g_object_add_weak_pointer (G_OBJECT (ev_window->priv->password_dialog),
-                                          (gpointer) &(ev_window->priv->password_dialog));
-               g_signal_connect (ev_window->priv->password_dialog,
-                                 "response",
-                                 G_CALLBACK (password_dialog_response),
-                                 ev_window);
-               gtk_widget_show (ev_window->priv->password_dialog);
-       } else {
-               ev_password_dialog_set_bad_pass (EV_PASSWORD_DIALOG (ev_window->priv->password_dialog));
-       }
+       password = ev_password_view_get_password (EV_PASSWORD_VIEW (ev_window->priv->password_view));
+       ev_job_load_set_password (EV_JOB_LOAD (ev_window->priv->load_job), password);
+       ev_job_scheduler_push_job (ev_window->priv->load_job, EV_JOB_PRIORITY_NONE);
 }
 
 static void
@@ -1406,6 +1363,18 @@ ev_window_load_job_cb (EvJob *job,
                        ev_window_add_recent (ev_window, ev_window->priv->uri);
                }
 
+               ev_window_title_set_type (ev_window->priv->title,
+                                         EV_WINDOW_TITLE_DOCUMENT);
+               if (job_load->password) {
+                       GPasswordSave flags;
+
+                       flags = ev_password_view_get_password_save_flags (
+                               EV_PASSWORD_VIEW (ev_window->priv->password_view));
+                       ev_keyring_save_password (ev_window->priv->uri,
+                                                 job_load->password,
+                                                 flags);
+               }
+
                if (job_load->dest) {
                        EvLink *link;
                        EvLinkAction *link_action;
@@ -1448,20 +1417,40 @@ ev_window_load_job_cb (EvJob *job,
 
        if (job->error->domain == EV_DOCUMENT_ERROR &&
            job->error->code == EV_DOCUMENT_ERROR_ENCRYPTED) {
-               GFile *file;
-               gchar *base_name;
-
+               gchar *password;
+               
                setup_view_from_metadata (ev_window);
+               
+               /* First look whether password is in keyring */
+               password = ev_keyring_lookup_password (ev_window->priv->uri);
+               if (password) {
+                       if (job_load->password && strcmp (password, job_load->password) == 0) {
+                               /* Password in kering is wrong */
+                               ev_job_load_set_password (job_load, NULL);
+                               /* FIXME: delete password from keyring? */
+                       } else {
+                               ev_job_load_set_password (job_load, password);
+                               ev_job_scheduler_push_job (job, EV_JOB_PRIORITY_NONE);
+                               g_free (password);
+                               return;
+                       }
+
+                       g_free (password);
+               }
+
+               /* We need to ask the user for a password */
+               ev_window_title_set_uri (ev_window->priv->title,
+                                        ev_window->priv->uri);
+               ev_window_title_set_type (ev_window->priv->title,
+                                         EV_WINDOW_TITLE_PASSWORD);
+
+               ev_password_view_set_uri (EV_PASSWORD_VIEW (ev_window->priv->password_view),
+                                         job_load->uri);
 
-               file = g_file_new_for_uri (job_load->uri);
-               base_name = g_file_get_basename (file);
-               ev_password_view_set_file_name (EV_PASSWORD_VIEW (ev_window->priv->password_view),
-                                               base_name);
-               g_object_unref (file);
-               g_free (base_name);
                ev_window_set_page_mode (ev_window, PAGE_MODE_PASSWORD);
-               
-               ev_window_popup_password_dialog (ev_window);
+
+               ev_job_load_set_password (job_load, NULL);
+               ev_password_view_ask_password (EV_PASSWORD_VIEW (ev_window->priv->password_view));
        } else {
                ev_window_error_message (ev_window, job->error, 
                                         "%s", _("Unable to open document"));
@@ -1518,10 +1507,6 @@ ev_window_get_uri (EvWindow *ev_window)
 static void
 ev_window_close_dialogs (EvWindow *ev_window)
 {
-       if (ev_window->priv->password_dialog)
-               gtk_widget_destroy (ev_window->priv->password_dialog);
-       ev_window->priv->password_dialog = NULL;
-       
        if (ev_window->priv->print_dialog)
                gtk_widget_destroy (ev_window->priv->print_dialog);
        ev_window->priv->print_dialog = NULL;
@@ -5650,10 +5635,10 @@ ev_window_init (EvWindow *ev_window)
        ev_window->priv->view = ev_view_new ();
        ev_view_set_screen_dpi (EV_VIEW (ev_window->priv->view),
                                get_screen_dpi (GTK_WINDOW (ev_window)));
-       ev_window->priv->password_view = ev_password_view_new ();
+       ev_window->priv->password_view = ev_password_view_new (GTK_WINDOW (ev_window));
        g_signal_connect_swapped (ev_window->priv->password_view,
                                  "unlock",
-                                 G_CALLBACK (ev_window_popup_password_dialog),
+                                 G_CALLBACK (ev_window_password_view_unlock),
                                  ev_window);
        g_signal_connect_object (ev_window->priv->view, "focus_in_event",
                                 G_CALLBACK (view_actions_focus_in_cb),