in mail/extensions/am-e2e/am-e2e.js [940:1394]
async function reloadOpenPgpUI() {
const result = {};
await EnigmailKeyRing.getAllSecretKeysByEmail(gIdentity.email, result, true);
let keyCount = result.all.length;
let externalKey = null;
if (Services.prefs.getBoolPref("mail.openpgp.allow_external_gnupg")) {
externalKey = gIdentity.getUnicharAttribute(
"last_entered_external_gnupg_key_id"
);
if (externalKey) {
keyCount++;
}
}
// Show the radiogroup container only if the current identity has keys.
// But still show it if a key (missing or unusable) is configured.
document.getElementById("openPgpKeyList").hidden = keyCount == 0 && !gKeyId;
// Update the OpenPGP intro description with the current key count.
if (keyCount) {
document.l10n.setAttributes(
document.getElementById("openPgpDescription"),
"openpgp-description-has-keys",
{
count: keyCount,
identity: gIdentity.email,
}
);
} else {
document.l10n.setAttributes(
document.getElementById("openPgpDescription"),
"openpgp-description-no-key",
{
identity: gIdentity.email,
}
);
}
const radiogroup = document.getElementById("openPgpKeyListRadio");
if (!gKeyId) {
radiogroup.selectedIndex = 0; // None
}
// Remove all the previously generated radio options, except the first.
while (radiogroup.lastChild.id != "openPgpOptionNone") {
radiogroup.removeChild(radiogroup.lastChild);
}
// Currently configured key is not in available, maybe deleted by the user?
if (gKeyId && !externalKey && !result.all.find(key => key.keyId == gKeyId)) {
const container = document.createXULElement("vbox");
container.id = `openPgpOption${gKeyId}`;
container.classList.add("content-blocking-category");
const box = document.createXULElement("hbox");
const radio = document.createXULElement("radio");
radio.setAttribute("flex", "1");
radio.disabled = true;
radio.id = `openPgp${gKeyId}`;
radio.value = gKeyId;
radio.label = `0x${gKeyId}`;
box.appendChild(radio);
const box2 = document.createXULElement("vbox");
box2.classList.add("indent");
const desc = document.createXULElement("description");
box2.appendChild(desc);
const key = EnigmailKeyRing.getKeyById(gKeyId);
if (key && !key.secretAvailable) {
document.l10n.setAttributes(desc, "openpgp-radio-key-not-usable");
} else if (key && !(await PgpSqliteDb2.isAcceptedAsPersonalKey(key.fpr))) {
document.l10n.setAttributes(desc, "openpgp-radio-key-not-accepted");
const btnContainer = document.createXULElement("hbox");
btnContainer.setAttribute("pack", "end");
btnContainer.style.width = "100%";
const info = document.createXULElement("button");
info.classList.add("openpgp-image-btn", "openpgp-props-btn");
document.l10n.setAttributes(info, "openpgp-key-man-key-props");
info.addEventListener("command", event => {
event.stopPropagation();
enigmailKeyDetails(key.keyId);
});
btnContainer.appendChild(info);
box2.appendChild(btnContainer);
} else {
document.l10n.setAttributes(desc, "openpgp-radio-key-not-found");
}
container.appendChild(box);
container.appendChild(box2);
radiogroup.appendChild(container);
}
// Sort keys by create date from newest to oldest.
result.all.sort((a, b) => {
return b.keyCreated - a.keyCreated;
});
// If the user has an external key saved, and the allow_external_gnupg
// pref is true, we show it on top of the list.
if (externalKey) {
const container = document.createXULElement("vbox");
container.id = `openPgpOption${externalKey}`;
container.classList.add("content-blocking-category");
const box = document.createXULElement("hbox");
const radio = document.createXULElement("radio");
radio.setAttribute("flex", "1");
radio.id = `openPgp${externalKey}`;
radio.value = externalKey;
radio.label = `0x${externalKey}`;
const remove = document.createXULElement("button");
document.l10n.setAttributes(remove, "openpgp-key-remove-external");
remove.addEventListener("command", removeExternalKey);
remove.classList.add("button-small");
box.appendChild(radio);
box.appendChild(remove);
const indent = document.createXULElement("vbox");
indent.classList.add("indent");
const dateContainer = document.createXULElement("hbox");
dateContainer.classList.add("expiration-date-container");
dateContainer.setAttribute("align", "center");
const external = document.createXULElement("description");
external.classList.add("external-pill");
document.l10n.setAttributes(external, "key-external-label");
dateContainer.appendChild(external);
indent.appendChild(dateContainer);
container.appendChild(box);
container.appendChild(indent);
radiogroup.appendChild(container);
}
// List all the available keys.
for (const key of result.all) {
const container = document.createXULElement("vbox");
container.id = `openPgpOption${key.keyId}`;
container.classList.add("content-blocking-category");
const box = document.createXULElement("hbox");
const radio = document.createXULElement("radio");
radio.setAttribute("flex", "1");
radio.id = `openPgp${key.keyId}`;
radio.value = key.keyId;
radio.label = `0x${key.keyId}`;
const toggle = document.createXULElement("button");
toggle.classList.add("arrowhead");
toggle.setAttribute("aria-expanded", "false");
document.l10n.setAttributes(toggle, "openpgp-key-expand-section");
toggle.addEventListener("command", toggleExpansion);
box.appendChild(radio);
box.appendChild(toggle);
const indent = document.createXULElement("vbox");
indent.classList.add("indent");
const dateContainer = document.createXULElement("hbox");
dateContainer.classList.add("expiration-date-container");
dateContainer.setAttribute("align", "center");
const dateIcon = document.createElement("img");
dateIcon.classList.add("expiration-date-icon");
const dateButton = document.createXULElement("button");
document.l10n.setAttributes(dateButton, "openpgp-key-man-change-expiry");
dateButton.addEventListener("command", event => {
event.stopPropagation();
enigmailEditKeyDate(key);
});
dateButton.setAttribute("hidden", "true");
dateButton.classList.add("button-small");
const description = document.createXULElement("description");
if (key.expiryTime) {
if (Math.round(Date.now() / 1000) > key.expiryTime) {
// Has expired.
dateContainer.classList.add("key-expired");
dateIcon.setAttribute(
"src",
"chrome://messenger/skin/icons/new/compact/warning.svg"
);
// Sets the title attribute.
// The alt attribute is not set because the accessible name is already
// set by the title.
document.l10n.setAttributes(dateIcon, "openpgp-key-has-expired-icon");
document.l10n.setAttributes(description, "openpgp-radio-key-expired", {
date: key.expiry,
});
dateButton.removeAttribute("hidden");
// This key is expired, so make it unselectable.
radio.setAttribute("disabled", "true");
} else {
// If the key expires in less than 6 months.
const sixMonths = new Date();
sixMonths.setMonth(sixMonths.getMonth() + 6);
if (Math.round(Date.parse(sixMonths) / 1000) > key.expiryTime) {
dateContainer.classList.add("key-is-expiring");
dateIcon.setAttribute(
"src",
"chrome://messenger/skin/icons/new/compact/info.svg"
);
// Sets the title attribute.
// The alt attribute is not set because the accessible name is already
// set by the title.
document.l10n.setAttributes(
dateIcon,
"openpgp-key-expires-within-6-months-icon"
);
dateButton.removeAttribute("hidden");
}
document.l10n.setAttributes(description, "openpgp-radio-key-expires", {
date: key.expiry,
});
}
} else {
document.l10n.setAttributes(description, "key-does-not-expire");
}
dateContainer.appendChild(dateIcon);
dateContainer.appendChild(description);
dateContainer.appendChild(dateButton);
let publishContainer = null;
// If this key is the currently selected key, suggest publishing.
if (key.keyId == gKeyId) {
publishContainer = document.createXULElement("hbox");
publishContainer.setAttribute("align", "center");
const publishButton = document.createElement("button");
document.l10n.setAttributes(publishButton, "openpgp-key-publish");
publishButton.addEventListener("click", () => {
amE2eUploadKey(key);
});
publishButton.classList.add("button-small");
const desc = document.createXULElement("description");
document.l10n.setAttributes(desc, "openpgp-suggest-publishing-key");
publishContainer.appendChild(desc);
publishContainer.appendChild(publishButton);
}
const hiddenContainer = document.createXULElement("vbox");
hiddenContainer.classList.add(
"content-blocking-extra-information",
"indent"
);
// Start key info section.
const grid = document.createXULElement("hbox");
grid.classList.add("extra-information-label");
// Key fingerprint.
const fingerprintImage = document.createElement("img");
fingerprintImage.setAttribute(
"src",
"chrome://messenger/skin/icons/new/compact/fingerprint.svg"
);
fingerprintImage.setAttribute("alt", "");
const fingerprintLabel = document.createXULElement("label");
document.l10n.setAttributes(
fingerprintLabel,
"openpgp-key-details-fingerprint-label"
);
fingerprintLabel.classList.add("extra-information-label-type");
const fgrInputContainer = document.createXULElement("hbox");
fgrInputContainer.classList.add("input-container");
fgrInputContainer.setAttribute("flex", "1");
const fingerprintInput = document.createElement("input");
fingerprintInput.setAttribute("type", "text");
fingerprintInput.classList.add("plain");
fingerprintInput.setAttribute("readonly", "readonly");
fingerprintInput.value = EnigmailKey.formatFpr(key.fpr);
fgrInputContainer.appendChild(fingerprintInput);
grid.appendChild(fingerprintImage);
grid.appendChild(fingerprintLabel);
grid.appendChild(fgrInputContainer);
// Key creation date.
const createdImage = document.createElement("img");
createdImage.setAttribute(
"src",
"chrome://messenger/skin/icons/new/compact/calendar.svg"
);
createdImage.setAttribute("alt", "");
const createdLabel = document.createXULElement("label");
document.l10n.setAttributes(
createdLabel,
"openpgp-key-details-created-header"
);
createdLabel.classList.add("extra-information-label-type");
const createdValueContainer = document.createXULElement("hbox");
createdValueContainer.classList.add("input-container");
createdValueContainer.setAttribute("flex", "1");
const createdValue = document.createElement("input");
createdValue.setAttribute("type", "text");
createdValue.classList.add("plain");
createdValue.setAttribute("readonly", "readonly");
createdValue.value = key.created;
createdValueContainer.appendChild(createdValue);
grid.appendChild(createdImage);
grid.appendChild(createdLabel);
grid.appendChild(createdValueContainer);
// End key info section.
hiddenContainer.appendChild(grid);
// Action buttons.
const btnContainer = document.createXULElement("hbox");
btnContainer.setAttribute("pack", "end");
const info = document.createXULElement("button");
info.classList.add("openpgp-image-btn", "openpgp-props-btn");
document.l10n.setAttributes(info, "openpgp-key-man-key-props");
info.addEventListener("command", event => {
event.stopPropagation();
enigmailKeyDetails(key.keyId);
});
const more = document.createXULElement("button");
more.setAttribute("type", "menu");
more.classList.add("openpgp-more-btn", "last-element");
document.l10n.setAttributes(more, "openpgp-key-man-key-more");
const menupopup = document.createXULElement("menupopup");
menupopup.classList.add("more-button-menupopup");
const copyItem = document.createXULElement("menuitem");
document.l10n.setAttributes(copyItem, "openpgp-key-copy-key");
copyItem.addEventListener("command", event => {
event.stopPropagation();
openPgpCopyToClipboard(`0x${key.keyId}`);
});
const sendItem = document.createXULElement("menuitem");
document.l10n.setAttributes(sendItem, "openpgp-key-send-key");
sendItem.addEventListener("command", event => {
event.stopPropagation();
openPgpSendKeyEmail(`0x${key.keyId}`);
});
const exportItem = document.createXULElement("menuitem");
document.l10n.setAttributes(exportItem, "openpgp-key-export-key");
exportItem.addEventListener("command", event => {
event.stopPropagation();
openPgpExportPublicKey(`0x${key.keyId}`);
});
const backupItem = document.createXULElement("menuitem");
document.l10n.setAttributes(backupItem, "openpgp-key-backup-key");
backupItem.addEventListener("command", event => {
event.stopPropagation();
openPgpExportSecretKey(`0x${key.keyId}`, `${key.fpr}`);
});
const revokeItem = document.createXULElement("menuitem");
document.l10n.setAttributes(revokeItem, "openpgp-key-man-revoke-key");
revokeItem.addEventListener("command", event => {
event.stopPropagation();
openPgpRevokeKey(key);
});
const deleteItem = document.createXULElement("menuitem");
document.l10n.setAttributes(deleteItem, "openpgp-delete-key");
deleteItem.addEventListener("command", event => {
event.stopPropagation();
enigmailDeleteKey(key);
});
menupopup.appendChild(copyItem);
menupopup.appendChild(sendItem);
menupopup.appendChild(exportItem);
menupopup.appendChild(document.createXULElement("menuseparator"));
menupopup.appendChild(backupItem);
menupopup.appendChild(document.createXULElement("menuseparator"));
menupopup.appendChild(revokeItem);
menupopup.appendChild(deleteItem);
more.appendChild(menupopup);
btnContainer.appendChild(info);
btnContainer.appendChild(more);
hiddenContainer.appendChild(btnContainer);
indent.appendChild(dateContainer);
if (publishContainer) {
indent.appendChild(publishContainer);
}
indent.appendChild(hiddenContainer);
container.appendChild(box);
container.appendChild(indent);
radiogroup.appendChild(container);
}
// Reflect the selected key in the UI.
radiogroup.selectedItem = radiogroup.querySelector(
`radio[value="${gKeyId}"]`
);
// Update all the encryption options based on the selected OpenPGP key.
if (gKeyId) {
enableEncryptionControls(true);
enableSigningControls(true);
} else {
const stillHaveOtherEncryption =
gEncryptionCertName && gEncryptionCertName.value;
if (!stillHaveOtherEncryption) {
enableEncryptionControls(false);
}
const stillHaveOtherSigning = gSignCertName && gSignCertName.value;
if (!stillHaveOtherSigning) {
enableSigningControls(false);
}
}
updateTechPref();
enableSelectButtons();
updateUIForSelectedOpenPgpKey();
gAttachKey.disabled = !gKeyId;
gEncryptSubject.disabled = !gKeyId;
gSendAutocryptHeaders.disabled = !gKeyId;
}