From ff3e857464ce32f626e080f93ea66ce1b5c372e3 Mon Sep 17 00:00:00 2001 From: Christian Persch Date: Sun, 23 Jul 2006 19:55:18 +0000 Subject: Implement nsIDOMCryptoDialogs, nsITokenDialogs and 2006-07-22 Christian Persch * embed/mozilla/GtkNSSDialogs.cpp: * embed/mozilla/GtkNSSDialogs.h: * embed/mozilla/MozRegisterComponents.cpp: Implement nsIDOMCryptoDialogs, nsITokenDialogs and nsITokenPasswordDialogs. Bug #312869. * embed/mozilla/EphyUtils.cpp: * embed/mozilla/EphyUtils.h: Add a helper function to get the DOM window off the native call context, to work around unavailable parent window in nsIDOMCryptoDialogs ( https://bugzilla.mozilla.org/show_bug.cgi?id=341914). --- embed/mozilla/EphyUtils.cpp | 50 +++++++++- embed/mozilla/EphyUtils.h | 2 + embed/mozilla/GtkNSSDialogs.cpp | 160 +++++++++++++++++++++++++++++--- embed/mozilla/MozRegisterComponents.cpp | 18 ++++ 4 files changed, 211 insertions(+), 19 deletions(-) (limited to 'embed') diff --git a/embed/mozilla/EphyUtils.cpp b/embed/mozilla/EphyUtils.cpp index ab6d78e1a..d5ac7fec6 100644 --- a/embed/mozilla/EphyUtils.cpp +++ b/embed/mozilla/EphyUtils.cpp @@ -21,21 +21,28 @@ #include "mozilla-config.h" #include "config.h" +#include + #include #include #include #include #include #include -#include #include #include #include #include +#include #include -#include #include -#include + +#ifdef HAVE_GECKO_1_9 +#include +#include /* for GetScriptContextFromJSContext */ +#include +#include +#endif #include "ephy-embed-shell.h" #include "ephy-embed-single.h" @@ -131,7 +138,7 @@ GtkWidget * EphyUtils::FindGtkParent (nsIDOMWindow *aDOMWindow) { GtkWidget *embed = FindEmbed (aDOMWindow); - NS_ENSURE_TRUE (embed, nsnull); + if (!embed) return nsnull; GtkWidget *toplevel = gtk_widget_get_toplevel (GTK_WIDGET (embed)); if (!GTK_WIDGET_TOPLEVEL (toplevel)) return nsnull; @@ -174,3 +181,38 @@ EphyJSUtils::IsCalledFromScript () return nsnull != ncc; } + +/* NOTE: Only call this when we're SURE that we're called directly from JS! */ +nsIDOMWindow * +EphyJSUtils::GetDOMWindowFromCallContext () +{ + /* TODO: We can do this on 1.8 too, but we'd need to use headers which include private string API + * so we'll have to move this to MozillaPrivate + */ +#ifdef HAVE_GECKO_1_9 + nsresult rv; + nsCOMPtr xpc (do_GetService(nsIXPConnect::GetCID(), &rv)); + NS_ENSURE_SUCCESS (rv, nsnull); + + nsCOMPtr ncc; + rv = xpc->GetCurrentNativeCallContext (getter_AddRefs (ncc)); + NS_ENSURE_SUCCESS (rv, nsnull); + + JSContext *cx = nsnull; + rv = ncc->GetJSContext(&cx); + NS_ENSURE_TRUE (NS_SUCCEEDED (rv) && cx, nsnull); + + nsIScriptContext* scriptContext = GetScriptContextFromJSContext (cx); + if (!scriptContext) return nsnull; + + nsIScriptGlobalObject *globalObject = scriptContext->GetGlobalObject(); + if (!globalObject) return nsnull; + + nsCOMPtr piWindow (do_QueryInterface (globalObject)); + if (!piWindow) return nsnull; + + return piWindow->GetOuterWindow (); +#else + return nsnull; +#endif +} diff --git a/embed/mozilla/EphyUtils.h b/embed/mozilla/EphyUtils.h index c19ae088f..64132f675 100644 --- a/embed/mozilla/EphyUtils.h +++ b/embed/mozilla/EphyUtils.h @@ -64,6 +64,8 @@ namespace EphyUtils namespace EphyJSUtils { PRBool IsCalledFromScript (); + + /* not addref'd! */ nsIDOMWindow* GetDOMWindowFromCallContext (); } #endif diff --git a/embed/mozilla/GtkNSSDialogs.cpp b/embed/mozilla/GtkNSSDialogs.cpp index 9c7f4cd12..151b4a179 100644 --- a/embed/mozilla/GtkNSSDialogs.cpp +++ b/embed/mozilla/GtkNSSDialogs.cpp @@ -53,6 +53,7 @@ #include #include #include +#include #include #include @@ -118,8 +119,6 @@ NS_IMPL_THREADSAFE_ISUPPORTS5 (GtkNSSDialogs, /* There's also nsICertPickDialogs which is implemented in mozilla * but has no callers. So we don't implement it. * Same for nsIUserCertPicker which is only used in mailnews. - * - * We should implement nsIFormSigningDialog, however. */ /** @@ -1420,8 +1419,15 @@ GtkNSSDialogs::SetPassword(nsIInterfaceRequestor *aCtx, flags); EphyPasswordDialog *password_dialog = EPHY_PASSWORD_DIALOG (dialog); - char *message = g_markup_printf_escaped (_("Change the password for the “%s” token"), - NS_ConvertUTF16toUTF8 (aTokenName).get ()); + char *message; + if (status == nsIPKCS11Slot::SLOT_UNINITIALIZED) { + message = g_markup_printf_escaped (_("Choose a password for the “%s” token"), + NS_ConvertUTF16toUTF8 (aTokenName).get ()); + } else { + message = g_markup_printf_escaped (_("Change the password for the “%s” token"), + NS_ConvertUTF16toUTF8 (aTokenName).get ()); + } + gtk_message_dialog_set_markup (GTK_MESSAGE_DIALOG (dialog), message); g_free (message); @@ -1529,31 +1535,155 @@ GtkNSSDialogs::GetPassword(nsIInterfaceRequestor *aCtx, /* nsITokenDialogs */ -/* void ChooseToken (in nsIInterfaceRequestor ctx, [array, size_is (count)] in wstring tokenNameList, in unsigned long count, out wstring tokenName, out boolean canceled); */ +static void +SelectionChangedCallback (GtkComboBox *combo, + GtkDialog *dialog) +{ + int active = gtk_combo_box_get_active (combo); + gtk_dialog_set_response_sensitive (dialog, GTK_RESPONSE_ACCEPT, active >= 0); +} + +/* void ChooseToken (in nsIInterfaceRequestor ctx, + [array, size_is (count)] in wstring tokenNameList, + in unsigned long count, + out wstring tokenName, + out boolean canceled); */ NS_IMETHODIMP -GtkNSSDialogs::ChooseToken (nsIInterfaceRequestor *ctx, +GtkNSSDialogs::ChooseToken (nsIInterfaceRequestor *aContext, const PRUnichar **tokenNameList, PRUint32 count, - PRUnichar **tokenName, - PRBool *canceled) + PRUnichar **_tokenName, + PRBool *_cancelled) { - /* FIXME: implement me! The only caller is from nsKeygenHandler */ - return NS_ERROR_NOT_IMPLEMENTED; + NS_ENSURE_ARG (tokenNameList); + NS_ENSURE_ARG (count); + + nsresult rv; + AutoJSContextStack stack; + rv = stack.Init (); + if (NS_FAILED (rv)) return rv; + + /* Didn't you know it? MOZILLA SUCKS! ChooseToken is always called with |aContext| == NULL! See + * http://bonsai.mozilla.org/cvsblame.cgi?file=mozilla/security/manager/ssl/src/nsKeygenHandler.cpp&rev=1.39&mark=346#346 + * Need to investigate if we it's always called directly from code called from JS, in which case we + * can use EphyJSUtils::GetDOMWindowFromCallContext. + */ + nsCOMPtr parent (do_GetInterface (aContext)); + GtkWidget *gparent = EphyUtils::FindGtkParent (parent); + + AutoWindowModalState modalState (parent); + + GtkWidget *dialog = gtk_message_dialog_new + (GTK_WINDOW (gparent), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_OTHER, + GTK_BUTTONS_CANCEL, + _("Please select a token:")); + + gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); + + GtkWidget *combo = gtk_combo_box_new_text (); + for (PRUint32 i = 0; i < count; ++i) { + gtk_combo_box_append_text (GTK_COMBO_BOX (combo), + NS_ConvertUTF16toUTF8 (tokenNameList[i]).get ()); + } + gtk_combo_box_set_active (GTK_COMBO_BOX (combo), -1); + g_signal_connect (combo, "changed", + G_CALLBACK (SelectionChangedCallback), dialog); + + /* FIXME: View Cert button? */ + + GtkWidget *vbox = GTK_MESSAGE_DIALOG (dialog)->label->parent; + gtk_box_pack_start (GTK_BOX (vbox), combo, FALSE, FALSE, 0); + + gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Select"), + GTK_RESPONSE_ACCEPT); + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT); + + int response = gtk_dialog_run (GTK_DIALOG (dialog)); + int selected = gtk_combo_box_get_active (GTK_COMBO_BOX (combo)); + + gtk_widget_destroy (dialog); + + *_cancelled = response != GTK_RESPONSE_ACCEPT; + + if (response == GTK_RESPONSE_ACCEPT) { + NS_ENSURE_TRUE (selected >= 0 && selected < (int) count, NS_ERROR_FAILURE); + *_tokenName = NS_StringCloneData (nsDependentString (tokenNameList[selected])); + } + + return NS_OK; } /* nsIDOMCryptoDialogs */ /* Note: this interface sucks! See https://bugzilla.mozilla.org/show_bug.cgi?id=341914 */ - + /* boolean ConfirmKeyEscrow (in nsIX509Cert escrowAuthority); */ NS_IMETHODIMP GtkNSSDialogs::ConfirmKeyEscrow (nsIX509Cert *aEscrowAuthority, PRBool *_retval) { - /* FIXME: show a dialogue to warn the user! */ + NS_ENSURE_ARG (aEscrowAuthority); - /* Escrow is evil, don't allow it. */ - *_retval = PR_FALSE; + nsresult rv; + AutoJSContextStack stack; + rv = stack.Init (); + if (NS_FAILED (rv)) return rv; - return NS_OK; +#if 0 + nsCOMPtr parent (do_GetInterface (aCtx)); +#endif + nsCOMPtr parent (EphyJSUtils::GetDOMWindowFromCallContext ()); + GtkWidget *gparent = EphyUtils::FindGtkParent (parent); + + AutoWindowModalState modalState (parent); + + /* FIXME: is that guaranteed to be non-empty? */ + nsString commonName; + aEscrowAuthority->GetCommonName (commonName); + + GtkWidget *dialog = gtk_message_dialog_new + (GTK_WINDOW (gparent), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_WARNING /* QUESTION really but it's also a strong warnings... */, + GTK_BUTTONS_NONE, + _("Escrow the secret key?")); + + /* FIXME: If I understand the documentation of generateCRMFRequest + * correctly, key escrow is never used for signing keys (if it were, + * we'd have to warn that the cert authority can forge your signature + * too). + */ + gtk_message_dialog_format_secondary_text + (GTK_MESSAGE_DIALOG (dialog), + _("The certificate authority “%s” requests that you give it a copy " + "of the newly generated secret key.\n\n" + "This will enable the certificate authority read any " + "communications encrypted with this key " + "without your knowledge or consent.\n\n" + "It is strongly recommended not to allow it."), + NS_ConvertUTF16toUTF8 (commonName).get ()); + + gtk_window_set_icon_name (GTK_WINDOW (dialog), "web-browser"); + + GtkWidget *button = gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Reject"), + GTK_RESPONSE_REJECT); + gtk_dialog_add_button (GTK_DIALOG (dialog), + _("_Allow"), + GTK_RESPONSE_ACCEPT); + /* FIXME: View Cert button? */ + + gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_REJECT); + gtk_widget_grab_focus (button); + + int response = gtk_dialog_run (GTK_DIALOG (dialog)); + gtk_widget_destroy (dialog); + + *_retval = response == GTK_RESPONSE_ACCEPT; + + return NS_OK; } diff --git a/embed/mozilla/MozRegisterComponents.cpp b/embed/mozilla/MozRegisterComponents.cpp index 86ce9fc21..64d5afc1a 100644 --- a/embed/mozilla/MozRegisterComponents.cpp +++ b/embed/mozilla/MozRegisterComponents.cpp @@ -184,6 +184,24 @@ static const nsModuleComponentInfo sAppComps[] = { NS_CERTIFICATEDIALOGS_CONTRACTID, GtkNSSDialogsConstructor }, + { + GTK_NSSDIALOGS_CLASSNAME, + GTK_NSSDIALOGS_CID, + NS_DOMCRYPTODIALOGS_CONTRACTID, + GtkNSSDialogsConstructor + }, + { + GTK_NSSDIALOGS_CLASSNAME, + GTK_NSSDIALOGS_CID, + NS_TOKENDIALOGS_CONTRACTID, + GtkNSSDialogsConstructor + }, + { + GTK_NSSDIALOGS_CLASSNAME, + GTK_NSSDIALOGS_CID, + NS_TOKENPASSWORDSDIALOG_CONTRACTID, + GtkNSSDialogsConstructor + }, { GTK_NSSKEYPAIRDIALOGS_CLASSNAME, GTK_NSSKEYPAIRDIALOGS_CID, -- cgit v1.2.3