Bug 1782374 - Ensure correct listener notification in nsImapMailFolder::CompactAll(). r=mkmelin
Differential Revision: https://phabricator.services.mozilla.com/D154081
This commit is contained in:
Родитель
16e33418ff
Коммит
23fa3b6ce7
|
@ -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() {
|
||||||
|
|
Загрузка…
Ссылка в новой задаче