From ff090527c4944b36faebdf7bcf098912cfa63ad3 Mon Sep 17 00:00:00 2001 From: "naving%netscape.com" Date: Mon, 9 Jul 2001 22:15:30 +0000 Subject: [PATCH] 17204. r=bienvenu sr=sspitzer; Add the automatically compact feature when the wasted space exceeds the purge_threshold for offline and local folders. This also includes a patch by bienvenu to make CompactOfflineStores work. git-svn-id: svn://10.0.0.236/trunk@98909 18797224-902f-48f8-a5cc-f745e15eee43 --- mozilla/mailnews/base/public/nsIMsgFolder.idl | 3 +- .../base/public/nsIMsgFolderCompactor.idl | 3 +- .../locale/en-US/messenger.properties | 1 + .../base/src/nsMsgFolderCompactor.cpp | 154 +++++++------ .../mailnews/base/src/nsMsgFolderCompactor.h | 5 + .../base/src/nsMsgFolderDataSource.cpp | 6 +- mozilla/mailnews/base/util/nsMsgDBFolder.cpp | 202 +++++++++++++++++- mozilla/mailnews/base/util/nsMsgDBFolder.h | 7 +- mozilla/mailnews/base/util/nsMsgFolder.cpp | 2 +- mozilla/mailnews/base/util/nsMsgFolder.h | 2 +- .../mailnews/imap/src/nsImapMailFolder.cpp | 7 +- mozilla/mailnews/imap/src/nsImapMailFolder.h | 2 +- .../mailnews/local/src/nsLocalMailFolder.cpp | 64 ++++-- .../mailnews/local/src/nsLocalMailFolder.h | 2 +- mozilla/mailnews/news/src/nsNewsFolder.cpp | 2 + mozilla/mailnews/news/src/nsNntpService.cpp | 2 +- 16 files changed, 370 insertions(+), 94 deletions(-) diff --git a/mozilla/mailnews/base/public/nsIMsgFolder.idl b/mozilla/mailnews/base/public/nsIMsgFolder.idl index d209f5c72b4..37ed9c4db21 100644 --- a/mozilla/mailnews/base/public/nsIMsgFolder.idl +++ b/mozilla/mailnews/base/public/nsIMsgFolder.idl @@ -147,7 +147,8 @@ const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is ne void createStorageIfMissing(in nsIUrlListener urlListener); void compact(in nsIUrlListener aListener, in nsIMsgWindow aMsgWindow); - void compactAll(in nsIUrlListener aListener, in nsIMsgWindow aMsgWindow); + void compactAll(in nsIUrlListener aListener, in nsIMsgWindow aMsgWindow, in nsISupportsArray aFolderArray, in boolean aCompactOfflineAlso, in nsISupportsArray aOfflineFolderArray); + void compactAllOfflineStores(in nsIMsgWindow aMsgWindow, in nsISupportsArray aOfflineFolderArray); void emptyTrash(in nsIMsgWindow aMsgWindow, in nsIUrlListener aListener); /** diff --git a/mozilla/mailnews/base/public/nsIMsgFolderCompactor.idl b/mozilla/mailnews/base/public/nsIMsgFolderCompactor.idl index 538ccf175af..f65995fc385 100644 --- a/mozilla/mailnews/base/public/nsIMsgFolderCompactor.idl +++ b/mozilla/mailnews/base/public/nsIMsgFolderCompactor.idl @@ -21,6 +21,7 @@ */ #include "nsISupports.idl" +#include "nsISupportsArray.idl" interface nsIMsgFolder; interface nsIMsgDatabase; @@ -35,7 +36,7 @@ interface nsIMsgFolderCompactor : nsISupports { void Init(in nsIMsgFolder folder, in string baseMsgUri, in nsIMsgDatabase db, in nsIFileSpec pathSpec, in nsIMsgWindow aMsgWindow); - void InitCompactAll(in nsIMsgFolder folder, in nsIMsgWindow aMsgWindow); + void startCompactingAll(in nsISupportsArray aArrayOfFoldersToCompact, in nsIMsgWindow aMsgWindow, in boolean compactOfflineAlso, in nsISupportsArray aOfflineFolderArray); // we probably want to add the ability to set an enumerator to determine which // messages to copy over in the compaction process. void StartCompacting(); diff --git a/mozilla/mailnews/base/resources/locale/en-US/messenger.properties b/mozilla/mailnews/base/resources/locale/en-US/messenger.properties index d0f54072504..d09fcd9650e 100644 --- a/mozilla/mailnews/base/resources/locale/en-US/messenger.properties +++ b/mozilla/mailnews/base/resources/locale/en-US/messenger.properties @@ -63,6 +63,7 @@ downloadingMail=Downloading Mail for Offline Use sendingUnsent=Sending Unsent Messages compactingFolder=Compacting folder %S... +autoCompactAllFolders=Do you wish to compact all local and offline folders because the total wasted space in all accounts exceeds the purge threshhold? # LOCALIZATION NOTES(verboseFolderFormat): %1$S is folder name, %2$S is server name verboseFolderFormat=%1$S on %2$S diff --git a/mozilla/mailnews/base/src/nsMsgFolderCompactor.cpp b/mozilla/mailnews/base/src/nsMsgFolderCompactor.cpp index 428ecfd2df0..ad2f3fb67cd 100644 --- a/mozilla/mailnews/base/src/nsMsgFolderCompactor.cpp +++ b/mozilla/mailnews/base/src/nsMsgFolderCompactor.cpp @@ -57,6 +57,7 @@ nsFolderCompactState::nsFolderCompactState() m_status = NS_OK; m_messageService = nsnull; m_compactAll = PR_FALSE; + m_compactOfflineAlso = PR_FALSE; m_folderIndex =0; } @@ -143,46 +144,21 @@ nsFolderCompactState::InitDB(nsIMsgDatabase *db) return rv; } -NS_IMETHODIMP nsFolderCompactState::InitCompactAll(nsIMsgFolder *folder, nsIMsgWindow *aMsgWindow) +NS_IMETHODIMP nsFolderCompactState::StartCompactingAll(nsISupportsArray *aArrayOfFoldersToCompact, nsIMsgWindow *aMsgWindow, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray) { nsresult rv = NS_OK; - nsCOMPtr rootFolder; - nsCOMPtr allDescendents; - folder->GetRootFolder(getter_AddRefs(rootFolder)); - NS_NewISupportsArray(getter_AddRefs(allDescendents)); - rootFolder->ListDescendents(allDescendents); - PRUint32 cnt =0; - rv = allDescendents->Count(&cnt); - NS_ENSURE_SUCCESS(rv,rv); + if (aArrayOfFoldersToCompact) + m_folderArray =do_QueryInterface(aArrayOfFoldersToCompact, &rv); + + if (NS_FAILED(rv) || !m_folderArray) + return rv; m_window = aMsgWindow; - NS_NewISupportsArray(getter_AddRefs(m_folderArray)); - PRUint32 expungedBytes=0; - for (PRUint32 i=0; i< cnt;i++) - { - nsCOMPtr supports = getter_AddRefs(allDescendents->ElementAt(i)); - nsCOMPtr folder = do_QueryInterface(supports, &rv); - NS_ENSURE_SUCCESS(rv,rv); - - expungedBytes=0; - if (folder) - rv = folder->GetExpungedBytes(&expungedBytes); - - NS_ENSURE_SUCCESS(rv,rv); - - if (expungedBytes > 0) - rv = m_folderArray->AppendElement(supports); + m_compactAll = PR_TRUE; + m_compactOfflineAlso = aCompactOfflineAlso; + if (m_compactOfflineAlso) + m_offlineFolderArray = do_QueryInterface(aOfflineFolderArray); - NS_ENSURE_SUCCESS(rv,rv); - } - - rv = m_folderArray->Count(&cnt); - NS_ENSURE_SUCCESS(rv,rv); - if ( cnt == 0) - return rv; //no folders to compact - else - m_compactAll = PR_TRUE; - m_folderIndex = 0; nsCOMPtr supports = getter_AddRefs(m_folderArray->ElementAt(m_folderIndex)); nsCOMPtr firstFolder = do_QueryInterface(supports, &rv); @@ -296,14 +272,11 @@ nsFolderCompactState::Init(nsIMsgFolder *folder, const char *baseMsgUri, nsIMsgD return rv; } -NS_IMETHODIMP nsFolderCompactState::StartCompacting() -{ - nsresult rv = NS_OK; - if (m_size > 0) +void nsFolderCompactState::ShowCompactingStatusMsg() { nsXPIDLString formatString; - rv = GetStatusFromMsgName("compactingFolder", getter_Copies(formatString)); + nsresult rv = GetStatusFromMsgName("compactingFolder", getter_Copies(formatString)); if (NS_SUCCEEDED(rv)) { nsXPIDLString folderName; @@ -313,19 +286,17 @@ NS_IMETHODIMP nsFolderCompactState::StartCompacting() ShowStatusMsg(u); PR_FREEIF(u); } +} + +NS_IMETHODIMP nsFolderCompactState::StartCompacting() +{ + nsresult rv = NS_OK; + if (m_size > 0) + { + ShowCompactingStatusMsg(); AddRef(); -#ifdef OLD_WAY - rv = BuildMessageURI(m_baseMessageUri, - m_keyArray[0], - m_messageUri); - if (NS_SUCCEEDED(rv)) - rv = m_messageService->CopyMessage( - m_messageUri, this, PR_FALSE, nsnull, - /* ### should get msg window! */ nsnull, nsnull); -#else rv = m_messageService->CopyMessages(&m_keyArray, m_folder, this, PR_FALSE, nsnull, m_window, nsnull); // m_curIndex = m_size; // advance m_curIndex to the end - we're done -#endif // OLD_WAY } else @@ -391,24 +362,39 @@ nsFolderCompactState::FinishCompact() m_folder->GetMsgDatabase(m_window, getter_AddRefs(db)); db = nsnull; if (m_compactAll) - { - m_folderIndex++; - PRUint32 cnt=0; - rv = m_folderArray->Count(&cnt); - NS_ENSURE_SUCCESS(rv,rv); - if (m_folderIndex == cnt) - return rv; - - nsCOMPtr supports = getter_AddRefs(m_folderArray->ElementAt(m_folderIndex)); - nsCOMPtr folder = do_QueryInterface(supports, &rv); - - if (NS_SUCCEEDED(rv) && folder) - CompactHelper(folder); - } + rv = CompactNextFolder(); return rv; } +nsresult +nsFolderCompactState::CompactNextFolder() +{ + nsresult rv = NS_OK; + m_folderIndex++; + PRUint32 cnt=0; + rv = m_folderArray->Count(&cnt); + NS_ENSURE_SUCCESS(rv,rv); + if (m_folderIndex == cnt) + { + if (m_compactOfflineAlso) + { + nsCOMPtr supports = getter_AddRefs(m_folderArray->ElementAt(m_folderIndex-1)); + nsCOMPtr folder = do_QueryInterface(supports, &rv); + if (NS_SUCCEEDED(rv) && folder) + folder->CompactAllOfflineStores(m_window, m_offlineFolderArray); + } + else + return rv; + } + nsCOMPtr supports = getter_AddRefs(m_folderArray->ElementAt(m_folderIndex)); + nsCOMPtr folder = do_QueryInterface(supports, &rv); + + if (NS_SUCCEEDED(rv) && folder) + rv = CompactHelper(folder); + return rv; +} + nsresult nsFolderCompactState::GetMessage(nsIMsgDBHdr **message) { @@ -514,6 +500,7 @@ nsOfflineStoreCompactState::OnStopRequest(nsIRequest *request, nsISupports *ctxt nsCOMPtr uri; nsCOMPtr msgHdr; nsCOMPtr newMsgHdr; + nsCOMPtr statusFeedback; if (NS_FAILED(rv)) goto done; uri = do_QueryInterface(ctxt, &rv); @@ -521,13 +508,20 @@ nsOfflineStoreCompactState::OnStopRequest(nsIRequest *request, nsISupports *ctxt rv = GetMessage(getter_AddRefs(msgHdr)); if (NS_FAILED(rv)) goto done; - msgHdr->SetMessageOffset(m_startOfNewMsg); + if (msgHdr) + msgHdr->SetMessageOffset(m_startOfNewMsg); - m_db->Commit(nsMsgDBCommitType::kLargeCommit); + if (m_window) + { + m_window->GetStatusFeedback(getter_AddRefs(statusFeedback)); + if (statusFeedback) + statusFeedback->ShowProgress (100 * m_curIndex / m_size); + } // advance to next message m_curIndex ++; if (m_curIndex >= m_size) { + m_db->Commit(nsMsgDBCommitType::kLargeCommit); msgHdr = nsnull;; newMsgHdr = nsnull; // no more to copy finish it up @@ -597,6 +591,10 @@ nsOfflineStoreCompactState::FinishCompact() // rename the copied folder to be the original folder m_fileSpec.Rename((const char*) idlName); + PRUnichar emptyStr = 0; + ShowStatusMsg(&emptyStr); + if (m_compactAll) + rv = CompactNextFolder(); return rv; } @@ -657,3 +655,27 @@ nsFolderCompactState::EndCopy(nsISupports *url, nsresult aStatus) return NS_OK; } +NS_IMETHODIMP nsOfflineStoreCompactState::StartCompacting() +{ + nsresult rv = NS_OK; + if (m_size > 0 && m_curIndex == 0) + { + AddRef(); // we own ourselves, until we're done, anyway. + ShowCompactingStatusMsg(); + m_messageUri.SetLength(0); // clear the previous message uri + rv = BuildMessageURI(m_baseMessageUri, + m_keyArray[0], + m_messageUri); + if (NS_SUCCEEDED(rv)) + rv = m_messageService->CopyMessage( + m_messageUri, this, PR_FALSE, nsnull, m_window, nsnull); + + } + else + { // no messages to copy with + FinishCompact(); +// Release(); // we don't "own" ourselves yet. + } + return rv; +} + diff --git a/mozilla/mailnews/base/src/nsMsgFolderCompactor.h b/mozilla/mailnews/base/src/nsMsgFolderCompactor.h index 63bcc93342c..840a01f08bf 100644 --- a/mozilla/mailnews/base/src/nsMsgFolderCompactor.h +++ b/mozilla/mailnews/base/src/nsMsgFolderCompactor.h @@ -55,6 +55,8 @@ public: nsresult BuildMessageURI(const char *baseURI, PRUint32 key, nsCString& uri); nsresult GetStatusFromMsgName(const char *statusMsgName, PRUnichar ** retval); nsresult ShowStatusMsg(const PRUnichar *aMsg); + void ShowCompactingStatusMsg(); + nsresult CompactNextFolder(); char *m_baseMessageUri; // base message uri nsCString m_messageUri; // current message uri being copy @@ -74,6 +76,8 @@ public: nsCOMPtr m_window; PRUint32 m_folderIndex; // tells which folder to compact in case of compact all PRBool m_compactAll; //flag for compact all + PRBool m_compactOfflineAlso; //whether to compact offline also + nsCOMPtr m_offlineFolderArray; }; @@ -85,6 +89,7 @@ public: virtual ~nsOfflineStoreCompactState(void); virtual nsresult InitDB(nsIMsgDatabase *db); + NS_IMETHOD StartCompacting(); NS_IMETHOD OnStopRequest(nsIRequest *request, nsISupports *ctxt, nsresult status); diff --git a/mozilla/mailnews/base/src/nsMsgFolderDataSource.cpp b/mozilla/mailnews/base/src/nsMsgFolderDataSource.cpp index 2d707935cac..0f5ee2d04af 100644 --- a/mozilla/mailnews/base/src/nsMsgFolderDataSource.cpp +++ b/mozilla/mailnews/base/src/nsMsgFolderDataSource.cpp @@ -731,7 +731,7 @@ nsMsgFolderDataSource::DoCommand(nsISupportsArray/**/* aSources, } else if ((aCommand == kNC_CompactAll)) { - rv = folder->CompactAll(nsnull, mWindow); + rv = folder->CompactAll(nsnull, mWindow, nsnull, PR_FALSE, nsnull); } else if ((aCommand == kNC_EmptyTrash)) { @@ -743,8 +743,8 @@ nsMsgFolderDataSource::DoCommand(nsISupportsArray/**/* aSources, nsCOMPtr literal = do_QueryInterface(elem, &rv); if(NS_SUCCEEDED(rv)) { - PRUnichar *name; - literal->GetValue(&name); + PRUnichar *name; + literal->GetValue(&name); rv = folder->Rename(name,mWindow); PR_FREEIF(name); diff --git a/mozilla/mailnews/base/util/nsMsgDBFolder.cpp b/mozilla/mailnews/base/util/nsMsgDBFolder.cpp index 3d9d0ca1562..8b60a09a664 100644 --- a/mozilla/mailnews/base/util/nsMsgDBFolder.cpp +++ b/mozilla/mailnews/base/util/nsMsgDBFolder.cpp @@ -38,11 +38,23 @@ #include "nsITransport.h" #include "nsIFileTransportService.h" #include "nsIMsgFolderCompactor.h" -#include "nsMsgUtils.h" +#include "nsIDocShell.h" +#include "nsIMsgWindow.h" +#include "nsIPrompt.h" +#include "nsIInterfaceRequestor.h" +#include "nsIStringBundle.h" +#define oneHour 3600000000 +#include "nsMsgUtils.h" + static NS_DEFINE_CID(kPrefServiceCID, NS_PREF_CID); static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID); +static PRTime gtimeOfLastPurgeCheck = 0; //variable to know when to check for purge_threshhold + + +#define PREF_MAIL_PROMPT_PURGE_THRESHOLD "mail.prompt_purge_threshhold" +#define PREF_MAIL_PURGE_THRESHOLD "mail.purge_threshhold" nsIAtom* nsMsgDBFolder::mFolderLoadedAtom=nsnull; nsIAtom* nsMsgDBFolder::mDeleteOrMoveMsgCompletedAtom=nsnull; @@ -576,7 +588,6 @@ nsresult nsMsgDBFolder::CreateFileSpecForDB(const char *userLeafName, nsFileSpec { NS_ENSURE_ARG_POINTER(dbFileSpec); NS_ENSURE_ARG_POINTER(userLeafName); - nsCAutoString proposedDBName(userLeafName); NS_MsgHashIfNecessary(proposedDBName); @@ -1326,3 +1337,190 @@ nsresult nsMsgDBFolder::CompactOfflineStore(nsIMsgWindow *inWindow) return rv; } +nsresult +nsMsgDBFolder::AutoCompact(nsIMsgWindow *aWindow) +{ + NS_ENSURE_ARG_POINTER(aWindow); + nsresult rv = NS_OK; + PRTime timeNow = PR_Now(); //time in microsec + PRTime timeOfLastPurgeCheck = gtimeOfLastPurgeCheck; + PRBool prompt; + rv = GetPromptPurgeThreshold(&prompt); + NS_ENSURE_SUCCESS(rv, rv); + timeOfLastPurgeCheck += oneHour; + if ((timeOfLastPurgeCheck == oneHour || timeOfLastPurgeCheck < timeNow) && prompt) + { + nsCOMPtr accountMgr = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + { + nsCOMPtr allServers; + accountMgr->GetAllServers(getter_AddRefs(allServers)); + NS_ENSURE_SUCCESS(rv,rv); + PRUint32 numServers, serverIndex=0; + rv = allServers->Count(&numServers); + PRInt32 offlineSupportLevel; + if ( numServers > 0 ) + { + nsCOMPtr serverSupports = allServers->ElementAt(serverIndex); + nsCOMPtr server = do_QueryInterface(serverSupports); + NS_ENSURE_SUCCESS(rv,rv); + nsCOMPtr folderArray; + nsCOMPtr offlineFolderArray; + NS_NewISupportsArray(getter_AddRefs(folderArray)); + NS_NewISupportsArray(getter_AddRefs(offlineFolderArray)); + PRInt32 totalExpungedBytes=0; + PRInt32 offlineExpungedBytes =0; + PRInt32 localExpungedBytes = 0; + do + { + nsCOMPtr rootFolder; + rv = server->GetRootFolder(getter_AddRefs(rootFolder)); + if(NS_SUCCEEDED(rv) && rootFolder) + { + rv = server->GetOfflineSupportLevel(&offlineSupportLevel); + NS_ENSURE_SUCCESS(rv,rv); + nsCOMPtr allDescendents; + NS_NewISupportsArray(getter_AddRefs(allDescendents)); + rootFolder->ListDescendents(allDescendents); + PRUint32 cnt=0; + rv = allDescendents->Count(&cnt); + NS_ENSURE_SUCCESS(rv,rv); + PRUint32 expungedBytes=0; + + if (offlineSupportLevel > 0) + { + PRUint32 flags; + for (PRUint32 i=0; i< cnt;i++) + { + nsCOMPtr supports = getter_AddRefs(allDescendents->ElementAt(i)); + nsCOMPtr folder = do_QueryInterface(supports, &rv); + expungedBytes = 0; + folder->GetFlags(&flags); + if (flags & MSG_FOLDER_FLAG_OFFLINE) + folder->GetExpungedBytes(&expungedBytes); + if (expungedBytes > 0 ) + { + offlineFolderArray->AppendElement(supports); + offlineExpungedBytes += expungedBytes; + } + } + } + else //pop or local + { + for (PRUint32 i=0; i< cnt;i++) + { + nsCOMPtr supports = getter_AddRefs(allDescendents->ElementAt(i)); + nsCOMPtr folder = do_QueryInterface(supports, &rv); + folder->GetExpungedBytes(&expungedBytes); + if (expungedBytes > 0 ) + { + folderArray->AppendElement(supports); + localExpungedBytes += expungedBytes; + } + } + } + } + serverSupports = allServers->ElementAt(++serverIndex); + server = do_QueryInterface(serverSupports, &rv); + } + while (serverIndex < numServers); + totalExpungedBytes = localExpungedBytes + offlineExpungedBytes; + PRInt32 purgeThreshold; + rv = GetPurgeThreshold(&purgeThreshold); + NS_ENSURE_SUCCESS(rv, rv); + if (totalExpungedBytes > (purgeThreshold*1024)) + { + nsCOMPtr docShell; + if (aWindow) + { + aWindow->GetRootDocShell(getter_AddRefs(docShell)); + nsCOMPtr bundleService = + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr bundle; + rv = bundleService->CreateBundle("chrome://messenger/locale/messenger.properties", + getter_AddRefs(bundle)); + NS_ENSURE_SUCCESS(rv, rv); + nsXPIDLString alertString; + bundle->GetStringFromName(NS_LITERAL_STRING("autoCompactAllFolders").get(), + getter_Copies(alertString)); + if (docShell) + { + nsCOMPtr dialog(do_GetInterface(docShell)); + if (dialog && alertString) + { + PRBool okToCompact = PR_FALSE; + dialog->Confirm(nsnull, alertString.get(), &okToCompact); + if (okToCompact) + { + if ( localExpungedBytes > 0) + { + nsCOMPtr aSupports = getter_AddRefs(folderArray->ElementAt(0)); + nsCOMPtr msgFolder = do_QueryInterface(aSupports, &rv); + if (msgFolder && NS_SUCCEEDED(rv)) + if (offlineExpungedBytes > 0) + msgFolder->CompactAll(nsnull, aWindow, folderArray, PR_TRUE, offlineFolderArray); + else + msgFolder->CompactAll(nsnull, aWindow, folderArray, PR_FALSE, nsnull); + } + else if (offlineExpungedBytes > 0) + CompactAllOfflineStores(aWindow, offlineFolderArray); + } + } + } + } + } + } + } + gtimeOfLastPurgeCheck = PR_Now(); + } + return rv; +} + +NS_IMETHODIMP +nsMsgDBFolder::CompactAllOfflineStores(nsIMsgWindow *aWindow, nsISupportsArray *aOfflineFolderArray) +{ + nsresult rv= NS_OK; + nsCOMPtr folderCompactor; + folderCompactor = do_CreateInstance(NS_MSGOFFLINESTORECOMPACTOR_CONTRACTID, &rv); + + if (NS_SUCCEEDED(rv) && folderCompactor) + rv = folderCompactor->StartCompactingAll(aOfflineFolderArray, aWindow, PR_FALSE, nsnull); + return rv; +} + +nsresult +nsMsgDBFolder::GetPromptPurgeThreshold(PRBool *aPrompt) +{ + NS_ENSURE_ARG(aPrompt); + nsresult rv; + nsCOMPtr prefService = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && prefService) + { + rv = prefService->GetBoolPref(PREF_MAIL_PROMPT_PURGE_THRESHOLD, aPrompt); + if (NS_FAILED(rv)) + { + *aPrompt = PR_FALSE; + rv = NS_OK; + } + } + return rv; +} + +nsresult +nsMsgDBFolder::GetPurgeThreshold(PRInt32 *aThreshold) +{ + NS_ENSURE_ARG(aThreshold); + nsresult rv; + nsCOMPtr prefService = do_GetService(NS_PREF_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv) && prefService) + { + rv = prefService->GetIntPref(PREF_MAIL_PURGE_THRESHOLD, aThreshold); + if (NS_FAILED(rv)) + { + *aThreshold = 0; + rv = NS_OK; + } + } + return rv; +} diff --git a/mozilla/mailnews/base/util/nsMsgDBFolder.h b/mozilla/mailnews/base/util/nsMsgDBFolder.h index 7c6c2a13ebf..b9efbf41f77 100644 --- a/mozilla/mailnews/base/util/nsMsgDBFolder.h +++ b/mozilla/mailnews/base/util/nsMsgDBFolder.h @@ -33,6 +33,7 @@ #include "nsIMsgHdr.h" #include "nsIOutputStream.h" #include "nsITransport.h" +#include "nsIMsgStringService.h" class nsIMsgFolderCacheElement; /* @@ -95,9 +96,11 @@ public: NS_IMETHOD SetRetentionSettings(nsIMsgRetentionSettings *settings); NS_IMETHOD GetDownloadSettings(nsIMsgDownloadSettings **settings); NS_IMETHOD SetDownloadSettings(nsIMsgDownloadSettings *settings); + NS_IMETHOD CompactAllOfflineStores(nsIMsgWindow *msgWindow, nsISupportsArray *aOfflineFolderArray); NS_IMETHOD GetOfflineStoreOutputStream(nsIOutputStream **outputStream); NS_IMETHOD GetOfflineStoreInputStream(nsIInputStream **outputStream); NS_IMETHOD IsCommandEnabled(const char *command, PRBool *result); + protected: virtual nsresult ReadDBFolderInfo(PRBool force); virtual nsresult FlushToFolderCache(); @@ -117,9 +120,11 @@ protected: nsresult WriteStartOfNewLocalMessage(); nsresult EndNewOfflineMessage(); nsresult CompactOfflineStore(nsIMsgWindow *inWindow); + nsresult AutoCompact(nsIMsgWindow *aWindow); // this is a helper routine that ignores whether MSG_FLAG_OFFLINE is set for the folder nsresult MsgFitsDownloadCriteria(nsMsgKey msgKey, PRBool *result); - + nsresult GetPromptPurgeThreshold(PRBool *aPrompt); + nsresult GetPurgeThreshold(PRInt32 *aThreshold); protected: nsCOMPtr mDatabase; nsString mCharset; diff --git a/mozilla/mailnews/base/util/nsMsgFolder.cpp b/mozilla/mailnews/base/util/nsMsgFolder.cpp index 331b31f5c5d..53e5681e66c 100644 --- a/mozilla/mailnews/base/util/nsMsgFolder.cpp +++ b/mozilla/mailnews/base/util/nsMsgFolder.cpp @@ -1165,7 +1165,7 @@ NS_IMETHODIMP nsMsgFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow *aMsg return NS_ERROR_NOT_IMPLEMENTED; } -NS_IMETHODIMP nsMsgFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow) +NS_IMETHODIMP nsMsgFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aCompactOfflineArray) { NS_ASSERTION(PR_FALSE, "should be overridden by child class"); return NS_ERROR_NOT_IMPLEMENTED; diff --git a/mozilla/mailnews/base/util/nsMsgFolder.h b/mozilla/mailnews/base/util/nsMsgFolder.h index d57ee78ee6a..2a69ddc9d45 100644 --- a/mozilla/mailnews/base/util/nsMsgFolder.h +++ b/mozilla/mailnews/base/util/nsMsgFolder.h @@ -95,7 +95,7 @@ public: NS_IMETHOD CreateSubfolder(const PRUnichar *folderName, nsIMsgWindow *msgWindow); NS_IMETHOD AddSubfolder(nsAutoString *folderName, nsIMsgFolder **newFolder); NS_IMETHOD Compact(nsIUrlListener *aListener, nsIMsgWindow *msgWindow); - NS_IMETHOD CompactAll(nsIUrlListener *aListener, nsIMsgWindow *msgWindow); + NS_IMETHOD CompactAll(nsIUrlListener *aListener, nsIMsgWindow *msgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray); NS_IMETHOD EmptyTrash(nsIMsgWindow *msgWindow, nsIUrlListener *aListener); NS_IMETHOD Rename(const PRUnichar *name, nsIMsgWindow *msgWindow); NS_IMETHOD ContainsChildNamed(const char *name, PRBool *_retval); diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp index 0bfbb38215f..b9d830ba4a5 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.cpp +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.cpp @@ -634,6 +634,8 @@ nsImapMailFolder::UpdateFolder(nsIMsgWindow *msgWindow) else if (NS_SUCCEEDED(rv)) // tell the front end that the folder is loaded if we're not going to { // actually run a url. NotifyFolderEvent(mFolderLoadedAtom); + rv = AutoCompact(msgWindow); + NS_ENSURE_SUCCESS(rv,rv); } return rv; @@ -738,6 +740,7 @@ NS_IMETHODIMP nsImapMailFolder::CreateClientSubfolderInfo(const char *folderName if (NS_FAILED(rv)) return rv; uri.Append('/'); uri.AppendWithConversion(parentName); + rv = rdf->GetResource(uri, getter_AddRefs(res)); if (NS_FAILED(rv)) return rv; @@ -1015,7 +1018,7 @@ NS_IMETHODIMP nsImapMailFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow // compact offline part purely for testing purposes if (WeAreOffline() && (mFlags & MSG_FOLDER_FLAG_OFFLINE)) { - rv = CompactOfflineStore(nsnull); + rv = CompactOfflineStore(aMsgWindow); } else { @@ -1028,7 +1031,7 @@ NS_IMETHODIMP nsImapMailFolder::Compact(nsIUrlListener *aListener, nsIMsgWindow return rv; } -NS_IMETHODIMP nsImapMailFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow) +NS_IMETHODIMP nsImapMailFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray) { return Compact(aListener, aMsgWindow); //for now } diff --git a/mozilla/mailnews/imap/src/nsImapMailFolder.h b/mozilla/mailnews/imap/src/nsImapMailFolder.h index e2a438ad172..5923675d852 100644 --- a/mozilla/mailnews/imap/src/nsImapMailFolder.h +++ b/mozilla/mailnews/imap/src/nsImapMailFolder.h @@ -126,7 +126,7 @@ public: NS_IMETHODIMP CreateStorageIfMissing(nsIUrlListener* urlListener); NS_IMETHOD Compact(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow); - NS_IMETHOD CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow); + NS_IMETHOD CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray); NS_IMETHOD EmptyTrash(nsIMsgWindow *msgWindow, nsIUrlListener *aListener); NS_IMETHOD Delete (); NS_IMETHOD Rename (const PRUnichar *newName, nsIMsgWindow *msgWindow); diff --git a/mozilla/mailnews/local/src/nsLocalMailFolder.cpp b/mozilla/mailnews/local/src/nsLocalMailFolder.cpp index e1d86c22bea..c27a3302f61 100644 --- a/mozilla/mailnews/local/src/nsLocalMailFolder.cpp +++ b/mozilla/mailnews/local/src/nsLocalMailFolder.cpp @@ -565,7 +565,7 @@ nsresult nsMsgLocalMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow) return NS_ERROR_NOT_INITIALIZED; } else - { + { //We must have loaded the folder so send a notification NotifyFolderEvent(mFolderLoadedAtom); //Otherwise we have a valid database so lets extract necessary info. @@ -583,13 +583,16 @@ nsMsgLocalMailFolder::UpdateFolder(nsIMsgWindow *aWindow) //If we don't currently have a database, get it. Otherwise, the folder has been updated (presumably this //changes when we download headers when opening inbox). If it's updated, send NotifyFolderLoaded. if(!mDatabase) - rv = GetDatabase(aWindow); // this will cause a reparse, if needed. + rv = GetDatabase(aWindow); // this will cause a reparse, if needed. else - NotifyFolderEvent(mFolderLoadedAtom); - return rv; -} - -NS_IMETHODIMP + { + NotifyFolderEvent(mFolderLoadedAtom); + rv = AutoCompact(aWindow); + NS_ENSURE_SUCCESS(rv,rv); + } + + return rv; +}NS_IMETHODIMP nsMsgLocalMailFolder::GetMessages(nsIMsgWindow *aMsgWindow, nsISimpleEnumerator* *result) { nsresult rv = GetDatabase(aMsgWindow); @@ -842,14 +845,50 @@ nsMsgLocalMailFolder::CreateSubfolder(const PRUnichar *folderName, nsIMsgWindow return rv; } -NS_IMETHODIMP nsMsgLocalMailFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow) +NS_IMETHODIMP nsMsgLocalMailFolder::CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray) { - nsresult rv; + nsresult rv = NS_OK; + nsCOMPtr folderArray; + if (!aFolderArray) + { + nsCOMPtr rootFolder; + nsCOMPtr allDescendents; + rv = GetRootFolder(getter_AddRefs(rootFolder)); + if (NS_SUCCEEDED(rv) && rootFolder) + { + NS_NewISupportsArray(getter_AddRefs(allDescendents)); + rootFolder->ListDescendents(allDescendents); + PRUint32 cnt =0; + rv = allDescendents->Count(&cnt); + NS_ENSURE_SUCCESS(rv,rv); + NS_NewISupportsArray(getter_AddRefs(folderArray)); + PRUint32 expungedBytes=0; + for (PRUint32 i=0; i< cnt;i++) + { + nsCOMPtr supports = getter_AddRefs(allDescendents->ElementAt(i)); + nsCOMPtr folder = do_QueryInterface(supports, &rv); + NS_ENSURE_SUCCESS(rv,rv); + + expungedBytes=0; + if (folder) + rv = folder->GetExpungedBytes(&expungedBytes); + + NS_ENSURE_SUCCESS(rv,rv); + + if (expungedBytes > 0) + rv = folderArray->AppendElement(supports); + } + rv = folderArray->Count(&cnt); + NS_ENSURE_SUCCESS(rv,rv); + if (cnt == 0 ) return NS_OK; + } + } nsCOMPtr folderCompactor = do_CreateInstance(NS_MSGLOCALFOLDERCOMPACTOR_CONTRACTID, &rv); if (NS_SUCCEEDED(rv) && folderCompactor) - { - rv=folderCompactor->InitCompactAll(this, aMsgWindow); // start with each folder compaction from there - } + if (aFolderArray) + rv = folderCompactor->StartCompactingAll(aFolderArray, aMsgWindow, aCompactOfflineAlso, aOfflineFolderArray); + else if (folderArray) + rv = folderCompactor->StartCompactingAll(folderArray, aMsgWindow, aCompactOfflineAlso, aOfflineFolderArray); return rv; } @@ -916,7 +955,6 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EmptyTrash(nsIMsgWindow *msgWindow, rv = aEnumerator->First(); //will fail if no subfolders if (NS_FAILED(rv)) return NS_OK; } - nsCOMPtr parent; rv = trashFolder->GetParent(getter_AddRefs(parent)); if (NS_SUCCEEDED(rv) && parent) diff --git a/mozilla/mailnews/local/src/nsLocalMailFolder.h b/mozilla/mailnews/local/src/nsLocalMailFolder.h index fb3e0268009..6e234a21716 100644 --- a/mozilla/mailnews/local/src/nsLocalMailFolder.h +++ b/mozilla/mailnews/local/src/nsLocalMailFolder.h @@ -111,7 +111,7 @@ public: NS_IMETHOD AddSubfolder(nsAutoString *folderName, nsIMsgFolder** newFolder); NS_IMETHOD Compact(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow); - NS_IMETHOD CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow); + NS_IMETHOD CompactAll(nsIUrlListener *aListener, nsIMsgWindow *aMsgWindow, nsISupportsArray *aFolderArray, PRBool aCompactOfflineAlso, nsISupportsArray *aOfflineFolderArray); NS_IMETHOD EmptyTrash(nsIMsgWindow *msgWindow, nsIUrlListener *aListener); NS_IMETHOD Delete (); NS_IMETHOD DeleteSubFolders(nsISupportsArray *folders, nsIMsgWindow *msgWindow); diff --git a/mozilla/mailnews/news/src/nsNewsFolder.cpp b/mozilla/mailnews/news/src/nsNewsFolder.cpp index 9320f041003..bb2f462ee21 100644 --- a/mozilla/mailnews/news/src/nsNewsFolder.cpp +++ b/mozilla/mailnews/news/src/nsNewsFolder.cpp @@ -429,6 +429,8 @@ nsMsgNewsFolder::UpdateFolder(nsIMsgWindow *aWindow) rv = mDatabase->ApplyRetentionSettings(retentionSettings); } rv = GetNewMessages(aWindow); + rv = AutoCompact(aWindow); + NS_ENSURE_SUCCESS(rv,rv); } if (rv == NS_MSG_ERROR_OFFLINE) { diff --git a/mozilla/mailnews/news/src/nsNntpService.cpp b/mozilla/mailnews/news/src/nsNntpService.cpp index b0e4a4bc079..6ceb2dd0b8a 100644 --- a/mozilla/mailnews/news/src/nsNntpService.cpp +++ b/mozilla/mailnews/news/src/nsNntpService.cpp @@ -271,8 +271,8 @@ nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aDisplayCon return server->DisplayOfflineMsg(aMsgWindow); } } + newsFolder->SetSaveArticleOffline(shouldStoreMsgOffline); } - newsFolder->SetSaveArticleOffline(shouldStoreMsgOffline); } // now is where our behavior differs....if the consumer is the docshell then we want to