Bug 1612244 - Remove nsIArray usage from nsIMsgLocalMailFolder. r=mkmelin DONTBUILD
authorBen Campbell <benc@thunderbird.net>
Sun, 03 May 2020 13:53:40 +0300
changeset 39000 7fa9014995043b86635e876945b5c375d32784ff
parent 38999 0d8a8aa30526b804336f71162e2e2f0619799865
child 39001 97f8ec74862a6c5c0bbaf72648c50b9f557d6222
push id401
push userclokep@gmail.com
push dateMon, 01 Jun 2020 20:41:59 +0000
reviewersmkmelin
bugs1612244
Bug 1612244 - Remove nsIArray usage from nsIMsgLocalMailFolder. r=mkmelin DONTBUILD
mailnews/base/search/src/nsMsgFilterService.cpp
mailnews/base/util/nsMsgUtils.cpp
mailnews/base/util/nsMsgUtils.h
mailnews/local/public/nsIMsgLocalMailFolder.idl
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsLocalUndoTxn.cpp
mailnews/local/src/nsParseMailbox.cpp
--- a/mailnews/base/search/src/nsMsgFilterService.cpp
+++ b/mailnews/base/search/src/nsMsgFilterService.cpp
@@ -938,19 +938,22 @@ nsresult nsMsgFilterAfterTheFact::ApplyF
         } break;
         case nsMsgFilterAction::DeleteFromPop3Server: {
           nsCOMPtr<nsIMsgLocalMailFolder> localFolder =
               do_QueryInterface(curFolder, &rv);
           BREAK_ACTION_IF_FAILURE(rv, "Current folder not a local folder");
           BREAK_ACTION_IF_FALSE(localFolder,
                                 "Current folder not a local folder");
           // This action ignores the deleteMailLeftOnServer preference
-          rv = localFolder->MarkMsgsOnPop3Server(m_searchHitHdrs,
-                                                 POP3_FORCE_DEL);
-          BREAK_ACTION_IF_FAILURE(rv, "MarkMsgsOnPop3Server failed");
+          {
+            nsTArray<RefPtr<nsIMsgDBHdr>> hdrs;
+            MsgHdrsToTArray(m_searchHitHdrs, hdrs);
+            rv = localFolder->MarkMsgsOnPop3Server(hdrs, POP3_FORCE_DEL);
+            BREAK_ACTION_IF_FAILURE(rv, "MarkMsgsOnPop3Server failed");
+          }
 
           nsCOMPtr<nsIMutableArray> partialMsgs;
           // Delete the partial headers. They're useless now
           //   that the server copy is being deleted.
           for (uint32_t msgIndex = 0; msgIndex < m_searchHits.Length();
                msgIndex++) {
             nsCOMPtr<nsIMsgDBHdr> msgHdr =
                 do_QueryElementAt(m_searchHitHdrs, msgIndex, &rv);
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -1873,8 +1873,18 @@ void MsgRemoveQueryPart(nsCString &aSpec
   // ?header=quotebody&part=1.2&filename=lijbmghmkilicioj.png
 
   // Truncate path at the first of /; or ?
   int32_t ind = aSpec.FindChar('?');
   if (ind != kNotFound) aSpec.SetLength(ind);
   ind = aSpec.Find("/;");
   if (ind != kNotFound) aSpec.SetLength(ind);
 }
+
+void MsgHdrsToTArray(nsIArray *messages, nsTArray<RefPtr<nsIMsgDBHdr>> &out) {
+  uint32_t count;
+  messages->GetLength(&count);
+  out.Clear();
+  out.SetCapacity(count);
+  for (uint32_t i = 0; i < count; ++i) {
+    out.AppendElement(do_QueryElementAt(messages, i));
+  }
+}
--- a/mailnews/base/util/nsMsgUtils.h
+++ b/mailnews/base/util/nsMsgUtils.h
@@ -399,16 +399,23 @@ void MsgRemoveQueryPart(nsCString &aSpec
  * #include "nsIConsoleService.h"
  *
  */
 
 NS_MSG_BASE
 void MsgLogToConsole4(const nsAString &aErrorText, const nsAString &aFilename,
                       uint32_t aLine, uint32_t flags);
 
+/**
+ * Stopgap helper for removal of nsIArray usage (Bug 1583030).
+ * Copy an nsIArray of nsIMsgDBHdrs into an nsTArray.
+ * TODO: Delete this function when we can!
+ */
+void MsgHdrsToTArray(nsIArray *messages, nsTArray<RefPtr<nsIMsgDBHdr>> &out);
+
 // Macro with filename and line number
 #define MSG_LOG_TO_CONSOLE(_text, _flag)                                  \
   MsgLogToConsole4(NS_LITERAL_STRING(_text), NS_LITERAL_STRING(__FILE__), \
                    __LINE__, _flag)
 #define MSG_LOG_ERR_TO_CONSOLE(_text) \
   MSG_LOG_TO_CONSOLE(_text, nsIScriptError::errorFlag)
 #define MSG_LOG_WARN_TO_CONSOLE(_text) \
   MSG_LOG_TO_CONSOLE(_text, nsIScriptError::warningFlag)
--- a/mailnews/local/public/nsIMsgLocalMailFolder.idl
+++ b/mailnews/local/public/nsIMsgLocalMailFolder.idl
@@ -1,15 +1,14 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * 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/. */
 
 #include "nsISupports.idl"
-interface nsIArray;
 interface nsIMsgWindow;
 interface nsIUrlListener;
 interface nsIMsgDatabase;
 interface nsIMsgDBHdr;
 interface nsIMsgFolder;
 interface nsIMsgCopyServiceListener;
 
 [ptr] native nsLocalFolderScanState(nsLocalFolderScanState);
@@ -45,17 +44,17 @@ interface nsIMsgLocalMailFolder : nsISup
    * If aReparseUrlListener is null, folder will use itself as the listener
    */
   nsIMsgDatabase getDatabaseWithReparse(in nsIUrlListener aReparseUrlListener, in nsIMsgWindow aMsgWindow);
   void parseFolder(in nsIMsgWindow aMsgWindow, in nsIUrlListener listener);
   void copyFolderLocal(in nsIMsgFolder srcFolder, in boolean isMove, in nsIMsgWindow msgWindow, in nsIMsgCopyServiceListener listener );
   void copyAllSubFolders(in nsIMsgFolder srcFolder, in nsIMsgWindow msgWindow, in nsIMsgCopyServiceListener listener );
   void onCopyCompleted(in nsISupports aSrcSupport, in boolean aMoveCopySucceeded);
   attribute boolean checkForNewMessagesAfterParsing;
-  void markMsgsOnPop3Server(in nsIArray aMessages, in int32_t aMark);
+  void markMsgsOnPop3Server(in Array<nsIMsgDBHdr> aMessages, in int32_t aMark);
 
   /**
    * File size on disk has possibly changed - update and notify.
    */
   void refreshSizeOnDisk();
 
   /**
    * Creates a subfolder to the current folder with the passed in folder name.
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -986,33 +986,26 @@ nsresult nsMsgLocalMailFolder::GetTrashF
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::DeleteMessages(nsIArray *messages,
                                      nsIMsgWindow *msgWindow,
                                      bool deleteStorage, bool isMove,
                                      nsIMsgCopyServiceListener *listener,
                                      bool allowUndo) {
   NS_ENSURE_ARG_POINTER(messages);
-
-  uint32_t messageCount;
-  nsresult rv = messages->GetLength(&messageCount);
-  NS_ENSURE_SUCCESS(rv, rv);
-
+  nsresult rv;
   // Stopgap. Build a parallel array of message headers while we complete
   // removal of nsIArray usage (Bug 1583030).
   nsTArray<RefPtr<nsIMsgDBHdr>> msgHeaders;
-  msgHeaders.SetCapacity(messageCount);
-  for (uint32_t i = 0; i < messageCount; ++i) {
-    msgHeaders.AppendElement(do_QueryElementAt(messages, i));
-  }
+  MsgHdrsToTArray(messages, msgHeaders);
 
   // shift delete case - (delete to trash is handled in EndMove)
   // this is also the case when applying retention settings.
   if (deleteStorage && !isMove) {
-    MarkMsgsOnPop3Server(messages, POP3_DELETE);
+    MarkMsgsOnPop3Server(msgHeaders, POP3_DELETE);
   }
 
   bool isTrashFolder = mFlags & nsMsgFolderFlags::Trash;
 
   // notify on delete from trash and shift-delete
   if (!isMove && (deleteStorage || isTrashFolder)) {
     nsCOMPtr<nsIMsgFolderNotificationService> notifier(
         do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
@@ -1035,17 +1028,17 @@ nsMsgLocalMailFolder::DeleteMessages(nsI
       return copyService->CopyMessages(this, messages, trashFolder, true,
                                        listener, msgWindow, allowUndo);
     }
   } else {
     nsCOMPtr<nsIMsgDatabase> msgDB;
     rv = GetDatabaseWOReparse(getter_AddRefs(msgDB));
     if (NS_SUCCEEDED(rv)) {
       if (deleteStorage && isMove && GetDeleteFromServerOnMove())
-        MarkMsgsOnPop3Server(messages, POP3_DELETE);
+        MarkMsgsOnPop3Server(msgHeaders, POP3_DELETE);
 
       nsCOMPtr<nsISupports> msgSupport;
       rv = EnableNotifications(allMessageCountNotifications, false);
       if (NS_SUCCEEDED(rv)) {
         nsCOMPtr<nsIMsgPluggableStore> msgStore;
         rv = GetMsgStore(getter_AddRefs(msgStore));
         if (NS_SUCCEEDED(rv)) {
           rv = msgStore->DeleteMessages(msgHeaders);
@@ -1105,23 +1098,18 @@ nsMsgLocalMailFolder::AddMessageDisposit
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::MarkMessagesRead(nsIArray *aMessages, bool aMarkRead) {
   nsresult rv = nsMsgDBFolder::MarkMessagesRead(aMessages, aMarkRead);
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Stopgap. Build a parallel array of message headers while we complete
   // removal of nsIArray usage (Bug 1583030).
-  uint32_t messageCount;
-  aMessages->GetLength(&messageCount);
   nsTArray<RefPtr<nsIMsgDBHdr>> msgHeaders;
-  msgHeaders.SetCapacity(messageCount);
-  for (uint32_t i = 0; i < messageCount; ++i) {
-    msgHeaders.AppendElement(do_QueryElementAt(aMessages, i));
-  }
+  MsgHdrsToTArray(aMessages, msgHeaders);
 
   nsCOMPtr<nsIMsgPluggableStore> msgStore;
   rv = GetMsgStore(getter_AddRefs(msgStore));
   NS_ENSURE_SUCCESS(rv, rv);
   return msgStore->ChangeFlags(msgHeaders, nsMsgMessageFlags::Read, aMarkRead);
 }
 
 NS_IMETHODIMP
@@ -1130,23 +1118,18 @@ nsMsgLocalMailFolder::MarkMessagesFlagge
   nsresult rv = nsMsgDBFolder::MarkMessagesFlagged(aMessages, aMarkFlagged);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr<nsIMsgPluggableStore> msgStore;
   rv = GetMsgStore(getter_AddRefs(msgStore));
   NS_ENSURE_SUCCESS(rv, rv);
 
   // Stopgap. Build a parallel array of message headers while we complete
   // removal of nsIArray usage (Bug 1583030).
-  uint32_t messageCount;
-  aMessages->GetLength(&messageCount);
   nsTArray<RefPtr<nsIMsgDBHdr>> msgHeaders;
-  msgHeaders.SetCapacity(messageCount);
-  for (uint32_t i = 0; i < messageCount; ++i) {
-    msgHeaders.AppendElement(do_QueryElementAt(aMessages, i));
-  }
+  MsgHdrsToTArray(aMessages, msgHeaders);
 
   return msgStore->ChangeFlags(msgHeaders, nsMsgMessageFlags::Marked,
                                aMarkFlagged);
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::MarkAllMessagesRead(nsIMsgWindow *aMsgWindow) {
   nsresult rv = GetDatabase();
@@ -1416,18 +1399,21 @@ nsMsgLocalMailFolder::CopyMessages(nsIMs
                      getter_AddRefs(localDstFolder));
       if (localDstFolder) {
         // If we are the trash and a local msg is being moved to us, mark the
         // source for delete from server, if so configured.
         if (mFlags & nsMsgFolderFlags::Trash) {
           // If we're deleting on all moves, we'll mark this message for
           // deletion when we call DeleteMessages on the source folder. So don't
           // mark it for deletion here, in that case.
-          if (!GetDeleteFromServerOnMove())
-            localDstFolder->MarkMsgsOnPop3Server(dstHdrs, POP3_DELETE);
+          if (!GetDeleteFromServerOnMove()) {
+            nsTArray<RefPtr<nsIMsgDBHdr>> hdrs;
+            MsgHdrsToTArray(dstHdrs, hdrs);
+            localDstFolder->MarkMsgsOnPop3Server(hdrs, POP3_DELETE);
+          }
         }
       }
     }
     return rv;
   }
   // If the store doesn't do the copy, we'll stream the source messages into
   // the target folder, using getMsgInputStream and getNewMsgOutputStream.
 
@@ -2411,19 +2397,21 @@ nsMsgLocalMailFolder::EndMove(bool moveS
         do_QueryInterface(srcFolder);
     if (localSrcFolder) {
       // if we are the trash and a local msg is being moved to us, mark the
       // source for delete from server, if so configured.
       if (mFlags & nsMsgFolderFlags::Trash) {
         // if we're deleting on all moves, we'll mark this message for deletion
         // when we call DeleteMessages on the source folder. So don't mark it
         // for deletion here, in that case.
-        if (!GetDeleteFromServerOnMove())
-          localSrcFolder->MarkMsgsOnPop3Server(mCopyState->m_messages,
-                                               POP3_DELETE);
+        if (!GetDeleteFromServerOnMove()) {
+          nsTArray<RefPtr<nsIMsgDBHdr>> hdrs;
+          MsgHdrsToTArray(mCopyState->m_messages, hdrs);
+          localSrcFolder->MarkMsgsOnPop3Server(hdrs, POP3_DELETE);
+        }
       }
     }
     // lets delete these all at once - much faster that way
     rv = srcFolder->DeleteMessages(mCopyState->m_messages,
                                    mCopyState->m_msgWindow, true, true, nullptr,
                                    mCopyState->m_allowUndo);
     AutoCompact(mCopyState->m_msgWindow);
 
@@ -2637,17 +2625,18 @@ nsresult nsMsgLocalMailFolder::CopyMessa
 // A message is being deleted from a POP3 mail file, so check and see if we have
 // the message being deleted in the server. If so, then we need to remove the
 // message from the server as well. We have saved the UIDL of the message in the
 // popstate.dat file and we must match this uidl, so read the message headers
 // and see if we have it, then mark the message for deletion from the server.
 // The next time we look at mail the message will be deleted from the server.
 
 NS_IMETHODIMP
-nsMsgLocalMailFolder::MarkMsgsOnPop3Server(nsIArray *aMessages, int32_t aMark) {
+nsMsgLocalMailFolder::MarkMsgsOnPop3Server(
+    const nsTArray<RefPtr<nsIMsgDBHdr>> &aMessages, int32_t aMark) {
   nsLocalFolderScanState folderScanState;
   nsCOMPtr<nsIPop3IncomingServer> curFolderPop3MailServer;
   nsCOMArray<nsIPop3IncomingServer>
       pop3Servers;  // servers with msgs deleted...
 
   nsCOMPtr<nsIMsgIncomingServer> incomingServer;
   nsresult rv = GetServer(getter_AddRefs(incomingServer));
   NS_ENSURE_SUCCESS(rv, NS_MSG_INVALID_OR_MISSING_SERVER);
@@ -2658,30 +2647,23 @@ nsMsgLocalMailFolder::MarkMsgsOnPop3Serv
 
   // I wonder if we should run through the pop3 accounts and see if any of them
   // have leave on server set. If not, we could short-circuit some of this.
 
   curFolderPop3MailServer = do_QueryInterface(incomingServer, &rv);
   rv = GetFolderScanState(&folderScanState);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  uint32_t srcCount;
-  aMessages->GetLength(&srcCount);
-
   // Filter delete requests are always honored, others are subject
   // to the deleteMailLeftOnServer preference.
   int32_t mark;
   mark = (aMark == POP3_FORCE_DEL) ? POP3_DELETE : aMark;
 
-  for (uint32_t i = 0; i < srcCount; i++) {
-    /* get uidl for this message */
-    nsCOMPtr<nsIMsgDBHdr> msgDBHdr(do_QueryElementAt(aMessages, i, &rv));
-
+  for (auto msgDBHdr : aMessages) {
     uint32_t flags = 0;
-
     if (msgDBHdr) {
       msgDBHdr->GetFlags(&flags);
       nsCOMPtr<nsIPop3IncomingServer> msgPop3Server = curFolderPop3MailServer;
       bool leaveOnServer = false;
       bool deleteMailLeftOnServer = false;
       // set up defaults, in case there's no x-mozilla-account header
       if (curFolderPop3MailServer) {
         curFolderPop3MailServer->GetDeleteMailLeftOnServer(
@@ -2812,17 +2794,19 @@ return NS_OK;
 NS_IMETHODIMP nsMsgLocalMailFolder::DownloadMessagesForOffline(
     nsIArray *aMessages, nsIMsgWindow *aWindow) {
   if (mDownloadState != DOWNLOAD_STATE_NONE)
     return NS_ERROR_FAILURE;  // already has a download in progress
 
   // We're starting a download...
   mDownloadState = DOWNLOAD_STATE_INITED;
 
-  MarkMsgsOnPop3Server(aMessages, POP3_FETCH_BODY);
+  nsTArray<RefPtr<nsIMsgDBHdr>> hdrs;
+  MsgHdrsToTArray(aMessages, hdrs);
+  MarkMsgsOnPop3Server(hdrs, POP3_FETCH_BODY);
 
   // Pull out all the PARTIAL messages into a new array
   uint32_t srcCount;
   aMessages->GetLength(&srcCount);
 
   nsresult rv;
   for (uint32_t i = 0; i < srcCount; i++) {
     nsCOMPtr<nsIMsgDBHdr> msgDBHdr(do_QueryElementAt(aMessages, i, &rv));
--- a/mailnews/local/src/nsLocalUndoTxn.cpp
+++ b/mailnews/local/src/nsLocalUndoTxn.cpp
@@ -224,19 +224,21 @@ nsresult nsLocalMoveCopyMsgTxn::UndoTran
         // Remember that we're actually moving things back from the destination
         //  to the source!
         notifier->NotifyMsgsMoveCopyCompleted(true, dstMessages, srcFolder,
                                               srcMessages);
       }
 
       nsCOMPtr<nsIMsgLocalMailFolder> localFolder =
           do_QueryInterface(srcFolder);
-      if (localFolder)
-        localFolder->MarkMsgsOnPop3Server(srcMessages,
-                                          POP3_NONE /*deleteMsgs*/);
+      if (localFolder) {
+        nsTArray<RefPtr<nsIMsgDBHdr>> hdrs;
+        MsgHdrsToTArray(srcMessages, hdrs);
+        localFolder->MarkMsgsOnPop3Server(hdrs, POP3_NONE /*deleteMsgs*/);
+      }
     } else  // undoing a move means moving the messages back.
     {
       nsCOMPtr<nsIMutableArray> dstMessages =
           do_CreateInstance(NS_ARRAY_CONTRACTID);
       m_numHdrsCopied = 0;
       m_srcKeyArray.Clear();
       for (i = 0; i < count; i++) {
         // GetMsgHdrForKey is not a test for whether the key exists, so check.
@@ -330,19 +332,21 @@ nsLocalMoveCopyMsgTxn::RedoTransaction()
 
       bool deleteFlag = false;  // message is un-deleted- we are trying to redo
       CheckForToggleDelete(srcFolder, m_srcKeyArray[0],
                            &deleteFlag);  // there could have been a toggle
       rv = UndoImapDeleteFlag(srcFolder, m_srcKeyArray, deleteFlag);
     } else if (m_canUndelete) {
       nsCOMPtr<nsIMsgLocalMailFolder> localFolder =
           do_QueryInterface(srcFolder);
-      if (localFolder)
-        localFolder->MarkMsgsOnPop3Server(srcMessages,
-                                          POP3_DELETE /*deleteMsgs*/);
+      if (localFolder) {
+        nsTArray<RefPtr<nsIMsgDBHdr>> hdrs;
+        MsgHdrsToTArray(srcMessages, hdrs);
+        localFolder->MarkMsgsOnPop3Server(hdrs, POP3_DELETE /*deleteMsgs*/);
+      }
 
       rv = srcDB->DeleteMessages(m_srcKeyArray, nullptr);
       srcDB->SetSummaryValid(true);
     } else {
       nsCOMPtr<nsIMsgDBHdr> srcHdr;
       m_numHdrsCopied = 0;
       m_dstKeyArray.Clear();
       for (i = 0; i < count; i++) {
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -2082,22 +2082,18 @@ NS_IMETHODIMP nsParseNewMailState::Apply
           msgHdr->GetFolder(getter_AddRefs(downloadFolder));
           nsCOMPtr<nsIMsgLocalMailFolder> localFolder =
               do_QueryInterface(downloadFolder, &rv);
           if (NS_FAILED(rv) || !localFolder) {
             MOZ_LOG(FILTERLOGMODULE, LogLevel::Error,
                     ("(Local) Couldn't find local mail folder"));
             break;
           }
-          nsCOMPtr<nsIMutableArray> messages =
-              do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
-          if (NS_FAILED(rv) || !messages) break;
-          messages->AppendElement(msgHdr);
           // This action ignores the deleteMailLeftOnServer preference
-          rv = localFolder->MarkMsgsOnPop3Server(messages, POP3_FORCE_DEL);
+          rv = localFolder->MarkMsgsOnPop3Server({&*msgHdr}, POP3_FORCE_DEL);
 
           // If this is just a header, throw it away. It's useless now
           // that the server copy is being deleted.
           uint32_t flags = 0;
           msgHdr->GetFlags(&flags);
           if (flags & nsMsgMessageFlags::Partial) {
             m_msgMovedByFilter = true;
             msgIsNew = false;
@@ -2111,21 +2107,17 @@ NS_IMETHODIMP nsParseNewMailState::Apply
           if (NS_FAILED(rv) || !localFolder) {
             MOZ_LOG(FILTERLOGMODULE, LogLevel::Error,
                     ("(Local) Couldn't find local mail folder"));
             break;
           }
           uint32_t flags = 0;
           msgHdr->GetFlags(&flags);
           if (flags & nsMsgMessageFlags::Partial) {
-            nsCOMPtr<nsIMutableArray> messages =
-                do_CreateInstance(NS_ARRAY_CONTRACTID, &rv);
-            if (NS_FAILED(rv) || !messages) break;
-            messages->AppendElement(msgHdr);
-            rv = localFolder->MarkMsgsOnPop3Server(messages, POP3_FETCH_BODY);
+            rv = localFolder->MarkMsgsOnPop3Server({&*msgHdr}, POP3_FETCH_BODY);
             // Don't add this header to the DB, we're going to replace it
             // with the full message.
             m_msgMovedByFilter = true;
             msgIsNew = false;
             // Don't do anything else in this filter, wait until we
             // have the full message.
             *applyMore = false;
           }