Bug 455932 - "Add nsIMsgFolderListener notifications for news messages" [r+sr=bienvenu]
authorSiddharth Agarwal <sid1337@gmail.com>
Thu, 18 Sep 2008 22:07:08 +0100
changeset 380 322f1a754d092b490853cada5b14cd059813c821
parent 379 89ec2aa13b4e26e5ad7be12f069cb817b0211dc9
child 381 c141ff9ff184030340b5268bd60bc8f92aef94e1
push idunknown
push userunknown
push dateunknown
bugs455932
Bug 455932 - "Add nsIMsgFolderListener notifications for news messages" [r+sr=bienvenu]
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/news/public/nsIMsgNewsFolder.idl
mailnews/news/src/nsNNTPArticleList.cpp
mailnews/news/src/nsNNTPNewsgroupList.cpp
mailnews/news/src/nsNewsFolder.cpp
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -2631,17 +2631,19 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndC
           srcFolder->NotifyFolderEvent(mDeleteOrMoveMsgCompletedAtom);
 
         (void) OnCopyCompleted(mCopyState->m_srcSupport, PR_TRUE);
         // enable the dest folder
         EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_FALSE /*dbBatching*/); //dest folder doesn't need db batching
       }
     }
     // Send the itemAdded notification in case we didn't send the itemMoveCopyCompleted notification earlier.
-    if (!numHdrs)
+    // Posting news messages involves this, yet doesn't have the newHdr initialized, so don't send any
+    // notifications in that case.
+    if (!numHdrs && newHdr)
     {
       nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
       if (notifier)
         notifier->NotifyMsgAdded(newHdr);
     }
   }
   return rv;
 }
--- a/mailnews/news/public/nsIMsgNewsFolder.idl
+++ b/mailnews/news/public/nsIMsgNewsFolder.idl
@@ -33,20 +33,26 @@
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "nsISupports.idl"
 #include "nsIMsgFolder.idl"
 
+%{C++
+#include "nsTArray.h"
+%}
+
 interface nsIMsgWindow;
 interface nsINntpIncomingServer;
 
-[scriptable, uuid(B6333473-54DC-47C4-B179-3D4744946C95)]
+[ref] native nsMsgKeyArrayRef(nsTArray<nsMsgKey>);
+
+[scriptable, uuid(7fe8c961-3fce-41e2-aa49-9ea3bc332d40)]
 interface nsIMsgNewsFolder : nsISupports {
   attribute ACString groupUsername;
   attribute ACString groupPassword;
 
   readonly attribute AString unicodeName;
   /**|rawName| is an 8-bit string to represent the name of a newsgroup used by 
    * a news server. It's offered for the convenience of callers so that they 
    * don't have to convert |unicodeName| to the server-side name when 
@@ -74,16 +80,17 @@ interface nsIMsgNewsFolder : nsISupports
   void setReadSetFromStr(in ACString setStr);
 
   readonly attribute ACString newsrcLine;
   readonly attribute ACString optionLines;
   readonly attribute ACString unsubscribedNewsgroupLines;
   void SetNewsrcHasChanged(in boolean newsrcHasChanged);
   void updateSummaryFromNNTPInfo(in long oldest, in long youngest, in long total);
   void removeMessage(in nsMsgKey key); 
+  [noscript] void removeMessages(in nsMsgKeyArrayRef aMsgKeys);
   void cancelComplete();
   void cancelFailed();
 
   ACString getMessageIdForKey(in nsMsgKey key);
 
   void getNextNMessages(in nsIMsgWindow aMsgWindow);
   void notifyDownloadedLine(in string line, in nsMsgKey key);
   void notifyFinishedDownloadinghdrs();
--- a/mailnews/news/src/nsNNTPArticleList.cpp
+++ b/mailnews/news/src/nsNNTPArticleList.cpp
@@ -89,28 +89,32 @@ nsNNTPArticleList::AddArticleKey(PRInt32
 #endif
 
   if (m_dbIndex < m_idsInDB.Length())
   {
     PRInt32 idInDBToCheck = m_idsInDB[m_dbIndex];
     // if there are keys in the database that aren't in the newsgroup
     // on the server, remove them. We probably shouldn't do this if
     // we have a copy of the article offline.
+    nsTArray<nsMsgKey> keysDeleted;
     while (idInDBToCheck < key)
     {
-      m_newsFolder->RemoveMessage(idInDBToCheck);
+      keysDeleted.AppendElement(idInDBToCheck);
 #ifdef DEBUG
       m_idsDeleted.AppendElement(idInDBToCheck);
 #endif
       if (m_dbIndex >= m_idsInDB.Length())
         break;
       idInDBToCheck = m_idsInDB[++m_dbIndex];
     }
     if (idInDBToCheck == key)
       m_dbIndex++;
+
+    if (keysDeleted.Length())
+      m_newsFolder->RemoveMessages(keysDeleted);
   }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsNNTPArticleList::FinishAddingArticleKeys()
 {
   // if the last n messages in the group are cancelled, they won't have gotten removed
--- a/mailnews/news/src/nsNNTPNewsgroupList.cpp
+++ b/mailnews/news/src/nsNNTPNewsgroupList.cpp
@@ -86,16 +86,17 @@
 
 #include "nsXPCOM.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIMsgWindow.h"
 #include "nsIDocShell.h"
 #include "nsIMutableArray.h"
+#include "nsIMsgFolderNotificationService.h"
 
 // update status on header download once per second
 #define MIN_STATUS_UPDATE_INTERVAL PR_USEC_PER_SEC
 
 
 nsNNTPNewsgroupList::nsNNTPNewsgroupList()
   : m_finishingXover(PR_FALSE),
   m_getOldMessages(PR_FALSE),
@@ -1120,22 +1121,29 @@ nsNNTPNewsgroupList::CallFilters()
   PRUint32 serverFilterCount = 0;
   if (m_serverFilterList)
   {
     rv = m_serverFilterList->GetFilterCount(&serverFilterCount);
     NS_ENSURE_SUCCESS(rv,rv);
   }
 
   PRUint32 count = m_newHeaders.Count();
-  
+
+  // Notify MsgFolderListeners of message adds
+  nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
+
   for (PRUint32 i = 0; i < count; i++)
   {
     if (!filterCount && !serverFilterCount)
     {
       m_newsDB->AddNewHdrToDB(m_newHeaders[i], PR_TRUE);
+
+      if (notifier)
+        notifier->NotifyMsgAdded(m_newHeaders[i]);
+
       continue;
     }
     m_addHdrToDB = PR_TRUE;
     m_newMsgHdr = m_newHeaders[i];
 
     // build up a "headers" for filter code
     nsCString subject, author, date;
     rv = m_newMsgHdr->GetSubject(getter_Copies(subject));
@@ -1186,17 +1194,21 @@ nsNNTPNewsgroupList::CallFilters()
       rv = m_serverFilterList->ApplyFiltersToHdr(nsMsgFilterType::NewsRule,
           m_newMsgHdr, folder, m_newsDB, fullHeaders.get(),
           fullHeaders.Length(), this, m_msgWindow, nsnull);
     }
 
     NS_ENSURE_SUCCESS(rv,rv);
 
     if (m_addHdrToDB)
+    {
       m_newsDB->AddNewHdrToDB(m_newMsgHdr, PR_TRUE);
+      if (notifier)
+        notifier->NotifyMsgAdded(m_newMsgHdr);
+    }
   }
   m_newHeaders.Clear();
   return NS_OK;
 }
 
 void
 nsNNTPNewsgroupList::SetProgressBarPercent(PRInt32 percent)
 {
--- a/mailnews/news/src/nsNewsFolder.cpp
+++ b/mailnews/news/src/nsNewsFolder.cpp
@@ -89,16 +89,18 @@
 #include "nsReadableUtils.h"
 #include "nsNewsDownloader.h"
 #include "nsIStringBundle.h"
 #include "nsEscape.h"
 #include "nsMsgI18N.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIMsgAccountManager.h"
 #include "nsArrayUtils.h"
+#include "nsIMsgFolderNotificationService.h"
+#include "nsIMutableArray.h"
 
 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
 
 // ###tw  This really ought to be the most
 // efficient file reading size for the current
 // operating system.
 #define NEWSRC_FILE_BUFFER_SIZE 1024
 
@@ -1459,19 +1461,53 @@ nsMsgNewsFolder::GetNntpServer(nsINntpIn
 }
 
 // this gets called after the message actually gets cancelled
 // it removes the cancelled message from the db
 NS_IMETHODIMP nsMsgNewsFolder::RemoveMessage(nsMsgKey key)
 {
   nsresult rv = GetDatabase(nsnull);
   NS_ENSURE_SUCCESS(rv, rv); // if GetDatabase succeeds, mDatabase will be non-null
+
+  // Notify listeners of a delete for a single message
+  nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
+  if (notifier)
+  {
+    nsCOMPtr<nsIMsgDBHdr> msgHdr;
+    rv = mDatabase->GetMsgHdrForKey(key, getter_AddRefs(msgHdr));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIMutableArray> msgHdrs(do_CreateInstance(NS_ARRAY_CONTRACTID));
+    msgHdrs->AppendElement(msgHdr, PR_FALSE);
+
+    notifier->NotifyMsgsDeleted(msgHdrs);
+  }
   return mDatabase->DeleteMessage(key, nsnull, PR_FALSE);
 }
 
+NS_IMETHODIMP nsMsgNewsFolder::RemoveMessages(nsTArray<nsMsgKey> &aMsgKeys)
+{
+  nsresult rv = GetDatabase(nsnull);
+  NS_ENSURE_SUCCESS(rv, rv); // if GetDatabase succeeds, mDatabase will be non-null
+  
+  // Notify listeners of a multiple message delete
+  nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
+
+  if (notifier)
+  {
+    nsCOMPtr<nsIMutableArray> msgHdrs(do_CreateInstance(NS_ARRAY_CONTRACTID));
+    rv = MsgGetHeadersFromKeys(mDatabase, aMsgKeys, msgHdrs);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    notifier->NotifyMsgsDeleted(msgHdrs);
+  }
+
+  return mDatabase->DeleteMessages(&aMsgKeys, nsnull);
+}
+
 NS_IMETHODIMP nsMsgNewsFolder::CancelComplete()
 {
   NotifyFolderEvent(mDeleteOrMoveMsgCompletedAtom);
   return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgNewsFolder::CancelFailed()
 {