summaryrefslogtreecommitdiffstats
path: root/security/manager/pki/resources/content/certManager.js
diff options
context:
space:
mode:
Diffstat (limited to 'security/manager/pki/resources/content/certManager.js')
-rw-r--r--security/manager/pki/resources/content/certManager.js769
1 files changed, 769 insertions, 0 deletions
diff --git a/security/manager/pki/resources/content/certManager.js b/security/manager/pki/resources/content/certManager.js
new file mode 100644
index 0000000000..00bb29f307
--- /dev/null
+++ b/security/manager/pki/resources/content/certManager.js
@@ -0,0 +1,769 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+/* import-globals-from pippki.js */
+"use strict";
+
+const gCertFileTypes = "*.p7b; *.crt; *.cert; *.cer; *.pem; *.der";
+
+var { NetUtil } = ChromeUtils.import("resource://gre/modules/NetUtil.jsm");
+
+var key;
+
+var certdialogs = Cc["@mozilla.org/nsCertificateDialogs;1"].getService(
+ Ci.nsICertificateDialogs
+);
+
+/**
+ * List of certs currently selected in the active tab.
+ *
+ * @type {nsIX509Cert[]}
+ */
+var selected_certs = [];
+var selected_tree_items = [];
+var selected_index = [];
+var certdb;
+
+/**
+ * Cert tree for the "Authorities" tab.
+ *
+ * @type {nsICertTree}
+ */
+var caTreeView;
+/**
+ * Cert tree for the "Servers" tab.
+ *
+ * @type {nsICertTree}
+ */
+var serverTreeView;
+
+var overrideService;
+
+function createRichlistItem(item) {
+ let innerHbox = document.createXULElement("hbox");
+ innerHbox.setAttribute("align", "center");
+ innerHbox.setAttribute("flex", "1");
+
+ let row = document.createXULElement("label");
+ row.setAttribute("flex", "1");
+ row.setAttribute("crop", "end");
+ row.setAttribute("style", "margin-inline-start: 15px;");
+ if ("raw" in item) {
+ row.setAttribute("value", item.raw);
+ } else {
+ document.l10n.setAttributes(row, item.l10nid);
+ }
+ row.setAttribute("ordinal", "1");
+ innerHbox.appendChild(row);
+
+ return innerHbox;
+}
+
+var serverRichList = {
+ richlist: undefined,
+
+ buildRichList() {
+ let overrides = overrideService.getOverrides().map(item => {
+ return {
+ hostPort: item.hostPort,
+ asciiHost: item.asciiHost,
+ port: item.port,
+ originAttributes: item.originAttributes,
+ fingerprint: item.fingerprint,
+ };
+ });
+ overrides.sort((a, b) => {
+ let criteria = ["hostPort", "fingerprint"];
+ for (let c of criteria) {
+ let res = a[c].localeCompare(b[c]);
+ if (res !== 0) {
+ return res;
+ }
+ }
+ return 0;
+ });
+
+ this.richlist.textContent = "";
+ this.richlist.clearSelection();
+
+ let frag = document.createDocumentFragment();
+ for (let override of overrides) {
+ let richlistitem = this._richBoxAddItem(override);
+ frag.appendChild(richlistitem);
+ }
+ this.richlist.appendChild(frag);
+
+ this._setButtonState();
+ this.richlist.addEventListener("select", () => this._setButtonState());
+ },
+
+ _richBoxAddItem(item) {
+ let richlistitem = document.createXULElement("richlistitem");
+
+ richlistitem.setAttribute("host", item.asciiHost);
+ richlistitem.setAttribute("port", item.port);
+ richlistitem.setAttribute("hostPort", item.hostPort);
+ richlistitem.setAttribute("fingerprint", item.fingerprint);
+ richlistitem.setAttribute(
+ "originAttributes",
+ JSON.stringify(item.originAttributes)
+ );
+
+ let hbox = document.createXULElement("hbox");
+ hbox.setAttribute("flex", "1");
+ hbox.setAttribute("equalsize", "always");
+
+ hbox.appendChild(createRichlistItem({ raw: item.hostPort }));
+ hbox.appendChild(createRichlistItem({ raw: item.fingerprint }));
+
+ richlistitem.appendChild(hbox);
+
+ return richlistitem;
+ },
+
+ deleteSelectedRichListItem() {
+ let selectedItem = this.richlist.selectedItem;
+ if (!selectedItem) {
+ return;
+ }
+
+ let retVals = {
+ deleteConfirmed: false,
+ };
+ window.browsingContext.topChromeWindow.openDialog(
+ "chrome://pippki/content/deletecert.xhtml",
+ "",
+ "chrome,centerscreen,modal",
+ "websites_tab",
+ [
+ {
+ hostPort: selectedItem.attributes.hostPort.value,
+ },
+ ],
+ retVals
+ );
+
+ if (retVals.deleteConfirmed) {
+ overrideService.clearValidityOverride(
+ selectedItem.attributes.host.value,
+ selectedItem.attributes.port.value,
+ JSON.parse(selectedItem.attributes.originAttributes.value)
+ );
+ this.buildRichList();
+ }
+ },
+
+ addException() {
+ let retval = {
+ exceptionAdded: false,
+ };
+ window.browsingContext.topChromeWindow.openDialog(
+ "chrome://pippki/content/exceptionDialog.xhtml",
+ "",
+ "chrome,centerscreen,modal",
+ retval
+ );
+ if (retval.exceptionAdded) {
+ this.buildRichList();
+ }
+ },
+
+ _setButtonState() {
+ let websiteDeleteButton = document.getElementById("websites_deleteButton");
+ websiteDeleteButton.disabled = this.richlist.selectedIndex < 0;
+ },
+};
+/**
+ * Cert tree for the "People" tab.
+ *
+ * @type {nsICertTree}
+ */
+var emailTreeView;
+/**
+ * Cert tree for the "Your Certificates" tab.
+ *
+ * @type {nsICertTree}
+ */
+var userTreeView;
+
+var clientAuthRememberService;
+
+var rememberedDecisionsRichList = {
+ richlist: undefined,
+
+ buildRichList() {
+ let rememberedDecisions = clientAuthRememberService.getDecisions();
+
+ let oldItems = this.richlist.querySelectorAll("richlistitem");
+ for (let item of oldItems) {
+ item.remove();
+ }
+
+ let frag = document.createDocumentFragment();
+ for (let decision of rememberedDecisions) {
+ let richlistitem = this._richBoxAddItem(decision);
+ frag.appendChild(richlistitem);
+ }
+ this.richlist.appendChild(frag);
+
+ this.richlist.addEventListener("select", () => this.setButtonState());
+ },
+
+ _richBoxAddItem(item) {
+ let richlistitem = document.createXULElement("richlistitem");
+
+ richlistitem.setAttribute("entryKey", item.entryKey);
+ richlistitem.setAttribute("dbKey", item.dbKey);
+
+ let hbox = document.createXULElement("hbox");
+ hbox.setAttribute("flex", "1");
+ hbox.setAttribute("equalsize", "always");
+
+ hbox.appendChild(createRichlistItem({ raw: item.asciiHost }));
+ if (item.dbKey == "") {
+ hbox.appendChild(
+ createRichlistItem({ l10nid: "send-no-client-certificate" })
+ );
+
+ hbox.appendChild(createRichlistItem({ raw: "" }));
+ } else {
+ let tmpCert = certdb.findCertByDBKey(item.dbKey);
+ // The certificate corresponding to this item's dbKey may not be
+ // available (for example, if it was stored on a token that's been
+ // removed, or if it was deleted).
+ if (tmpCert) {
+ hbox.appendChild(createRichlistItem({ raw: tmpCert.commonName }));
+ hbox.appendChild(createRichlistItem({ raw: tmpCert.serialNumber }));
+ } else {
+ hbox.appendChild(
+ createRichlistItem({ l10nid: "certificate-not-available" })
+ );
+ hbox.appendChild(
+ createRichlistItem({ l10nid: "certificate-not-available" })
+ );
+ }
+ }
+
+ richlistitem.appendChild(hbox);
+
+ return richlistitem;
+ },
+
+ deleteSelectedRichListItem() {
+ let selectedItem = this.richlist.selectedItem;
+ let index = this.richlist.selectedIndex;
+ if (index < 0) {
+ return;
+ }
+
+ clientAuthRememberService.forgetRememberedDecision(
+ selectedItem.attributes.entryKey.value
+ );
+
+ this.buildRichList();
+ this.setButtonState();
+ },
+
+ viewSelectedRichListItem() {
+ let selectedItem = this.richlist.selectedItem;
+ let index = this.richlist.selectedIndex;
+ if (index < 0) {
+ return;
+ }
+
+ if (selectedItem.attributes.dbKey.value != "") {
+ let cert = certdb.findCertByDBKey(selectedItem.attributes.dbKey.value);
+ viewCertHelper(window, cert);
+ }
+ },
+
+ setButtonState() {
+ let rememberedDeleteButton = document.getElementById(
+ "remembered_deleteButton"
+ );
+ let rememberedViewButton = document.getElementById("remembered_viewButton");
+
+ rememberedDeleteButton.disabled = this.richlist.selectedIndex < 0;
+ rememberedViewButton.disabled =
+ this.richlist.selectedItem == null
+ ? true
+ : this.richlist.selectedItem.attributes.dbKey.value == "";
+ },
+};
+
+function LoadCerts() {
+ certdb = Cc["@mozilla.org/security/x509certdb;1"].getService(
+ Ci.nsIX509CertDB
+ );
+ var certcache = certdb.getCerts();
+
+ caTreeView = Cc["@mozilla.org/security/nsCertTree;1"].createInstance(
+ Ci.nsICertTree
+ );
+ caTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.CA_CERT);
+ document.getElementById("ca-tree").view = caTreeView;
+
+ emailTreeView = Cc["@mozilla.org/security/nsCertTree;1"].createInstance(
+ Ci.nsICertTree
+ );
+ emailTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.EMAIL_CERT);
+ document.getElementById("email-tree").view = emailTreeView;
+
+ userTreeView = Cc["@mozilla.org/security/nsCertTree;1"].createInstance(
+ Ci.nsICertTree
+ );
+ userTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.USER_CERT);
+ document.getElementById("user-tree").view = userTreeView;
+
+ clientAuthRememberService = Cc[
+ "@mozilla.org/security/clientAuthRememberService;1"
+ ].getService(Ci.nsIClientAuthRememberService);
+
+ overrideService = Cc["@mozilla.org/security/certoverride;1"].getService(
+ Ci.nsICertOverrideService
+ );
+
+ rememberedDecisionsRichList.richlist =
+ document.getElementById("rememberedList");
+ serverRichList.richlist = document.getElementById("serverList");
+
+ rememberedDecisionsRichList.buildRichList();
+ serverRichList.buildRichList();
+
+ rememberedDecisionsRichList.setButtonState();
+
+ enableBackupAllButton();
+}
+
+function enableBackupAllButton() {
+ let backupAllButton = document.getElementById("mine_backupAllButton");
+ backupAllButton.disabled = userTreeView.rowCount < 1;
+}
+
+function getSelectedCerts() {
+ var ca_tab = document.getElementById("ca_tab");
+ var mine_tab = document.getElementById("mine_tab");
+ var others_tab = document.getElementById("others_tab");
+ var items = null;
+ if (ca_tab.selected) {
+ items = caTreeView.selection;
+ } else if (mine_tab.selected) {
+ items = userTreeView.selection;
+ } else if (others_tab.selected) {
+ items = emailTreeView.selection;
+ }
+ selected_certs = [];
+ var cert = null;
+ var nr = 0;
+ if (items != null) {
+ nr = items.getRangeCount();
+ }
+ if (nr > 0) {
+ for (let i = 0; i < nr; i++) {
+ var o1 = {};
+ var o2 = {};
+ items.getRangeAt(i, o1, o2);
+ var min = o1.value;
+ var max = o2.value;
+ for (let j = min; j <= max; j++) {
+ if (ca_tab.selected) {
+ cert = caTreeView.getCert(j);
+ } else if (mine_tab.selected) {
+ cert = userTreeView.getCert(j);
+ } else if (others_tab.selected) {
+ cert = emailTreeView.getCert(j);
+ }
+ if (cert) {
+ var sc = selected_certs.length;
+ selected_certs[sc] = cert;
+ selected_index[sc] = j;
+ }
+ }
+ }
+ }
+}
+
+function getSelectedTreeItems() {
+ var ca_tab = document.getElementById("ca_tab");
+ var mine_tab = document.getElementById("mine_tab");
+ var others_tab = document.getElementById("others_tab");
+ var items = null;
+ if (ca_tab.selected) {
+ items = caTreeView.selection;
+ } else if (mine_tab.selected) {
+ items = userTreeView.selection;
+ } else if (others_tab.selected) {
+ items = emailTreeView.selection;
+ }
+ selected_certs = [];
+ selected_tree_items = [];
+ selected_index = [];
+ var tree_item = null;
+ var nr = 0;
+ if (items != null) {
+ nr = items.getRangeCount();
+ }
+ if (nr > 0) {
+ for (let i = 0; i < nr; i++) {
+ var o1 = {};
+ var o2 = {};
+ items.getRangeAt(i, o1, o2);
+ var min = o1.value;
+ var max = o2.value;
+ for (let j = min; j <= max; j++) {
+ if (ca_tab.selected) {
+ tree_item = caTreeView.getTreeItem(j);
+ } else if (mine_tab.selected) {
+ tree_item = userTreeView.getTreeItem(j);
+ } else if (others_tab.selected) {
+ tree_item = emailTreeView.getTreeItem(j);
+ }
+ if (tree_item) {
+ var sc = selected_tree_items.length;
+ selected_tree_items[sc] = tree_item;
+ selected_index[sc] = j;
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Returns true if nothing in the given cert tree is selected or if the
+ * selection includes a container. Returns false otherwise.
+ *
+ * @param {nsICertTree} certTree
+ * @returns {boolean}
+ */
+function nothingOrContainerSelected(certTree) {
+ var certTreeSelection = certTree.selection;
+ var numSelectionRanges = certTreeSelection.getRangeCount();
+
+ if (numSelectionRanges == 0) {
+ return true;
+ }
+
+ for (var i = 0; i < numSelectionRanges; i++) {
+ var o1 = {};
+ var o2 = {};
+ certTreeSelection.getRangeAt(i, o1, o2);
+ var minIndex = o1.value;
+ var maxIndex = o2.value;
+ for (var j = minIndex; j <= maxIndex; j++) {
+ if (certTree.isContainer(j)) {
+ return true;
+ }
+ }
+ }
+
+ return false;
+}
+
+async function promptError(aErrorCode) {
+ if (aErrorCode != Ci.nsIX509CertDB.Success) {
+ let msgName = "pkcs12-unknown-err";
+ switch (aErrorCode) {
+ case Ci.nsIX509CertDB.ERROR_PKCS12_NOSMARTCARD_EXPORT:
+ msgName = "pkcs12-info-no-smartcard-backup";
+ break;
+ case Ci.nsIX509CertDB.ERROR_PKCS12_RESTORE_FAILED:
+ msgName = "pkcs12-unknown-err-restore";
+ break;
+ case Ci.nsIX509CertDB.ERROR_PKCS12_BACKUP_FAILED:
+ msgName = "pkcs12-unknown-err-backup";
+ break;
+ case Ci.nsIX509CertDB.ERROR_PKCS12_CERT_COLLISION:
+ case Ci.nsIX509CertDB.ERROR_PKCS12_DUPLICATE_DATA:
+ msgName = "pkcs12-dup-data";
+ break;
+ case Ci.nsIX509CertDB.ERROR_BAD_PASSWORD:
+ msgName = "pk11-bad-password";
+ break;
+ case Ci.nsIX509CertDB.ERROR_DECODE_ERROR:
+ msgName = "pkcs12-decode-err";
+ break;
+ default:
+ break;
+ }
+ let [message] = await document.l10n.formatValues([{ id: msgName }]);
+ let prompter = Services.ww.getNewPrompter(window);
+ prompter.alert(null, message);
+ }
+}
+
+/**
+ * Enables or disables buttons corresponding to a cert tree depending on what
+ * is selected in the cert tree.
+ *
+ * @param {nsICertTree} certTree
+ * @param {Array} idList A list of string identifiers for button elements to
+ * enable or disable.
+ */
+function enableButtonsForCertTree(certTree, idList) {
+ let disableButtons = nothingOrContainerSelected(certTree);
+
+ for (let id of idList) {
+ document.getElementById(id).setAttribute("disabled", disableButtons);
+ }
+}
+
+function ca_enableButtons() {
+ let idList = [
+ "ca_viewButton",
+ "ca_editButton",
+ "ca_exportButton",
+ "ca_deleteButton",
+ ];
+ enableButtonsForCertTree(caTreeView, idList);
+}
+
+function mine_enableButtons() {
+ let idList = ["mine_viewButton", "mine_backupButton", "mine_deleteButton"];
+ enableButtonsForCertTree(userTreeView, idList);
+}
+
+function email_enableButtons() {
+ let idList = ["email_viewButton", "email_exportButton", "email_deleteButton"];
+ enableButtonsForCertTree(emailTreeView, idList);
+}
+
+async function backupCerts() {
+ getSelectedCerts();
+ var numcerts = selected_certs.length;
+ if (numcerts == 0) {
+ return;
+ }
+
+ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ let [backupFileDialog, filePkcs12Spec] = await document.l10n.formatValues([
+ { id: "choose-p12-backup-file-dialog" },
+ { id: "file-browse-pkcs12-spec" },
+ ]);
+ fp.init(window, backupFileDialog, Ci.nsIFilePicker.modeSave);
+ fp.appendFilter(filePkcs12Spec, "*.p12");
+ fp.appendFilters(Ci.nsIFilePicker.filterAll);
+ fp.defaultExtension = "p12";
+ fp.open(rv => {
+ if (
+ rv == Ci.nsIFilePicker.returnOK ||
+ rv == Ci.nsIFilePicker.returnReplace
+ ) {
+ let password = {};
+ if (certdialogs.setPKCS12FilePassword(window, password)) {
+ let errorCode = certdb.exportPKCS12File(
+ fp.file,
+ selected_certs,
+ password.value
+ );
+ promptError(errorCode);
+ }
+ }
+ });
+}
+
+function backupAllCerts() {
+ // Select all rows, then call doBackup()
+ userTreeView.selection.selectAll();
+ backupCerts();
+}
+
+function editCerts() {
+ getSelectedCerts();
+
+ for (let cert of selected_certs) {
+ window.browsingContext.topChromeWindow.openDialog(
+ "chrome://pippki/content/editcacert.xhtml",
+ "",
+ "chrome,centerscreen,modal",
+ cert
+ );
+ }
+}
+
+async function restoreCerts() {
+ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ let [restoreFileDialog, filePkcs12Spec, fileCertSpec] =
+ await document.l10n.formatValues([
+ { id: "choose-p12-restore-file-dialog" },
+ { id: "file-browse-pkcs12-spec" },
+ { id: "file-browse-certificate-spec" },
+ ]);
+ fp.init(window, restoreFileDialog, Ci.nsIFilePicker.modeOpen);
+ fp.appendFilter(filePkcs12Spec, "*.p12; *.pfx");
+ fp.appendFilter(fileCertSpec, gCertFileTypes);
+ fp.appendFilters(Ci.nsIFilePicker.filterAll);
+ fp.open(rv => {
+ if (rv != Ci.nsIFilePicker.returnOK) {
+ return;
+ }
+
+ // If this is an X509 user certificate, import it as one.
+
+ var isX509FileType = false;
+ var fileTypesList = gCertFileTypes.slice(1).split("; *");
+ for (var type of fileTypesList) {
+ if (fp.file.path.endsWith(type)) {
+ isX509FileType = true;
+ break;
+ }
+ }
+
+ if (isX509FileType) {
+ let fstream = Cc[
+ "@mozilla.org/network/file-input-stream;1"
+ ].createInstance(Ci.nsIFileInputStream);
+ fstream.init(fp.file, -1, 0, 0);
+ let dataString = NetUtil.readInputStreamToString(
+ fstream,
+ fstream.available()
+ );
+ let dataArray = [];
+ for (let i = 0; i < dataString.length; i++) {
+ dataArray.push(dataString.charCodeAt(i));
+ }
+ fstream.close();
+ let prompter = Services.ww.getNewPrompter(window);
+ let interfaceRequestor = {
+ getInterface() {
+ return prompter;
+ },
+ };
+ certdb.importUserCertificate(
+ dataArray,
+ dataArray.length,
+ interfaceRequestor
+ );
+ } else {
+ // Otherwise, assume it's a PKCS12 file and import it that way.
+ let password = {};
+ let errorCode = Ci.nsIX509CertDB.ERROR_BAD_PASSWORD;
+ while (
+ errorCode == Ci.nsIX509CertDB.ERROR_BAD_PASSWORD &&
+ certdialogs.getPKCS12FilePassword(window, password)
+ ) {
+ errorCode = certdb.importPKCS12File(fp.file, password.value);
+ if (
+ errorCode == Ci.nsIX509CertDB.ERROR_BAD_PASSWORD &&
+ !password.value.length
+ ) {
+ // It didn't like empty string password, try no password.
+ errorCode = certdb.importPKCS12File(fp.file, null);
+ }
+ promptError(errorCode);
+ }
+ }
+
+ var certcache = certdb.getCerts();
+ userTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.USER_CERT);
+ userTreeView.selection.clearSelection();
+ caTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.CA_CERT);
+ caTreeView.selection.clearSelection();
+ enableBackupAllButton();
+ });
+}
+
+async function exportCerts() {
+ getSelectedCerts();
+
+ for (let cert of selected_certs) {
+ await exportToFile(window, cert);
+ }
+}
+
+/**
+ * Deletes the selected certs in the active tab.
+ */
+function deleteCerts() {
+ getSelectedTreeItems();
+ let numcerts = selected_tree_items.length;
+ if (numcerts == 0) {
+ return;
+ }
+
+ const treeViewMap = {
+ mine_tab: userTreeView,
+ ca_tab: caTreeView,
+ others_tab: emailTreeView,
+ };
+ let selTab = document.getElementById("certMgrTabbox").selectedItem;
+ let selTabID = selTab.getAttribute("id");
+
+ if (!(selTabID in treeViewMap)) {
+ return;
+ }
+
+ let retVals = {
+ deleteConfirmed: false,
+ };
+ window.browsingContext.topChromeWindow.openDialog(
+ "chrome://pippki/content/deletecert.xhtml",
+ "",
+ "chrome,centerscreen,modal",
+ selTabID,
+ selected_tree_items,
+ retVals
+ );
+
+ if (retVals.deleteConfirmed) {
+ let treeView = treeViewMap[selTabID];
+
+ for (let t = numcerts - 1; t >= 0; t--) {
+ treeView.deleteEntryObject(selected_index[t]);
+ }
+
+ selected_tree_items = [];
+ selected_index = [];
+ treeView.selection.clearSelection();
+ if (selTabID == "mine_tab") {
+ enableBackupAllButton();
+ }
+ }
+}
+
+function viewCerts() {
+ getSelectedCerts();
+
+ for (let cert of selected_certs) {
+ viewCertHelper(window, cert);
+ }
+}
+
+async function addCACerts() {
+ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ let [importCa, fileCertSpec] = await document.l10n.formatValues([
+ { id: "import-ca-certs-prompt" },
+ { id: "file-browse-certificate-spec" },
+ ]);
+ fp.init(window, importCa, Ci.nsIFilePicker.modeOpen);
+ fp.appendFilter(fileCertSpec, gCertFileTypes);
+ fp.appendFilters(Ci.nsIFilePicker.filterAll);
+ fp.open(rv => {
+ if (rv == Ci.nsIFilePicker.returnOK) {
+ certdb.importCertsFromFile(fp.file, Ci.nsIX509Cert.CA_CERT);
+ let certcache = certdb.getCerts();
+ caTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.CA_CERT);
+ caTreeView.selection.clearSelection();
+ }
+ });
+}
+
+async function addEmailCert() {
+ var fp = Cc["@mozilla.org/filepicker;1"].createInstance(Ci.nsIFilePicker);
+ let [importEmail, fileCertSpec] = await document.l10n.formatValues([
+ { id: "import-email-cert-prompt" },
+ { id: "file-browse-certificate-spec" },
+ ]);
+ fp.init(window, importEmail, Ci.nsIFilePicker.modeOpen);
+ fp.appendFilter(fileCertSpec, gCertFileTypes);
+ fp.appendFilters(Ci.nsIFilePicker.filterAll);
+ fp.open(rv => {
+ if (rv == Ci.nsIFilePicker.returnOK) {
+ certdb.importCertsFromFile(fp.file, Ci.nsIX509Cert.EMAIL_CERT);
+ var certcache = certdb.getCerts();
+ emailTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.EMAIL_CERT);
+ emailTreeView.selection.clearSelection();
+ caTreeView.loadCertsFromCache(certcache, Ci.nsIX509Cert.CA_CERT);
+ caTreeView.selection.clearSelection();
+ }
+ });
+}