Bug 1603813, Unify general encryption options in composer window. r=mkmelin
authorKai Engert <kaie@kuix.de>
Sun, 16 Feb 2020 13:25:22 +0100
changeset 37377 7937d619f3d85df384e55fcea67c8c52750413b2
parent 37376 c14efa91e66c10f64d0c5a4de8231ced0eaa2669
child 37378 826a884758f8571d980c02a2d5b6004fc54e412e
push id2566
push userclokep@gmail.com
push dateMon, 09 Mar 2020 19:20:31 +0000
treeherdercomm-beta@a352facfa0a4 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin
bugs1603813
Bug 1603813, Unify general encryption options in composer window. r=mkmelin
mail/components/compose/content/MsgComposeCommands.js
mail/components/compose/content/messengercompose.xhtml
mail/extensions/smime/content/msgCompSMIMEOverlay.js
mail/installer/package-manifest.in
mail/locales/en-US/chrome/messenger-smime/msgCompSMIMEOverlay.dtd
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -1,15 +1,16 @@
 /* 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/. */
 
 /* global MozElements */
 
 /* import-globals-from ../../../../mailnews/addrbook/content/abDragDrop.js */
+/* import-globals-from ../../../../mailnews/base/prefs/content/accountUtils.js */
 /* import-globals-from ../../../base/content/mailCore.js */
 /* import-globals-from ../../../base/content/utilityOverlay.js */
 /* import-globals-from addressingWidgetOverlay.js */
 /* import-globals-from ComposerCommands.js */
 /* import-globals-from editor.js */
 /* import-globals-from editorUtilities.js */
 
 /* global updateRecipientsPanelVisibility, updateUIforNNTPAccount
@@ -43,16 +44,19 @@ var { InlineSpellChecker } = ChromeUtils
 );
 var { PluralForm } = ChromeUtils.import(
   "resource://gre/modules/PluralForm.jsm"
 );
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { AppConstants } = ChromeUtils.import(
   "resource://gre/modules/AppConstants.jsm"
 );
+var { MailConstants } = ChromeUtils.import(
+  "resource:///modules/MailConstants.jsm"
+);
 
 var { Localization } = ChromeUtils.import(
   "resource://gre/modules/Localization.jsm"
 );
 var l10n = new Localization(
   ["messenger/messengercompose/messengercompose.ftl"],
   true
 );
@@ -101,16 +105,36 @@ var gMsgAttachmentElement;
 var gMsgHeadersToolbarElement;
 // TODO: Maybe the following two variables can be combined.
 var gManualAttachmentReminder;
 var gDisableAttachmentReminder;
 var gComposeType;
 var gLanguageObserver;
 var gBodyFromArgs;
 
+var gSMFields = null;
+var gSelectedTechnologyIsPGP = false;
+
+var gSendSigned = false;
+var gAttachMyPublicPGPKey = false;
+
+var gSendEncrypted = false;
+var gOptionalEncryption = false; // Only encrypt if possible. Ignored if !gSendEncrypted.
+
+var gUserTouchedSendEncrypted = false;
+var gUserTouchedSendSigned = false;
+var gUserTouchedAttachMyPubKey = false;
+
+var gIsRelatedToEncryptedOriginal = false;
+var gIsRelatedToSignedOriginal = false;
+
+var gEncryptedURIService = Cc[
+  "@mozilla.org/messenger-smime/smime-encrypted-uris-service;1"
+].getService(Ci.nsIEncryptedSMIMEURIsService);
+
 // i18n globals
 var gCharsetConvertManager;
 var _gComposeBundle;
 function getComposeBundle() {
   // That one has to be lazy. Getting a reference to an element with a XBL
   // binding attached will cause the XBL constructors to fire if they haven't
   // already. If we get a reference to the compose bundle at script load-time,
   // this will cause the XBL constructor that's responsible for the personas to
@@ -1521,16 +1545,159 @@ function InitFileSaveAsMenu() {
   document
     .getElementById("cmd_saveAsDraft")
     .setAttribute("checked", defaultSaveOperation == "draft");
   document
     .getElementById("cmd_saveAsTemplate")
     .setAttribute("checked", defaultSaveOperation == "template");
 }
 
+function toggleGlobalSignMessage() {
+  gSendSigned = !gSendSigned;
+  gUserTouchedSendSigned = true;
+  setEncSigStatusUI();
+
+  /*
+  if (gSMFields.signMessage) // make sure we have a cert name...
+  {
+    if (!gCurrentIdentity.getUnicharAttribute("signing_cert_name"))
+    {
+      gSMFields.signMessage = false;
+      showSMNeedSetupInfo();
+      return;
+    }
+  }
+  */
+}
+
+function setGlobalEncryptMessage(mode) {
+  let oldSendEnc = gSendEncrypted;
+  let oldOptEnc = gOptionalEncryption;
+
+  switch (mode) {
+    case 0:
+      gSendEncrypted = false;
+      gOptionalEncryption = false;
+      break;
+    case 1:
+      gSendEncrypted = true;
+      gOptionalEncryption = true;
+      break;
+    case 2:
+      gSendEncrypted = true;
+      gOptionalEncryption = false;
+      break;
+    default:
+      return;
+  }
+
+  if (oldSendEnc != gSendEncrypted || oldOptEnc != gOptionalEncryption) {
+    gUserTouchedSendEncrypted = true;
+  }
+
+  setEncSigStatusUI();
+
+  /*
+  if (gSMFields.requireEncryptMessage)
+  {
+    // Make sure we have a cert.
+    if (!gCurrentIdentity.getUnicharAttribute("encryption_cert_name"))
+    {
+      gSMFields.requireEncryptMessage = false;
+      showSMNeedSetupInfo();
+      return;
+    }
+  }
+  */
+}
+
+function toggleAttachMyPublicKey() {
+  gAttachMyPublicPGPKey = !gAttachMyPublicPGPKey;
+  gUserTouchedAttachMyPubKey = true;
+}
+
+function setSecuritySettings(menu_id) {
+  document
+    .getElementById("menu_securityEncryptDisable" + menu_id)
+    .setAttribute("checked", !gSendEncrypted && !gOptionalEncryption);
+  /*
+  document
+    .getElementById("menu_securityEncryptOptional" + menu_id)
+    .setAttribute("checked", gSendEncrypted && gOptionalEncryption);
+  */
+  document
+    .getElementById("menu_securityEncryptRequire" + menu_id)
+    .setAttribute("checked", gSendEncrypted && !gOptionalEncryption);
+
+  document
+    .getElementById("menu_securitySign" + menu_id)
+    .setAttribute("checked", gSendSigned);
+
+  if (MailConstants.MOZ_OPENPGP) {
+    document
+      .getElementById("encTech_OpenPGP" + menu_id)
+      .setAttribute("checked", gSelectedTechnologyIsPGP);
+    document
+      .getElementById("encTech_SMIME" + menu_id)
+      .setAttribute("checked", !gSelectedTechnologyIsPGP);
+
+    let sep = document.getElementById("myPublicKeySeparator" + menu_id);
+    let box = document.getElementById("menu_securityMyPublicKey" + menu_id);
+
+    sep.setAttribute("hidden", !gSelectedTechnologyIsPGP);
+    box.setAttribute("hidden", !gSelectedTechnologyIsPGP);
+    box.setAttribute("checked", gAttachMyPublicPGPKey);
+  }
+}
+
+function showMessageComposeSecurityStatus() {
+  Recipients2CompFields(gMsgCompose.compFields);
+
+  window.openDialog(
+    "chrome://messenger-smime/content/msgCompSecurityInfo.xhtml",
+    "",
+    "chrome,modal,resizable,centerscreen",
+    {
+      compFields: gMsgCompose.compFields,
+      subject: document.getElementById("msgSubject").value,
+      smFields: gSMFields,
+      isSigningCertAvailable:
+        gCurrentIdentity.getUnicharAttribute("signing_cert_name") != "",
+      isEncryptionCertAvailable:
+        gCurrentIdentity.getUnicharAttribute("encryption_cert_name") != "",
+      currentIdentity: gCurrentIdentity,
+    }
+  );
+}
+
+function showSMNeedSetupInfo() {
+  let compSmimeBundle = document.getElementById("bundle_comp_smime");
+  let brandBundle = document.getElementById("brandBundle");
+  if (!compSmimeBundle || !brandBundle) {
+    return;
+  }
+
+  let buttonPressed = Services.prompt.confirmEx(
+    window,
+    brandBundle.getString("brandShortName"),
+    compSmimeBundle.getString("NeedSetup"),
+    Services.prompt.STD_YES_NO_BUTTONS,
+    0,
+    0,
+    0,
+    null,
+    {}
+  );
+  if (buttonPressed == 0) {
+    let servers = MailServices.accounts.getServersForIdentity(gCurrentIdentity);
+    let server = servers.queryElementAt(0, Ci.nsIMsgIncomingServer);
+    MsgAccountManager("am-smime.xhtml", server);
+  }
+}
+
 function openEditorContextMenu(popup) {
   gSpellChecker.clearSuggestionsFromMenu();
   gSpellChecker.initFromEvent(
     document.popupRangeParent,
     document.popupRangeOffset
   );
   var onMisspelling = gSpellChecker.overMisspelling;
   document.getElementById(
@@ -3463,16 +3630,39 @@ function ComposeLoad() {
   var toolbox = document.getElementById("compose-toolbox");
   toolbox.customizeDone = function(aEvent) {
     MailToolboxCustomizeDone(aEvent, "CustomizeComposeToolbar");
   };
 
   updateAttachmentPane();
   attachmentBucketMarkEmptyBucket();
   updateStringsOfAddressingFields();
+
+  top.controllers.appendController(SecurityController);
+  gMsgCompose.compFields.composeSecure = null;
+  gSMFields = Cc[
+    "@mozilla.org/messengercompose/composesecure;1"
+  ].createInstance(Ci.nsIMsgComposeSecure);
+  if (gSMFields) {
+    gMsgCompose.compFields.composeSecure = gSMFields;
+  }
+
+  // TODO: call code to get default settings for gSendEncrypted etc.
+  if (
+    gEncryptedURIService &&
+    gEncryptedURIService.isEncrypted(gMsgCompose.originalMsgURI)
+  ) {
+    gIsRelatedToEncryptedOriginal = true;
+  }
+
+  if (gIsRelatedToEncryptedOriginal) {
+    gSendEncrypted = true;
+  }
+
+  setEncSigStatusUI();
 }
 
 function ComposeUnload() {
   // Send notification that the window is going away completely.
   document
     .getElementById("msgcomposeWindow")
     .dispatchEvent(
       new Event("compose-window-unload", { bubbles: false, cancelable: false })
@@ -3509,17 +3699,99 @@ function ComposeUnload() {
   if (gAutoSaveTimeout) {
     clearTimeout(gAutoSaveTimeout);
   }
   if (msgWindow) {
     msgWindow.closeWindow();
   }
 
   ReleaseGlobalVariables();
-}
+
+  top.controllers.removeController(SecurityController);
+}
+
+function setEncSigStatusUI() {
+  document
+    .getElementById("signing-status")
+    .classList.toggle("signing-msg", gSendSigned);
+  document
+    .getElementById("encryption-status")
+    .classList.toggle("encrypting-msg", gSendEncrypted);
+
+  if (MailConstants.MOZ_OPENPGP) {
+    let techStatus = top.document.getElementById("encryption-tech");
+    if (gSelectedTechnologyIsPGP) {
+      techStatus.value = "OpenPGP";
+    } else {
+      techStatus.value = "S/MIME";
+    }
+    techStatus.collapsed = !gSendSigned && !gSendEncrypted;
+  }
+}
+
+function onSecurityChoice(value) {
+  switch (value) {
+    case "enc0":
+      setGlobalEncryptMessage(0);
+      break;
+
+    case "enc1":
+      setGlobalEncryptMessage(1);
+      break;
+
+    case "enc2":
+      setGlobalEncryptMessage(2);
+      break;
+
+    case "sig":
+      toggleGlobalSignMessage();
+      break;
+
+    case "mykey":
+      toggleAttachMyPublicKey();
+      break;
+
+    case "OpenPGP":
+      gSelectedTechnologyIsPGP = true;
+      setEncSigStatusUI();
+      break;
+
+    case "SMIME":
+      gSelectedTechnologyIsPGP = false;
+      setEncSigStatusUI();
+      break;
+
+    case "status":
+    case undefined: // toolbar button was clicked
+      showMessageComposeSecurityStatus();
+      break;
+  }
+}
+
+var SecurityController = {
+  supportsCommand(command) {
+    switch (command) {
+      case "cmd_viewSecurityStatus":
+        return true;
+
+      default:
+        return false;
+    }
+  },
+
+  isCommandEnabled(command) {
+    switch (command) {
+      case "cmd_viewSecurityStatus":
+        return true;
+
+      default:
+        return false;
+    }
+  },
+};
 
 function SetDocumentCharacterSet(aCharset) {
   if (gMsgCompose) {
     // Replace generic Japanese with ISO-2022-JP.
     if (aCharset == "Japanese") {
       aCharset = "ISO-2022-JP";
     }
     gMsgCompose.SetDocumentCharset(aCharset);
@@ -3623,16 +3895,59 @@ function GetCharsetUIString() {
       // Not a canonical charset after all...
       Cu.reportError("No charset title for charset=" + charset);
       return charset;
     }
   }
   return "";
 }
 
+function onSendSMIME() {
+  let emailAddresses = [];
+
+  try {
+    if (!gMsgCompose.compFields.composeSecure.requireEncryptMessage) {
+      return;
+    }
+
+    Cc["@mozilla.org/messenger-smime/smimejshelper;1"]
+      .createInstance(Ci.nsISMimeJSHelper)
+      .getNoCertAddresses(gMsgCompose.compFields, emailAddresses);
+  } catch (e) {
+    return;
+  }
+
+  if (emailAddresses.length > 0) {
+    // The rules here: If the current identity has a directoryServer set, then
+    // use that, otherwise, try the global preference instead.
+
+    let autocompleteDirectory;
+
+    // Does the current identity override the global preference?
+    if (gCurrentIdentity.overrideGlobalPref) {
+      autocompleteDirectory = gCurrentIdentity.directoryServer;
+    } else if (Services.prefs.getBoolPref("ldap_2.autoComplete.useDirectory")) {
+      // Try the global one
+      autocompleteDirectory = Services.prefs.getCharPref(
+        "ldap_2.autoComplete.directoryServer"
+      );
+    }
+
+    if (autocompleteDirectory) {
+      window.openDialog(
+        "chrome://messenger-smime/content/certFetchingStatus.xhtml",
+        "",
+        "chrome,modal,resizable,centerscreen",
+        autocompleteDirectory,
+        emailAddresses.value
+      );
+    }
+  }
+}
+
 // Add-ons can override this to customize the behavior.
 function DoSpellCheckBeforeSend() {
   return Services.prefs.getBoolPref("mail.SpellCheckBeforeSend");
 }
 
 /**
  * Updates gMsgCompose.compFields to match the UI.
  *
@@ -3938,20 +4253,26 @@ function CompleteGenericSendMessage(msgT
       fallbackCharset &&
       fallbackCharset.value &&
       fallbackCharset.value != ""
     ) {
       gMsgCompose.SetDocumentCharset(fallbackCharset.value);
     }
   }
 
+  if (!gSelectedTechnologyIsPGP) {
+    gMsgCompose.compFields.composeSecure.requireEncryptMessage = gSendEncrypted;
+    gMsgCompose.compFields.composeSecure.signMessage = gSendSigned;
+    onSendSMIME();
+  }
+
   try {
     // Just before we try to send the message, fire off the
-    // compose-send-message event for listeners such as smime so they can do
-    // any pre-security work such as fetching certificates before sending.
+    // compose-send-message event for listeners, so they can do
+    // any pre-security work before sending.
     var event = document.createEvent("UIEvents");
     event.initEvent("compose-send-message", false, true);
     var msgcomposeWindow = document.getElementById("msgcomposeWindow");
     msgcomposeWindow.setAttribute("msgtype", msgType);
     msgcomposeWindow.dispatchEvent(event);
     if (event.defaultPrevented) {
       throw Cr.NS_ERROR_ABORT;
     }
--- a/mail/components/compose/content/messengercompose.xhtml
+++ b/mail/components/compose/content/messengercompose.xhtml
@@ -1681,17 +1681,17 @@
                     label="&colorsAndBackground.label;"
                     accesskey="&colorsAndBackground.accesskey;"
                     oncommand="goDoCommand('cmd_colorProperties')"
                     observes="cmd_renderedHTMLEnabler"/>
         </menupopup>
       </menu>
 
       <menu id="optionsMenu" label="&optionsMenu.label;" accesskey="&optionsMenu.accesskey;">
-        <menupopup id="optionsMenuPopup" onpopupshowing="setSecuritySettings(1);">
+        <menupopup id="optionsMenuPopup" onpopupshowing="setSecuritySettings('_Menubar');">
           <menuitem id="menu_checkspelling"
                     label="&checkSpellingCmd2.label;"
                     accesskey="&checkSpellingCmd2.accesskey;"
                     key="key_checkspelling"
                     command="cmd_spelling"
                     class="menuitem-iconic"/>
           <menuitem label="&enableInlineSpellChecker.label;" id="menu_inlineSpellCheck"
                     accesskey="&enableInlineSpellChecker.accesskey;" checked="false"
@@ -1732,28 +1732,74 @@
                 accesskey="&fileCarbonCopyCmd.accesskey;"
                 oncommand="MessageFcc(event.target._folder)">
             <menupopup is="folder-menupopup" id="fccMenuPopup" mode="filing"
                        showFileHereLabel="true" fileHereLabel="&fileHereMenu.label;"/>
           </menu>
           <menuseparator/>
           <menuitem type="checkbox" command="cmd_customizeFromAddress"
                     accesskey="&customizeFromAddress.accesskey;"/>
-          <menuseparator id="smimeOptionsSeparator"/>
+
+#ifdef MOZ_OPENPGP
+          <menuseparator id="encryptTechOptionsSeparator_Menubar"/>
+
+          <menu id="menu_encTech_Menubar"
+                label="&menu_securityTech.label;" accesskey="&menu_securityTech.accesskey;">
+            <menupopup id="button-encTech_Menubar" oncommand="onSecurityChoice(event.target.value);">
+              <menuitem id="encTech_OpenPGP_Menubar"
+                        label="&menu_techPGP.label;" accesskey="&menu_techPGP.accesskey;"
+                        value="OpenPGP" type="radio" name="radiogroup_encTech"/>
+              <menuitem id="encTech_SMIME_Menubar"
+                        label="&menu_techSMIME.label;" accesskey="&menu_techSMIME.accesskey;"
+                        value="SMIME" type="radio" name="radiogroup_encTech"/>
+            </menupopup>
+          </menu>
+#endif
+
+          <menuseparator id="encryptOptionsSeparator_Menubar"/>
 
-          <menuitem id="menu_securityEncryptRequire1"
-                    type="checkbox"
-                    label="&menu_securityEncryptRequire.label;"
+          <menuitem id="menu_securityEncryptDisable_Menubar"
+                    type="radio" name="radiogroup_encEnable"
+                    label="&menu_securityDoNotEncrypt.label;"
+                    accesskey="&menu_securityDoNotEncrypt.accesskey;"
+                    value="enc0"
+                    oncommand="onSecurityChoice(event.target.value);"/>
+          <!--
+          <menuitem id="menu_securityEncryptOptional_Menubar"
+                    type="radio" name="radiogroup_encEnable"
+                    label="&menu_securityEncryptOptional.label;"
+                    accesskey="&menu_securityEncryptOptional.accesskey;"
+                    value="enc1"
+                    oncommand="onSecurityChoice(event.target.value);"/>
+          -->
+          <menuitem id="menu_securityEncryptRequire_Menubar"
+                    type="radio" name="radiogroup_encEnable"
+                    label="&menu_securityEncryptRequire2.label;"
                     accesskey="&menu_securityEncryptRequire.accesskey;"
-                    oncommand="toggleEncryptMessage();"/>
-          <menuitem id="menu_securitySign1"
+                    value="enc2"
+                    oncommand="onSecurityChoice(event.target.value);"/>
+
+          <menuseparator id="signOptionsSeparator_Menubar"/>
+
+          <menuitem id="menu_securitySign_Menubar"
                     type="checkbox"
                     label="&menu_securitySign.label;"
                     accesskey="&menu_securitySign.accesskey;"
-                    oncommand="toggleSignMessage();"/>
+                    value="sig"
+                    oncommand="onSecurityChoice(event.target.value);"/>
+
+#ifdef MOZ_OPENPGP
+        <menuseparator id="myPublicKeySeparator_Menubar"/>
+        <menuitem id="menu_securityMyPublicKey_Menubar"
+                  type="checkbox"
+                  label="&menu_securityAttachMyKey.label;"
+                  accesskey="&menu_securityAttachMyKey.accesskey;"
+                  value="mykey"
+                  oncommand="onSecurityChoice(event.target.value);"/>
+#endif
         </menupopup>
       </menu>
 
       <menu id="tasksMenu" label="&tasksMenu.label;" accesskey="&tasksMenu.accesskey;">
           <menupopup id="taskPopup">
             <!-- Moving the first two items to the Window menu on the Mac -->
 #ifndef XP_MACOSX
             <menuitem id="tasksMenuMail" accesskey="&messengerCmd.accesskey;"
@@ -1858,33 +1904,74 @@
       </menupopup>
     </toolbarbutton>
 
     <toolbarbutton is="toolbarbutton-menu-button" id="button-security"
                    type="menu-button"
                    class="toolbarbutton-1"
                    label="&securityButton.label;"
                    tooltiptext="&securityButton.tooltip;"
-                   oncommand="doSecurityButton();">
-      <menupopup onpopupshowing="setSecuritySettings(2);">
-        <menuitem id="menu_securityEncryptRequire2"
-                  type="checkbox"
-                  label="&menu_securityEncryptRequire.label;"
+                   oncommand="onSecurityChoice(event.target.value);">
+      <menupopup onpopupshowing="setSecuritySettings('_Toolbar');">
+#ifdef MOZ_OPENPGP
+        <menu id="menu_encTech_Toolbar"
+              label="&menu_securityTech.label;" accesskey="&menu_securityTech.accesskey;">
+          <menupopup id="button-encTech_Toolbar">
+            <menuitem id="encTech_OpenPGP_Toolbar"
+                      label="&menu_techPGP.label;" accesskey="&menu_techPGP.accesskey;"
+                      value="OpenPGP" type="radio" name="radiogroup_encTech"/>
+            <menuitem id="encTech_SMIME_Toolbar"
+                      label="&menu_techSMIME.label;" accesskey="&menu_techSMIME.accesskey;"
+                      value="SMIME" type="radio" name="radiogroup_encTech"/>
+          </menupopup>
+        </menu>
+#endif
+
+        <menuseparator id="encryptOptionsSeparator_Toolbar"/>
+
+        <menuitem id="menu_securityEncryptDisable_Toolbar"
+                  type="radio" name="radiogroup_encEnable"
+                  label="&menu_securityDoNotEncrypt.label;"
+                  accesskey="&menu_securityDoNotEncrypt.accesskey;"
+                  value="enc0"/>
+        <!--
+        <menuitem id="menu_securityEncryptOptional_Toolbar"
+                  type="radio" name="radiogroup_encEnable"
+                  label="&menu_securityEncryptOptional.label;"
+                  accesskey="&menu_securityEncryptOptional.accesskey;"
+                  value="enc1"/>
+        -->
+        <menuitem id="menu_securityEncryptRequire_Toolbar"
+                  type="radio" name="radiogroup_encEnable"
+                  label="&menu_securityEncryptRequire2.label;"
                   accesskey="&menu_securityEncryptRequire.accesskey;"
-                  oncommand="setNextCommand('encryptMessage');"/>
-        <menuitem id="menu_securitySign2"
+                  value="enc2"/>
+
+        <menuseparator id="signOptionsSeparator_Toolbar"/>
+
+        <menuitem id="menu_securitySign_Toolbar"
                   type="checkbox"
                   label="&menu_securitySign.label;"
                   accesskey="&menu_securitySign.accesskey;"
-                  oncommand="setNextCommand('signMessage');"/>
-        <menuseparator id="smimeToolbarButtonSeparator"/>
-        <menuitem id="menu_securityStatus2"
+                  value="sig"/>
+
+#ifdef MOZ_OPENPGP
+        <menuseparator id="myPublicKeySeparator_Toolbar"/>
+        <menuitem id="menu_securityMyPublicKey_Toolbar"
+                  type="checkbox"
+                  label="&menu_securityAttachMyKey.label;"
+                  accesskey="&menu_securityAttachMyKey.accesskey;"
+                  value="mykey"/>
+#endif
+
+        <menuseparator id="statusInfoSeparator"/>
+        <menuitem id="menu_securityStatus_Toolbar"
                   label="&menu_securityStatus.label;"
                   accesskey="&menu_securityStatus.accesskey;"
-                  oncommand="setNextCommand('show');"/>
+                  value="status"/>
       </menupopup>
     </toolbarbutton>
 
     <toolbarbutton is="toolbarbutton-menu-button" id="spellingButton"
                    type="menu-button"
                    class="toolbarbutton-1"
                    label="&spellingButton.label;"
                    tooltiptext="&spellingButton.tooltip;"
@@ -2424,16 +2511,19 @@
 
   <hbox id="status-bar" class="statusbar chromeclass-status">
     <label id="statusText" class="statusbarpanel" flex="1" crop="end"/>
     <hbox id="statusbar-progresspanel"
           class="statusbarpanel statusbarpanel-progress"
           collapsed="true">
       <html:progress id="compose-progressmeter" class="progressmeter-statusbar" value="0" max="100"/>
     </hbox>
+#ifdef MOZ_OPENPGP
+    <label id="encryption-tech" class="statusbarpanel"/>
+#endif
     <hbox id="signing-status"
           class="statusbarpanel statusbarpanel-iconic"
           collapsed="true"
           oncommand="showMessageComposeSecurityStatus();">
       <image/>
     </hbox>
     <hbox id="encryption-status"
           class="statusbarpanel statusbarpanel-iconic"
--- a/mail/extensions/smime/content/msgCompSMIMEOverlay.js
+++ b/mail/extensions/smime/content/msgCompSMIMEOverlay.js
@@ -1,365 +1,4 @@
 /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  * 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 ../../../../mailnews/base/prefs/content/accountUtils.js */
-/* import-globals-from ../../../components/compose/content/MsgComposeCommands.js */
-/* import-globals-from ../../../components/compose/content/addressingWidgetOverlay.js */
-
-var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
-var { MailServices } = ChromeUtils.import(
-  "resource:///modules/MailServices.jsm"
-);
-
-// Account encryption policy values:
-// const kEncryptionPolicy_Never = 0;
-// 'IfPossible' was used by ns4.
-// const kEncryptionPolicy_IfPossible = 1;
-var kEncryptionPolicy_Always = 2;
-
-var gEncryptedURIService = Cc[
-  "@mozilla.org/messenger-smime/smime-encrypted-uris-service;1"
-].getService(Ci.nsIEncryptedSMIMEURIsService);
-
-var gNextSecurityButtonCommand = "";
-var gSMFields = null;
-
-var gEncryptOptionChanged;
-var gSignOptionChanged;
-
-function onComposerLoad() {
-  // Are we already set up ? Or are the required fields missing ?
-  if (gSMFields || !gMsgCompose || !gMsgCompose.compFields) {
-    return;
-  }
-
-  gMsgCompose.compFields.composeSecure = null;
-
-  gSMFields = Cc[
-    "@mozilla.org/messengercompose/composesecure;1"
-  ].createInstance(Ci.nsIMsgComposeSecure);
-  if (!gSMFields) {
-    return;
-  }
-
-  gMsgCompose.compFields.composeSecure = gSMFields;
-
-  // Set up the initial security state.
-  gSMFields.requireEncryptMessage =
-    gCurrentIdentity.getIntAttribute("encryptionpolicy") ==
-    kEncryptionPolicy_Always;
-  if (
-    !gSMFields.requireEncryptMessage &&
-    gEncryptedURIService &&
-    gEncryptedURIService.isEncrypted(gMsgCompose.originalMsgURI)
-  ) {
-    // Override encryption setting if original is known as encrypted.
-    gSMFields.requireEncryptMessage = true;
-  }
-  if (gSMFields.requireEncryptMessage) {
-    setEncryptionUI();
-  } else {
-    setNoEncryptionUI();
-  }
-
-  gSMFields.signMessage = gCurrentIdentity.getBoolAttribute("sign_mail");
-  if (gSMFields.signMessage) {
-    setSignatureUI();
-  } else {
-    setNoSignatureUI();
-  }
-}
-
-addEventListener("load", smimeComposeOnLoad, { capture: false, once: true });
-
-// this function gets called multiple times.
-function smimeComposeOnLoad() {
-  onComposerLoad();
-
-  top.controllers.appendController(SecurityController);
-
-  addEventListener("compose-from-changed", onComposerFromChanged, true);
-  addEventListener("compose-send-message", onComposerSendMessage, true);
-
-  addEventListener("unload", smimeComposeOnUnload, {
-    capture: false,
-    once: true,
-  });
-}
-
-function smimeComposeOnUnload() {
-  removeEventListener("compose-from-changed", onComposerFromChanged, true);
-  removeEventListener("compose-send-message", onComposerSendMessage, true);
-
-  top.controllers.removeController(SecurityController);
-}
-
-function GetServer() {
-  let servers = MailServices.accounts.getServersForIdentity(gCurrentIdentity);
-  return servers.queryElementAt(0, Ci.nsIMsgIncomingServer);
-}
-
-function showNeedSetupInfo() {
-  let compSmimeBundle = document.getElementById("bundle_comp_smime");
-  let brandBundle = document.getElementById("brandBundle");
-  if (!compSmimeBundle || !brandBundle) {
-    return;
-  }
-
-  let buttonPressed = Services.prompt.confirmEx(
-    window,
-    brandBundle.getString("brandShortName"),
-    compSmimeBundle.getString("NeedSetup"),
-    Services.prompt.STD_YES_NO_BUTTONS,
-    0,
-    0,
-    0,
-    null,
-    {}
-  );
-  if (buttonPressed == 0) {
-    MsgAccountManager("am-smime.xhtml", GetServer());
-  }
-}
-
-function toggleEncryptMessage() {
-  if (!gSMFields) {
-    return;
-  }
-
-  gSMFields.requireEncryptMessage = !gSMFields.requireEncryptMessage;
-
-  if (gSMFields.requireEncryptMessage) {
-    // Make sure we have a cert.
-    if (!gCurrentIdentity.getUnicharAttribute("encryption_cert_name")) {
-      gSMFields.requireEncryptMessage = false;
-      showNeedSetupInfo();
-      return;
-    }
-
-    setEncryptionUI();
-  } else {
-    setNoEncryptionUI();
-  }
-
-  gEncryptOptionChanged = true;
-}
-
-function toggleSignMessage() {
-  if (!gSMFields) {
-    return;
-  }
-
-  gSMFields.signMessage = !gSMFields.signMessage;
-
-  if (gSMFields.signMessage) {
-    // make sure we have a cert name...
-    if (!gCurrentIdentity.getUnicharAttribute("signing_cert_name")) {
-      gSMFields.signMessage = false;
-      showNeedSetupInfo();
-      return;
-    }
-
-    setSignatureUI();
-  } else {
-    setNoSignatureUI();
-  }
-
-  gSignOptionChanged = true;
-}
-
-function setSecuritySettings(menu_id) {
-  if (!gSMFields) {
-    return;
-  }
-
-  document
-    .getElementById("menu_securityEncryptRequire" + menu_id)
-    .setAttribute("checked", gSMFields.requireEncryptMessage);
-  document
-    .getElementById("menu_securitySign" + menu_id)
-    .setAttribute("checked", gSMFields.signMessage);
-}
-
-function setNextCommand(what) {
-  gNextSecurityButtonCommand = what;
-}
-
-function doSecurityButton() {
-  var what = gNextSecurityButtonCommand;
-  gNextSecurityButtonCommand = "";
-
-  switch (what) {
-    case "encryptMessage":
-      toggleEncryptMessage();
-      break;
-
-    case "signMessage":
-      toggleSignMessage();
-      break;
-
-    case "show":
-    default:
-      showMessageComposeSecurityStatus();
-  }
-}
-
-function setNoSignatureUI() {
-  top.document.getElementById("signing-status").classList.remove("signing-msg");
-}
-
-function setSignatureUI() {
-  top.document.getElementById("signing-status").classList.add("signing-msg");
-}
-
-function setNoEncryptionUI() {
-  top.document
-    .getElementById("encryption-status")
-    .classList.remove("encrypting-msg");
-}
-
-function setEncryptionUI() {
-  top.document
-    .getElementById("encryption-status")
-    .classList.add("encrypting-msg");
-}
-
-function showMessageComposeSecurityStatus() {
-  Recipients2CompFields(gMsgCompose.compFields);
-
-  window.openDialog(
-    "chrome://messenger-smime/content/msgCompSecurityInfo.xhtml",
-    "",
-    "chrome,modal,resizable,centerscreen",
-    {
-      compFields: gMsgCompose.compFields,
-      subject: document.getElementById("msgSubject").value,
-      smFields: gSMFields,
-      isSigningCertAvailable:
-        gCurrentIdentity.getUnicharAttribute("signing_cert_name") != "",
-      isEncryptionCertAvailable:
-        gCurrentIdentity.getUnicharAttribute("encryption_cert_name") != "",
-      currentIdentity: gCurrentIdentity,
-    }
-  );
-}
-
-var SecurityController = {
-  supportsCommand(command) {
-    switch (command) {
-      case "cmd_viewSecurityStatus":
-        return true;
-
-      default:
-        return false;
-    }
-  },
-
-  isCommandEnabled(command) {
-    switch (command) {
-      case "cmd_viewSecurityStatus":
-        return true;
-
-      default:
-        return false;
-    }
-  },
-};
-
-function onComposerSendMessage() {
-  let emailAddresses = [];
-
-  try {
-    if (!gMsgCompose.compFields.composeSecure.requireEncryptMessage) {
-      return;
-    }
-
-    Cc["@mozilla.org/messenger-smime/smimejshelper;1"]
-      .createInstance(Ci.nsISMimeJSHelper)
-      .getNoCertAddresses(gMsgCompose.compFields, emailAddresses);
-  } catch (e) {
-    return;
-  }
-
-  if (emailAddresses.length > 0) {
-    // The rules here: If the current identity has a directoryServer set, then
-    // use that, otherwise, try the global preference instead.
-
-    let autocompleteDirectory;
-
-    // Does the current identity override the global preference?
-    if (gCurrentIdentity.overrideGlobalPref) {
-      autocompleteDirectory = gCurrentIdentity.directoryServer;
-    } else if (Services.prefs.getBoolPref("ldap_2.autoComplete.useDirectory")) {
-      // Try the global one
-      autocompleteDirectory = Services.prefs.getCharPref(
-        "ldap_2.autoComplete.directoryServer"
-      );
-    }
-
-    if (autocompleteDirectory) {
-      window.openDialog(
-        "chrome://messenger-smime/content/certFetchingStatus.xhtml",
-        "",
-        "chrome,modal,resizable,centerscreen",
-        autocompleteDirectory,
-        emailAddresses.value
-      );
-    }
-  }
-}
-
-function onComposerFromChanged() {
-  if (!gSMFields) {
-    return;
-  }
-
-  var encryptionPolicy = gCurrentIdentity.getIntAttribute("encryptionpolicy");
-  var useEncryption = false;
-  if (!gEncryptOptionChanged) {
-    // Encryption wasn't manually checked.
-    // Set up the encryption policy from the setting of the new identity.
-
-    useEncryption = encryptionPolicy == kEncryptionPolicy_Always;
-  } else if (encryptionPolicy != kEncryptionPolicy_Always) {
-    // The encryption policy was manually checked. That means we can get into
-    // the situation that the new identity doesn't have a cert to encrypt with.
-    // If it doesn't, don't encrypt.
-
-    // Encrypted (policy unencrypted, manually changed).
-    // Make sure we have a cert for encryption.
-    useEncryption = !!gCurrentIdentity.getUnicharAttribute(
-      "encryption_cert_name"
-    );
-  }
-  gSMFields.requireEncryptMessage = useEncryption;
-  if (useEncryption) {
-    setEncryptionUI();
-  } else {
-    setNoEncryptionUI();
-  }
-
-  var signMessage = gCurrentIdentity.getBoolAttribute("sign_mail");
-  var useSigning = false;
-  if (!gSignOptionChanged) {
-    // Signing wasn't manually checked.
-    // Set up the signing policy from the setting of the new identity.
-
-    useSigning = signMessage;
-  } else if (!signMessage) {
-    // The signing policy was manually checked. That means we can get into
-    // the situation that the new identity doesn't have a cert to sign with.
-    // If it doesn't, don't sign.
-
-    // Signed (policy unsigned, manually changed).
-    // Make sure we have a cert for signing.
-    useSigning = !!gCurrentIdentity.getUnicharAttribute("signing_cert_name");
-  }
-  gSMFields.signMessage = useSigning;
-  if (useSigning) {
-    setSignatureUI();
-  } else {
-    setNoSignatureUI();
-  }
-}
--- a/mail/installer/package-manifest.in
+++ b/mail/installer/package-manifest.in
@@ -252,20 +252,29 @@
 @RESPATH@/defaults/pref/smime.js
 @RESPATH@/defaults/pref/thunderbird-branding.js
 @RESPATH@/defaults/permissions
 @RESPATH@/defaults/settings/blocklists
 @RESPATH@/defaults/settings/pinning
 @RESPATH@/defaults/settings/main
 @RESPATH@/greprefs.js
 
+#ifdef MOZ_OPENPGP
+@RESPATH@/defaults/pref/openpgp-prefs.js
+#endif
+
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ; App extensions to Mail
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
+#ifdef MOZ_OPENPGP
+@RESPATH@/chrome/openpgp@JAREXT@
+@RESPATH@/chrome/openpgp.manifest
+#endif
+
 ; LDAP components
 #ifdef MOZ_LDAP_XPCOM
 @RESPATH@/components/nsLDAPProtocolHandler.js
 @RESPATH@/components/ldapComponents.manifest
 @BINPATH@/@DLL_PREFIX@ldap60@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@ldif60@DLL_SUFFIX@
 @BINPATH@/@DLL_PREFIX@prldap60@DLL_SUFFIX@
 #endif
--- a/mail/locales/en-US/chrome/messenger-smime/msgCompSMIMEOverlay.dtd
+++ b/mail/locales/en-US/chrome/messenger-smime/msgCompSMIMEOverlay.dtd
@@ -1,20 +1,39 @@
 <!-- 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/. -->
 
 <!--LOCALIZATION NOTE msgCompSMIMEOverlay.dtd UI for s/mime hooks in message composition -->
 
-<!ENTITY menu_securityEncryptRequire.label "Encrypt This Message">
+<!ENTITY menu_securityDoNotEncrypt.label "Do Not Encrypt">
+<!ENTITY menu_securityDoNotEncrypt.accesskey "o">
+
+<!-- not yet used
+<!ENTITY menu_securityEncryptOptional.label "Allow Encryption">
+<!ENTITY menu_securityEncryptOptional.accesskey "w">
+-->
+
+<!ENTITY menu_securityEncryptRequire2.label "Require Encryption">
 <!ENTITY menu_securityEncryptRequire.accesskey "E">
 
 <!ENTITY menu_securitySign.label "Digitally Sign This Message">
 <!ENTITY menu_securitySign.accesskey "M">
 
+<!ENTITY menu_securityAttachMyKey.label "Attach My Public Key">
+<!ENTITY menu_securityAttachMyKey.accesskey "A">
+
+<!ENTITY menu_securityTech.label "Encryption Technology">
+<!ENTITY menu_securityTech.accesskey "T">
+
+<!ENTITY menu_techPGP.label "OpenPGP">
+<!ENTITY menu_techPGP.accesskey "O">
+<!ENTITY menu_techSMIME.label "S/MIME">
+<!ENTITY menu_techSMIME.accesskey "S">
+
 <!ENTITY menu_securityStatus.label "View Security Info">
 <!ENTITY menu_securityStatus.accesskey "I">
 
 <!ENTITY securityButton.label "Security">
 <!ENTITY securityButton.tooltip "View or change security settings">
 
 <!ENTITY menu_viewSecurityStatus.label "Message Security Info">
 <!ENTITY menu_viewSecurityStatus.accesskey "I">