Bug 1782374 - Ensure correct listener notification in nsImapMailFolder::CompactAll(). r=mkmelin

Differential Revision: https://phabricator.services.mozilla.com/D154081
This commit is contained in:
Ben Campbell 2022-08-09 11:23:20 +00:00
Родитель 16e33418ff
Коммит 23fa3b6ce7
2 изменённых файлов: 78 добавлений и 30 удалений

Просмотреть файл

@ -1330,48 +1330,98 @@ NS_IMETHODIMP nsImapMailFolder::CompactAll(nsIUrlListener* aListener,
nsIMsgWindow* aMsgWindow) { nsIMsgWindow* aMsgWindow) {
nsresult rv; nsresult rv;
nsCOMPtr<nsIMsgFolderCompactor> folderCompactor =
do_CreateInstance(NS_MSGFOLDERCOMPACTOR_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIMsgFolder> rootFolder; nsCOMPtr<nsIMsgFolder> rootFolder;
rv = GetRootFolder(getter_AddRefs(rootFolder)); rv = GetRootFolder(getter_AddRefs(rootFolder));
NS_ENSURE_SUCCESS(rv, rv); NS_ENSURE_SUCCESS(rv, rv);
nsTArray<RefPtr<nsIMsgFolder>> folderArray;
{ nsCOMPtr<nsIMsgWindow> msgWindow = aMsgWindow;
// Set up a callable which will start the compaction phase.
auto doCompact = [folderCompactor, rootFolder,
listener = nsCOMPtr<nsIUrlListener>(aListener),
msgWindow]() {
// Collect all the compactable folders.
nsTArray<RefPtr<nsIMsgFolder>> foldersToCompact;
nsTArray<RefPtr<nsIMsgFolder>> allDescendants; nsTArray<RefPtr<nsIMsgFolder>> allDescendants;
rootFolder->GetDescendants(allDescendants); rootFolder->GetDescendants(allDescendants);
for (auto folder : allDescendants) { for (auto folder : allDescendants) {
uint32_t folderFlags; uint32_t flags;
folder->GetFlags(&folderFlags); folder->GetFlags(&flags);
if (!(folderFlags & if (flags &
(nsMsgFolderFlags::Virtual | nsMsgFolderFlags::ImapNoselect))) { (nsMsgFolderFlags::Virtual | nsMsgFolderFlags::ImapNoselect)) {
folderArray.AppendElement(folder); continue;
} }
// Folder can be compacted?
nsCOMPtr<nsIMsgPluggableStore> msgStore;
folder->GetMsgStore(getter_AddRefs(msgStore));
if (!msgStore) {
continue;
}
bool storeSupportsCompaction;
msgStore->GetSupportsCompaction(&storeSupportsCompaction);
if (storeSupportsCompaction) {
foldersToCompact.AppendElement(folder);
}
}
nsresult rv =
folderCompactor->CompactFolders(foldersToCompact, listener, msgWindow);
if (NS_FAILED(rv) && listener) {
// Make sure the listener hears about the failure.
listener->OnStopRunningUrl(nullptr, rv);
}
};
// Collect all the expungeable folders.
nsTArray<RefPtr<nsIMsgImapMailFolder>> foldersToExpunge;
nsTArray<RefPtr<nsIMsgFolder>> allDescendants;
rootFolder->GetDescendants(allDescendants);
for (auto folder : allDescendants) {
nsCOMPtr<nsIMsgImapMailFolder> imapFolder(do_QueryInterface(folder));
if (!imapFolder) {
continue;
}
uint32_t folderFlags;
folder->GetFlags(&folderFlags);
if (!(folderFlags &
(nsMsgFolderFlags::Virtual | nsMsgFolderFlags::ImapNoselect))) {
foldersToExpunge.AppendElement(imapFolder);
} }
} }
nsCOMPtr<nsIMsgPluggableStore> msgStore; if (!WeAreOffline() && !foldersToExpunge.IsEmpty()) {
rv = GetMsgStore(getter_AddRefs(msgStore)); // Kick off expunge on all the folders (the IMAP protocol will handle
NS_ENSURE_SUCCESS(rv, rv); // queuing them up as needed).
bool storeSupportsCompaction;
msgStore->GetSupportsCompaction(&storeSupportsCompaction);
if (storeSupportsCompaction) { // A listener to track the completed expunges.
nsCOMPtr<nsIMsgFolderCompactor> folderCompactor = UrlListener* l = new UrlListener();
do_CreateInstance(NS_MSGFOLDERCOMPACTOR_CONTRACTID, &rv); l->mStopFn = [expungeCount = foldersToExpunge.Length(), doCompact](
NS_ENSURE_SUCCESS(rv, rv); nsIURI* url, nsresult status) mutable -> nsresult {
rv = folderCompactor->CompactFolders(folderArray, aListener, aMsgWindow); // NOTE: we're ignoring expunge result code - nothing much we can do
NS_ENSURE_SUCCESS(rv, rv); // here to recover, so just plough on.
} --expungeCount;
if (expungeCount == 0) {
if (!WeAreOffline()) { // All the expunges are done so start compacting.
// Tell all the folders to also kick off an Expunge on the server. doCompact();
for (auto& folder : folderArray) { }
nsCOMPtr<nsIMsgImapMailFolder> imapFolder(do_QueryInterface(folder)); return NS_OK;
if (imapFolder) { };
nsCOMPtr<nsIUrlListener> l(do_QueryInterface(folder)); // Go!
rv = imapFolder->Expunge(l, aMsgWindow); for (auto& imapFolder : foldersToExpunge) {
NS_ENSURE_SUCCESS(rv, rv); rv = imapFolder->Expunge(l, aMsgWindow);
if (NS_FAILED(rv)) {
// Make sure expungeCount is kept in sync!
l->OnStopRunningUrl(nullptr, rv);
} }
} }
} else {
// No expunging. Start the compaction immediately.
doCompact();
} }
return NS_OK; return NS_OK;
} }

Просмотреть файл

@ -162,8 +162,6 @@ add_task(async function compactOfflineStore() {
let listener = new PromiseTestUtils.PromiseUrlListener(); let listener = new PromiseTestUtils.PromiseUrlListener();
gRootFolder.compactAll(listener, null); gRootFolder.compactAll(listener, null);
await listener.promise; await listener.promise;
// eslint-disable-next-line mozilla/no-arbitrary-setTimeout
await new Promise(resolve => setTimeout(resolve, 300));
}); });
add_task(function test_checkCompactionResult1() { add_task(function test_checkCompactionResult1() {