Bug 1614846 - Remove nsIArray use in nsIMsgAccountManager.getIdentitiesForServer(). r=mkmelin
authorBen Campbell <benc@thunderbird.net>
Thu, 02 Apr 2020 13:39:46 +0300
changeset 38664 c3a2ed94fe276a125838a24edc43b215f90da865
parent 38663 43a129b74441061e812b31cf0b40fa59205f5dee
child 38665 c368a253924a4515cb915d17715a0a154bf685f9
push id400
push userclokep@gmail.com
push dateMon, 04 May 2020 18:56:09 +0000
reviewersmkmelin
bugs1614846
Bug 1614846 - Remove nsIArray use in nsIMsgAccountManager.getIdentitiesForServer(). r=mkmelin
calendar/base/modules/utils/calItipUtils.jsm
mail/base/content/folderDisplay.js
mail/base/modules/MailUtils.jsm
mail/extensions/openpgp/content/modules/filters.jsm
mailnews/base/public/nsIMsgAccountManager.idl
mailnews/base/search/content/searchWidgets.js
mailnews/base/src/nsMsgAccountManager.cpp
mailnews/base/src/nsMsgAccountManager.h
mailnews/base/test/unit/test_accountMgr2.js
mailnews/compose/src/nsMsgCompose.cpp
mailnews/extensions/mdn/src/nsMsgMdnGenerator.cpp
mailnews/imap/src/nsImapMailFolder.cpp
suite/mailnews/content/mailCommands.js
--- a/calendar/base/modules/utils/calItipUtils.jsm
+++ b/calendar/base/modules/utils/calItipUtils.jsm
@@ -2,16 +2,17 @@
  * 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/. */
 
 var { Services } = ChromeUtils.import("resource://gre/modules/Services.jsm");
 var { MailServices } = ChromeUtils.import("resource:///modules/MailServices.jsm");
 var { calendarDeactivator } = ChromeUtils.import(
   "resource:///modules/calendar/calCalendarDeactivator.jsm"
 );
+const { fixIterator } = ChromeUtils.import("resource:///modules/iteratorUtils.jsm");
 
 ChromeUtils.defineModuleGetter(this, "cal", "resource:///modules/calendar/calUtils.jsm");
 
 /*
  * Scheduling and iTIP helper code
  */
 
 // NOTE: This module should not be loaded directly, it is available when
@@ -507,17 +508,20 @@ var calitip = {
       return null;
     }
 
     let identities;
     let actMgr = MailServices.accounts;
     if (aMsgHdr.accountKey) {
       // First, check if the message has an account key. If so, we can use the
       // account identities to find the correct recipient
-      identities = actMgr.getAccount(aMsgHdr.accountKey).identities;
+      // Note: fixIterator here is a stopgap, to be removed (see Bug 1612239).
+      identities = [
+        ...fixIterator(actMgr.getAccount(aMsgHdr.accountKey).identities, Ci.nsIMsgIdentity),
+      ];
     } else if (aMsgHdr.folder) {
       // Without an account key, we have to revert back to using the server
       identities = actMgr.getIdentitiesForServer(aMsgHdr.folder.server);
     }
 
     let emailMap = {};
     if (!identities || identities.length == 0) {
       let identity;
@@ -537,18 +541,17 @@ var calitip = {
         } else {
           // If there are no identities at all, we cannot get a recipient.
           return null;
         }
       }
       emailMap[identity.email.toLowerCase()] = true;
     } else {
       // Build a map of usable email addresses
-      for (let i = 0; i < identities.length; i++) {
-        let identity = identities.queryElementAt(i, Ci.nsIMsgIdentity);
+      for (let identity of identities) {
         emailMap[identity.email.toLowerCase()] = true;
       }
     }
 
     // First check the recipient list
     let toList = MailServices.headerParser.makeFromDisplayAddress(aMsgHdr.recipients || "");
     for (let recipient of toList) {
       if (recipient.email.toLowerCase() in emailMap) {
--- a/mail/base/content/folderDisplay.js
+++ b/mail/base/content/folderDisplay.js
@@ -2272,29 +2272,24 @@ FolderDisplayWidget.prototype = {
         return folderIdentity.archiveEnabled;
       }
 
       if (this.displayedFolder.server) {
         let serverIdentities = MailServices.accounts.getIdentitiesForServer(
           this.displayedFolder.server
         );
 
-        const nsIMsgIdentity = Ci.nsIMsgIdentity;
-        let allEnabled = undefined;
-        for (let identity of fixIterator(serverIdentities, nsIMsgIdentity)) {
-          if (allEnabled === undefined) {
-            allEnabled = identity.archiveEnabled;
-          } else if (identity.archiveEnabled != allEnabled) {
-            allEnabled = undefined;
-            break;
-          }
+        // Do all identities have the same archiveEnabled setting?
+        if (serverIdentities.every(id => id.archiveEnabled)) {
+          return true;
         }
-        if (allEnabled !== undefined) {
-          return allEnabled;
+        if (serverIdentities.every(id => !id.archiveEnabled)) {
+          return false;
         }
+        // If we get here it's a mixture, so have to examine all the messages.
       }
     }
 
     // Either we've selected a small number of messages or we just can't
     // fast-path the result; examine all the messages.
     return this.selectedMessages.every(function(msg) {
       let identity = MailUtils.getIdentityForHeader(msg);
       return Boolean(identity && identity.archiveEnabled);
--- a/mail/base/modules/MailUtils.jsm
+++ b/mail/base/modules/MailUtils.jsm
@@ -458,21 +458,18 @@ var MailUtils = {
         return defaultAccount.defaultIdentity;
       }
     }
 
     return identities[0];
   },
 
   getIdentityForServer(server, optionalHint) {
-    var identities = MailServices.accounts.getIdentitiesForServer(server);
-    return this.getBestIdentity(
-      [...fixIterator(identities, Ci.nsIMsgIdentity)],
-      optionalHint
-    );
+    let identities = MailServices.accounts.getIdentitiesForServer(server);
+    return this.getBestIdentity(identities, optionalHint);
   },
 
   /**
    * Get the identity for the given header.
    * @param hdr nsIMsgHdr message header
    * @param type nsIMsgCompType compose type the identity is used for.
    */
   getIdentityForHeader(hdr, type, hint = "") {
--- a/mail/extensions/openpgp/content/modules/filters.jsm
+++ b/mail/extensions/openpgp/content/modules/filters.jsm
@@ -369,25 +369,19 @@ function shutdownNewMailListener() {
     ].getService(Ci.nsIMsgFolderNotificationService);
     notificationService.removeListener(newMailListener);
     gNewMailListenerInitiated = false;
   }
 }
 
 function getIdentityForSender(senderEmail, msgServer) {
   let identities = MailServices.accounts.getIdentitiesForServer(msgServer);
-
-  for (let i = 0; i < identities.length; i++) {
-    let id = identities.queryElementAt(i, Ci.nsIMsgIdentity);
-    if (id.email.toLowerCase() === senderEmail.toLowerCase()) {
-      return id;
-    }
-  }
-
-  return null;
+  return identities.find(
+    id => id.email.toLowerCase() === senderEmail.toLowerCase()
+  );
 }
 
 var consumerList = [];
 
 function JsmimeEmitter(requireBody) {
   this.requireBody = requireBody;
   this.mimeTree = {
     partNum: "",
--- a/mailnews/base/public/nsIMsgAccountManager.idl
+++ b/mailnews/base/public/nsIMsgAccountManager.idl
@@ -143,17 +143,17 @@ interface nsIMsgAccountManager : nsISupp
    * @return        If found, the nsIMsgAccount representing the account found.
    *                Otherwise returns null.
    */
   nsIMsgAccount FindAccountForServer(in nsIMsgIncomingServer server);
 
   /* given a server, return all identities in accounts that have this server
    * returns an array of nsIMsgIdentity
    */
-  nsIArray getIdentitiesForServer(in nsIMsgIncomingServer server);
+  Array<nsIMsgIdentity> getIdentitiesForServer(in nsIMsgIncomingServer server);
 
   /**
    * given a server, return the first identity in accounts that have this server
    */
   nsIMsgIdentity getFirstIdentityForServer(in nsIMsgIncomingServer server);
 
   /* given an identity, return all servers in accounts that have
    * this identity
--- a/mailnews/base/search/content/searchWidgets.js
+++ b/mailnews/base/search/content/searchWidgets.js
@@ -1385,22 +1385,19 @@
       }
 
       /**
        * Check if there exist any templates in this account.
        * @return {Object[]} - An array of template headers: each has a label and
        *                      a value.
        */
       findTemplates() {
-        let identitiesRaw = MailServices.accounts.getIdentitiesForServer(
+        let identities = MailServices.accounts.getIdentitiesForServer(
           gFilterList.folder.server
         );
-        let identities = Array.from(
-          fixIterator(identitiesRaw, Ci.nsIMsgIdentity)
-        );
         // Typically if this is Local Folders.
         if (identities.length == 0) {
           if (MailServices.accounts.defaultAccount) {
             identities.push(
               MailServices.accounts.defaultAccount.defaultIdentity
             );
           }
         }
--- a/mailnews/base/src/nsMsgAccountManager.cpp
+++ b/mailnews/base/src/nsMsgAccountManager.cpp
@@ -1857,78 +1857,67 @@ nsMsgAccountManager::FindAccountForServe
 }
 
 NS_IMETHODIMP
 nsMsgAccountManager::GetFirstIdentityForServer(nsIMsgIncomingServer *aServer,
                                                nsIMsgIdentity **aIdentity) {
   NS_ENSURE_ARG_POINTER(aServer);
   NS_ENSURE_ARG_POINTER(aIdentity);
 
-  nsCOMPtr<nsIArray> identities;
-  nsresult rv = GetIdentitiesForServer(aServer, getter_AddRefs(identities));
+  nsTArray<RefPtr<nsIMsgIdentity>> identities;
+  nsresult rv = GetIdentitiesForServer(aServer, identities);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // not all servers have identities
   // for example, Local Folders
-  uint32_t numIdentities;
-  rv = identities->GetLength(&numIdentities);
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  if (numIdentities > 0) {
-    nsCOMPtr<nsIMsgIdentity> identity(do_QueryElementAt(identities, 0, &rv));
-    NS_ENSURE_SUCCESS(rv, rv);
-    identity.forget(aIdentity);
-  } else
+  if (identities.IsEmpty()) {
     *aIdentity = nullptr;
+  } else {
+    NS_IF_ADDREF(*aIdentity = identities[0]);
+  }
   return rv;
 }
 
 NS_IMETHODIMP
-nsMsgAccountManager::GetIdentitiesForServer(nsIMsgIncomingServer *server,
-                                            nsIArray **_retval) {
+nsMsgAccountManager::GetIdentitiesForServer(
+    nsIMsgIncomingServer *server,
+    nsTArray<RefPtr<nsIMsgIdentity>> &identities) {
   NS_ENSURE_ARG_POINTER(server);
-  NS_ENSURE_ARG_POINTER(_retval);
   nsresult rv = LoadAccounts();
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIMutableArray> identities(
-      do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
-  NS_ENSURE_SUCCESS(rv, rv);
+  identities.Clear();
 
   nsAutoCString serverKey;
   rv = server->GetKey(serverKey);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  for (uint32_t i = 0; i < m_accounts.Length(); ++i) {
-    nsCOMPtr<nsIMsgAccount> account(m_accounts[i]);
-
+  for (auto account : m_accounts) {
     nsCOMPtr<nsIMsgIncomingServer> thisServer;
     rv = account->GetIncomingServer(getter_AddRefs(thisServer));
     if (NS_FAILED(rv) || !thisServer) continue;
 
     nsAutoCString thisServerKey;
     rv = thisServer->GetKey(thisServerKey);
     if (serverKey.Equals(thisServerKey)) {
       nsCOMPtr<nsIArray> theseIdentities;
       rv = account->GetIdentities(getter_AddRefs(theseIdentities));
       if (NS_SUCCEEDED(rv)) {
         uint32_t theseLength;
         rv = theseIdentities->GetLength(&theseLength);
         if (NS_SUCCEEDED(rv)) {
           for (uint32_t j = 0; j < theseLength; ++j) {
-            nsCOMPtr<nsISupports> id(
+            nsCOMPtr<nsIMsgIdentity> id(
                 do_QueryElementAt(theseIdentities, j, &rv));
-            if (NS_SUCCEEDED(rv)) identities->AppendElement(id);
+            if (NS_SUCCEEDED(rv)) identities.AppendElement(id);
           }
         }
       }
     }
   }
-
-  identities.forget(_retval);
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsMsgAccountManager::GetServersForIdentity(nsIMsgIdentity *aIdentity,
                                            nsIArray **_retval) {
   NS_ENSURE_ARG_POINTER(aIdentity);
 
--- a/mailnews/base/src/nsMsgAccountManager.h
+++ b/mailnews/base/src/nsMsgAccountManager.h
@@ -81,23 +81,23 @@ class nsMsgAccountManager : public nsIMs
   nsresult Shutdown();
   void LogoutOfServer(nsIMsgIncomingServer *aServer);
 
  private:
   virtual ~nsMsgAccountManager();
 
   bool m_accountsLoaded;
   nsCOMPtr<nsIMsgFolderCache> m_msgFolderCache;
-  nsTArray<nsCOMPtr<nsIMsgAccount> > m_accounts;
+  nsTArray<nsCOMPtr<nsIMsgAccount>> m_accounts;
   nsInterfaceHashtable<nsCStringHashKey, nsIMsgIdentity> m_identities;
   nsInterfaceHashtable<nsCStringHashKey, nsIMsgIncomingServer>
       m_incomingServers;
   nsCOMPtr<nsIMsgAccount> m_defaultAccount;
   nsCOMArray<nsIIncomingServerListener> m_incomingServerListeners;
-  nsTObserverArray<RefPtr<VirtualFolderChangeListener> >
+  nsTObserverArray<RefPtr<VirtualFolderChangeListener>>
       m_virtualFolderListeners;
   nsCOMPtr<nsIMsgFolder> m_folderDoingEmptyTrash;
   nsCOMPtr<nsIMsgFolder> m_folderDoingCleanupInbox;
   bool m_emptyTrashInProgress;
   bool m_cleanupInboxInProgress;
 
   nsCString mAccountKeyList;
 
@@ -205,12 +205,12 @@ class nsMsgAccountManager : public nsIMs
   //
 
   // this array is for folder listeners that are supposed to be listening
   // on the root folders.
   // When a new server is created, all of the the folder listeners
   //    should be added to the new server
   // When a new listener is added, it should be added to all root folders.
   // similar for when servers are deleted or listeners removed
-  nsTObserverArray<nsCOMPtr<nsIFolderListener> > mFolderListeners;
+  nsTObserverArray<nsCOMPtr<nsIFolderListener>> mFolderListeners;
 
   void removeListenersFromFolder(nsIMsgFolder *aFolder);
 };
--- a/mailnews/base/test/unit/test_accountMgr2.js
+++ b/mailnews/base/test/unit/test_accountMgr2.js
@@ -49,9 +49,14 @@ add_task(async function() {
   // Setup done. Now check that things are as we expect.
 
   // At this point we should have 3 accounts and servers (imap, pop, local).
   Assert.equal(mgr.accounts.length, 3);
   Assert.equal(mgr.allServers.length, 3);
 
   // The identities we explicitly created.
   Assert.equal(mgr.allIdentities.length, 3);
+
+  // Check we find the right number of identities associated with each server.
+  Assert.equal(mgr.getIdentitiesForServer(acc1.incomingServer).length, 2);
+  Assert.equal(mgr.getIdentitiesForServer(acc2.incomingServer).length, 2);
+  Assert.equal(mgr.getIdentitiesForServer(mgr.localFoldersServer).length, 0);
 });
--- a/mailnews/compose/src/nsMsgCompose.cpp
+++ b/mailnews/compose/src/nsMsgCompose.cpp
@@ -2477,41 +2477,28 @@ QuotingOutputStreamListener::OnStopReque
         nsCOMPtr<nsIMsgFolder> msgFolder;
         rv = mOrigMsgHdr->GetFolder(getter_AddRefs(msgFolder));
 
         if (NS_SUCCEEDED(rv) && msgFolder) {
           nsCOMPtr<nsIMsgIncomingServer> nsIMsgIncomingServer;
           rv = msgFolder->GetServer(getter_AddRefs(nsIMsgIncomingServer));
 
           if (NS_SUCCEEDED(rv) && nsIMsgIncomingServer) {
-            // TODO: Bug 1614846 - stopgap until
-            // nsIAccountManager.getIdentitiesForServer(). takes nsTArray<>.
-            nsCOMPtr<nsIArray> tmp;
             rv = accountManager->GetIdentitiesForServer(nsIMsgIncomingServer,
-                                                        getter_AddRefs(tmp));
+                                                        identities);
             NS_ENSURE_SUCCESS(rv, rv);
-            uint32_t numElements;
-            rv = tmp->GetLength(&numElements);
-            NS_ENSURE_SUCCESS(rv, rv);
-            for (uint32_t i = 0; i < numElements; i++) {
-              nsCOMPtr<nsIMsgIdentity> ident = do_QueryElementAt(tmp, i, &rv);
-              NS_ENSURE_SUCCESS(rv, rv);
-              identities.AppendElement(ident);
-            }
           }
         }
       }
 
       bool isReplyToSelf = false;
       nsCOMPtr<nsIMsgIdentity> selfIdentity;
       if (!identities.IsEmpty()) {
         // Go through the identities to see if any of them is the author of
         // the email.
-        nsCOMPtr<nsIMsgIdentity> lookupIdentity;
-
         for (auto lookupIdentity : identities) {
           selfIdentity = lookupIdentity;
 
           nsCString curIdentityEmail;
           lookupIdentity->GetEmail(curIdentityEmail);
 
           // See if it's a reply to own message, but not a reply between
           // identities.
--- a/mailnews/extensions/mdn/src/nsMsgMdnGenerator.cpp
+++ b/mailnews/extensions/mdn/src/nsMsgMdnGenerator.cpp
@@ -787,55 +787,47 @@ nsresult nsMsgMdnGenerator::InitAndProce
       if (account) account->GetIncomingServer(getter_AddRefs(m_server));
 
       if (m_server) {
         // Find the correct identity based on the "To:" and "Cc:" header
         nsCString mailTo;
         nsCString mailCC;
         m_headers->ExtractHeader(HEADER_TO, true, mailTo);
         m_headers->ExtractHeader(HEADER_CC, true, mailCC);
-        nsCOMPtr<nsIArray> servIdentities;
-        accountManager->GetIdentitiesForServer(m_server,
-                                               getter_AddRefs(servIdentities));
-        if (servIdentities) {
-          nsCOMPtr<nsIMsgIdentity> ident;
+        nsTArray<RefPtr<nsIMsgIdentity>> servIdentities;
+        accountManager->GetIdentitiesForServer(m_server, servIdentities);
+
+        // First check in the "To:" header
+        for (auto ident : servIdentities) {
           nsCString identEmail;
-          uint32_t count = 0;
-          servIdentities->GetLength(&count);
-          // First check in the "To:" header
-          for (uint32_t i = 0; i < count; i++) {
-            ident = do_QueryElementAt(servIdentities, i, &rv);
-            if (NS_FAILED(rv)) continue;
+          ident->GetEmail(identEmail);
+          if (!mailTo.IsEmpty() && !identEmail.IsEmpty() &&
+              mailTo.Find(identEmail, /* ignoreCase = */ true) != kNotFound) {
+            m_identity = ident;
+            break;
+          }
+        }
+        // If no match, check the "Cc:" header
+        if (!m_identity) {
+          for (auto ident : servIdentities) {
+            nsCString identEmail;
             ident->GetEmail(identEmail);
-            if (!mailTo.IsEmpty() && !identEmail.IsEmpty() &&
-                mailTo.Find(identEmail, /* ignoreCase = */ true) != kNotFound) {
+            if (!mailCC.IsEmpty() && !identEmail.IsEmpty() &&
+                mailCC.Find(identEmail, /* ignoreCase = */ true) != kNotFound) {
               m_identity = ident;
               break;
             }
           }
-          // If no match, check the "Cc:" header
-          if (!m_identity) {
-            for (uint32_t i = 0; i < count; i++) {
-              ident = do_QueryElementAt(servIdentities, i, &rv);
-              if (NS_FAILED(rv)) continue;
-              ident->GetEmail(identEmail);
-              if (!mailCC.IsEmpty() && !identEmail.IsEmpty() &&
-                  mailCC.Find(identEmail, /* ignoreCase = */ true) !=
-                      kNotFound) {
-                m_identity = ident;
-                break;
-              }
-            }
-          }
         }
 
-        // If no match again, use the first identity
-        if (!m_identity)
+        // If still no match, use the first identity
+        if (!m_identity) {
           rv = accountManager->GetFirstIdentityForServer(
               m_server, getter_AddRefs(m_identity));
+        }
       }
     }
     NS_ENSURE_SUCCESS(rv, rv);
 
     if (m_identity) {
       bool useCustomPrefs = false;
       m_identity->GetBoolAttribute("use_custom_prefs", &useCustomPrefs);
       if (useCustomPrefs) {
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -8696,33 +8696,26 @@ NS_IMETHODIMP nsImapMailFolder::GetCusto
       NS_ENSURE_SUCCESS(rv, rv);
       ourIdentity->GetEmail(ourEmailAddress);
       int32_t atPos = ourEmailAddress.FindChar('@');
       if (atPos != kNotFound) {
         nsCString otherUsersEmailAddress;
         GetFolderOwnerUserName(otherUsersEmailAddress);
         otherUsersEmailAddress.Append(
             Substring(ourEmailAddress, atPos, ourEmailAddress.Length()));
-        nsCOMPtr<nsIArray> identities;
-        rv = accountManager->GetIdentitiesForServer(server,
-                                                    getter_AddRefs(identities));
+        nsTArray<RefPtr<nsIMsgIdentity>> identities;
+        rv = accountManager->GetIdentitiesForServer(server, identities);
         NS_ENSURE_SUCCESS(rv, rv);
-        uint32_t numIdentities;
-        rv = identities->GetLength(&numIdentities);
-        NS_ENSURE_SUCCESS(rv, rv);
-        for (uint32_t identityIndex = 0; identityIndex < numIdentities;
-             identityIndex++) {
-          nsCOMPtr<nsIMsgIdentity> identity =
-              do_QueryElementAt(identities, identityIndex);
+
+        for (auto identity : identities) {
           if (!identity) continue;
           nsCString identityEmail;
           identity->GetEmail(identityEmail);
           if (identityEmail.Equals(otherUsersEmailAddress)) {
             retIdentity = identity;
-            ;
             break;
           }
         }
         if (!retIdentity) {
           // create the identity
           rv = accountManager->CreateIdentity(getter_AddRefs(retIdentity));
           NS_ENSURE_SUCCESS(rv, rv);
           retIdentity->SetEmail(otherUsersEmailAddress);
--- a/suite/mailnews/content/mailCommands.js
+++ b/suite/mailnews/content/mailCommands.js
@@ -50,18 +50,18 @@ function getBestIdentity(identities, opt
     }
   }
   // Return only found identity or pick the first one from list if no matches found.
   return identities[0];
 }
 
 function getIdentityForServer(server, optionalHint)
 {
-  var identities = accountManager.getIdentitiesForServer(server);
-  return getBestIdentity(fixIterator(identities, nsIMsgAccount), optionalHint);
+  let identities = accountManager.getIdentitiesForServer(server);
+  return getBestIdentity(identities, optionalHint);
 }
 
 /**
  * Get the identity for the given header.
  * @param hdr nsIMsgHdr message header
  * @param type nsIMsgCompType compose type the identity ise used for.
  */