Bug 1536104 - OTR: Allow the user to disable logging of encrypted conversations. r=florian
authorKai Engert <kaie@kuix.de>
Tue, 28 May 2019 17:07:40 +0200
changeset 35886 809b8d802ea7791542957699f82a88a7fc45c29d
parent 35885 e5d177f7e623430192c9fc87db123171e1d755fd
child 35887 ef63fe1ce237872810ca5209db1a1f5d55cb6ea7
push id392
push userclokep@gmail.com
push dateMon, 02 Sep 2019 20:17:19 +0000
reviewersflorian
bugs1536104
Bug 1536104 - OTR: Allow the user to disable logging of encrypted conversations. r=florian Differential Revision: https://phabricator.services.mozilla.com/D32840
chat/components/public/imIConversationsService.idl
chat/components/src/imConversations.js
chat/components/src/logger.js
chat/content/otr/am-im-otr.ftl
chat/modules/OTR.jsm
mail/app/profile/all-thunderbird.js
mail/components/im/content/am-im.js
mail/components/im/content/am-im.xul
mail/components/im/imIncomingServer.js
--- a/chat/components/public/imIConversationsService.idl
+++ b/chat/components/public/imIConversationsService.idl
@@ -96,9 +96,13 @@ interface imIOutgoingMessage: nsISupport
 interface imIMessage: prplIMessage {
            attribute boolean cancelled;
            // Holds the sender color for Chats.
            // Empty string by default, it is set by the conversation binding.
            attribute AUTF8String color;
 
            // What eventually gets shown to the user.
            attribute AUTF8String displayMessage;
+
+           // The related incoming or outgoing message is transmitted
+           // with encryption.
+           attribute boolean encrypted;
 };
--- a/chat/components/src/imConversations.js
+++ b/chat/components/src/imConversations.js
@@ -48,16 +48,17 @@ OutgoingMessage.prototype = {
 function imMessage(aPrplMessage) {
   this.prplMessage = aPrplMessage;
 }
 imMessage.prototype = {
   __proto__: ClassInfo(["imIMessage", "prplIMessage"], "IM Message"),
   cancelled: false,
   color: "",
   _displayMessage: null,
+  encrypted: false,
 
   get displayMessage() {
     // Explicitly test for null so that blank messages don't fall back to
     // the original. Especially problematic in encryption extensions like OTR.
     return this._displayMessage !== null ?
       this._displayMessage : this.prplMessage.originalMessage;
   },
   set displayMessage(aMsg) { this._displayMessage = aMsg; },
--- a/chat/components/src/logger.js
+++ b/chat/components/src/logger.js
@@ -898,17 +898,24 @@ Logger.prototype = {
       Services.obs.removeObserver(this, "final-ui-startup");
       ["new-text", "conversation-closed", "conversation-left-chat",
        "account-connected", "account-disconnected",
        "account-buddy-status-changed"].forEach(function(aEvent) {
         Services.obs.addObserver(this, aEvent);
       }, this);
       break;
     case "new-text":
-      if (!aSubject.noLog) {
+      let excludeBecauseEncrypted = false;
+      if (aSubject.encrypted) {
+        excludeBecauseEncrypted = !Services.prefs.getBoolPref(
+          "messenger.account." + aSubject.conversation.account.id +
+          ".options.otrAllowMsgLog",
+          Services.prefs.getBoolPref("chat.otr.default.allowMsgLog"));
+      }
+      if (!aSubject.noLog && !excludeBecauseEncrypted) {
         let log = getLogWriter(aSubject.conversation);
         log.logMessage(aSubject);
       }
       break;
     case "conversation-closed":
     case "conversation-left-chat":
       closeLogWriter(aSubject);
       break;
--- a/chat/content/otr/am-im-otr.ftl
+++ b/chat/content/otr/am-im-otr.ftl
@@ -8,14 +8,17 @@ account-otr-label = Off-the-Record Messa
 account-otr-description = { -brand-short-name } supports end-to-end encryption of one-to-one conversations to prevent third parties from eavesdropping on a conversation. End-to-end encryption is available when your conversation partner also uses software that supports OTR.
 otr-encryption-title = Verified Encryption
 otr-encryption-caption = To enable others to verify your identity in OTR chats, share your own OTR fingerprint using an outside (out-of-band) communication channel.
 otr-fingerprint-label = Your Fingerprint:
 view-fingerprint-button =
     .label = Manage Fingerprints Of Contacts
     .accesskey = F
 otr-settings-title = OTR Settings
+otr-log =
+    .label = Messages that were transmitted with OTR encryption are included in conversation logs
 otr-requireEncryption =
     .label = Require end-to-end encryption for one-to-one conversations
 otr-verifyNudge =
     .label = Always remind me to verify an unverified contact
 
 otr-notYetAvailable = not yet available
+
--- a/chat/modules/OTR.jsm
+++ b/chat/modules/OTR.jsm
@@ -503,18 +503,18 @@ var OTR = {
 
   getAccountPref(prefName, accountId, defaultVal) {
     return Services.prefs.getBoolPref(
       "messenger.account." + accountId + ".options." + prefName,
       defaultVal);
   },
 
   sendQueryMsg(conv) {
-    let req = this.getAccountPref("otrRequireEncryption",
-      conv.account.id, OTR.defaultOtrRequireEncryption());
+    let req = this.getAccountPref("otrRequireEncryption", conv.account.id,
+      Services.prefs.getBoolPref("chat.otr.default.requireEncryption"));
     let query = OTRLib.otrl_proto_default_query_msg(
       conv.account.normalizedName,
       req ?
         OTRLib.OTRL_POLICY_ALWAYS : OTRLib.OTRL_POLICY_OPPORTUNISTIC
     );
     if (query.isNull()) {
       Cu.reportError(new Error("Sending query message failed."));
       return;
@@ -552,24 +552,16 @@ var OTR = {
         break;
       case OTRLib.messageState.OTRL_MSGSTATE_FINISHED:
         level = this.trustState.TRUST_FINISHED;
         break;
     }
     return level;
   },
 
-  defaultOtrRequireEncryption() {
-    return false;
-  },
-
-  defaultOtrVerifyNudge() {
-    return true;
-  },
-
   getPrefBranchFromWrappedContext(wContext) {
     for (let acc of Services.accounts.getAccounts()) {
       if (wContext.account == acc.normalizedName &&
           wContext.protocol == acc.protocol.normalizedName) {
         return acc.prefBranch;
       }
     }
     return null;
@@ -582,17 +574,17 @@ var OTR = {
    */
   policy_cb(opdata, context) {
     let wContext = new Context(context);
     let pb = OTR.getPrefBranchFromWrappedContext(wContext);
     if (!pb) {
       return new ctypes.unsigned_int(0);
     }
     let prefRequire = pb.getBoolPref("options.otrRequireEncryption",
-      OTR.defaultOtrRequireEncryption());
+      Services.prefs.getBoolPref("chat.otr.default.requireEncryption"));
     return prefRequire ? OTRLib.OTRL_POLICY_ALWAYS
                        : OTRLib.OTRL_POLICY_OPPORTUNISTIC;
   },
 
   /**
    * Create a private key for the given accountname/protocol if desired.
    */
   create_privkey_cb(opdata, accountname, protocol) {
@@ -645,21 +637,21 @@ var OTR = {
       if (CLib.memcmp(fingerprint, fp.contents.fingerprint, new ctypes.size_t(20))) {
         seen = true;
         break;
       }
       fp = fp.contents.next;
     }
 
     let wContext = new Context(context);
-    let prefNudge = OTR.defaultOtrVerifyNudge();
+    let defaultNudge = Services.prefs.getBoolPref("chat.otr.default.verifyNudge");
+    let prefNudge = defaultNudge;
     let pb = OTR.getPrefBranchFromWrappedContext(wContext);
     if (pb) {
-      prefNudge = pb.getBoolPref("options.otrVerifyNudge",
-        OTR.defaultOtrVerifyNudge());
+      prefNudge = pb.getBoolPref("options.otrVerifyNudge", defaultNudge);
     }
 
     // Only nudge on new fingerprint, as opposed to always.
     if (!prefNudge)
       this.notifyObservers(wContext, "otr:unverified",
         (seen ? "seen" : "unseen"));
   },
 
@@ -670,21 +662,21 @@ var OTR = {
     this.writeFingerprints();
   },
 
   /**
    * A ConnContext has entered a secure state.
    */
   gone_secure_cb(opdata, context) {
     let wContext = new Context(context);
-    let prefNudge = OTR.defaultOtrVerifyNudge();
+    let defaultNudge = Services.prefs.getBoolPref("chat.otr.default.verifyNudge");
+    let prefNudge = defaultNudge;
     let pb = OTR.getPrefBranchFromWrappedContext(wContext);
     if (pb) {
-      prefNudge = pb.getBoolPref("options.otrVerifyNudge",
-        OTR.defaultOtrVerifyNudge());
+      prefNudge = pb.getBoolPref("options.otrVerifyNudge", defaultNudge);
     }
     let strid = "context-gone_secure_" + (wContext.trust ? "private" : "unverified");
     this.notifyObservers(wContext, "otr:msg-state");
     this.sendAlert(wContext, _strArgs(strid, {name: wContext.username}));
     if (prefNudge && !wContext.trust)
       this.notifyObservers(wContext, "otr:unverified", "unseen");
   },
 
@@ -1111,16 +1103,24 @@ var OTR = {
   onReceive(im) {
     if (im.cancelled || im.system)
       return;
 
     let conv = im.conversation;
     if (conv.isChat)
       return;
 
+    // After outgoing messages have been handled in onSend,
+    // they are again passed back to us, here in onReceive.
+    // This is our chance to prevent both outgoing and incoming OTR
+    // messages from being logged here.
+    if (im.originalMessage.startsWith("?OTR")) {
+      im.encrypted = true;
+    }
+
     if (im.outgoing) {
       this.log("outgoing message to display: " + im.displayMessage);
       this.pluckMsg(im);
       return;
     }
 
     let newMessage = new ctypes.char.ptr();
     let tlvs = new OTRLib.OtrlTLV.ptr();
--- a/mail/app/profile/all-thunderbird.js
+++ b/mail/app/profile/all-thunderbird.js
@@ -710,16 +710,20 @@ pref("mail.chat.show_desktop_notificatio
 pref("mail.chat.notification_info", 0);
 pref("mail.chat.play_sound", true);
 // 0 == default system sound, 1 == user specified wav
 pref("mail.chat.play_sound.type", 0);
 // if sound is user specified, this needs to be a file url
 pref("mail.chat.play_sound.url", "");
 // Enable/Disable support for OTR chat encryption.
 pref("chat.otr.enable", false);
+// Default values for chat account prefs.
+pref("chat.otr.default.requireEncryption", false);
+pref("chat.otr.default.verifyNudge", true);
+pref("chat.otr.default.allowMsgLog", true);
 
 // BigFiles
 pref("mail.cloud_files.enabled", true);
 pref("mail.cloud_files.inserted_urls.footer.link", "https://www.thunderbird.net");
 pref("mail.cloud_files.learn_more_url", "https://support.thunderbird.net/kb/filelink-large-attachments");
 
 // Ignore threads
 pref("mail.ignore_thread.learn_more_url", "https://support.thunderbird.net/kb/ignore-threads");
--- a/mail/components/im/content/am-im.js
+++ b/mail/components/im/content/am-im.js
@@ -54,16 +54,17 @@ var account = {
         password.removeAttribute("wsm_persist");
       }
     }
 
     document.getElementById("server.alias").value = this.account.alias;
 
     if (OTRUI.enabled) {
       document.getElementById("imTabOTR").hidden = false;
+      document.getElementById("server.otrAllowMsgLog").value = this.account.otrAllowMsgLog;
       document.getElementById("server.otrVerifyNudge").value = this.account.otrVerifyNudge;
       document.getElementById("server.otrRequireEncryption").value = this.account.otrRequireEncryption;
 
       let fpa = this.account.normalizedName;
       let fpp = this.account.protocol.normalizedName;
       let fp = OTR.privateKeyFingerprint(fpa, fpp);
       if (!fp) {
         fp = await document.l10n.formatValue("otr-notYetAvailable");
@@ -124,17 +125,9 @@ var account = {
       advanced.hidden = true;
     }
   },
 
   viewFingerprintKeys() {
     window.openDialog("chrome://chat/content/otr-finger.xul", "",
                       "chrome,modal,titlebar,centerscreen", this.account);
   },
-
-  updateRequireEncryption() {
-    console.log("require");
-  },
-
-  updateVerifyNudge() {
-    console.log("verify");
-  },
 };
--- a/mail/components/im/content/am-im.xul
+++ b/mail/components/im/content/am-im.xul
@@ -79,28 +79,33 @@
         <tabpanel orient="vertical">
           <label class="header" data-l10n-id="account-otr-label" />
           <description data-l10n-id="account-otr-description" />
 
           <separator/>
 
           <vbox>
             <label class="header" data-l10n-id="otr-settings-title" />
+            <checkbox id="server.otrAllowMsgLog"
+                      data-l10n-id="otr-log"
+                      crop="end"
+                      wsm_persist="true"
+                      preftype="bool"
+                      genericattr="true"
+                      />
             <checkbox id="server.otrRequireEncryption"
                       data-l10n-id="otr-requireEncryption"
                       crop="end"
-                      oncommand="account.updateRequireEncryption();"
                       wsm_persist="true"
                       preftype="bool"
                       genericattr="true"
                       />
             <checkbox id="server.otrVerifyNudge"
                       data-l10n-id="otr-verifyNudge"
                       crop="end"
-                      oncommand="account.updateVerifyNudge();"
                       wsm_persist="true"
                       preftype="bool"
                       genericattr="true"
                       />
           </vbox>
 
           <separator/>
 
--- a/mail/components/im/imIncomingServer.js
+++ b/mail/components/im/imIncomingServer.js
@@ -161,20 +161,23 @@ imIncomingServer.prototype = {
       return Services.prefs.getIntPref(prefName);
     } catch (x) {
       return this._getDefault(aPrefName);
     }
   },
   _defaultOptionValues: null,
   _getDefault(aPrefName) {
     if (aPrefName == "otrVerifyNudge") {
-      return true;
+      return Services.prefs.getBoolPref("chat.otr.default.verifyNudge");
     }
     if (aPrefName == "otrRequireEncryption") {
-      return false;
+      return Services.prefs.getBoolPref("chat.otr.default.requireEncryption");
+    }
+    if (aPrefName == "otrAllowMsgLog") {
+      return Services.prefs.getBoolPref("chat.otr.default.allowMsgLog");
     }
     if (this._defaultOptionValues)
       return this._defaultOptionValues[aPrefName];
 
 
     this._defaultOptionValues = {};
     let options = this.imAccount.protocol.getOptions();
     while (options.hasMoreElements()) {