michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /* michael@0: * Dialog services for PIP. michael@0: */ michael@0: #include "nsCOMPtr.h" michael@0: #include "nsString.h" michael@0: #include "nsXPIDLString.h" michael@0: #include "nsReadableUtils.h" michael@0: #include "nsIDOMWindow.h" michael@0: #include "nsIDialogParamBlock.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsIStringBundle.h" michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIInterfaceRequestorUtils.h" michael@0: #include "nsIX509Cert.h" michael@0: #include "nsIX509CertDB.h" michael@0: #include "nsIDateTimeFormat.h" michael@0: #include "nsDateTimeFormatCID.h" michael@0: #include "nsPromiseFlatString.h" michael@0: michael@0: #include "nsNSSDialogs.h" michael@0: #include "nsPKIParamBlock.h" michael@0: #include "nsIKeygenThread.h" michael@0: #include "nsIProtectedAuthThread.h" michael@0: #include "nsNSSDialogHelper.h" michael@0: #include "nsIWindowWatcher.h" michael@0: #include "nsIX509CertValidity.h" michael@0: michael@0: #include "nsEmbedCID.h" michael@0: #include "nsIPromptService.h" michael@0: michael@0: #define PIPSTRING_BUNDLE_URL "chrome://pippki/locale/pippki.properties" michael@0: michael@0: /* ==== */ michael@0: michael@0: nsNSSDialogs::nsNSSDialogs() michael@0: { michael@0: } michael@0: michael@0: nsNSSDialogs::~nsNSSDialogs() michael@0: { michael@0: } michael@0: michael@0: NS_IMPL_ISUPPORTS(nsNSSDialogs, nsITokenPasswordDialogs, michael@0: nsICertificateDialogs, michael@0: nsIClientAuthDialogs, michael@0: nsICertPickDialogs, michael@0: nsITokenDialogs, michael@0: nsIDOMCryptoDialogs, michael@0: nsIGeneratingKeypairInfoDialogs, michael@0: nsISSLCertErrorDialog) michael@0: michael@0: nsresult michael@0: nsNSSDialogs::Init() michael@0: { michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr service = michael@0: do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = service->CreateBundle(PIPSTRING_BUNDLE_URL, michael@0: getter_AddRefs(mPIPStringBundle)); michael@0: return rv; michael@0: } michael@0: michael@0: nsresult michael@0: nsNSSDialogs::SetPassword(nsIInterfaceRequestor *ctx, michael@0: const char16_t *tokenName, bool* _canceled) michael@0: { michael@0: nsresult rv; michael@0: michael@0: *_canceled = false; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: michael@0: // void ChangePassword(in wstring tokenName, out int status); michael@0: rv = block->SetString(1, tokenName); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/changepassword.xul", michael@0: block); michael@0: michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: int32_t status; michael@0: michael@0: rv = block->GetInt(1, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: *_canceled = (status == 0)?true:false; michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: nsresult michael@0: nsNSSDialogs::GetPassword(nsIInterfaceRequestor *ctx, michael@0: const char16_t *tokenName, michael@0: char16_t **_password, michael@0: bool* _canceled) michael@0: { michael@0: nsresult rv; michael@0: *_canceled = false; michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: // Set the token name in the window michael@0: rv = block->SetString(1, tokenName); michael@0: if (NS_FAILED(rv)) return rv; michael@0: // open up the window michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/getpassword.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: // see if user canceled michael@0: int32_t status; michael@0: rv = block->GetInt(1, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: *_canceled = (status == 0) ? true : false; michael@0: if (!*_canceled) { michael@0: // retrieve the password michael@0: rv = block->GetString(2, _password); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::ConfirmDownloadCACert(nsIInterfaceRequestor *ctx, michael@0: nsIX509Cert *cert, michael@0: uint32_t *_trust, michael@0: bool *_retval) michael@0: { michael@0: nsresult rv; michael@0: michael@0: *_retval = true; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_PKIPARAMBLOCK_CONTRACTID); michael@0: if (!block) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: rv = block->SetISupportAtIndex(1, cert); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/downloadcert.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: int32_t status; michael@0: int32_t ssl, email, objsign; michael@0: michael@0: nsCOMPtr dlgParamBlock = do_QueryInterface(block); michael@0: michael@0: rv = dlgParamBlock->GetInt(1, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: rv = dlgParamBlock->GetInt(2, &ssl); michael@0: if (NS_FAILED(rv)) return rv; michael@0: rv = dlgParamBlock->GetInt(3, &email); michael@0: if (NS_FAILED(rv)) return rv; michael@0: rv = dlgParamBlock->GetInt(4, &objsign); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: *_trust = nsIX509CertDB::UNTRUSTED; michael@0: *_trust |= (ssl) ? nsIX509CertDB::TRUSTED_SSL : 0; michael@0: *_trust |= (email) ? nsIX509CertDB::TRUSTED_EMAIL : 0; michael@0: *_trust |= (objsign) ? nsIX509CertDB::TRUSTED_OBJSIGN : 0; michael@0: michael@0: *_retval = (status == 0)?false:true; michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::NotifyCACertExists(nsIInterfaceRequestor *ctx) michael@0: { michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr promptSvc(do_GetService(NS_PROMPTSERVICE_CONTRACTID)); michael@0: if (!promptSvc) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: michael@0: nsAutoString title; michael@0: rv = mPIPStringBundle->GetStringFromName(MOZ_UTF16("caCertExistsTitle"), michael@0: getter_Copies(title)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: nsAutoString msg; michael@0: rv = mPIPStringBundle->GetStringFromName(MOZ_UTF16("caCertExistsMessage"), michael@0: getter_Copies(msg)); michael@0: NS_ENSURE_SUCCESS(rv, rv); michael@0: michael@0: rv = promptSvc->Alert(parent, title.get(), msg.get()); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::ChooseCertificate(nsIInterfaceRequestor *ctx, const char16_t *cn, const char16_t *organization, const char16_t *issuer, const char16_t **certNickList, const char16_t **certDetailsList, uint32_t count, int32_t *selectedIndex, bool *canceled) michael@0: { michael@0: nsresult rv; michael@0: uint32_t i; michael@0: michael@0: *canceled = false; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: michael@0: block->SetNumberStrings(4+count*2); michael@0: michael@0: rv = block->SetString(0, cn); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = block->SetString(1, organization); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = block->SetString(2, issuer); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: for (i = 0; i < count; i++) { michael@0: rv = block->SetString(i+3, certNickList[i]); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: for (i = 0; i < count; i++) { michael@0: rv = block->SetString(i+count+3, certDetailsList[i]); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: rv = block->SetInt(0, count); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(nullptr, michael@0: "chrome://pippki/content/clientauthask.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: int32_t status; michael@0: rv = block->GetInt(0, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: nsCOMPtr extraResult = do_QueryInterface(ctx); michael@0: if (extraResult) { michael@0: int32_t rememberSelection; michael@0: rv = block->GetInt(2, &rememberSelection); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: extraResult->SetRememberClientAuthCertificate(rememberSelection!=0); michael@0: } michael@0: } michael@0: michael@0: *canceled = (status == 0)?true:false; michael@0: if (!*canceled) { michael@0: // retrieve the nickname michael@0: rv = block->GetInt(1, selectedIndex); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::PickCertificate(nsIInterfaceRequestor *ctx, michael@0: const char16_t **certNickList, michael@0: const char16_t **certDetailsList, michael@0: uint32_t count, michael@0: int32_t *selectedIndex, michael@0: bool *canceled) michael@0: { michael@0: nsresult rv; michael@0: uint32_t i; michael@0: michael@0: *canceled = false; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: michael@0: block->SetNumberStrings(1+count*2); michael@0: michael@0: for (i = 0; i < count; i++) { michael@0: rv = block->SetString(i, certNickList[i]); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: for (i = 0; i < count; i++) { michael@0: rv = block->SetString(i+count, certDetailsList[i]); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: rv = block->SetInt(0, count); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = block->SetInt(1, *selectedIndex); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(nullptr, michael@0: "chrome://pippki/content/certpicker.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: int32_t status; michael@0: michael@0: rv = block->GetInt(0, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: *canceled = (status == 0)?true:false; michael@0: if (!*canceled) { michael@0: rv = block->GetInt(1, selectedIndex); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::SetPKCS12FilePassword(nsIInterfaceRequestor *ctx, michael@0: nsAString &_password, michael@0: bool *_retval) michael@0: { michael@0: nsresult rv; michael@0: *_retval = true; michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: // open up the window michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/setp12password.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: // see if user canceled michael@0: int32_t status; michael@0: rv = block->GetInt(1, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: *_retval = (status == 0) ? false : true; michael@0: if (*_retval) { michael@0: // retrieve the password michael@0: char16_t *pw; michael@0: rv = block->GetString(2, &pw); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: _password = pw; michael@0: nsMemory::Free(pw); michael@0: } michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::GetPKCS12FilePassword(nsIInterfaceRequestor *ctx, michael@0: nsAString &_password, michael@0: bool *_retval) michael@0: { michael@0: nsresult rv; michael@0: *_retval = true; michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: // open up the window michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/getp12password.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: // see if user canceled michael@0: int32_t status; michael@0: rv = block->GetInt(1, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: *_retval = (status == 0) ? false : true; michael@0: if (*_retval) { michael@0: // retrieve the password michael@0: char16_t *pw; michael@0: rv = block->GetString(2, &pw); michael@0: if (NS_SUCCEEDED(rv)) { michael@0: _password = pw; michael@0: nsMemory::Free(pw); michael@0: } michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: /* void viewCert (in nsIX509Cert cert); */ michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::ViewCert(nsIInterfaceRequestor *ctx, michael@0: nsIX509Cert *cert) michael@0: { michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_PKIPARAMBLOCK_CONTRACTID); michael@0: if (!block) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: rv = block->SetISupportAtIndex(1, cert); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(ctx); michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/certViewer.xul", michael@0: block, michael@0: false); michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::DisplayGeneratingKeypairInfo(nsIInterfaceRequestor *aCtx, nsIKeygenThread *runnable) michael@0: { michael@0: nsresult rv; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(aCtx); michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(parent, michael@0: "chrome://pippki/content/createCertInfo.xul", michael@0: runnable); michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::ChooseToken(nsIInterfaceRequestor *aCtx, const char16_t **aTokenList, uint32_t aCount, char16_t **aTokenChosen, bool *aCanceled) { michael@0: nsresult rv; michael@0: uint32_t i; michael@0: michael@0: *aCanceled = false; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(aCtx); michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_DIALOGPARAMBLOCK_CONTRACTID); michael@0: if (!block) return NS_ERROR_FAILURE; michael@0: michael@0: block->SetNumberStrings(aCount); michael@0: michael@0: for (i = 0; i < aCount; i++) { michael@0: rv = block->SetString(i, aTokenList[i]); michael@0: if (NS_FAILED(rv)) return rv; michael@0: } michael@0: michael@0: rv = block->SetInt(0, aCount); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(nullptr, michael@0: "chrome://pippki/content/choosetoken.xul", michael@0: block); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: int32_t status; michael@0: michael@0: rv = block->GetInt(0, &status); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: *aCanceled = (status == 0)?true:false; michael@0: if (!*aCanceled) { michael@0: // retrieve the nickname michael@0: rv = block->GetString(0, aTokenChosen); michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: /* boolean ConfirmKeyEscrow (in nsIX509Cert escrowAuthority); */ michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::ConfirmKeyEscrow(nsIX509Cert *escrowAuthority, bool *_retval) michael@0: michael@0: { michael@0: *_retval = false; michael@0: michael@0: nsresult rv; michael@0: michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_PKIPARAMBLOCK_CONTRACTID); michael@0: if (!block) michael@0: return NS_ERROR_FAILURE; michael@0: michael@0: rv = block->SetISupportAtIndex(1, escrowAuthority); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(nullptr, michael@0: "chrome://pippki/content/escrowWarn.xul", michael@0: block); michael@0: michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: int32_t status=0; michael@0: nsCOMPtr dlgParamBlock = do_QueryInterface(block); michael@0: rv = dlgParamBlock->GetInt(1, &status); michael@0: michael@0: if (status) { michael@0: *_retval = true; michael@0: } michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::DisplayProtectedAuth(nsIInterfaceRequestor *aCtx, nsIProtectedAuthThread *runnable) michael@0: { michael@0: // We cannot use nsNSSDialogHelper here. We cannot allow close widget michael@0: // in the window because protected authentication is interruptible michael@0: // from user interface and changing nsNSSDialogHelper's static variable michael@0: // would not be thread-safe michael@0: michael@0: nsresult rv = NS_ERROR_FAILURE; michael@0: michael@0: // Get the parent window for the dialog michael@0: nsCOMPtr parent = do_GetInterface(aCtx); michael@0: michael@0: nsCOMPtr windowWatcher = michael@0: do_GetService("@mozilla.org/embedcomp/window-watcher;1", &rv); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: if (!parent) { michael@0: windowWatcher->GetActiveWindow(getter_AddRefs(parent)); michael@0: } michael@0: michael@0: nsCOMPtr newWindow; michael@0: rv = windowWatcher->OpenWindow(parent, michael@0: "chrome://pippki/content/protectedAuth.xul", michael@0: "_blank", michael@0: "centerscreen,chrome,modal,titlebar,close=no", michael@0: runnable, michael@0: getter_AddRefs(newWindow)); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsNSSDialogs::ShowCertError(nsIInterfaceRequestor *ctx, michael@0: nsISSLStatus *status, michael@0: nsIX509Cert *cert, michael@0: const nsAString & textErrorMessage, michael@0: const nsAString & htmlErrorMessage, michael@0: const nsACString & hostName, michael@0: uint32_t portNumber) michael@0: { michael@0: nsCOMPtr block = michael@0: do_CreateInstance(NS_PKIPARAMBLOCK_CONTRACTID); michael@0: if (!block) michael@0: return NS_ERROR_OUT_OF_MEMORY; michael@0: michael@0: nsCOMPtr dialogBlock = do_QueryInterface(block); michael@0: michael@0: nsresult rv; michael@0: rv = dialogBlock->SetInt(1, portNumber); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: rv = dialogBlock->SetString(1, NS_ConvertUTF8toUTF16(hostName).get()); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: rv = dialogBlock->SetString(2, PromiseFlatString(textErrorMessage).get()); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: rv = block->SetISupportAtIndex(1, cert); michael@0: if (NS_FAILED(rv)) michael@0: return rv; michael@0: michael@0: rv = nsNSSDialogHelper::openDialog(nullptr, michael@0: "chrome://pippki/content/certerror.xul", michael@0: block); michael@0: return rv; michael@0: }