Bug 507541 - Ignore selection when not replying to displayed message. r=aceman
authorJorg K <jorgk@jorgk.com>
Sun, 30 Jul 2017 20:37:18 +0200
changeset 28519 5dcb4353fcec7451997c1ccc1364cf27c001b71c
parent 28518 efffc843dbfae1557386e2fb84991013f07c6954
child 28520 538e19f624671e70877fb3d2dece742398f94329
push id1986
push userclokep@gmail.com
push dateWed, 02 Aug 2017 14:43:31 +0000
treeherdercomm-beta@b51c9adf2c9e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersaceman
bugs507541
Bug 507541 - Ignore selection when not replying to displayed message. r=aceman
mail/base/content/mailCommands.js
mailnews/compose/public/nsIMsgComposeParams.idl
mailnews/compose/src/nsMsgComposeService.cpp
--- a/mail/base/content/mailCommands.js
+++ b/mail/base/content/mailCommands.js
@@ -159,45 +159,68 @@ function GetMsgKeyFromURI(uri) {
   //   ex : mailbox-message://john%2Edoe@pop.isp.invalid/Drafts#123456?fetchCompleteMessage=true
   //   ex : mailbox-message://john%2Edoe@pop.isp.invalid/Drafts#12345
   // We keep only the part after '#' and before an optional '?'.
   // The regexp expects 'key' to be an integer (a serie of digits) : '\d+'.
   let match = /.+#(\d+)/.exec(uri);
   return (match) ? match[1] : null;
 }
 
-// type is a nsIMsgCompType and format is a nsIMsgCompFormat
+/**
+ * Compose a message.
+ *
+ * @param type   nsIMsgCompType    Type of composition (new message, reply, draft, etc.)
+ * @param format nsIMsgCompFormat  Requested format (plain text, html, default)
+ * @param folder nsIMsgFolder      Folder where the original message is stored
+ * @param messageArray             Array of messages to process, often only holding one element.
+ */
 function ComposeMessage(type, format, folder, messageArray)
 {
+  let msgComposeType = Components.interfaces.nsIMsgCompType;
+  let ignoreQuote = false;
+  let msgKey;
   if (messageArray && messageArray.length == 1) {
-    if (GetMsgKeyFromURI(messageArray[0]) != gMessageDisplay.keyForCharsetOverride) {
+    msgKey = GetMsgKeyFromURI(messageArray[0]);
+    if (msgKey != gMessageDisplay.keyForCharsetOverride) {
       msgWindow.charsetOverride = false;
     }
+    if (type == msgComposeType.Reply ||
+        type == msgComposeType.ReplyAll ||
+        type == msgComposeType.ReplyToSender ||
+        type == msgComposeType.ReplyToGroup ||
+        type == msgComposeType.ReplyToSenderAndGroup ||
+        type == msgComposeType.ReplyToList) {
+      let displayKey = ("messageKey" in gMessageDisplay.displayedMessage) ?
+        gMessageDisplay.displayedMessage.messageKey : null;
+      if (msgKey != displayKey) {
+        // Not replying to the displayed message, so remove the selection
+        // in order not to quote from the wrong message.
+        ignoreQuote = true;
+      }
+    }
   }
 
   // Check if the draft is already open in another window. If it is, just focus the window.
-  if (type == Components.interfaces.nsIMsgCompType.Draft && messageArray.length == 1) {
+  if (type == msgComposeType.Draft && messageArray.length == 1) {
     // We'll search this uri in the opened windows.
-    let messageKey = GetMsgKeyFromURI(messageArray[0]);
     let wenum = Services.wm.getEnumerator("");
     while (wenum.hasMoreElements()) {
       let w = wenum.getNext();
       // Check if it is a compose window.
       if (w.document.defaultView.gMsgCompose && w.document.defaultView.gMsgCompose.compFields.draftId) {
         let wKey = GetMsgKeyFromURI(w.document.defaultView.gMsgCompose.compFields.draftId);
-        if (wKey == messageKey) {
+        if (wKey == msgKey) {
           // Found ! just focus it...
           w.focus();
           // ...and nothing to do anymore.
           return;
         }
       }
     }
   }
-  var msgComposeType = Components.interfaces.nsIMsgCompType;
   var identity = null;
   var newsgroup = null;
   var hdr;
 
   // dump("ComposeMessage folder=" + folder + "\n");
   try
   {
     if (folder)
@@ -274,17 +297,20 @@ function ComposeMessage(type, format, fo
         {
           // Do not use the header derived identity for feeds, pass on only a
           // possible server identity from above.
           openComposeWindowForRSSArticle(null, hdr, messageUri, type,
                                          format, identity, msgWindow);
         }
         else
         {
+          // Replies come here.
           let hdrIdentity = getIdentityForHeader(hdr, type);
+          if (ignoreQuote)
+            type += msgComposeType.ReplyIgnoreQuote;
           MailServices.compose.OpenComposeWindow(null, hdr, messageUri, type,
                                                  format, hdrIdentity, msgWindow);
         }
       }
   }
 }
 
 function NewMessageToSelectedAddresses(type, format, identity) {
--- a/mailnews/compose/public/nsIMsgComposeParams.idl
+++ b/mailnews/compose/public/nsIMsgComposeParams.idl
@@ -33,16 +33,22 @@ interface nsIMsgCompType {
      * Will resend the original message keeping the Subject and the body the
      * same, and will set the Reply-To: header to the sender of the original
      * message.  This gets the redirector "out of the loop" because replies
      * to the message will go to the original sender.  This is not the same
      * as the Resent mechanism described in section 3.6.6 of RFC 2822, and
      * so therefore does not use Resent-* headers.
      */
     const long Redirect                 = 14;
+
+    /**
+     * Add this value to a reply type to suppress quoting the current selection
+     * which may not belong to the message being replied to.
+     */
+    const long ReplyIgnoreQuote         = 100;
 };
 
 
 typedef long MSG_ComposeFormat;
 
 [scriptable, uuid(a28325e8-7531-11d3-8f1c-006008948010)]
 interface nsIMsgCompFormat {
     const long Default                  = 0;
--- a/mailnews/compose/src/nsMsgComposeService.cpp
+++ b/mailnews/compose/src/nsMsgComposeService.cpp
@@ -365,16 +365,23 @@ nsMsgComposeService::GetOrigWindowSelect
 }
 
 NS_IMETHODIMP
 nsMsgComposeService::OpenComposeWindow(const char *msgComposeWindowURL, nsIMsgDBHdr *origMsgHdr, const char *originalMsgURI,
   MSG_ComposeType type, MSG_ComposeFormat format, nsIMsgIdentity * aIdentity, nsIMsgWindow *aMsgWindow)
 {
   nsresult rv;
 
+  // Check for any reply type that wants to ignore the quote.
+  bool ignoreQuote = false;
+  if (type >= nsIMsgCompType::ReplyIgnoreQuote) {
+    type -= nsIMsgCompType::ReplyIgnoreQuote;
+    ignoreQuote = true;
+  }
+
   nsCOMPtr<nsIMsgIdentity> identity = aIdentity;
   if (!identity)
     GetDefaultIdentity(getter_AddRefs(identity));
 
   /* Actually, the only way to implement forward inline is to simulate a template message.
      Maybe one day when we will have more time we can change that
   */
   if (type == nsIMsgCompType::ForwardInline || type == nsIMsgCompType::Draft || type == nsIMsgCompType::Template
@@ -398,22 +405,23 @@ nsMsgComposeService::OpenComposeWindow(c
     nsCOMPtr<nsIMsgCompFields> pMsgCompFields (do_CreateInstance(NS_MSGCOMPFIELDS_CONTRACTID, &rv));
     if (NS_SUCCEEDED(rv) && pMsgCompFields)
     {
       pMsgComposeParams->SetType(type);
       pMsgComposeParams->SetFormat(format);
       pMsgComposeParams->SetIdentity(identity);
 
       // When doing a reply (except with a template) see if there's a selection that we should quote
-      if (type == nsIMsgCompType::Reply ||
-          type == nsIMsgCompType::ReplyAll ||
-          type == nsIMsgCompType::ReplyToSender ||
-          type == nsIMsgCompType::ReplyToGroup ||
-          type == nsIMsgCompType::ReplyToSenderAndGroup ||
-          type == nsIMsgCompType::ReplyToList)
+      if (!ignoreQuote &&
+          (type == nsIMsgCompType::Reply ||
+           type == nsIMsgCompType::ReplyAll ||
+           type == nsIMsgCompType::ReplyToSender ||
+           type == nsIMsgCompType::ReplyToGroup ||
+           type == nsIMsgCompType::ReplyToSenderAndGroup ||
+           type == nsIMsgCompType::ReplyToList))
       {
         nsAutoCString selHTML;
         if (NS_SUCCEEDED(GetOrigWindowSelection(type, aMsgWindow, selHTML)))
           pMsgComposeParams->SetHtmlToQuote(selHTML);
       }
 
       if (originalMsgURI && *originalMsgURI)
       {