Bug 1562158 - Remove xpidl [array] use from nsIMsgHeaderParser. r=jorgk
authorBen Campbell <benc@thunderbird.net>
Mon, 07 Oct 2019 10:34:11 +0200
changeset 37091 471b8c1ca0f42fcf72ce060549f39c4b72ed5986
parent 37090 a9df26051fec724a5abb232f47e2d98cabca7a2a
child 37092 bb1bd474fda9e9c32990f9e86b28a36abb67e66a
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewersjorgk
bugs1562158
Bug 1562158 - Remove xpidl [array] use from nsIMsgHeaderParser. r=jorgk
mail/base/content/msgHdrView.js
mail/components/compose/content/MsgComposeCommands.js
mail/components/compose/content/addressingWidgetOverlay.js
mailnews/compose/src/nsMsgCompUtils.cpp
mailnews/mime/public/nsIMsgHeaderParser.idl
mailnews/mime/src/MimeHeaderParser.cpp
mailnews/mime/src/mimeJSComponents.js
mailnews/mime/test/unit/test_nsIMsgHeaderParser4.js
suite/mailnews/components/compose/content/MsgComposeCommands.js
suite/mailnews/components/compose/content/addressingWidgetOverlay.js
suite/mailnews/content/mailContextMenus.js
--- a/mail/base/content/msgHdrView.js
+++ b/mail/base/content/msgHdrView.js
@@ -1718,21 +1718,20 @@ function SendMailToNode(addressNode, aEv
   ].createInstance(Ci.nsIMsgCompFields);
   let params = Cc[
     "@mozilla.org/messengercompose/composeparams;1"
   ].createInstance(Ci.nsIMsgComposeParams);
 
   fields.newsgroups = addressNode.getAttribute("newsgroup");
   if (addressNode.hasAttribute("fullAddress")) {
     let addresses = MailServices.headerParser.makeFromDisplayAddress(
-      addressNode.getAttribute("fullAddress"),
-      {}
+      addressNode.getAttribute("fullAddress")
     );
     if (addresses.length > 0) {
-      fields.to = MailServices.headerParser.makeMimeHeader(addresses, 1);
+      fields.to = MailServices.headerParser.makeMimeHeader([addresses[0]]);
     }
   }
 
   params.type = Ci.nsIMsgCompType.New;
 
   // If aEvent is passed, check if Shift key was pressed for composition in
   // non-default format (HTML vs. plaintext).
   params.format =
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -3529,20 +3529,17 @@ function DoSpellCheckBeforeSend() {
  */
 function GenericSendMessage(msgType) {
   var msgCompFields = gMsgCompose.compFields;
 
   Recipients2CompFields(msgCompFields);
   let addresses = MailServices.headerParser.makeFromDisplayAddress(
     GetMsgIdentityElement().value
   );
-  msgCompFields.from = MailServices.headerParser.makeMimeHeader(
-    addresses,
-    addresses.length
-  );
+  msgCompFields.from = MailServices.headerParser.makeMimeHeader(addresses);
   var subject = GetMsgSubjectElement().value;
   msgCompFields.subject = subject;
   Attachments2CompFields(msgCompFields);
   // Some other msgCompFields have already been updated instantly in their respective
   // toggle functions, e.g. ToggleReturnReceipt(), ToggleDSN(),  ToggleAttachVCard(),
   // and toggleAttachmentReminder().
 
   let sending =
--- a/mail/components/compose/content/addressingWidgetOverlay.js
+++ b/mail/components/compose/content/addressingWidgetOverlay.js
@@ -128,17 +128,17 @@ function Recipients2CompFields(msgCompFi
       switch (recipientType) {
         case "addr_to":
         case "addr_cc":
         case "addr_bcc":
         case "addr_reply":
           try {
             let headerParser = MailServices.headerParser;
             recipient = headerParser
-              .makeFromDisplayAddress(fieldValue, {})
+              .makeFromDisplayAddress(fieldValue)
               .map(fullValue =>
                 headerParser.makeMimeAddress(fullValue.name, fullValue.email)
               )
               .join(", ");
           } catch (ex) {
             recipient = fieldValue;
           }
           break;
--- a/mailnews/compose/src/nsMsgCompUtils.cpp
+++ b/mailnews/compose/src/nsMsgCompUtils.cpp
@@ -366,17 +366,18 @@ nsresult mime_generate_headers(nsIMsgCom
           if (NS_SUCCEEDED(rv)) {
             nsString undisclosedRecipients;
             rv = composeStringBundle->GetStringFromName("undisclosedRecipients",
                                                         undisclosedRecipients);
             if (NS_SUCCEEDED(rv) && !undisclosedRecipients.IsEmpty()) {
               nsCOMPtr<nsIMsgHeaderParser> headerParser(
                   mozilla::services::GetHeaderParser());
               nsCOMPtr<msgIAddressObject> group;
-              headerParser->MakeGroupObject(undisclosedRecipients, nullptr, 0,
+              nsTArray<RefPtr<msgIAddressObject>> noRecipients;
+              headerParser->MakeGroupObject(undisclosedRecipients, noRecipients,
                                             getter_AddRefs(group));
               recipients.AppendElement(group);
               finalHeaders->SetAddressingHeader("To", recipients);
             }
           }
         }
       }
     }
--- a/mailnews/mime/public/nsIMsgHeaderParser.idl
+++ b/mailnews/mime/public/nsIMsgHeaderParser.idl
@@ -84,68 +84,56 @@ interface nsIMsgHeaderParser : nsISuppor
    * passed into nsIMimeConverter.
    *
    * @param aEncodedHeader  The RFC 2047-encoded header to parse.
    * @param aHeaderCharset  The charset to assume for raw octets.
    * @param aPreserveGroups If false (the default), the result is a flat array
    *                        of mailbox objects, containing no group objects.
    * @return                An array corresponding to the header description.
    */
-  void parseEncodedHeader(in ACString aEncodedHeader,
+  Array<msgIAddressObject> parseEncodedHeader(in ACString aEncodedHeader,
                           [optional] in string aHeaderCharset,
-                          [optional] in bool aPreserveGroups,
-                          [optional] out unsigned long length,
-                          [retval, array, size_is(length)]
-                          out msgIAddressObject addresses);
+                          [optional] in bool aPreserveGroups);
 
   /**
    * Parse an address-based header that has not yet been 2047-decoded and does not
    * contain raw octets but instead wide (UTF-16) characters.
    *
    * @param aEncodedHeader  The RFC 2047-encoded header to parse.
    * @return                An array corresponding to the header description.
    */
-  void parseEncodedHeaderW(in AString aEncodedHeader,
-                           [optional] out unsigned long length,
-                           [retval, array, size_is(length)]
-                           out msgIAddressObject addresses);
+  Array<msgIAddressObject> parseEncodedHeaderW(in AString aEncodedHeader);
 
 /**
    * Parse an address-based header that has been 2047-decoded.
    *
    * The result of this method is an array of objects described in the above
    * comment. Note that the header is a binary string that will be decoded as if
    * passed into nsIMimeConverter.
    *
    * @param aDecodedHeader  The non-RFC 2047-encoded header to parse.
    * @param aPreserveGroups If false (the default), the result is a flat array
    *                        of mailbox objects, containing no group objects.
    * @return                An array corresponding to the header description.
    */
-  void parseDecodedHeader(in AString aDecodedHeader,
-                          [optional] in bool aPreserveGroups,
-                          [optional] out unsigned long length,
-                          [retval, array, size_is(length)]
-                          out msgIAddressObject addresses);
+   Array<msgIAddressObject> parseDecodedHeader(in AString aDecodedHeader,
+                          [optional] in bool aPreserveGroups);
 
   /**
    * Given an array of addresses, make a MIME header suitable for emission.
    *
    * The return value of this method is not directly suitable for use in a MIME
    * message but rather needs to be passed through nsIMimeConverter first to
    * have RFC-2047 encoding applied and the resulting output wrapped to adhere
    * to maximum line length formats.
    *
    * @param aAddresses An array corresponding to the header description.
-   * @param aLength    The length of said array of addresses.
    * @return           A string that is suitable for writing in a MIME message.
    */
-  AString makeMimeHeader([array, size_is(aLength)]
-                         in msgIAddressObject aAddresses,
-                         in unsigned long aLength);
+  AString makeMimeHeader(in Array<msgIAddressObject> aAddresses);
 
   /**
    * Return the first address in the list in a format suitable for display.
    *
    * This is largely a convenience method for handling From headers (or similar),
    * which are expected to only have a single element in them. It is exactly
    * equivalent to saying (parseDecodedHeader(decodedHeader))[0].toString().
    *
@@ -173,32 +161,29 @@ interface nsIMsgHeaderParser : nsISuppor
   AUTF8String removeDuplicateAddresses(in AUTF8String aAddrs,
                                        [optional] in AUTF8String aOtherAddrs);
 
   /// Return a structured mailbox object having the given name and email.
   msgIAddressObject makeMailboxObject(in AString aName, in AString aEmail);
 
   /// Return a structured group object having the given name and members.
   msgIAddressObject makeGroupObject(in AString aName,
-    [array, size_is(aLength)] in msgIAddressObject aMembers,
-    in unsigned long aLength);
+                                    in Array<msgIAddressObject> aMembers);
 
   /**
    * Return an array of structured mailbox objects for the given display name
    * string.
    *
    * The string is expected to be a comma-separated sequence of strings that
    * would be produced by msgIAddressObject::toString(). For example, the string
    * "Bond, James <agent007@mi5.invalid>" would produce one address object,
    * while the string "webmaster@nowhere.invalid, child@nowhere.invalid" would
    * produce two address objects.
    */
-  void makeFromDisplayAddress(in AString aDisplayAddresses,
-                              [optional] out unsigned long count,
-                              [retval, array, size_is(count)] out msgIAddressObject addresses);
+  Array<msgIAddressObject> makeFromDisplayAddress(in AString aDisplayAddresses);
 
   /**
    * Given a string which contains a list of Header addresses, returns a
    * comma-separated list of just the `mailbox' portions.
    *
    * @param aLine          The header line to parse.
    * @return               A comma-separated list of just the mailbox parts
    *                       of the email-addresses.
--- a/mailnews/mime/src/MimeHeaderParser.cpp
+++ b/mailnews/mime/src/MimeHeaderParser.cpp
@@ -33,18 +33,19 @@ void MakeMimeAddress(const nsACString &a
 }
 
 void MakeMimeAddress(const nsAString &aName, const nsAString &aEmail,
                      nsAString &full) {
   nsCOMPtr<nsIMsgHeaderParser> headerParser(services::GetHeaderParser());
 
   nsCOMPtr<msgIAddressObject> address;
   headerParser->MakeMailboxObject(aName, aEmail, getter_AddRefs(address));
-  msgIAddressObject *obj = address;
-  headerParser->MakeMimeHeader(&obj, 1, full);
+  nsTArray<RefPtr<msgIAddressObject>> addresses;
+  addresses.AppendElement(address);
+  headerParser->MakeMimeHeader(addresses, full);
 }
 
 void MakeDisplayAddress(const nsAString &aName, const nsAString &aEmail,
                         nsAString &full) {
   nsCOMPtr<nsIMsgHeaderParser> headerParser(services::GetHeaderParser());
 
   nsCOMPtr<msgIAddressObject> object;
   headerParser->MakeMailboxObject(aName, aEmail, getter_AddRefs(object));
@@ -65,68 +66,64 @@ void RemoveDuplicateAddresses(const nsAC
 
 nsCOMArray<msgIAddressObject> DecodedHeader(const nsAString &aHeader) {
   nsCOMArray<msgIAddressObject> retval;
   if (aHeader.IsEmpty()) {
     return retval;
   }
   nsCOMPtr<nsIMsgHeaderParser> headerParser(services::GetHeaderParser());
   NS_ENSURE_TRUE(headerParser, retval);
-  msgIAddressObject **addresses = nullptr;
-  uint32_t length;
-  nsresult rv =
-      headerParser->ParseDecodedHeader(aHeader, false, &length, &addresses);
+  nsTArray<RefPtr<msgIAddressObject>> addresses;
+  nsresult rv = headerParser->ParseDecodedHeader(aHeader, false, addresses);
   MOZ_ASSERT(NS_SUCCEEDED(rv), "Javascript jsmime returned an error!");
-  if (NS_SUCCEEDED(rv) && length > 0 && addresses) {
-    // retval.Adopt(addresses, length);
-    retval.Clear();
-    retval.AppendElements(addresses, length);
-    free(addresses);
+  if (NS_SUCCEEDED(rv) && addresses.Length() > 0) {
+    retval.SetCapacity(addresses.Length());
+    for (auto &addr : addresses) {
+      retval.AppendElement(addr);
+    }
   }
   return retval;
 }
 
 nsCOMArray<msgIAddressObject> EncodedHeader(const nsACString &aHeader,
                                             const char *aCharset) {
   nsCOMArray<msgIAddressObject> retval;
   if (aHeader.IsEmpty()) {
     return retval;
   }
   nsCOMPtr<nsIMsgHeaderParser> headerParser(services::GetHeaderParser());
   NS_ENSURE_TRUE(headerParser, retval);
-  msgIAddressObject **addresses = nullptr;
-  uint32_t length;
-  nsresult rv = headerParser->ParseEncodedHeader(aHeader, aCharset, false,
-                                                 &length, &addresses);
+  nsTArray<RefPtr<msgIAddressObject>> addresses;
+  nsresult rv =
+      headerParser->ParseEncodedHeader(aHeader, aCharset, false, addresses);
   MOZ_ASSERT(NS_SUCCEEDED(rv), "This should never fail!");
-  if (NS_SUCCEEDED(rv) && length > 0 && addresses) {
-    // retval.Adopt(addresses, length);
-    retval.Clear();
-    retval.AppendElements(addresses, length);
-    free(addresses);
+  if (NS_SUCCEEDED(rv) && addresses.Length() > 0) {
+    retval.SetCapacity(addresses.Length());
+    for (auto &addr : addresses) {
+      retval.AppendElement(addr);
+    }
   }
   return retval;
 }
 
 nsCOMArray<msgIAddressObject> EncodedHeaderW(const nsAString &aHeader) {
   nsCOMArray<msgIAddressObject> retval;
   if (aHeader.IsEmpty()) {
     return retval;
   }
   nsCOMPtr<nsIMsgHeaderParser> headerParser(services::GetHeaderParser());
   NS_ENSURE_TRUE(headerParser, retval);
-  msgIAddressObject **addresses = nullptr;
-  uint32_t length;
-  nsresult rv = headerParser->ParseEncodedHeaderW(aHeader, &length, &addresses);
+  nsTArray<RefPtr<msgIAddressObject>> addresses;
+  nsresult rv = headerParser->ParseEncodedHeaderW(aHeader, addresses);
   MOZ_ASSERT(NS_SUCCEEDED(rv), "This should never fail!");
-  if (NS_SUCCEEDED(rv) && length > 0 && addresses) {
-    // retval.Adopt(addresses, length);
-    retval.Clear();
-    retval.AppendElements(addresses, length);
-    free(addresses);
+  if (NS_SUCCEEDED(rv) && addresses.Length() > 0) {
+    retval.SetCapacity(addresses.Length());
+    for (auto &addr : addresses) {
+      retval.AppendElement(addr);
+    }
   }
   return retval;
 }
 
 void ExtractAllAddresses(const nsCOMArray<msgIAddressObject> &aHeader,
                          nsTArray<nsString> &names,
                          nsTArray<nsString> &emails) {
   uint32_t count = aHeader.Length();
--- a/mailnews/mime/src/mimeJSComponents.js
+++ b/mailnews/mime/src/mimeJSComponents.js
@@ -277,43 +277,43 @@ function fixArray(addresses, preserveGro
   return outputArray;
 }
 
 function MimeAddressParser() {}
 MimeAddressParser.prototype = {
   classID: Components.ID("96bd8769-2d0e-4440-963d-22b97fb3ba77"),
   QueryInterface: ChromeUtils.generateQI([Ci.nsIMsgHeaderParser]),
 
-  parseEncodedHeader(aHeader, aCharset, aPreserveGroups, count) {
+  parseEncodedHeader(aHeader, aCharset, aPreserveGroups) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(
       aHeader,
       MimeParser.HEADER_ADDRESS | MimeParser.HEADER_OPTION_ALL_I18N,
       aCharset
     );
-    return fixArray(value, aPreserveGroups, count);
+    return fixArray(value, aPreserveGroups);
   },
-  parseEncodedHeaderW(aHeader, count) {
+  parseEncodedHeaderW(aHeader) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(
       aHeader,
       MimeParser.HEADER_ADDRESS |
         MimeParser.HEADER_OPTION_DECODE_2231 |
         MimeParser.HEADER_OPTION_DECODE_2047,
       undefined
     );
-    return fixArray(value, false, count);
+    return fixArray(value, false);
   },
-  parseDecodedHeader(aHeader, aPreserveGroups, count) {
+  parseDecodedHeader(aHeader, aPreserveGroups) {
     aHeader = aHeader || "";
     let value = MimeParser.parseHeaderField(aHeader, MimeParser.HEADER_ADDRESS);
-    return fixArray(value, aPreserveGroups, count);
+    return fixArray(value, aPreserveGroups);
   },
 
-  makeMimeHeader(addresses, length) {
+  makeMimeHeader(addresses) {
     addresses = fixXpconnectAddresses(addresses);
     // Don't output any necessary continuations, so make line length as large as
     // possible first.
     let options = {
       softMargin: 900,
       hardMargin: 900,
       useASCII: false, // We don't want RFC 2047 encoding here.
     };
@@ -382,17 +382,17 @@ MimeAddressParser.prototype = {
 
   makeGroupObject(aName, aMembers) {
     let object = Object.create(EmailGroup);
     object.name = aName;
     object.group = aMembers;
     return object;
   },
 
-  makeFromDisplayAddress(aDisplay, count) {
+  makeFromDisplayAddress(aDisplay) {
     if (aDisplay.includes(";") && !/:.*;/.test(aDisplay)) {
       // Using semicolons as mailbox separators in against the standard, but
       // used in the wild by some clients.
       // Looks like this isn't using group syntax, so let's assume it's a
       // non-standards compliant input string, and fix it.
       // Replace semicolons with commas, unless the semicolon is inside a quote.
       // The regexp uses tricky lookahead, see bug 1059988 comment #70 for details.
       aDisplay = aDisplay.replace(/;(?=(?:(?:[^"]*"){2})*[^"]*$)/g, ",");
@@ -419,19 +419,16 @@ MimeAddressParser.prototype = {
         addr = aDisplay;
         aDisplay = "";
       }
       addr = addr.trimLeft();
       if (addr) {
         output.push(this._makeSingleAddress(addr));
       }
     }
-    if (count) {
-      count.value = output.length;
-    }
     return output;
   },
 
   // Construct a single email address from a name <local@domain> token.
   _makeSingleAddress(aDisplayName) {
     if (aDisplayName.includes("<")) {
       let lbracket = aDisplayName.lastIndexOf("<");
       let rbracket = aDisplayName.lastIndexOf(">");
--- a/mailnews/mime/test/unit/test_nsIMsgHeaderParser4.js
+++ b/mailnews/mime/test/unit/test_nsIMsgHeaderParser4.js
@@ -108,20 +108,18 @@ function run_test() {
         ["Marge", "marge@example.com"],
       ],
     },
   ];
 
   // Test -  strings
 
   for (let i = 0; i < checks.length; ++i) {
-    dump("Test " + i + "\n");
     let addrs = MailServices.headerParser.makeFromDisplayAddress(
-      checks[i].displayString,
-      {}
+      checks[i].displayString
     );
     let checkaddrs = checks[i].addresses;
     Assert.equal(addrs.length, checkaddrs.length);
     for (let j = 0; j < addrs.length; j++) {
       Assert.equal(addrs[j].name, checkaddrs[j][0]);
       Assert.equal(addrs[j].email, checkaddrs[j][1]);
     }
   }
--- a/suite/mailnews/components/compose/content/MsgComposeCommands.js
+++ b/suite/mailnews/components/compose/content/MsgComposeCommands.js
@@ -1598,17 +1598,17 @@ function GenericSendMessage( msgType )
   if (gMsgCompose != null)
   {
     var msgCompFields = gMsgCompose.compFields;
     if (msgCompFields)
     {
       Recipients2CompFields(msgCompFields);
       var address = GetMsgIdentityElement().value;
       address = MailServices.headerParser.makeFromDisplayAddress(address);
-      msgCompFields.from = MailServices.headerParser.makeMimeHeader(address, 1);
+      msgCompFields.from = MailServices.headerParser.makeMimeHeader([address[0]]);
       var subject = GetMsgSubjectElement().value;
       msgCompFields.subject = subject;
       Attachments2CompFields(msgCompFields);
 
       if (msgType == nsIMsgCompDeliverMode.Now ||
           msgType == nsIMsgCompDeliverMode.Later ||
           msgType == nsIMsgCompDeliverMode.Background)
       {
--- a/suite/mailnews/components/compose/content/addressingWidgetOverlay.js
+++ b/suite/mailnews/components/compose/content/addressingWidgetOverlay.js
@@ -113,17 +113,17 @@ function Recipients2CompFields(msgCompFi
         {
           case "addr_to"    :
           case "addr_cc"    :
           case "addr_bcc"   :
           case "addr_reply" :
             try {
               let headerParser = MailServices.headerParser;
               recipient =
-                headerParser.makeFromDisplayAddress(fieldValue, {}).map(fullValue =>
+                headerParser.makeFromDisplayAddress(fieldValue).map(fullValue =>
                   headerParser.makeMimeAddress(fullValue.name, fullValue.email))
               .join(", ");
             } catch (ex) {recipient = fieldValue;}
             break;
         }
 
         switch (recipientType)
         {
--- a/suite/mailnews/content/mailContextMenus.js
+++ b/suite/mailnews/content/mailContextMenus.js
@@ -460,17 +460,17 @@ function SendMailTo(fullAddress, aEvent)
 {
   var fields = Cc["@mozilla.org/messengercompose/composefields;1"]
                  .createInstance(Ci.nsIMsgCompFields);
   var params = Cc["@mozilla.org/messengercompose/composeparams;1"]
                  .createInstance(Ci.nsIMsgComposeParams);
 
   var headerParser = MailServices.headerParser;
   var addresses = headerParser.makeFromDisplayAddress(fullAddress);
-  fields.to = headerParser.makeMimeHeader(addresses, 1);
+  fields.to = headerParser.makeMimeHeader([addresses[0]]);
   params.type = Ci.nsIMsgCompType.New;
 
   // If aEvent is passed, check if Shift key was pressed for composition in
   // non-default format (HTML vs. plaintext).
   params.format = (aEvent && aEvent.shiftKey) ?
     Ci.nsIMsgCompFormat.OppositeOfDefault :
     Ci.nsIMsgCompFormat.Default;