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: const Ci = Components.interfaces; michael@0: const Cu = Components.utils; michael@0: const Cc = Components.classes; michael@0: michael@0: Cu.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Cu.import("resource://gre/modules/Services.jsm"); michael@0: Cu.import("resource://gre/modules/Prompt.jsm"); michael@0: michael@0: // ----------------------------------------------------------------------- michael@0: // NSS Dialog Service michael@0: // ----------------------------------------------------------------------- michael@0: michael@0: function dump(a) { michael@0: Components.classes["@mozilla.org/consoleservice;1"].getService(Ci.nsIConsoleService).logStringMessage(a); michael@0: } michael@0: michael@0: function NSSDialogs() { } michael@0: michael@0: NSSDialogs.prototype = { michael@0: classID: Components.ID("{cbc08081-49b6-4561-9c18-a7707a50bda1}"), michael@0: QueryInterface: XPCOMUtils.generateQI([Ci.nsICertificateDialogs, Ci.nsIClientAuthDialogs]), michael@0: michael@0: getString: function(aName) { michael@0: if (!this.bundle) { michael@0: this.bundle = Services.strings.createBundle("chrome://browser/locale/pippki.properties"); michael@0: } michael@0: return this.bundle.GetStringFromName(aName); michael@0: }, michael@0: michael@0: formatString: function(aName, argList) { michael@0: if (!this.bundle) { michael@0: this.bundle = Services.strings.createBundle("chrome://browser/locale/pippki.properties"); michael@0: } michael@0: return this.bundle.formatStringFromName(aName, argList, 1); michael@0: }, michael@0: michael@0: getPrompt: function(aTitle, aText, aButtons) { michael@0: return new Prompt({ michael@0: title: aTitle, michael@0: text: aText, michael@0: buttons: aButtons, michael@0: }); michael@0: }, michael@0: michael@0: showPrompt: function(aPrompt) { michael@0: let response = null; michael@0: aPrompt.show(function(data) { michael@0: response = data; michael@0: }); michael@0: michael@0: // Spin this thread while we wait for a result michael@0: let thread = Services.tm.currentThread; michael@0: while (response === null) michael@0: thread.processNextEvent(true); michael@0: michael@0: return response; michael@0: }, michael@0: michael@0: confirmDownloadCACert: function(aCtx, aCert, aTrust) { michael@0: while (true) { michael@0: let prompt = this.getPrompt(this.getString("downloadCert.title"), michael@0: this.getString("downloadCert.message1"), michael@0: [ this.getString("nssdialogs.ok.label"), michael@0: this.getString("downloadCert.viewCert.label"), michael@0: this.getString("nssdialogs.cancel.label") michael@0: ]); michael@0: michael@0: prompt.addCheckbox({ id: "trustSSL", label: this.getString("downloadCert.trustSSL"), checked: false }) michael@0: .addCheckbox({ id: "trustEmail", label: this.getString("downloadCert.trustEmail"), checked: false }) michael@0: .addCheckbox({ id: "trustSign", label: this.getString("downloadCert.trustObjSign"), checked: false }); michael@0: let response = this.showPrompt(prompt); michael@0: michael@0: // they hit the "view cert" button, so show the cert and try again michael@0: if (response.button == 1) { michael@0: this.viewCert(aCtx, aCert); michael@0: continue; michael@0: } else if (response.button != 0) { michael@0: return false; michael@0: } michael@0: michael@0: aTrust.value = Ci.nsIX509CertDB.UNTRUSTED; michael@0: if (response.trustSSL == "true") aTrust.value |= Ci.nsIX509CertDB.TRUSTED_SSL; michael@0: if (response.trustEmail == "true") aTrust.value |= Ci.nsIX509CertDB.TRUSTED_EMAIL; michael@0: if (response.trustSign == "true") aTrust.value |= Ci.nsIX509CertDB.TRUSTED_OBJSIGN; michael@0: return true; michael@0: } michael@0: }, michael@0: michael@0: notifyCACertExists: function(aCtx) { michael@0: let p = this.getPrompt(this.getString("caCertExists.title"), this.getString("caCertExists.message")); michael@0: this.showPrompt(p); michael@0: }, michael@0: michael@0: setPKCS12FilePassword: function(aCtx, aPassword) { michael@0: // this dialog is never shown in Fennec; in Desktop it is shown while backing up a personal michael@0: // certificate to a file via Preferences->Advanced->Encryption->View Certificates->Your Certificates michael@0: throw "Unimplemented"; michael@0: }, michael@0: michael@0: getPKCS12FilePassword: function(aCtx, aPassword) { michael@0: let prompt = this.getPrompt(this.getString("pkcs12.getpassword.title"), michael@0: this.getString("pkcs12.getpassword.message"), michael@0: [ this.getString("nssdialogs.ok.label"), michael@0: this.getString("nssdialogs.cancel.label") michael@0: ]).addPassword({id: "pw"}); michael@0: let response = this.showPrompt(prompt); michael@0: if (response.button != 0) { michael@0: return false; michael@0: } michael@0: michael@0: aPassword.value = response.pw; michael@0: return true; michael@0: }, michael@0: michael@0: certInfoSection: function(aHeading, aDataPairs, aTrailingNewline = true) { michael@0: var str = "" + this.getString(aHeading) + "
"; michael@0: for (var i = 0; i < aDataPairs.length; i += 2) { michael@0: str += this.getString(aDataPairs[i]) + ": " + aDataPairs[i+1] + "
"; michael@0: } michael@0: return str + (aTrailingNewline ? "
" : ""); michael@0: }, michael@0: michael@0: viewCert: function(aCtx, aCert) { michael@0: let p = this.getPrompt(this.getString("certmgr.title"), michael@0: "", michael@0: [ this.getString("nssdialogs.ok.label") ]) michael@0: p.addLabel({ label: this.certInfoSection("certmgr.subjectinfo.label", michael@0: ["certmgr.certdetail.cn", aCert.commonName, michael@0: "certmgr.certdetail.o", aCert.organization, michael@0: "certmgr.certdetail.ou", aCert.organizationalUnit, michael@0: "certmgr.certdetail.serialnumber", aCert.serialNumber])}) michael@0: .addLabel({ label: this.certInfoSection("certmgr.issuerinfo.label", michael@0: ["certmgr.certdetail.cn", aCert.issuerCommonName, michael@0: "certmgr.certdetail.o", aCert.issuerOrganization, michael@0: "certmgr.certdetail.ou", aCert.issuerOrganizationUnit])}) michael@0: .addLabel({ label: this.certInfoSection("certmgr.periodofvalidity.label", michael@0: ["certmgr.begins", aCert.validity.notBeforeLocalDay, michael@0: "certmgr.expires", aCert.validity.notAfterLocalDay])}) michael@0: .addLabel({ label: this.certInfoSection("certmgr.fingerprints.label", michael@0: ["certmgr.certdetail.sha1fingerprint", aCert.sha1Fingerprint, michael@0: "certmgr.certdetail.md5fingerprint", aCert.md5Fingerprint], false) }); michael@0: this.showPrompt(p); michael@0: }, michael@0: michael@0: viewCertDetails: function(details) { michael@0: let p = this.getPrompt(this.getString("clientAuthAsk.message3"), michael@0: '', michael@0: [ this.getString("nssdialogs.ok.label") ]); michael@0: p.addLabel({ label: details }); michael@0: this.showPrompt(p); michael@0: }, michael@0: michael@0: ChooseCertificate: function(aCtx, cn, organization, issuer, certNickList, certDetailsList, count, selectedIndex, canceled) { michael@0: let rememberSetting = true; michael@0: var pref = Cc['@mozilla.org/preferences-service;1'] michael@0: .getService(Components.interfaces.nsIPrefService); michael@0: if (pref) { michael@0: pref = pref.getBranch(null); michael@0: try { michael@0: rememberSetting = pref.getBoolPref("security.remember_cert_checkbox_default_setting"); michael@0: } catch (e) { michael@0: // pref is missing michael@0: } michael@0: } michael@0: michael@0: let organizationString = this.formatString("clientAuthAsk.organization", michael@0: [organization]); michael@0: let issuerString = this.formatString("clientAuthAsk.issuer", michael@0: [issuer]); michael@0: let serverRequestedDetails = cn + '
' + organizationString + '
' + issuerString; michael@0: michael@0: selectedIndex = 0; michael@0: while (true) { michael@0: let prompt = this.getPrompt(this.getString("clientAuthAsk.title"), michael@0: this.getString("clientAuthAsk.message1"), michael@0: [ this.getString("nssdialogs.ok.label"), michael@0: this.getString("clientAuthAsk.viewCert.label"), michael@0: this.getString("nssdialogs.cancel.label") michael@0: ]) michael@0: .addLabel({ id: "requestedDetails", label: serverRequestedDetails } ) michael@0: .addMenulist({ michael@0: id: "nicknames", michael@0: label: this.getString("clientAuthAsk.message2"), michael@0: values: certNickList, selected: selectedIndex michael@0: }).addCheckbox({ michael@0: id: "rememberBox", michael@0: label: this.getString("clientAuthAsk.remember.label"), michael@0: checked: rememberSetting michael@0: }); michael@0: let response = this.showPrompt(prompt); michael@0: selectedIndex = response.nicknames; michael@0: if (response.button == 1) { michael@0: this.viewCertDetails(certDetailsList[selectedIndex]); michael@0: continue; michael@0: } else if (response.button == 0) { michael@0: canceled.value = false; michael@0: if (response.rememberBox == "true") { michael@0: aCtx.QueryInterface(Ci.nsIClientAuthUserDecision).rememberClientAuthCertificate = true; michael@0: } michael@0: return true; michael@0: } michael@0: canceled.value = true; michael@0: return false; michael@0: } michael@0: } michael@0: }; michael@0: michael@0: this.NSGetFactory = XPCOMUtils.generateNSGetFactory([NSSDialogs]);