[gnome-keyring] Implement support for prompting for unlock options



commit 3aab72fc09aa0d70eb0915285d589e5a76d0a8f8
Author: Stef Walter <stef memberwebs com>
Date:   Mon Feb 1 02:27:40 2010 +0000

    Implement support for prompting for unlock options

 daemon/dbus/gkd-secret-unlock.c |  151 ++++++++++++++++++++++++++++++--------
 daemon/prompt/Makefile.am       |    2 +
 daemon/prompt/gkd-prompt-tool.c |   76 ++++++++++++--------
 daemon/prompt/gkd-prompt.c      |   50 +++++++++++++
 daemon/prompt/gkd-prompt.h      |    8 ++
 daemon/prompt/gkd-prompt.ui     |  123 +-------------------------------
 6 files changed, 228 insertions(+), 182 deletions(-)
---
diff --git a/daemon/dbus/gkd-secret-unlock.c b/daemon/dbus/gkd-secret-unlock.c
index 6fad92a..78d57c4 100644
--- a/daemon/dbus/gkd-secret-unlock.c
+++ b/daemon/dbus/gkd-secret-unlock.c
@@ -80,13 +80,31 @@ location_string_for_collection (GP11Object *collection)
 	return location;
 }
 
+static gchar*
+label_string_for_collection (GP11Object *collection)
+{
+	GError *error = NULL;
+	gpointer data;
+	gsize n_data;
+
+	data = gp11_object_get_data (collection, CKA_LABEL, &n_data, &error);
+	if (!data) {
+		g_warning ("couldn't get label for collection: %s", error->message);
+		g_clear_error (&error);
+	}
+
+	if (!data || !n_data)
+		return g_strdup (_("Unnamed"));
+	else /* gp11_object_get_data returns null terminated */
+		return data;
+}
+
 static void
 prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll)
 {
+	GP11Attributes *template;
 	GError *error = NULL;
 	GkdPrompt *prompt;
-	gpointer data;
-	gsize n_data;
 	gchar *label;
 	gchar *text;
 
@@ -95,17 +113,7 @@ prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll)
 
 	prompt = GKD_PROMPT (self);
 
-	data = gp11_object_get_data (coll, CKA_LABEL, &n_data, &error);
-	if (!data) {
-		g_warning ("couldn't get label for collection: %s", error->message);
-		g_clear_error (&error);
-	}
-
-	if (!data || !n_data)
-		label = g_strdup (_("Unnamed"));
-	else
-		label = g_strndup (data, n_data);
-	g_free (data);
+	label = label_string_for_collection (coll);
 
 	gkd_prompt_reset (prompt);
 
@@ -121,10 +129,21 @@ prepare_unlock_prompt (GkdSecretUnlock *self, GP11Object *coll)
 
 	gkd_prompt_hide_widget (prompt, "name_area");
 	gkd_prompt_hide_widget (prompt, "confirm_area");
-	gkd_prompt_hide_widget (prompt, "details_area");
+	gkd_prompt_show_widget (prompt, "details_area");
 	gkd_prompt_show_widget (prompt, "password_area");
+	gkd_prompt_show_widget (prompt, "lock_area");
 
 	g_free (label);
+
+	/* Setup the unlock options */
+	template = gp11_object_get_template (coll, CKA_G_CREDENTIAL_TEMPLATE, &error);
+	if (template) {
+		gkd_prompt_set_unlock_options (prompt, template);
+		gp11_attributes_unref (template);
+	} else {
+		g_warning ("couldn't get credential template for collection: %s", error->message);
+		g_clear_error (&error);
+	}
 }
 
 static void
@@ -154,21 +173,70 @@ check_locked_collection (GP11Object *collection, gboolean *locked)
 	return TRUE;
 }
 
+static void
+attach_credential_to_login (GP11Object *collection, GP11Object *cred)
+{
+	GError *error = NULL;
+	gpointer value;
+	gsize n_value;
+	gchar *location;
+	gchar *label;
+	gchar *display;
+
+	g_assert (GP11_IS_OBJECT (collection));
+	g_assert (GP11_IS_OBJECT (cred));
+
+	location = location_string_for_collection (collection);
+	label = label_string_for_collection (collection);
+	display = g_strdup_printf (_("Unlock password for %s keyring"), label);
+	g_free (label);
+
+	value = gp11_object_get_data_full (cred, CKA_VALUE, egg_secure_realloc, NULL, &n_value, &error);
+	if (value) {
+		if (g_utf8_validate (value, n_value, NULL))
+			gkd_login_attach_secret (display, value, "keyring", location, NULL);
+		else
+			g_warning ("couldn't save non utf-8 unlock credentials in login keyring");
+		egg_secure_clear (value, n_value);
+		egg_secure_free (value);
+
+	} else {
+		g_warning ("couldn't read unlock credentials to save in login keyring: %s", error->message);
+		g_clear_error (&error);
+	}
+
+	g_free (location);
+	g_free (display);
+}
+
+static void
+common_unlock_attributes (GP11Attributes *attrs, GP11Object *collection)
+{
+	g_assert (attrs);
+	g_assert (GP11_IS_OBJECT (collection));
+	gp11_attributes_add_ulong (attrs, CKA_CLASS, CKO_G_CREDENTIAL);
+	gp11_attributes_add_ulong (attrs, CKA_G_OBJECT, gp11_object_get_handle (collection));
+}
+
 static gboolean
 authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean *locked)
 {
 	DBusError derr = DBUS_ERROR_INIT;
 	GkdSecretSecret *master;
-	gboolean result;
+	GP11Attributes *template;
+	GP11Object *cred;
+	gboolean transient;
 
 	g_assert (GKD_SECRET_IS_UNLOCK (self));
 	g_assert (GP11_IS_OBJECT (collection));
 	g_assert (locked);
 
-	/* Bail out early, just checking locked status */
-	if (!gkd_prompt_has_response (GKD_PROMPT (self))) {
-		return check_locked_collection (collection, locked);
-	}
+	if (!check_locked_collection (collection, locked))
+		return FALSE;
+
+	/* Shortcut if already unlocked, or just checking locked status */
+	if (!*locked || !gkd_prompt_has_response (GKD_PROMPT (self)))
+		return TRUE;
 
 	master = gkd_secret_prompt_get_secret (GKD_SECRET_PROMPT (self), "password");
 	if (master == NULL) {
@@ -176,14 +244,33 @@ authenticate_collection (GkdSecretUnlock *self, GP11Object *collection, gboolean
 		return FALSE;
 	}
 
-	result = gkd_secret_unlock_with_secret (collection, master, &derr);
+	/* The various unlock options */
+	template = gp11_attributes_new ();
+	common_unlock_attributes (template, collection);
+	gkd_prompt_get_unlock_options (GKD_PROMPT (self), template);
+
+	/* If it's supposed to save non-transient, then we override that */
+	if (!gp11_attributes_find_boolean (template, CKA_GNOME_TRANSIENT, &transient))
+		transient = TRUE;
+
+	cred = gkd_secret_session_create_credential (master->session, NULL, template, master, &derr);
 	gkd_secret_secret_free (master);
 
-	if (result) {
+	if (cred) {
+		/* Save it to the login keyring */
+		if (!transient)
+			attach_credential_to_login (collection, cred);
+		g_object_unref (cred);
+
+		/* Save away the unlock options for next time */
+		gp11_object_set_template (collection, CKA_G_CREDENTIAL_TEMPLATE, template, NULL);
+		gp11_attributes_unref (template);
+
 		*locked = FALSE;
 		return TRUE; /* Operation succeeded, and unlocked */
 
 	} else {
+		gp11_attributes_unref (template);
 		if (dbus_error_has_name (&derr, INTERNAL_ERROR_DENIED)) {
 			dbus_error_free (&derr);
 			*locked = TRUE;
@@ -434,11 +521,10 @@ gkd_secret_unlock_with_secret (GP11Object *collection, GkdSecretSecret *master,
 	if (check_locked_collection (collection, &locked) && !locked)
 		return TRUE;
 
-	attrs = gp11_attributes_newv (CKA_CLASS, GP11_ULONG, CKO_G_CREDENTIAL,
-	                              CKA_G_OBJECT, GP11_ULONG, gp11_object_get_handle (collection),
-	                              CKA_GNOME_TRANSIENT, GP11_BOOLEAN, TRUE,
-	                              CKA_TOKEN, GP11_BOOLEAN, TRUE,
-	                              GP11_INVALID);
+	attrs = gp11_attributes_new ();
+	common_unlock_attributes (attrs, collection);
+	gp11_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, TRUE);
+	gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
 
 	cred = gkd_secret_session_create_credential (master->session, NULL, attrs, master, derr);
 
@@ -453,6 +539,7 @@ gboolean
 gkd_secret_unlock_with_password (GP11Object *collection, const guchar *password,
                                  gsize n_password, DBusError *derr)
 {
+	GP11Attributes *attrs;
 	GError *error = NULL;
 	GP11Session *session;
 	GP11Object *cred;
@@ -467,13 +554,13 @@ gkd_secret_unlock_with_password (GP11Object *collection, const guchar *password,
 	session = gp11_object_get_session (collection);
 	g_return_val_if_fail (session, FALSE);
 
-	cred = gp11_session_create_object (session, &error, CKA_CLASS, GP11_ULONG, CKO_G_CREDENTIAL,
-	                                   CKA_G_OBJECT, GP11_ULONG, gp11_object_get_handle (collection),
-	                                   CKA_GNOME_TRANSIENT, GP11_BOOLEAN, TRUE,
-	                                   CKA_TOKEN, GP11_BOOLEAN, TRUE,
-	                                   CKA_VALUE, n_password, password,
-	                                   GP11_INVALID);
+	attrs = gp11_attributes_new_full (egg_secure_realloc);
+	common_unlock_attributes (attrs, collection);
+	gp11_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, TRUE);
+	gp11_attributes_add_boolean (attrs, CKA_TOKEN, TRUE);
+	gp11_attributes_add_data (attrs, CKA_VALUE, password, n_password);
 
+	cred = gp11_session_create_object_full (session, attrs, NULL, &error);
 	if (cred == NULL) {
 		if (error->code == CKR_PIN_INCORRECT) {
 			dbus_set_error_const (derr, INTERNAL_ERROR_DENIED, "The password was incorrect.");
diff --git a/daemon/prompt/Makefile.am b/daemon/prompt/Makefile.am
index 01c0a2f..44821ea 100644
--- a/daemon/prompt/Makefile.am
+++ b/daemon/prompt/Makefile.am
@@ -68,10 +68,12 @@ gnome_keyring_prompt_SOURCES = \
 gnome_keyring_prompt_LDADD = \
 	$(top_builddir)/egg/libegg-prompt.la \
 	$(top_builddir)/egg/libegg-entry-buffer.la \
+	$(top_builddir)/gcr/libgcr.la \
 	$(LIBGCRYPT_LIBS) \
 	$(GTK_LIBS)
 
 gnome_keyring_prompt_CFLAGS = \
 	-DUIDIR=\""$(uidir)"\" \
+	-DGCR_API_SUBJECT_TO_CHANGE \
 	$(LIBGCRYPT_CFLAGS) \
 	$(GTK_CFLAGS)
diff --git a/daemon/prompt/gkd-prompt-tool.c b/daemon/prompt/gkd-prompt-tool.c
index a50300e..029704f 100644
--- a/daemon/prompt/gkd-prompt-tool.c
+++ b/daemon/prompt/gkd-prompt-tool.c
@@ -29,6 +29,8 @@
 #include "egg/egg-libgcrypt.h"
 #include "egg/egg-secure-memory.h"
 
+#include "gcr/gcr-unlock-options-widget.h"
+
 #include <gcrypt.h>
 
 #include <glib/gi18n.h>
@@ -305,41 +307,35 @@ prepare_security (GtkBuilder *builder, GtkDialog *dialog)
 }
 
 static void
-on_auto_check_unlock_toggled (GtkToggleButton *check, GtkBuilder *builder)
-{
-	GtkWidget *area;
-
-	area = GTK_WIDGET (gtk_builder_get_object (builder, "options_area"));
-	gtk_widget_set_sensitive (area, !gtk_toggle_button_get_active (check));
-}
-
-static void
-on_timeout_choices_toggled (GtkToggleButton *unused, GtkBuilder *builder)
+prepare_lock (GtkBuilder *builder, GtkDialog *dialog)
 {
-	GtkWidget *spin, *after, *idle;
+	GtkWidget *unlock, *area;
+	gboolean unlock_auto, unlock_global;
+	gint unlock_idle, unlock_timeout;
 
-	spin = GTK_WIDGET (gtk_builder_get_object (builder, "lock_minutes_spin"));
-	after = GTK_WIDGET (gtk_builder_get_object (builder, "lock_after_choice"));
-	idle = GTK_WIDGET (gtk_builder_get_object (builder, "lock_idle_choice"));
-	gtk_widget_set_sensitive (spin, gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (after)) ||
-	                                gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(idle)));
+	unlock = gcr_unlock_options_widget_new ();
+	area = GTK_WIDGET (gtk_builder_get_object (builder, "lock_area"));
+	g_object_set_data (G_OBJECT (dialog), "unlock-options-widget", unlock);
+	gtk_container_add (GTK_CONTAINER (area), unlock);
+	gtk_widget_show (unlock);
 
-}
+	unlock_auto = g_key_file_get_boolean (input_data, "unlock-options", "unlock-auto", NULL);
 
-static void
-prepare_lock (GtkBuilder *builder, GtkDialog *dialog)
-{
-	GtkWidget *check;
+	/* Defaults to TRUE */
+	if (!g_key_file_has_key (input_data, "unlock-options", "unlock-global", NULL))
+		unlock_global = TRUE;
+	else
+		unlock_global = g_key_file_get_boolean (input_data, "unlock-options", "unlock-global", NULL);
 
-	check = GTK_WIDGET (gtk_builder_get_object (builder, "auto_unlock_check"));
-	g_signal_connect (check, "toggled", G_CALLBACK (on_auto_check_unlock_toggled), builder);
-	on_auto_check_unlock_toggled (GTK_TOGGLE_BUTTON (check), builder);
+	unlock_idle = g_key_file_get_integer (input_data, "unlock-options", "unlock-idle", NULL);
+	unlock_timeout = g_key_file_get_integer (input_data, "unlock-options", "unlock-timeout", NULL);
 
-	check = GTK_WIDGET (gtk_builder_get_object (builder, "lock_after_choice"));
-	g_signal_connect (check, "toggled", G_CALLBACK (on_timeout_choices_toggled), builder);
-	check = GTK_WIDGET (gtk_builder_get_object (builder, "lock_idle_choice"));
-	g_signal_connect (check, "toggled", G_CALLBACK (on_timeout_choices_toggled), builder);
-	on_timeout_choices_toggled (GTK_TOGGLE_BUTTON (check), builder);
+	g_object_set (unlock,
+	              "unlock-auto", unlock_auto,
+	              "unlock-global", unlock_global,
+	              "unlock-idle", unlock_idle,
+	              "unlock-timeout", unlock_timeout,
+	              NULL);
 }
 
 static GtkDialog*
@@ -554,11 +550,33 @@ gather_response (gint response)
 }
 
 static void
+gather_unlock_options (GtkBuilder *builder, GtkDialog *dialog)
+{
+	gboolean unlock_auto, unlock_global;
+	gint unlock_timeout, unlock_idle;
+
+	GtkWidget *unlock = g_object_get_data (G_OBJECT (dialog), "unlock-options-widget");
+
+	g_object_get (unlock,
+	              "unlock-auto", &unlock_auto,
+	              "unlock-global", &unlock_global,
+	              "unlock-timeout", &unlock_timeout,
+	              "unlock-idle", &unlock_idle,
+	              NULL);
+
+	g_key_file_set_boolean (output_data, "unlock-options", "unlock-auto", unlock_auto);
+	g_key_file_set_boolean (output_data, "unlock-options", "unlock-global", unlock_global);
+	g_key_file_set_integer (output_data, "unlock-options", "unlock-timeout", unlock_timeout);
+	g_key_file_set_integer (output_data, "unlock-options", "unlock-idle", unlock_idle);
+}
+
+static void
 gather_dialog (GtkBuilder *builder, GtkDialog *dialog)
 {
 	gather_password (builder, "password");
 	gather_password (builder, "confirm");
 	gather_password (builder, "original");
+	gather_unlock_options (builder, dialog);
 }
 
 static void
diff --git a/daemon/prompt/gkd-prompt.c b/daemon/prompt/gkd-prompt.c
index 999964e..d62397f 100644
--- a/daemon/prompt/gkd-prompt.c
+++ b/daemon/prompt/gkd-prompt.c
@@ -31,6 +31,8 @@
 #include "egg/egg-secure-memory.h"
 #include "egg/egg-spawn.h"
 
+#include "pkcs11/pkcs11i.h"
+
 #include <gcrypt.h>
 
 #define DEBUG_PROMPT 1
@@ -811,6 +813,54 @@ gkd_prompt_get_transport_password (GkdPrompt *self, const gchar *password_type,
 	return TRUE;
 }
 
+void
+gkd_prompt_get_unlock_options (GkdPrompt *self, GP11Attributes *attrs)
+{
+	gboolean bval;
+	gint ival;
+
+	g_return_if_fail (GKD_IS_PROMPT (self));
+	g_return_if_fail (attrs);
+	g_return_if_fail (self->pv->output);
+
+	bval = g_key_file_get_boolean (self->pv->output, "unlock-options", "unlock-auto", NULL);
+	gp11_attributes_add_boolean (attrs, CKA_GNOME_TRANSIENT, !bval);
+
+	bval = TRUE;
+	if (g_key_file_has_key (self->pv->output, "unlock-options", "unlock-global", NULL))
+		bval = g_key_file_get_boolean (self->pv->output, "unlock-options", "unlock-global", NULL);
+	gp11_attributes_add_boolean (attrs, CKA_TOKEN, bval);
+
+	ival = g_key_file_get_integer (self->pv->output, "unlock-options", "unlock-idle", NULL);
+	gp11_attributes_add_ulong (attrs, CKA_G_DESTRUCT_IDLE, ival <= 0 ? 0 : ival);
+
+	ival = g_key_file_get_integer (self->pv->output, "unlock-options", "unlock-timeout", NULL);
+	gp11_attributes_add_ulong (attrs, CKA_G_DESTRUCT_AFTER, ival <= 0 ? 0 : ival);
+}
+
+void
+gkd_prompt_set_unlock_options (GkdPrompt *self, GP11Attributes *attrs)
+{
+	gboolean bval;
+	gulong uval;
+
+	g_return_if_fail (GKD_IS_PROMPT (self));
+	g_return_if_fail (attrs);
+	g_return_if_fail (self->pv->input);
+
+	if (gp11_attributes_find_boolean (attrs, CKA_GNOME_TRANSIENT, &bval))
+		g_key_file_set_boolean (self->pv->input, "unlock-options", "unlock-auto", !bval);
+
+	if (gp11_attributes_find_boolean (attrs, CKA_TOKEN, &bval))
+		g_key_file_set_boolean (self->pv->input, "unlock-options", "unlock-global", bval);
+
+	if (gp11_attributes_find_ulong (attrs, CKA_G_DESTRUCT_IDLE, &uval))
+		g_key_file_set_boolean (self->pv->input, "unlock-options", "unlock-idle", (int)uval);
+
+	if (gp11_attributes_find_ulong (attrs, CKA_G_DESTRUCT_AFTER, &uval))
+		g_key_file_set_boolean (self->pv->input, "unlock-options", "unlock-timeout", (int)uval);
+}
+
 /* ----------------------------------------------------------------------------------
  * ATTENTION QUEUES
  */
diff --git a/daemon/prompt/gkd-prompt.h b/daemon/prompt/gkd-prompt.h
index 4cc8a91..df0a9c5 100644
--- a/daemon/prompt/gkd-prompt.h
+++ b/daemon/prompt/gkd-prompt.h
@@ -24,6 +24,8 @@
 
 #include <glib-object.h>
 
+#include <gp11/gp11.h>
+
 typedef enum {
 	GKD_RESPONSE_FAILURE      = -1,
 	GKD_RESPONSE_NONE         = 0,
@@ -109,6 +111,12 @@ gboolean            gkd_prompt_get_transport_password (GkdPrompt *self,
                                                        gpointer *value,
                                                        gsize *n_value);
 
+void                gkd_prompt_get_unlock_options     (GkdPrompt *self,
+                                                       GP11Attributes *attrs);
+
+void                gkd_prompt_set_unlock_options     (GkdPrompt *self,
+                                                       GP11Attributes *attrs);
+
 gboolean            gkd_prompt_is_widget_selected     (GkdPrompt *prompt,
                                                        const gchar *widget);
 
diff --git a/daemon/prompt/gkd-prompt.ui b/daemon/prompt/gkd-prompt.ui
index 9c5de3b..772cfd3 100644
--- a/daemon/prompt/gkd-prompt.ui
+++ b/daemon/prompt/gkd-prompt.ui
@@ -264,132 +264,13 @@ An application wants access to the keyring 'xxx', but it is locked.</property>
                         <property name="orientation">vertical</property>
                         <property name="spacing">6</property>
                         <child>
-                          <object class="GtkFrame" id="lock_area">
+                          <object class="GtkAlignment" id="lock_area">
                             <property name="visible">True</property>
-                            <property name="label_xalign">0</property>
-                            <property name="shadow_type">none</property>
                             <child>
-                              <object class="GtkAlignment" id="options_area">
-                                <property name="visible">True</property>
-                                <property name="top_padding">3</property>
-                                <property name="left_padding">12</property>
-                                <child>
-                                  <object class="GtkVBox" id="vbox4">
-                                    <property name="visible">True</property>
-                                    <property name="orientation">vertical</property>
-                                    <property name="spacing">6</property>
-                                    <child>
-                                      <object class="GtkCheckButton" id="per_application_check">
-                                        <property name="label" translatable="yes">Prompt me for each application that accesses this keyring.</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="draw_indicator">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="position">0</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkRadioButton" id="lock_logout_choice">
-                                        <property name="label" translatable="yes">Lock this keyring when I log out.</property>
-                                        <property name="visible">True</property>
-                                        <property name="can_focus">True</property>
-                                        <property name="receives_default">False</property>
-                                        <property name="active">True</property>
-                                        <property name="draw_indicator">True</property>
-                                      </object>
-                                      <packing>
-                                        <property name="position">1</property>
-                                      </packing>
-                                    </child>
-                                    <child>
-                                      <object class="GtkHBox" id="hbox2">
-                                        <property name="visible">True</property>
-                                        <property name="spacing">6</property>
-                                        <child>
-                                          <object class="GtkVBox" id="vbox5">
-                                            <property name="visible">True</property>
-                                            <property name="orientation">vertical</property>
-                                            <property name="spacing">6</property>
-                                            <child>
-                                              <object class="GtkRadioButton" id="lock_after_choice">
-                                                <property name="label" translatable="yes">Lock this keyring after</property>
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">True</property>
-                                                <property name="receives_default">False</property>
-                                                <property name="active">True</property>
-                                                <property name="draw_indicator">True</property>
-                                                <property name="group">lock_logout_choice</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">False</property>
-                                                <property name="position">0</property>
-                                              </packing>
-                                            </child>
-                                            <child>
-                                              <object class="GtkRadioButton" id="lock_idle_choice">
-                                                <property name="label" translatable="yes">Lock this keyring if idle for</property>
-                                                <property name="visible">True</property>
-                                                <property name="can_focus">True</property>
-                                                <property name="receives_default">False</property>
-                                                <property name="active">True</property>
-                                                <property name="draw_indicator">True</property>
-                                                <property name="group">lock_logout_choice</property>
-                                              </object>
-                                              <packing>
-                                                <property name="expand">False</property>
-                                                <property name="position">1</property>
-                                              </packing>
-                                            </child>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">0</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkSpinButton" id="lock_minutes_spin">
-                                            <property name="visible">True</property>
-                                            <property name="can_focus">True</property>
-                                            <property name="invisible_char">&#x2022;</property>
-                                          </object>
-                                          <packing>
-                                            <property name="expand">False</property>
-                                            <property name="position">1</property>
-                                          </packing>
-                                        </child>
-                                        <child>
-                                          <object class="GtkLabel" id="label2">
-                                            <property name="visible">True</property>
-                                            <property name="xalign">0</property>
-                                            <property name="label" translatable="yes">minutes.</property>
-                                          </object>
-                                          <packing>
-                                            <property name="position">2</property>
-                                          </packing>
-                                        </child>
-                                      </object>
-                                      <packing>
-                                        <property name="position">2</property>
-                                      </packing>
-                                    </child>
-                                  </object>
-                                </child>
-                              </object>
-                            </child>
-                            <child type="label">
-                              <object class="GtkCheckButton" id="auto_unlock_check">
-                                <property name="label" translatable="yes">Automatically unlock this keyring whenever I'm logged in.</property>
-                                <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="receives_default">False</property>
-                                <property name="draw_indicator">True</property>
-                              </object>
+                              <placeholder/>
                             </child>
                           </object>
                           <packing>
-                            <property name="expand">False</property>
                             <property name="position">0</property>
                           </packing>
                         </child>



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