2 * Copyright © 2003 Crispin Flowerday <gnome@flowerday.cx>
3 * Copyright © 2006 Christian Persch
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 * This file provides Gtk implementations of the mozilla Certificate dialogs
24 * such as the ones displayed when connecting to a site with a self-signed
25 * or expired certificate.
28 #include "mozilla-config.h"
33 #include <glib/gi18n.h>
34 #include <gtk/gtkalignment.h>
35 #include <gtk/gtkbutton.h>
36 #include <gtk/gtkcellrenderertext.h>
37 #include <gtk/gtkcheckbutton.h>
38 #include <gtk/gtkdialog.h>
39 #include <gtk/gtkeditable.h>
40 #include <gtk/gtkentry.h>
41 #include <gtk/gtkhbox.h>
42 #include <gtk/gtkimage.h>
43 #include <gtk/gtklabel.h>
44 #include <gtk/gtkmessagedialog.h>
45 #include <gtk/gtkprogressbar.h>
46 #include <gtk/gtksizegroup.h>
47 #include <gtk/gtkstock.h>
48 #include <gtk/gtktable.h>
49 #include <gtk/gtktextbuffer.h>
50 #include <gtk/gtktextview.h>
51 #include <gtk/gtktogglebutton.h>
52 #include <gtk/gtktreeselection.h>
53 #include <gtk/gtktreestore.h>
54 #include <gtk/gtktreeview.h>
55 #include <gtk/gtkvbox.h>
56 #include <gtk/gtkcombobox.h>
57 #include <gconf/gconf-client.h>
58 #include <glade/glade-xml.h>
60 #include <nsStringAPI.h>
64 #include <nsIASN1Object.h>
65 #include <nsIASN1Sequence.h>
66 #include <nsICRLInfo.h>
67 #include <nsIDOMWindow.h>
68 #include <nsIInterfaceRequestor.h>
69 #include <nsIInterfaceRequestorUtils.h>
70 #include <nsIPKCS11ModuleDB.h>
71 #include <nsIPKCS11Slot.h>
72 #include <nsIPK11Token.h>
73 #include <nsIPK11TokenDB.h>
74 #include <nsIServiceManager.h>
75 #include <nsISimpleEnumerator.h>
76 #include <nsIX509CertDB.h>
77 #include <nsIX509Cert.h>
78 #include <nsIX509CertValidity.h>
80 #include <nsServiceManagerUtils.h>
82 #ifdef HAVE_NSIMUTABLEARRAY_H
83 #include <nsIMutableArray.h>
86 #include "ephy-file-helpers.h"
88 #include "ephy-password-dialog.h"
89 #include "ephy-stock-icons.h"
91 #include "AutoJSContextStack.h"
92 #include "AutoWindowModalState.h"
93 #include "EphyUtils.h"
95 #include "GtkNSSDialogs.h"
97 NS_DEFINE_CID (kX509CertCID, NS_IX509CERT_IID);
98 NS_DEFINE_CID (kASN1ObjectCID, NS_IASN1OBJECT_IID);
102 NSSDIALOG_RESPONSE_VIEW_CERT = 10
105 GtkNSSDialogs::GtkNSSDialogs ()
109 GtkNSSDialogs::~GtkNSSDialogs ()
113 NS_IMPL_THREADSAFE_ISUPPORTS5 (GtkNSSDialogs,
114 nsICertificateDialogs,
116 nsITokenPasswordDialogs,
120 /* There's also nsICertPickDialogs which is implemented in mozilla
121 * but has no callers. So we don't implement it.
122 * Same for nsIUserCertPicker which is only used in mailnews.
126 * Call the mozilla service to display a certificate
129 view_certificate (nsIInterfaceRequestor *ctx, nsIX509Cert *cert)
132 nsCOMPtr<nsICertificateDialogs> certDialogs =
133 do_GetService (NS_CERTIFICATEDIALOGS_CONTRACTID, &rv);
134 NS_ENSURE_SUCCESS (rv, );
136 certDialogs->ViewCert (ctx, cert);
140 * Indent a widget according the HIG
142 * @returns: The new indented widget
145 higgy_indent_widget (GtkWidget *widget)
150 hbox = gtk_hbox_new (FALSE, 6);
152 label = gtk_label_new (NULL);
153 gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, TRUE, 6);
154 gtk_widget_show (label);
156 gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 0);
162 * Setup up a dialog with the correct HIG'gy spacings, adding the content_widget
165 higgy_setup_dialog (GtkDialog *dialog, const gchar *stock_icon,
166 GtkWidget **content_label,
167 GtkWidget **content_vbox)
169 GtkWidget *hbox, *label, *image, *vbox;
171 g_return_if_fail (GTK_IS_DIALOG (dialog));
172 g_return_if_fail (content_label);
174 gtk_dialog_set_has_separator (dialog, FALSE);
175 gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
176 gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
178 hbox = gtk_hbox_new (FALSE, 12);
179 gtk_container_set_border_width (GTK_CONTAINER (hbox), 5);
180 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (dialog)->vbox), hbox);
182 image = gtk_image_new_from_stock (stock_icon, GTK_ICON_SIZE_DIALOG);
183 gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.0);
184 gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);
186 vbox = gtk_vbox_new (FALSE, 12);
187 gtk_box_pack_start (GTK_BOX (hbox), vbox, TRUE, TRUE, 0);
189 label = gtk_label_new (NULL);
190 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
191 gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
192 gtk_label_set_selectable (GTK_LABEL (label), TRUE);
193 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.0);
195 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
197 gtk_widget_show (image);
198 gtk_widget_show (vbox);
199 gtk_widget_show (hbox);
200 gtk_widget_show (label);
202 /* Set up the spacing for the dialog internal widgets */
203 gtk_box_set_spacing (GTK_BOX(dialog->vbox), 14); /* 24 = 2 * 5 + 14 */
205 *content_label = label;
208 *content_vbox = vbox;
214 * Display a dialog box, showing 'View Certificate', 'Cancel',
215 * and 'Accept' buttons. Optionally a checkbox can be shown,
216 * or the text can be NULL to avoid it being displayed
218 * @returns: GTK_RESPONSE_ACCEPT if the user clicked Accept
221 display_cert_warning_box (nsIInterfaceRequestor *ctx,
223 const char *markup_text,
224 const char *checkbox_text,
225 gboolean *checkbox_value,
226 const char *affirmative_text)
228 GtkWidget *dialog, *label, *checkbox, *vbox, *button;
231 g_return_val_if_fail (markup_text, GTK_RESPONSE_CANCEL);
232 g_return_val_if_fail (!checkbox_text || checkbox_value, GTK_RESPONSE_CANCEL);
235 AutoJSContextStack stack;
237 if (NS_FAILED (rv)) return rv;
239 /* NOTE: Due to a mozilla bug [https://bugzilla.mozilla.org/show_bug.cgi?id=306288],
240 * we will always end up without a parent!
242 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
243 GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
245 AutoWindowModalState modalState (parent);
247 dialog = gtk_dialog_new_with_buttons ("", gparent,
248 GTK_DIALOG_DESTROY_WITH_PARENT,
252 gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
253 GTK_WINDOW (dialog));
256 gtk_dialog_set_has_separator (GTK_DIALOG (dialog), FALSE);
257 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
259 higgy_setup_dialog (GTK_DIALOG (dialog),
260 GTK_STOCK_DIALOG_WARNING, &label, &vbox);
262 /* Add the buttons */
263 gtk_dialog_add_button (GTK_DIALOG (dialog), _("_View Certificate"),
264 NSSDIALOG_RESPONSE_VIEW_CERT);
266 gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_CANCEL,
267 GTK_RESPONSE_CANCEL);
269 if (affirmative_text == NULL)
271 affirmative_text = _("_Accept");
274 button = gtk_dialog_add_button (GTK_DIALOG (dialog),
276 GTK_RESPONSE_ACCEPT);
277 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
281 checkbox = gtk_check_button_new_with_mnemonic (checkbox_text);
282 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbox),
285 gtk_box_pack_start (GTK_BOX (vbox), checkbox, TRUE, TRUE, 0);
292 /* We don't want focus on the checkbox */
293 gtk_widget_grab_focus (button);
295 gtk_label_set_markup (GTK_LABEL (label), markup_text);
296 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
297 gtk_widget_show_all (dialog);
301 res = gtk_dialog_run (GTK_DIALOG (dialog));
302 if (res == NSSDIALOG_RESPONSE_VIEW_CERT)
304 view_certificate (ctx, cert);
311 if (res == GTK_RESPONSE_ACCEPT && checkbox)
313 *checkbox_value = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbox));
316 gtk_widget_destroy (dialog);
321 /* Helper functions */
324 GtkNSSDialogs::GetTokenAndSlotFromName (const PRUnichar *aName,
325 nsIPK11Token **aToken,
326 nsIPKCS11Slot **aSlot)
328 nsresult rv = NS_ERROR_FAILURE;
332 nsCOMPtr<nsIPK11TokenDB> tokenDB = do_GetService("@mozilla.org/security/pk11tokendb;1");
333 nsCOMPtr<nsIPKCS11ModuleDB> pkcs11DB = do_GetService("@mozilla.org/security/pkcs11moduledb;1");
334 if (!tokenDB || !pkcs11DB) return rv;
336 rv = tokenDB->FindTokenByName (aName, aToken);
337 NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && *aToken, rv);
339 pkcs11DB->FindSlotByName (aName, aSlot);
341 NS_ENSURE_TRUE (*aSlot, NS_ERROR_FAILURE);
343 #ifdef GNOME_ENABLE_DEBUG
344 /* Dump some info about this token */
345 nsIPK11Token *token = *aToken;
346 PRUnichar *tName, *tLabel, *tManID, *tHWVersion, *tFWVersion, *tSN;
348 PRBool needsInit, isHW, needsLogin, isFriendly;
350 token->GetTokenName(&tName);
351 token->GetTokenLabel(&tLabel);
352 token->GetTokenManID(&tManID);
353 token->GetTokenHWVersion(&tHWVersion);
354 token->GetTokenFWVersion(&tFWVersion);
355 token->GetTokenSerialNumber(&tSN);
356 token->GetMinimumPasswordLength(&minPwdLen);
357 token->GetNeedsUserInit(&needsInit);
358 token->IsHardwareToken(&isHW);
359 token->NeedsLogin(&needsLogin);
360 token->IsFriendly(&isFriendly);
362 g_print ("Token '%s' has \nName: %s\nLabel: %s\nManID: %s\nHWversion: %s\nFWVersion: %s\nSN: %s\n"
363 "MinPwdLen: %d\nNeedsUserInit: %d\nIsHWToken: %d\nNeedsLogin: %d\nIsFriendly: %d\n\n",
364 NS_ConvertUTF16toUTF8(aName).get(),
366 NS_ConvertUTF16toUTF8(tName).get(),
367 NS_ConvertUTF16toUTF8(tLabel).get(),
368 NS_ConvertUTF16toUTF8(tManID).get(),
369 NS_ConvertUTF16toUTF8(tHWVersion).get(),
370 NS_ConvertUTF16toUTF8(tFWVersion).get(),
371 NS_ConvertUTF16toUTF8(tSN).get(),
378 nsIPKCS11Slot *slot = *aSlot;
380 slot->GetDesc(&slDesc);
381 g_print ("Slot description: %s\n", NS_ConvertUTF16toUTF8 (slDesc).get());
387 /* nsICertificateDialogs */
390 GtkNSSDialogs::ConfirmMismatchDomain (nsIInterfaceRequestor *ctx,
391 const nsACString &targetURL,
392 nsIX509Cert *cert, PRBool *_retval)
394 char *first, *second, *msg;
398 cert->GetCommonName (commonName);
400 NS_ConvertUTF16toUTF8 cCommonName (commonName);
402 nsCString cTargetUrl (targetURL);
404 first = g_markup_printf_escaped (_("The site “%s” returned security information for "
405 "“%s”. It is possible that someone is intercepting "
406 "your communication to obtain your confidential "
408 cTargetUrl.get(), cCommonName.get());
410 second = g_markup_printf_escaped (_("You should only accept the security information if you "
411 "trust “%s” and “%s”."),
412 cTargetUrl.get(), cCommonName.get());
414 msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n\n%s",
415 _("Accept incorrect security information?"),
418 res = display_cert_warning_box (ctx, cert, msg, NULL, NULL, NULL);
424 *_retval = (res == GTK_RESPONSE_ACCEPT);
430 GtkNSSDialogs::ConfirmUnknownIssuer (nsIInterfaceRequestor *ctx,
431 nsIX509Cert *cert, PRInt16 *outAddType,
434 gboolean accept_perm = FALSE;
435 char *secondary, *tertiary, *msg;
439 cert->GetCommonName (commonName);
441 NS_ConvertUTF16toUTF8 cCommonName (commonName);
443 secondary = g_markup_printf_escaped
444 (_("It was not possible to automatically trust “%s”. "
445 "It is possible that someone is intercepting your "
446 "communication to obtain your confidential information."),
449 tertiary = g_markup_printf_escaped
450 (_("You should only connect to the site if you are certain "
451 "you are connected to “%s”."),
454 msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n\n%s",
455 _("Connect to untrusted site?"),
456 secondary, tertiary);
458 res = display_cert_warning_box (ctx, cert, msg,
459 _("_Trust this security information from now on"),
460 &accept_perm, _("Co_nnect"));
465 if (res != GTK_RESPONSE_ACCEPT)
468 *outAddType = UNINIT_ADD_FLAG;
475 *outAddType = ADD_TRUSTED_PERMANENTLY;
480 *outAddType = ADD_TRUSTED_FOR_SESSION;
488 /* boolean confirmCertExpired (in nsIInterfaceRequestor socketInfo,
489 in nsIX509Cert cert); */
491 GtkNSSDialogs::ConfirmCertExpired (nsIInterfaceRequestor *ctx,
492 nsIX509Cert *cert, PRBool *_retval)
495 PRTime now = PR_Now();
496 PRTime notAfter, notBefore, timeToUse;
497 PRInt64 normalizedTime;
500 char formattedDate[128];
502 const char *primary, *text;
503 char *secondary, *msg;
507 nsCOMPtr<nsIX509CertValidity> validity;
508 rv = cert->GetValidity (getter_AddRefs(validity));
509 if (NS_FAILED(rv)) return rv;
511 rv = validity->GetNotAfter (¬After);
512 if (NS_FAILED(rv)) return rv;
514 rv = validity->GetNotBefore (¬Before);
515 if (NS_FAILED(rv)) return rv;
517 if (LL_CMP(now, >, notAfter))
519 primary = _("Accept expired security information?");
520 /* Translators: first %s is a hostname, second %s is a time/date */
521 text = _("The security information for “%s” "
523 timeToUse = notAfter;
527 primary = _("Accept not yet valid security information?");
528 /* Translators: first %s is a hostname, second %s is a time/date */
529 text = _("The security information for “%s” isn't valid until %s.");
530 timeToUse = notBefore;
534 cert->GetCommonName (commonName);
536 NS_ConvertUTF16toUTF8 cCommonName (commonName);
538 LL_DIV (normalizedTime, timeToUse, PR_USEC_PER_SEC);
539 LL_L2UI (t, normalizedTime);
540 /* To translators: this a time format that is used while displaying the
541 * expiry or start date of an SSL certificate, for the format see
543 strftime (formattedDate, sizeof(formattedDate), _("%a %d %b %Y"),
544 localtime_r (&t, &tm));
545 /* FIXME! this isn't actually correct, LC_CTIME codeset could be different than locale codeset! */
546 fdate = g_locale_to_utf8 (formattedDate, -1, NULL, NULL, NULL);
548 secondary = g_markup_printf_escaped (text, cCommonName.get(), fdate);
550 msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s\n\n%s",
552 _("You should ensure that your computer's time is correct."));
554 int res = display_cert_warning_box (ctx, cert, msg, NULL, NULL, NULL);
560 *_retval = (res == GTK_RESPONSE_ACCEPT);
565 /* void notifyCrlNextupdate (in nsIInterfaceRequestor socketInfo,
566 in AUTF8String targetURL,
567 in nsIX509Cert cert); */
569 GtkNSSDialogs::NotifyCrlNextupdate (nsIInterfaceRequestor *ctx,
570 const nsACString & targetURL,
573 nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
574 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
576 nsCString cTargetUrl (targetURL);
579 cert->GetCommonName (commonName);
581 GtkWidget *dialog = gtk_message_dialog_new
582 (GTK_WINDOW (gparent),
583 GTK_DIALOG_DESTROY_WITH_PARENT,
586 _("Cannot establish connection to “%s”"),
589 gtk_message_dialog_format_secondary_text
590 (GTK_MESSAGE_DIALOG (dialog),
591 _("The certificate revocation list (CRL) from “%s” "
592 "needs to be updated.\n\n"
593 "Please ask your system administrator for assistance."),
594 NS_ConvertUTF16toUTF8 (commonName).get ());
595 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
597 g_signal_connect (dialog, "response",
598 (GCallback) gtk_widget_destroy, NULL);
600 gtk_widget_show_all (dialog);
605 GtkNSSDialogs::ConfirmDownloadCACert(nsIInterfaceRequestor *ctx,
610 GtkWidget *dialog, *label;
614 AutoJSContextStack stack;
616 if (NS_FAILED (rv)) return rv;
618 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
619 GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
621 AutoWindowModalState modalState (parent);
623 dialog = gtk_dialog_new_with_buttons (_("Trust new Certificate Authority?"), gparent,
624 GTK_DIALOG_DESTROY_WITH_PARENT,
625 _("_View Certificate"),
626 NSSDIALOG_RESPONSE_VIEW_CERT,
627 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
628 _("_Trust CA"), GTK_RESPONSE_ACCEPT,
633 gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
634 GTK_WINDOW (dialog));
637 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
639 higgy_setup_dialog (GTK_DIALOG (dialog), GTK_STOCK_DIALOG_WARNING,
641 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
644 cert->GetCommonName (commonName);
646 NS_ConvertUTF16toUTF8 cCommonName (commonName);
648 primary = g_markup_printf_escaped (_("Trust new Certificate Authority “%s” to identify web sites?"),
651 msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
653 _("Before trusting a Certificate Authority (CA) you should "
654 "verify the certificate is authentic."));
655 gtk_label_set_markup (GTK_LABEL (label), msg);
659 gtk_widget_show_all (dialog);
664 ret = gtk_dialog_run (GTK_DIALOG (dialog));
665 if (ret == NSSDIALOG_RESPONSE_VIEW_CERT)
667 view_certificate (ctx, cert);
674 if (ret != GTK_RESPONSE_ACCEPT)
680 if (ret == GTK_RESPONSE_ACCEPT)
682 *_trust |= nsIX509CertDB::TRUSTED_SSL;
686 *_trust = nsIX509CertDB::UNTRUSTED;
691 gtk_widget_destroy (dialog);
698 GtkNSSDialogs::NotifyCACertExists (nsIInterfaceRequestor *ctx)
700 GtkWidget *dialog, *label;
703 nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
704 GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
706 dialog = gtk_dialog_new_with_buttons ("", gparent,
707 GTK_DIALOG_DESTROY_WITH_PARENT,
714 gtk_window_group_add_window (ephy_gui_ensure_window_group (gparent),
715 GTK_WINDOW (dialog));
718 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
720 higgy_setup_dialog (GTK_DIALOG (dialog), GTK_STOCK_DIALOG_ERROR,
723 msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>\n\n%s",
724 _("Certificate already exists."),
725 _("The certificate has already been imported."));
726 gtk_label_set_markup (GTK_LABEL (label), msg);
729 g_signal_connect (G_OBJECT (dialog),
731 (GCallback)gtk_widget_destroy, NULL);
733 gtk_widget_show_all (dialog);
737 /* FIXME: This interface sucks! There is way to know the name of the certificate! */
739 GtkNSSDialogs::SetPKCS12FilePassword(nsIInterfaceRequestor *ctx,
740 nsAString &_password,
747 AutoJSContextStack stack;
749 if (NS_FAILED (rv)) return rv;
751 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
752 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
754 AutoWindowModalState modalState (parent);
756 dialog = ephy_password_dialog_new (gparent,
757 _("Select Password"),
758 EphyPasswordDialogFlags(EPHY_PASSWORD_DIALOG_FLAGS_SHOW_NEW_PASSWORD |
759 EPHY_PASSWORD_DIALOG_FLAGS_SHOW_QUALITY_METER));
760 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
761 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
763 /* FIXME: set accept button text to (_("_Back Up Certificate") ?
764 * That's not actually correct, since this function is also called from other places!
767 msg = g_markup_printf_escaped (_("Select a password to protect this certificate"));
768 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
771 int response = gtk_dialog_run (GTK_DIALOG (dialog));
772 gtk_widget_hide (dialog);
774 if (response == GTK_RESPONSE_ACCEPT)
776 const char *text = ephy_password_dialog_get_new_password (EPHY_PASSWORD_DIALOG (dialog));
777 g_return_val_if_fail (text != NULL, NS_ERROR_FAILURE);
778 NS_CStringToUTF16 (nsDependentCString (text),
779 NS_CSTRING_ENCODING_UTF8, _password);
782 *_retval = response == GTK_RESPONSE_ACCEPT;
784 gtk_widget_destroy (dialog);
790 GtkNSSDialogs::GetPKCS12FilePassword(nsIInterfaceRequestor *ctx,
791 nsAString &_password,
794 g_print ("GtkNSSDialogs::GetPKCS12FilePassword\n");
797 AutoJSContextStack stack;
799 if (NS_FAILED (rv)) return rv;
801 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
802 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
804 AutoWindowModalState modalState (parent);
806 GtkWidget *dialog = ephy_password_dialog_new
809 EphyPasswordDialogFlags (EPHY_PASSWORD_DIALOG_FLAGS_SHOW_PASSWORD));
810 EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog);
811 /* FIXME: set accept button text to _("I_mport Certificate") ? */
813 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
815 /* FIXME: mozilla sucks, no way to get the name of the certificate / cert file! */
816 char *msg = g_markup_printf_escaped (_("Enter the password for this certificate"));
817 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), msg);
820 int response = gtk_dialog_run (GTK_DIALOG (dialog));
822 if (response == GTK_RESPONSE_ACCEPT)
824 const char *pwd = ephy_password_dialog_get_password (password_dialog);
825 NS_CStringToUTF16 (nsDependentCString (pwd),
826 NS_CSTRING_ENCODING_UTF8, _password);
829 *_retval = response == GTK_RESPONSE_ACCEPT;
831 gtk_widget_destroy (dialog);
838 set_table_row (GtkWidget *table,
843 GtkWidget *header, *label;
846 if (text == NULL || text[0] == 0) return;
848 bold = g_markup_printf_escaped ("<b>%s</b>", title);
849 header = gtk_label_new (bold);
852 gtk_label_set_use_markup (GTK_LABEL (header), TRUE);
853 gtk_misc_set_alignment (GTK_MISC (header), 0, 0);
854 gtk_widget_show (header);
855 gtk_table_attach (GTK_TABLE (table), header, 0, 1, row, row+1,
856 GTK_FILL, GTK_FILL, 0, 0);
858 label = gtk_label_new (text);
859 gtk_misc_set_alignment (GTK_MISC (label), 0, 0);
860 gtk_label_set_selectable (GTK_LABEL (label), TRUE);
861 gtk_label_set_ellipsize (GTK_LABEL (label), PANGO_ELLIPSIZE_END);
862 gtk_label_set_max_width_chars (GTK_LABEL (label), 48);
863 gtk_widget_show (label);
864 gtk_table_attach_defaults (GTK_TABLE (table), label, 1, 2, row, row+1);
870 GtkNSSDialogs::CrlImportStatusDialog(nsIInterfaceRequestor *ctx, nsICRLInfo *crl)
873 GtkWidget *dialog, *label, *table, *vbox;
877 nsCOMPtr<nsIDOMWindow> parent = do_GetInterface (ctx);
878 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
880 dialog = gtk_dialog_new_with_buttons ("",
881 GTK_WINDOW (gparent),
882 GTK_DIALOG_DESTROY_WITH_PARENT,
883 GTK_STOCK_OK, GTK_RESPONSE_OK,
886 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
887 gtk_window_set_title (GTK_WINDOW (dialog), _("Certificate Revocation List Imported"));
889 /* Needed because gparent == NULL always because of mozilla sucks */
890 gtk_window_set_skip_pager_hint (GTK_WINDOW (dialog), TRUE);
891 gtk_window_set_skip_taskbar_hint (GTK_WINDOW (dialog), TRUE);
893 higgy_setup_dialog (GTK_DIALOG (dialog), GTK_STOCK_DIALOG_INFO,
896 msg = g_strdup_printf ("<span weight=\"bold\" size=\"larger\">%s</span>",
897 _("Certificate Revocation List (CRL) successfully imported"));
898 gtk_label_set_markup (GTK_LABEL (label), msg);
901 table = gtk_table_new (2, 3, FALSE);
902 gtk_table_set_row_spacings (GTK_TABLE (table), 6);
903 gtk_table_set_col_spacings (GTK_TABLE (table), 12);
905 nsString org, orgUnit, nextUpdate;
906 rv = crl->GetOrganization (org);
907 if (NS_FAILED(rv)) return rv;
909 rv = crl->GetOrganizationalUnit (orgUnit);
910 if (NS_FAILED(rv)) return rv;
912 rv = crl->GetNextUpdateLocale (nextUpdate);
913 if (NS_FAILED(rv)) return rv;
916 set_table_row (table, row, _("Organization:"), NS_ConvertUTF16toUTF8 (org).get ());
918 set_table_row (table, row, _("Unit:"), NS_ConvertUTF16toUTF8 (orgUnit).get ());
920 set_table_row (table, row, _("Next Update:"), NS_ConvertUTF16toUTF8 (nextUpdate).get ());
922 gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
924 gtk_widget_show_all (dialog);
925 g_signal_connect (G_OBJECT (dialog),
927 (GCallback)gtk_widget_destroy, NULL);
929 gtk_widget_show_all (dialog);
934 * Help function to fill in the labels on the General tab
937 set_label_cert_attribute (GladeXML* gxml, const char* label_id, nsAString &value)
940 label = glade_xml_get_widget (gxml, label_id);
942 g_return_if_fail (GTK_IS_LABEL (label));
944 if (!value.Length()) {
945 gtk_label_set_use_markup (GTK_LABEL (label), TRUE);
946 char *msg = g_strdup_printf ("<i><%s></i>",
947 _("Not part of certificate"));
948 gtk_label_set_markup (GTK_LABEL (label), msg);
953 gtk_label_set_use_markup (GTK_LABEL (label), FALSE);
954 gtk_label_set_text (GTK_LABEL (label), NS_ConvertUTF16toUTF8 (value).get());
960 * Do that actual filling in of the certificate tree
963 fill_cert_chain_tree (GtkTreeView *treeview, nsIArray *certChain)
966 GtkTreeModel * model = gtk_tree_view_get_model (treeview);
970 rv = certChain->GetLength (&numCerts);
971 if (NS_FAILED(rv) || numCerts < 1) return FALSE;
973 for (int i = (int)numCerts-1 ; i >= 0; i--)
975 nsCOMPtr<nsIX509Cert> nsCert;
976 rv = certChain->QueryElementAt (i, kX509CertCID,
977 getter_AddRefs(nsCert));
978 if (NS_FAILED(rv)) return FALSE;
981 gtk_tree_store_append (GTK_TREE_STORE (model), &iter,
982 (i == (int)numCerts-1) ? NULL : &parent);
985 rv = nsCert->GetCommonName (value);
986 if (NS_FAILED(rv)) return FALSE;
988 NS_ConvertUTF16toUTF8 cValue (value);
990 nsIX509Cert *nsCertP = nsCert;
993 gtk_tree_store_set (GTK_TREE_STORE(model), &iter,
1001 rv = nsCert->GetWindowTitle (&title);
1002 if (NS_FAILED(rv)) return FALSE;
1004 gtk_tree_store_set (GTK_TREE_STORE(model),
1005 &iter, 0, title, 1, nsCertP, -1);
1006 nsMemory::Free (title);
1010 gtk_tree_view_expand_all (GTK_TREE_VIEW (treeview));
1012 /* And select the last entry, and scroll the view so it's visible */
1013 GtkTreeSelection *select = gtk_tree_view_get_selection (treeview);
1014 GtkTreePath *path = gtk_tree_model_get_path (model, &parent);
1015 gtk_tree_selection_select_path (select, path);
1016 gtk_tree_view_scroll_to_cell (treeview, path, NULL, TRUE, 0.5, 0.0);
1017 gtk_tree_path_free (path);
1023 * Add an ASN object to the treeview, recursing if the object was a
1027 add_asn1_object_to_tree(GtkTreeModel *model, nsIASN1Object *object, GtkTreeIter *parent)
1030 object->GetDisplayName(dispNameU);
1033 gtk_tree_store_append (GTK_TREE_STORE (model), &iter, parent);
1035 gtk_tree_store_set (GTK_TREE_STORE(model), &iter,
1036 0, NS_ConvertUTF16toUTF8 (dispNameU).get(),
1040 nsCOMPtr<nsIASN1Sequence> sequence(do_QueryInterface(object));
1041 if (!sequence) return;
1043 nsCOMPtr<nsIMutableArray> asn1Objects;
1044 sequence->GetASN1Objects(getter_AddRefs(asn1Objects));
1046 PRUint32 numObjects;
1047 asn1Objects->GetLength(&numObjects);
1048 if (!asn1Objects) return;
1050 for (PRUint32 i = 0; i < numObjects ; i++)
1052 nsCOMPtr<nsIASN1Object> currObject;
1053 asn1Objects->QueryElementAt (i, kASN1ObjectCID,
1054 getter_AddRefs (currObject));
1055 add_asn1_object_to_tree (model, currObject, &iter);
1061 * Update the "Certificate Fields" treeview when a different cert
1062 * is selected in the hierarchy text view
1065 cert_chain_tree_view_selection_changed_cb (GtkTreeSelection *selection,
1066 GtkWidget* tree_view)
1069 nsIX509Cert *nsCert;
1071 GtkTreeModel * model;
1073 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1075 gtk_tree_model_get (model, &iter, 1, &nsCert, -1);
1077 nsCOMPtr<nsIASN1Object> object;
1078 rv = nsCert->GetASN1Structure (getter_AddRefs(object));
1079 if (NS_FAILED(rv)) return;
1081 model = gtk_tree_view_get_model (GTK_TREE_VIEW (tree_view));
1082 gtk_tree_store_clear (GTK_TREE_STORE (model));
1083 add_asn1_object_to_tree (model, object, NULL);
1085 gtk_tree_view_expand_all (GTK_TREE_VIEW (tree_view));
1090 * When the "Certificate Field" treeview is changed, update the
1091 * text_view to display the value of the currently selected field
1094 field_tree_view_selection_changed_cb (GtkTreeSelection *selection,
1095 GtkWidget* text_view)
1098 GtkTreeModel *model;
1099 GtkTextBuffer * text_buffer =
1100 gtk_text_view_get_buffer (GTK_TEXT_VIEW (text_view));
1102 if (gtk_tree_selection_get_selected (selection, &model, &iter))
1104 nsIASN1Object *object;
1106 gtk_tree_model_get (model, &iter, 1, &object, -1);
1109 object->GetDisplayValue(dispValU);
1111 gtk_text_buffer_set_text (text_buffer, NS_ConvertUTF16toUTF8 (dispValU).get(), -1);
1115 gtk_text_buffer_set_text (text_buffer, "", 0);
1120 * Setup the various treeviews, the textview, and fill the treeviews
1123 setup_view_cert_tree (GtkWidget *dialog, GladeXML*gxml, nsIArray *certChain)
1125 GtkCellRenderer *renderer;
1126 GtkWidget *chain_tree_view, *field_tree_view, *text_view;
1127 PangoFontDescription *monospace_font_desc;
1128 GConfClient *conf_client;
1129 char *monospace_font;
1131 chain_tree_view = glade_xml_get_widget (gxml, "treeview_cert_chain");
1132 field_tree_view = glade_xml_get_widget (gxml, "treeview_cert_info");
1133 text_view = glade_xml_get_widget (gxml, "textview_field_value");
1135 /* Setup the certificate chain view */
1136 GtkTreeStore *store = gtk_tree_store_new (2,
1139 gtk_tree_view_set_model (GTK_TREE_VIEW (chain_tree_view), GTK_TREE_MODEL (store));
1140 g_object_unref (store);
1143 renderer = gtk_cell_renderer_text_new ();
1144 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (chain_tree_view),
1150 GtkTreeSelection *select = gtk_tree_view_get_selection (GTK_TREE_VIEW (chain_tree_view));
1151 gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
1153 g_signal_connect (G_OBJECT (select), "changed",
1154 G_CALLBACK (cert_chain_tree_view_selection_changed_cb),
1157 /* Setup the certificate field view */
1158 store = gtk_tree_store_new (2,
1161 gtk_tree_view_set_model (GTK_TREE_VIEW (field_tree_view), GTK_TREE_MODEL (store));
1162 g_object_unref (store);
1165 gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (field_tree_view),
1166 0, "Certificate Field",
1171 select = gtk_tree_view_get_selection (GTK_TREE_VIEW (field_tree_view));
1172 gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE);
1174 g_signal_connect (G_OBJECT (select), "changed",
1175 G_CALLBACK (field_tree_view_selection_changed_cb),
1178 /* Get the text_view displaying a propertional font
1180 * Pick up the monospace font from desktop preferences */
1181 conf_client = gconf_client_get_default ();
1182 monospace_font = gconf_client_get_string (conf_client,
1183 "/desktop/gnome/interface/monospace_font_name", NULL);
1186 monospace_font_desc = pango_font_description_from_string (monospace_font);
1187 gtk_widget_modify_font (text_view, monospace_font_desc);
1188 pango_font_description_free (monospace_font_desc);
1190 g_object_unref (conf_client);
1192 /* And fill the certificate chain tree */
1193 return fill_cert_chain_tree (GTK_TREE_VIEW (chain_tree_view), certChain);
1196 /* void viewCert (in nsIX509Cert cert); */
1198 GtkNSSDialogs::ViewCert(nsIInterfaceRequestor *ctx,
1201 GtkWidget *dialog, *widget;
1204 PRUint32 verifystate, count;
1206 GtkSizeGroup * sizegroup;
1209 AutoJSContextStack stack;
1211 if (NS_FAILED (rv)) return rv;
1213 gxml = glade_xml_new (ephy_file ("certificate-dialogs.glade"),
1214 "viewcert_dialog", NULL);
1215 g_return_val_if_fail (gxml != NULL, NS_ERROR_FAILURE);
1217 dialog = glade_xml_get_widget (gxml, "viewcert_dialog");
1218 g_return_val_if_fail (dialog != NULL, NS_ERROR_FAILURE);
1220 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (ctx));
1221 GtkWindow *gparent = GTK_WINDOW (EphyUtils::FindGtkParent (parent));
1223 AutoWindowModalState modalState (parent);
1227 gtk_window_set_transient_for (GTK_WINDOW(dialog), GTK_WINDOW(gparent));
1228 gtk_window_group_add_window (ephy_gui_ensure_window_group (GTK_WINDOW (gparent)),
1229 GTK_WINDOW (dialog));
1230 gtk_window_set_destroy_with_parent (GTK_WINDOW (dialog), TRUE);
1233 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
1235 gtk_window_set_title (GTK_WINDOW (dialog), _("Certificate Properties"));
1236 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_CLOSE);
1238 /* Set up the GtkSizeGroup so that the columns line up */
1239 sizegroup = gtk_size_group_new (GTK_SIZE_GROUP_HORIZONTAL);
1240 widget = glade_xml_get_widget (gxml, "label_size1");
1241 gtk_size_group_add_widget (sizegroup, widget);
1242 widget = glade_xml_get_widget (gxml, "label_size2");
1243 gtk_size_group_add_widget (sizegroup, widget);
1244 widget = glade_xml_get_widget (gxml, "label_size3");
1245 gtk_size_group_add_widget (sizegroup, widget);
1246 widget = glade_xml_get_widget (gxml, "label_size4");
1247 gtk_size_group_add_widget (sizegroup, widget);
1248 g_object_unref (sizegroup);
1250 rv = cert->GetUsagesArray (FALSE, &verifystate, &count, &usage);
1251 if (NS_FAILED(rv)) return rv;
1254 switch (verifystate)
1256 case nsIX509Cert::VERIFIED_OK:
1257 text = _("This certificate has been verified for the following uses:");
1259 case nsIX509Cert::CERT_REVOKED:
1260 text = _("Could not verify this certificate because it has been revoked.");
1262 case nsIX509Cert::CERT_EXPIRED:
1263 text = _("Could not verify this certificate because it has expired.");
1265 case nsIX509Cert::CERT_NOT_TRUSTED:
1266 text = _("Could not verify this certificate because it is not trusted.");
1268 case nsIX509Cert::ISSUER_NOT_TRUSTED:
1269 text = _("Could not verify this certificate because the issuer is not trusted.");
1271 case nsIX509Cert::ISSUER_UNKNOWN:
1272 text = _("Could not verify this certificate because the issuer is unknown.");
1274 case nsIX509Cert::INVALID_CA:
1275 text = _("Could not verify this certificate because the CA certificate is invalid.");
1277 case nsIX509Cert::NOT_VERIFIED_UNKNOWN:
1278 case nsIX509Cert::USAGE_NOT_ALLOWED:
1280 text = _("Could not verify this certificate for unknown reasons.");
1283 char *vmsg = g_strdup_printf ("<b>%s</b>", text);
1284 widget = glade_xml_get_widget (gxml, "label_verify_text");
1285 g_return_val_if_fail (GTK_IS_LABEL (widget), NS_ERROR_FAILURE);
1286 gtk_label_set_markup (GTK_LABEL (widget), vmsg);
1291 GtkWidget *vbox = gtk_vbox_new (FALSE, 3);
1293 for (PRUint32 i = 0 ; i < count ; i++)
1295 GtkWidget *label = gtk_label_new (NS_ConvertUTF16toUTF8 (usage[i]).get());
1296 gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
1297 gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
1298 nsMemory::Free (usage[i]);
1300 nsMemory::Free (usage);
1301 indent = higgy_indent_widget (vbox);
1302 widget = glade_xml_get_widget (gxml, "vbox_validity");
1303 g_return_val_if_fail (GTK_IS_BOX (widget), NS_ERROR_FAILURE);
1305 gtk_box_pack_start (GTK_BOX (widget), indent, FALSE, FALSE, 0);
1308 cert->GetCommonName (value);
1309 set_label_cert_attribute (gxml, "label_cn", value);
1311 cert->GetOrganization (value);
1312 set_label_cert_attribute (gxml, "label_o", value);
1314 cert->GetOrganizationalUnit (value);
1315 set_label_cert_attribute (gxml, "label_ou", value);
1317 cert->GetSerialNumber (value);
1318 set_label_cert_attribute (gxml, "label_serial", value);
1320 rv = cert->GetIssuerCommonName (value);
1321 if (NS_FAILED(rv)) return rv;
1322 set_label_cert_attribute (gxml, "label_issuer_cn", value);
1324 cert->GetIssuerOrganization (value);
1325 set_label_cert_attribute (gxml, "label_issuer_o", value);
1327 cert->GetIssuerOrganizationUnit (value);
1328 set_label_cert_attribute (gxml, "label_issuer_ou", value);
1330 nsCOMPtr<nsIX509CertValidity> validity;
1331 rv = cert->GetValidity (getter_AddRefs(validity));
1332 if (NS_FAILED(rv)) return rv;
1334 rv = validity->GetNotAfterLocalDay (value);
1335 if (NS_FAILED(rv)) return rv;
1336 set_label_cert_attribute (gxml, "label_notafter", value);
1338 rv = validity->GetNotBeforeLocalDay (value);
1339 if (NS_FAILED(rv)) return rv;
1340 set_label_cert_attribute (gxml, "label_notbefore", value);
1342 cert->GetSha1Fingerprint (value);
1343 set_label_cert_attribute (gxml, "label_sha_print", value);
1345 cert->GetMd5Fingerprint (value);
1346 set_label_cert_attribute (gxml, "label_md5_print", value);
1348 /* Hold a reference to each certificate in the chain while the
1349 * dialog is displayed, this holds the reference for the ASN
1350 * objects as well */
1352 nsCOMPtr<nsIArray> certChain;
1353 rv = cert->GetChain (getter_AddRefs(certChain));
1354 if (NS_FAILED(rv)) return rv;
1356 gboolean ret = setup_view_cert_tree (dialog, gxml, certChain);
1357 if (ret == FALSE) return NS_ERROR_FAILURE;
1359 g_object_unref (gxml);
1361 gtk_widget_show_all (dialog);
1366 res = gtk_dialog_run (GTK_DIALOG (dialog));
1367 if (res == GTK_RESPONSE_HELP)
1369 ephy_gui_help (GTK_WINDOW (dialog), "epiphany", "using-certificate-viewer");
1375 gtk_widget_destroy (dialog);
1379 /* nsITokenPasswordDialogs */
1381 /* NOTE: This interface totally sucks, see https://bugzilla.mozilla.org/show_bug.cgi?id=306993 */
1383 /* void setPassword (in nsIInterfaceRequestor ctx, in wstring tokenName, out boolean canceled); */
1385 GtkNSSDialogs::SetPassword(nsIInterfaceRequestor *aCtx,
1386 const PRUnichar *aTokenName,
1389 NS_ENSURE_ARG_POINTER(aCancelled);
1392 nsCOMPtr<nsIPK11Token> token;
1393 nsCOMPtr<nsIPKCS11Slot> slot;
1394 rv = GetTokenAndSlotFromName (aTokenName, getter_AddRefs (token),
1395 getter_AddRefs (slot));
1396 NS_ENSURE_SUCCESS (rv, rv);
1397 NS_ENSURE_TRUE (token && slot, NS_ERROR_FAILURE);
1399 AutoJSContextStack stack;
1401 if (NS_FAILED (rv)) return rv;
1403 PRUint32 status = nsIPKCS11Slot::SLOT_UNINITIALIZED;
1404 slot->GetStatus (&status);
1406 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aCtx));
1407 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
1409 AutoWindowModalState modalState (parent);
1411 EphyPasswordDialogFlags flags =
1412 EphyPasswordDialogFlags (EPHY_PASSWORD_DIALOG_FLAGS_SHOW_NEW_PASSWORD |
1413 EPHY_PASSWORD_DIALOG_FLAGS_SHOW_QUALITY_METER);
1414 if (status != nsIPKCS11Slot::SLOT_UNINITIALIZED)
1415 flags = EphyPasswordDialogFlags (flags | EPHY_PASSWORD_DIALOG_FLAGS_SHOW_PASSWORD);
1417 GtkWidget *dialog = ephy_password_dialog_new
1419 _("Change Token Password"),
1421 EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog);
1424 if (status == nsIPKCS11Slot::SLOT_UNINITIALIZED) {
1425 message = g_markup_printf_escaped (_("Choose a password for the “%s” token"),
1426 NS_ConvertUTF16toUTF8 (aTokenName).get ());
1428 message = g_markup_printf_escaped (_("Change the password for the “%s” token"),
1429 NS_ConvertUTF16toUTF8 (aTokenName).get ());
1432 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
1437 nsString oldPassword;
1438 PRBool pwdOk, needsLogin;
1440 response = gtk_dialog_run (GTK_DIALOG (dialog));
1442 if (status != nsIPKCS11Slot::SLOT_UNINITIALIZED)
1444 const char *pwd = ephy_password_dialog_get_password (password_dialog);
1445 oldPassword = NS_ConvertUTF8toUTF16 (pwd);
1447 } while (response == GTK_RESPONSE_OK &&
1448 status != nsIPKCS11Slot::SLOT_UNINITIALIZED &&
1449 NS_SUCCEEDED (token->NeedsLogin (&needsLogin)) && needsLogin &&
1450 NS_SUCCEEDED (token->CheckPassword (oldPassword.get (), &pwdOk) &&
1453 if (response == GTK_RESPONSE_ACCEPT)
1455 const char *pwd = ephy_password_dialog_get_new_password (password_dialog);
1457 NS_ConvertUTF8toUTF16 newPassword (pwd);
1459 if (status == nsIPKCS11Slot::SLOT_UNINITIALIZED)
1461 rv = token->InitPassword (newPassword.get ());
1465 rv = token->ChangePassword (oldPassword.get (),
1466 newPassword.get ());
1474 gtk_widget_destroy (GTK_WIDGET (dialog));
1476 *aCancelled = response != GTK_RESPONSE_ACCEPT;
1481 /* void getPassword (in nsIInterfaceRequestor ctx, in wstring tokenName, out wstring password, out boolean canceled); */
1483 GtkNSSDialogs::GetPassword(nsIInterfaceRequestor *aCtx,
1484 const PRUnichar *aTokenName,
1485 PRUnichar **aPassword,
1488 NS_ENSURE_ARG_POINTER(aCancelled);
1491 nsCOMPtr<nsIPK11Token> token;
1492 nsCOMPtr<nsIPKCS11Slot> slot;
1493 rv = GetTokenAndSlotFromName (aTokenName, getter_AddRefs (token),
1494 getter_AddRefs (slot));
1495 NS_ENSURE_SUCCESS (rv, rv);
1496 NS_ENSURE_TRUE (token && slot, NS_ERROR_FAILURE);
1498 AutoJSContextStack stack;
1500 if (NS_FAILED (rv)) return rv;
1502 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aCtx));
1503 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
1505 AutoWindowModalState modalState (parent);
1507 EphyPasswordDialogFlags flags =
1508 EphyPasswordDialogFlags (EPHY_PASSWORD_DIALOG_FLAGS_SHOW_PASSWORD);
1510 GtkWidget *dialog = ephy_password_dialog_new
1512 _("Get Token Password"), /* FIXME */
1514 EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog);
1516 /* Translators: A "token" is something that enables the user to authenticate himself or
1517 * prove his credentials. This can be either a hardware device (e.g. a smart-card), or
1518 * a data file (e.g. a cryptographic certificate).
1520 char *message = g_markup_printf_escaped (_("Please enter the password for the “%s” token"),
1521 NS_ConvertUTF16toUTF8 (aTokenName).get ());
1522 gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog),
1526 int response = gtk_dialog_run (GTK_DIALOG (dialog));
1528 if (response == GTK_RESPONSE_ACCEPT)
1530 const char *pwd = ephy_password_dialog_get_password (password_dialog);
1531 *aPassword = NS_StringCloneData (NS_ConvertUTF8toUTF16 (pwd));
1534 gtk_widget_destroy (GTK_WIDGET (dialog));
1536 *aCancelled = response != GTK_RESPONSE_ACCEPT;
1541 /* nsITokenDialogs */
1544 SelectionChangedCallback (GtkComboBox *combo,
1547 int active = gtk_combo_box_get_active (combo);
1548 gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_ACCEPT, active >= 0);
1551 /* void ChooseToken (in nsIInterfaceRequestor ctx,
1552 [array, size_is (count)] in wstring tokenNameList,
1553 in unsigned long count,
1554 out wstring tokenName,
1555 out boolean canceled); */
1557 GtkNSSDialogs::ChooseToken (nsIInterfaceRequestor *aContext,
1558 const PRUnichar **tokenNameList,
1560 PRUnichar **_tokenName,
1563 NS_ENSURE_ARG (tokenNameList);
1564 NS_ENSURE_ARG (count);
1567 AutoJSContextStack stack;
1569 if (NS_FAILED (rv)) return rv;
1571 /* Didn't you know it? MOZILLA SUCKS! ChooseToken is always called with |aContext| == NULL! See
1572 * http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/manager/ssl/src/nsKeygenHandler.cpp&rev=1.39&mark=346#346
1573 * Need to investigate if we it's always called directly from code called from JS, in which case we
1574 * can use EphyJSUtils::GetDOMWindowFromCallContext.
1576 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aContext));
1577 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
1579 AutoWindowModalState modalState (parent);
1581 GtkWidget *dialog = gtk_message_dialog_new
1582 (GTK_WINDOW (gparent),
1583 GTK_DIALOG_DESTROY_WITH_PARENT,
1586 _("Please select a token:"));
1588 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
1590 GtkWidget *combo = gtk_combo_box_new_text ();
1591 for (PRUint32 i = 0; i < count; ++i) {
1592 gtk_combo_box_append_text (GTK_COMBO_BOX (combo),
1593 NS_ConvertUTF16toUTF8 (tokenNameList[i]).get ());
1595 gtk_combo_box_set_active (GTK_COMBO_BOX (combo), -1);
1596 g_signal_connect (combo, "changed",
1597 G_CALLBACK (SelectionChangedCallback), dialog);
1599 /* FIXME: View Cert button? */
1601 GtkWidget *vbox = GTK_MESSAGE_DIALOG (dialog)->label->parent;
1602 gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0);
1604 gtk_dialog_add_button (GTK_DIALOG (dialog),
1606 GTK_RESPONSE_ACCEPT);
1608 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
1610 int response = gtk_dialog_run (GTK_DIALOG (dialog));
1611 int selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combo));
1613 gtk_widget_destroy (dialog);
1615 *_cancelled = response != GTK_RESPONSE_ACCEPT;
1617 if (response == GTK_RESPONSE_ACCEPT) {
1618 NS_ENSURE_TRUE (selected >= 0 && selected < (int) count, NS_ERROR_FAILURE);
1619 *_tokenName = NS_StringCloneData (nsDependentString (tokenNameList[selected]));
1625 /* nsIDOMCryptoDialogs */
1627 /* Note: this interface sucks! See https://bugzilla.mozilla.org/show_bug.cgi?id=341914 */
1629 /* boolean ConfirmKeyEscrow (in nsIX509Cert escrowAuthority); */
1631 GtkNSSDialogs::ConfirmKeyEscrow (nsIX509Cert *aEscrowAuthority,
1634 NS_ENSURE_ARG (aEscrowAuthority);
1637 AutoJSContextStack stack;
1639 if (NS_FAILED (rv)) return rv;
1642 nsCOMPtr<nsIDOMWindow> parent (do_GetInterface (aCtx));
1644 nsCOMPtr<nsIDOMWindow> parent (EphyJSUtils::GetDOMWindowFromCallContext ());
1645 GtkWidget *gparent = EphyUtils::FindGtkParent (parent);
1647 AutoWindowModalState modalState (parent);
1649 /* FIXME: is that guaranteed to be non-empty? */
1650 nsString commonName;
1651 aEscrowAuthority->GetCommonName (commonName);
1653 GtkWidget *dialog = gtk_message_dialog_new
1654 (GTK_WINDOW (gparent),
1655 GTK_DIALOG_DESTROY_WITH_PARENT,
1656 GTK_MESSAGE_WARNING /* QUESTION really but it's also a strong warnings... */,
1658 _("Escrow the secret key?"));
1660 /* FIXME: If I understand the documentation of generateCRMFRequest
1661 * correctly, key escrow is never used for signing keys (if it were,
1662 * we'd have to warn that the cert authority can forge your signature
1665 gtk_message_dialog_format_secondary_text
1666 (GTK_MESSAGE_DIALOG (dialog),
1667 _("The certificate authority “%s” requests that you give it a copy "
1668 "of the newly generated secret key.\n\n"
1669 "This will enable the certificate authority read any "
1670 "communications encrypted with this key "
1671 "without your knowledge or consent.\n\n"
1672 "It is strongly recommended not to allow it."),
1673 NS_ConvertUTF16toUTF8 (commonName).get ());
1675 gtk_window_set_icon_name (GTK_WINDOW (dialog), EPHY_STOCK_EPHY);
1677 GtkWidget *button = gtk_dialog_add_button (GTK_DIALOG (dialog),
1679 GTK_RESPONSE_REJECT);
1680 gtk_dialog_add_button (GTK_DIALOG (dialog),
1682 GTK_RESPONSE_ACCEPT);
1683 /* FIXME: View Cert button? */
1685 gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT);
1686 gtk_widget_grab_focus (button);
1688 int response = gtk_dialog_run (GTK_DIALOG (dialog));
1689 gtk_widget_destroy (dialog);
1691 *_retval = response == GTK_RESPONSE_ACCEPT;