[feat] Display encryption status when viewing a message
authorSukhbir Singh <sukhbir@torproject.org>
Sat, 13 Jan 2018 05:44:14 +0000 (00:44 -0500)
committerSukhbir Singh <sukhbir@torproject.org>
Mon, 29 Jan 2018 21:50:52 +0000 (16:50 -0500)
Display a notification bar in the message pane if the message was
encrypted for messages in the "Inbox" folder.

For messages in the "Sent" folder, we have placeholder code for
displaying the message state and for adding custom headers if required.
However, we need to understand how to handle the case for multiple
recipients with different encryption states since it's possible to send
encrypted messages to recipients with known keys but the same message
will be send unencrypted to recipients whose keys are not known. In such
a case we can display the message status per-recipient.

chrome/content/accountWizard/bitmaskMessengerOverlay.js
chrome/content/accountWizard/bitmaskMessengerOverlay.xul
chrome/content/bitmask.js
chrome/content/messengercompose.js
chrome/locale/en-US/bitmaskMessengerOverlay.properties
chrome/skin/accountWizard.css

index 148290c..31e7887 100644 (file)
@@ -1,10 +1,50 @@
-window.addEventListener("load", function() {
-  overlayStartup();
-}, false);
+var { interfaces: Ci, utils: Cu, classes: Cc } = Components;
 
-window.setInterval(function() {
-  overlayStartup();
-}, 3000);
+Cu.import("resource:///modules/imServices.jsm");
+Cu.import("resource:///modules/imXPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyGetter(this, "_", () =>
+  l10nHelper("chrome://bitmask/locale/bitmaskMessengerOverlay.properties")
+);
+
+var notificationBar = {
+  onStartHeaders: function() {
+    let currentFolder = gFolderDisplay.displayedFolder.name;
+    if (currentFolder === "Inbox") {
+      let promise = bitmask.mail.msg_status(gFolderDisplay.displayedFolder.username,
+                                            currentFolder.toUpperCase(),
+                                            gFolderDisplay.selectedMessage.messageId);
+      promise.then(function(data) {
+        // If the message was encrypted, display the notification bar.
+        let result = data["secured"];
+        if (result === true) {
+          document.getElementById("msgNotificationBar").collapsed = false;
+          document.getElementById("bitmaskDescription").value = _("bitmaskMsgEncrypted");
+        } else {
+          document.getElementById("msgNotificationBar").collapsed = true;
+        }
+      }, function(error) {
+        // Something went wrong, like the message was not found.
+        document.getElementById("msgNotificationBar").collapsed = true;
+      });
+    }
+  },
+
+  onEndHeaders: function() {
+  },
+
+  load: function() {
+    // Update the notification bar when the selected message changes.
+    gMessageListeners.push(notificationBar);
+    // This is borrowed from Lightning so that we can hide the notification
+    // bar in case the folder is changed.
+    notificationBar.tbHideMessageHeaderPane = HideMessageHeaderPane;
+    HideMessageHeaderPane = function() {
+      document.getElementById("msgNotificationBar").collapsed = true;
+      notificationBar.tbHideMessageHeaderPane.apply(null, arguments);
+    };
+  }
+}
 
 function overlayStartup() {
   let myPanel = document.getElementById("bitmaskStatusBarPanel");
@@ -14,7 +54,7 @@ function overlayStartup() {
   // authorize with it using the token from bitmask.js
   let promise = bitmask.core.status();
   promise.then(function(data) {
-    myPanel.label = strBundle.getFormattedString("bitmaskStatusOn", [ data["mail"] ]);
+    myPanel.label = _("bitmaskStatusOn", data["mail"]);
     myPanel.style.color = "green";
     myPanel.src = "chrome://bitmask/skin/on.png";
   }, function(error) {
@@ -24,3 +64,11 @@ function overlayStartup() {
     console.log(error);
   });
 }
+
+window.addEventListener("load", function() {
+  overlayStartup();
+}, false);
+
+window.setInterval(function() { overlayStartup(); }, 3000);
+
+window.addEventListener("messagepane-loaded", notificationBar.load, true);
index da906f6..57967e3 100644 (file)
@@ -1,5 +1,9 @@
 <?xml version="1.0"?>
+
+<?xml-stylesheet href="chrome://bitmask/skin/accountWizard.css" type="text/css"?>
+
 <!DOCTYPE overlay SYSTEM "chrome://bitmask/locale/bitmaskMessengerOverlay.dtd">
+
 <overlay id="bitmaskMessengerOverlay" 
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript"
@@ -9,9 +13,11 @@
   <script type="application/javascript"
           src="chrome://bitmask/content/accountWizard/bitmaskMessengerOverlay.js"/>
 
-  <stringbundleset id="stringbundleset">
-    <stringbundle id="bitmaskMessengerStrings" src="chrome://bitmask/locale/bitmaskMessengerOverlay.properties"/>
-  </stringbundleset>
+  <notificationbox id="msgNotificationBar" collapsed="true">
+    <hbox id="bitmaskHeader" class="bitmaskNotificationBar">
+      <description id="bitmaskDescription" />
+    </hbox>
+  </notificationbox>
 
   <statusbar id="status-bar">
     <statusbarpanel id="bitmaskStatusBarPanel" class="statusbarpanel-iconic-text" />
index 6ab87ff..e549c3e 100644 (file)
@@ -395,6 +395,19 @@ var bitmask = function(){
             },
 
             /**
+             * Get message status of one email
+             *
+             * @param {string} uid The uid to get status about
+             * @param {string} mbox The name of the mailbox where the message is stored
+             * @param {string} message_id The Message-Id from the headers of the email
+             *
+             * @return {Promise<{'secured': bool}>} Returns the status of the email
+             */
+            msg_status: function(uid, mbox, message_id) {
+                return call(['mail', 'msg_status', uid, mbox, message_id]);
+            },
+
+            /**
              * Get status on the mixnet for an address.
              *
              * @param {string} uid The uid to get status about
index 4b12f64..c0c5ec3 100644 (file)
@@ -1,8 +1,33 @@
+// Assume that gBitmaskEncryptionState is true; if we detect a recipient
+// whose public key we don't know, we will set it to false, indicating
+// that the message will not be encrypted.
+var gBitmaskEncryptionState = true;
+
 var composeStateListener = {
   NotifyComposeBodyReady: function() {
   }
 };
 
+function insertEncryptionHeaders(event) {
+  // let msgComposeWindow = document.getElementById("msgcomposeWindow");
+  // let msgType = msgComposeWindow.getAttribute("msgType");
+
+  // // We only care about an actual send event.
+  // if (!(msgType == nsIMsgCompDeliverMode.Now || msgType == nsIMsgCompDeliverMode.Later))
+  //   return;
+
+  // // If gBitmaskEncryptionState is true that means that we know the public key
+  // // of all the recipients (see updateEncryptionStatus) and therefore we
+  // // manually add the encryption headers so that when we later call msg_status
+  // // from Bitmask, Thunderbird will know that the message was sent as
+  // // encrypted. This however does not work for older messages; see
+  // // https://0xacab.org/leap/bitmask-dev/issues/9202
+  // if (gBitmaskEncryptionState === true) {
+  //   gMsgCompose.compFields.setHeader("X-Leap-Encryption", "decrypted");
+  //   gMsgCompose.compFields.setHeader("X-Leap-Signature", "valid");
+  // }
+}
+
 // From addressingWidgetOverlay.js; we use this to call the function to update
 // the status of the encryption keys for the various "To" fields.  This is for
 // the case where the user presses "Return" or "Tab" and Thunderbird inserts a
@@ -62,6 +87,8 @@ var checkToField = {
           toField.getElementsByTagName("image")[0].setAttribute("src",
             "chrome://bitmask/skin/lock.png");
         }).catch(function(error) {
+          // We detected a missing public key; message will be unencrypted.
+          gBitmaskEncryptionState = false;
           toField.getElementsByTagName("image")[0].setAttribute("src",
             "chrome://bitmask/skin/unlock.png");
         });
@@ -76,3 +103,5 @@ var checkToField = {
 window.addEventListener("compose-window-init", function(event) {
   gMsgCompose.RegisterStateListener(composeStateListener);
 }, true);
+
+window.addEventListener("compose-send-message", insertEncryptionHeaders, true);
index eaf9434..59a95a3 100644 (file)
@@ -1,2 +1,4 @@
 bitmaskStatusOn=bitmask is %S
 bitmaskStatusOff=bitmask is not running
+
+bitmaskMsgEncrypted=Bitmask Encrypted Message
index 3bf6846..056d429 100644 (file)
@@ -8,3 +8,8 @@
   font-weight: bold;
 }
 
+.bitmaskNotificationBar {
+  color: black;
+  font-weight:bold;
+  background-color: #add8e6;
+}