Bug 439225 Revamp nsIMsgFolderNotificationService. p=Siddharth Agarwal <sid1337@gmail.com>,r/sr=bienvenu,r=me for test changes

This commit is contained in:
bugzilla%standard8.plus.com 2008-06-25 13:53:23 +00:00
Родитель 7098a36d61
Коммит 838c75a62c
15 изменённых файлов: 362 добавлений и 159 удалений

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

@ -77,7 +77,7 @@ XPIDLSRCS = \
nsIMsgCopyService.idl \
nsIMsgCopyServiceListener.idl \
nsIMsgFolderListener.idl \
nsIMsgFolderNotificationService.idl \
nsIMsgFolderNotificationService.idl \
nsIMsgStatusFeedback.idl \
nsIMsgMailNewsUrl.idl \
nsIMsgWindow.idl \

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* David Bienvenu <bienvenu@mozilla.com>
* Siddharth Agarwal <sid1337@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -37,29 +38,100 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIMsgDBHdr;
interface nsIMsgFolder;
interface nsIArray;
// This is similar to nsIFolderListener, but with slightly different semantics,
// especially w.r.t. moving messages and folders. Some listeners want to know
// about moves, instead of getting an itemAdded and itemRemoved notification.
// Folder listeners also only tend to get called if a view is open on the folder,
// which is not always the case. I don't want to change nsIFolderListener at this
// point since there are lots of extensions that rely on it. Eventually,
// these two interfaces should be combined somehow.
/**
* This is similar to nsIFolderListener, but with slightly different semantics,
* especially w.r.t. moving messages and folders. Some listeners want to know
* about moves, instead of getting an itemAdded and itemRemoved notification.
* Folder listeners also only tend to get called if a view is open on the folder,
* which is not always the case. I don't want to change nsIFolderListener at this
* point since there are lots of extensions that rely on it. Eventually,
* these two interfaces should be combined somehow.
*/
[scriptable, uuid(4b89a390-0bd4-4b50-a87a-c31ddfde58f7)]
[scriptable, uuid(4dee6994-1a7d-4200-b9a7-b1fc54df3397)]
interface nsIMsgFolderListener : nsISupports {
// new msg or folder added
void itemAdded(in nsISupports aItem);
// folder or msg deleted (no trash)
void itemDeleted(in nsISupports aItem);
void itemMoveCopyCompleted(in boolean aMove,
in nsIArray aSrcItems,
in nsIMsgFolder aDestFolder);
/**
* Notified immediately after a message is added to a folder. This could be a new incoming
* message to a local folder, or a new message in an IMAP folder when it is opened.
*
* @param aMsg The message header that was just added
*/
void msgAdded(in nsIMsgDBHdr aMsg);
/**
* Notified after a command to delete a group of messages has been given, but before the
* messages have actually been deleted.
*
* @param aMsgs An array of the message headers about to be deleted
*
* @note
* This notification will not take place if the messages are being deleted from the folder
* as the result of a move to another folder. Instead, the msgsMoveCopyCompleted() notification
* takes place.
*
* @note
* "Deleting" to a trash folder is actually a move, and is covered by msgsMoveCopyCompleted()
*
* @note
* If the user has selected the IMAP delete model (marking messages as deleted, then purging them
* later) for an IMAP account, this notification will not take place on the delete. This will only
* take place on the purge.
*/
void msgsDeleted(in nsIArray aMsgs);
/**
* Notified after a command to move or copy a group of messages completes. In case of a move,
* this is before the messages have been deleted from the source folder.
*
* @param aMove true if a move, false if a copy
* @param aSrcMsgs An array of the message headers in the source folder
* @param aDestFolder The folder these messages were moved to
*/
void msgsMoveCopyCompleted(in boolean aMove,
in nsIArray aSrcMsgs,
in nsIMsgFolder aDestFolder);
/**
* Notified after a folder has been deleted and its corresponding file(s) deleted from disk.
*
* @param aFolder The folder that has just been deleted
*
* @note
* "Deleting" to a trash folder is actually a move, and is covered by folderMoveCopyCompleted()
*/
void folderDeleted(in nsIMsgFolder aFolder);
/**
* Notified after a command to move or copy a folder completes. In case of a move, at this point,
* the original folder and its files have already been moved to the new location.
*
* @param aMove true if a move, false if a copy
* @param aSrcFolder The original folder that was moved
* @param aDestFolder The parent folder this folder was moved to
*/
void folderMoveCopyCompleted(in boolean aMove,
in nsIMsgFolder aSrcFolder,
in nsIMsgFolder aDestFolder);
/**
* Notified after a folder is renamed.
*
* @param aOrigFolder The folder with the old name
* @param aNewFolder The folder with the new name
*/
void folderRenamed(in nsIMsgFolder aOrigFolder, in nsIMsgFolder aNewFolder);
// extensibility hook
/**
* Notified when a particular event takes place for an item. Currently this is
* unused.
*
* @param aItem The item the event takes place on
* @param aEvent String describing the event
* @param aData Data relevant to the event
*/
void itemEvent(in nsISupports aItem, in ACString aEvent, in nsISupports aData);
};

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* David Bienvenu <bienvenu@mozilla.com>
* Siddharth Agarwal <sid1337@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -37,27 +38,34 @@
* ***** END LICENSE BLOCK ***** */
#include "nsISupports.idl"
interface nsIMsgDBHdr;
interface nsIMsgFolder;
interface nsIMsgFolderListener;
interface nsIArray;
[scriptable, uuid(d96b19df-a11d-4df2-90b7-ce553176c621)]
[scriptable, uuid(fc5bb4cf-7ad1-4b11-a5a6-550f713fa334)]
interface nsIMsgFolderNotificationService : nsISupports {
readonly attribute boolean hasListeners;
void addListener(in nsIMsgFolderListener aListener);
void removeListener(in nsIMsgFolderListener aListener);
void notifyItemAdded(in nsISupports aItem);
// for the convenience of the callers, we allow this to be an nsIArray of items,
// or an individual nsISupports.
void notifyItemDeleted(in nsISupports aItem);
void notifyItemMoveCopyCompleted(in boolean aMove,
in nsIArray aSrcItems,
in nsIMsgFolder aDestFolder);
// message-specific functions
// single message for added, array for delete/move/copy
void notifyMsgAdded(in nsIMsgDBHdr aMsg);
void notifyMsgsDeleted(in nsIArray aMsgs);
void notifyMsgsMoveCopyCompleted(in boolean aMove,
in nsIArray aSrcMsgs,
in nsIMsgFolder aDestFolder);
// folder specific functions
// single folders, all the time
void notifyFolderDeleted(in nsIMsgFolder aFolder);
void notifyFolderMoveCopyCompleted(in boolean aMove,
in nsIMsgFolder aSrcFolder,
in nsIMsgFolder aDestFolder);
void notifyFolderRenamed(in nsIMsgFolder aOrigFolder, in nsIMsgFolder aNewFolder);
// extensibility hook
void notifyItemEvent(in nsISupports aItem, in ACString aEvent, in nsISupports aData);
};

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

@ -181,26 +181,21 @@ nsMsgCopyService::ClearRequest(nsCopyRequest* aRequest, nsresult rv)
// Send notifications to nsIMsgFolderListeners
if (NS_SUCCEEDED(rv) && aRequest->m_requestType == nsCopyFoldersType)
{
nsCOMPtr <nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
{
PRBool hasListeners;
notifier->GetHasListeners(&hasListeners);
if (hasListeners)
{
nsCOMPtr<nsIMutableArray> folderArray(do_CreateInstance(NS_ARRAY_CONTRACTID, &rv));
if (folderArray)
// Iterate over the copy sources and append their message arrays to this mutable array
// or in the case of folders, the source folder.
PRInt32 cnt, i;
cnt = aRequest->m_copySourceArray.Count();
for (i = 0; i < cnt; i++)
{
// Iterate over the copy sources and append their message arrays to this mutable array
// or in the case of folders, the source folder.
PRInt32 cnt, i;
cnt = aRequest->m_copySourceArray.Count();
for (i=0; i < cnt; i++)
{
nsCopySource *copySource = (nsCopySource*) aRequest->m_copySourceArray.ElementAt(i);
folderArray->AppendElement(copySource->m_msgFolder, PR_FALSE);
}
notifier->NotifyItemMoveCopyCompleted(aRequest->m_isMoveOrDraftOrTemplate, folderArray, aRequest->m_dstFolder);
nsCopySource *copySource = (nsCopySource*) aRequest->m_copySourceArray.ElementAt(i);
notifier->NotifyFolderMoveCopyCompleted(aRequest->m_isMoveOrDraftOrTemplate, copySource->m_msgFolder, aRequest->m_dstFolder);
}
}
}

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

@ -21,6 +21,7 @@
*
* Contributor(s):
* David Bienvenu <bienvenu@mozilla.org>
* Siddharth Agarwal <sid1337@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either of the GNU General Public License Version 2 or later (the "GPL"),
@ -81,76 +82,121 @@ NS_IMETHODIMP nsMsgFolderNotificationService::RemoveListener(nsIMsgFolderListene
return NS_OK;
}
/* void notifItemAdded (in nsISupports aItem); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyItemAdded(nsISupports *aItem)
{
PRInt32 count = m_listeners.Count();
for(PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
return NS_ERROR_FAILURE;
listener->ItemAdded(aItem);
}
return NS_OK;
}
/* void notifyItemDeleted (in nsISupports aItem); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyItemDeleted(nsISupports *aItem)
/* void notifyMsgAdded (in nsIMsgDBHdr aMsg); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyMsgAdded(nsIMsgDBHdr *aMsg)
{
PRInt32 count = m_listeners.Count();
for(PRInt32 i = 0; i < count; i++)
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
return NS_ERROR_FAILURE;
listener->ItemDeleted(aItem);
listener->MsgAdded(aMsg);
}
return NS_OK;
}
/* void notifyItemMoveCopyCompleted (in boolean aMove, in nsISupportsArray aSrcItems, in nsIMsgFolder aDestFolder); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyItemMoveCopyCompleted(PRBool aMove, nsIArray *aSrcItems, nsIMsgFolder *aDestFolder)
/* void notifyMsgsDeleted (in nsIArray aMsgs); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyMsgsDeleted(nsIArray *aMsgs)
{
PRInt32 count = m_listeners.Count();
for(PRInt32 i = 0; i < count; i++)
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
if (!listener)
return NS_ERROR_FAILURE;
listener->ItemMoveCopyCompleted(aMove, aSrcItems, aDestFolder);
listener->MsgsDeleted(aMsgs);
}
return NS_OK;
}
/* void notifyMsgsMoveCopyCompleted (in boolean aMove, in nsIArray aSrcMsgs, in nsIMsgFolder aDestFolder); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyMsgsMoveCopyCompleted(PRBool aMove, nsIArray *aSrcMsgs, nsIMsgFolder *aDestFolder)
{
PRInt32 count = m_listeners.Count();
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
return NS_ERROR_FAILURE;
listener->MsgsMoveCopyCompleted(aMove, aSrcMsgs, aDestFolder);
}
return NS_OK;
}
/* void notifyFolderDeleted(in nsIMsgFolder aFolder); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyFolderDeleted(nsIMsgFolder *aFolder)
{
PRInt32 count = m_listeners.Count();
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
return NS_ERROR_FAILURE;
listener->FolderDeleted(aFolder);
}
return NS_OK;
}
/* void notifyFolderMoveCopyCompleted(in boolean aMove, in nsIMsgFolder aSrcFolder, in nsIMsgFolder aDestFolder); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyFolderMoveCopyCompleted(PRBool aMove, nsIMsgFolder *aSrcFolder, nsIMsgFolder *aDestFolder)
{
PRInt32 count = m_listeners.Count();
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
return NS_ERROR_FAILURE;
listener->FolderMoveCopyCompleted(aMove, aSrcFolder, aDestFolder);
}
return NS_OK;
}
/* void notifyFolderRenamed (in nsIMsgFolder aOrigFolder, in nsIMsgFolder aNewFolder); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyFolderRenamed(nsIMsgFolder *aOrigFolder, nsIMsgFolder *aNewFolder)
{
return NS_ERROR_NOT_IMPLEMENTED;
PRInt32 count = m_listeners.Count();
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
return NS_ERROR_FAILURE;
listener->FolderRenamed(aOrigFolder, aNewFolder);
}
return NS_OK;
}
/* void notifyItemEvent (in nsISupports aItem, in string aEvent, in nsISupports aData); */
NS_IMETHODIMP nsMsgFolderNotificationService::NotifyItemEvent(nsISupports *aItem, const nsACString &aEvent, nsISupports *aData)
{
PRInt32 count = m_listeners.Count();
for(PRInt32 i = 0; i < count; i++)
for (PRInt32 i = 0; i < count; i++)
{
nsCOMPtr<nsIMsgFolderListener> listener = m_listeners[i];
NS_ASSERTION(listener, "listener is null");
if (!listener)
if (!listener)
return NS_ERROR_FAILURE;
listener->ItemEvent(aItem, aEvent, aData);
}
return NS_OK;
}

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

@ -36,11 +36,13 @@ var gExpectedEvents;
// Events, use these to indicate which events are expected.
const kEvents =
{
itemAdded: 0,
itemDeleted: 1,
itemMoveCopyCompleted: 2,
folderRenamed: 3,
itemEvent: 4
msgAdded: 0,
msgsDeleted: 1,
msgsMoveCopyCompleted: 2,
folderDeleted: 3,
folderMoveCopyCompleted: 4,
folderRenamed: 5,
itemEvent: 6
};
// The current status (what all has been done)
@ -62,9 +64,9 @@ var gMsgHdrs = new Array();
// Our listener, which captures events and verifies them as they are received.
var gMFListener =
{
itemAdded: function(aItem)
msgAdded: function(aMsg)
{
verify([kEvents.itemAdded, aItem]);
verify([kEvents.msgAdded, aMsg]);
var hdr = gHdrsReceived.pop();
gMsgHdrs.push({hdr: hdr, ID: hdr.messageId});
if (gExpectedEvents.length == 0)
@ -75,9 +77,9 @@ var gMFListener =
}
},
itemDeleted: function(aItem)
msgsDeleted: function(aMsgs)
{
verify([kEvents.itemDeleted, aItem]);
verify([kEvents.msgsDeleted, aMsgs]);
if (gExpectedEvents.length == 0)
{
gCurrStatus |= kStatus.notificationsDone;
@ -86,9 +88,42 @@ var gMFListener =
}
},
itemMoveCopyCompleted: function(aMove, aSrcItems, aDestFolder)
msgsMoveCopyCompleted: function(aMove, aSrcMsgs, aDestFolder)
{
verify([kEvents.itemMoveCopyCompleted, aMove, aSrcItems, aDestFolder]);
verify([kEvents.msgsMoveCopyCompleted, aMove, aSrcMsgs, aDestFolder]);
if (gExpectedEvents.length == 0)
{
gCurrStatus |= kStatus.notificationsDone;
if (gCurrStatus == kStatus.everythingDone)
resetStatusAndProceed();
}
},
folderDeleted: function(aFolder)
{
verify([kEvents.folderDeleted, aFolder]);
if (gExpectedEvents.length == 0)
{
gCurrStatus |= kStatus.notificationsDone;
if (gCurrStatus == kStatus.everythingDone)
resetStatusAndProceed();
}
},
folderMoveCopyCompleted: function(aMove, aSrcFolder, aDestFolder)
{
verify([kEvents.folderMoveCopyCompleted, aMove, aSrcFolder, aDestFolder]);
if (gExpectedEvents.length == 0)
{
gCurrStatus |= kStatus.notificationsDone;
if (gCurrStatus == kStatus.everythingDone)
resetStatusAndProceed();
}
},
folderRenamed: function(aOrigFolder, aNewFolder)
{
verify([gEvents.folderRenamed, aOrigFolder, aNewFolder]);
if (gExpectedEvents.length == 0)
{
gCurrStatus |= kStatus.notificationsDone;
@ -170,6 +205,9 @@ Array.prototype.hasExactlyElements = function(elements)
// Check: the element should be present
do_check_neq(this.indexOf(elements), -1);
}
// This shouldn't happen
else
do_throw("Unrecognized item returned from listener");
};
// Verifies an event
@ -185,20 +223,29 @@ function verify(event)
switch (eventType)
{
case kEvents.itemAdded:
case kEvents.itemDeleted:
// Check: headers/folders match.
case kEvents.msgAdded:
case kEvents.msgsDeleted:
case kEvents.folderDeleted:
// Check: headers match/folder matches.
expected[1].hasExactlyElements(event[1]);
break;
case kEvents.itemMoveCopyCompleted:
case kEvents.msgsMoveCopyCompleted:
case kEvents.folderMoveCopyCompleted:
// Check: Move or copy as expected.
do_check_eq(expected[1], event[1]);
// Check: headers/folders match.
// Check: headers match/folder matches.
expected[2].hasExactlyElements(event[2]);
// Check: destination folder matches.
do_check_eq(expected[3], event[3]);
break;
case kEvents.folderRenamed:
// Check: source folder matches
expected[1].hasExactlyElements(event[1]);
// Check: destination folder name matches
do_check_eq(expected[2], event[2].prettiestName);
break;
}
}

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

@ -8,19 +8,20 @@
/*
* Test suite for basic functionality with nsIMsgFolderListeners.
*
* Currently tests itemAdded, itemDeleted, itemMoveCopyCompleted, and itemEvent.
*/
const mFNSContractID = "@mozilla.org/messenger/msgnotificationservice;1";
const nsIMFNService = Ci.nsIMsgFolderNotificationService;
const nsIMFListener = Ci.nsIMsgFolderListener;
const kItemAdded = 0x1;
const kItemDeleted = 0x2;
const kItemMoveCopyCompleted = 0x4;
const kItemEvent = 0x8;
const numOptions = 4;
const kMsgAdded = 0x1;
const kMsgsDeleted = 0x2;
const kMsgsMoveCopyCompleted = 0x4;
const kFolderDeleted = 0x8;
const kFolderMoveCopyCompleted = 0x10;
const kFolderRenamed = 0x20;
const kItemEvent = 0x40;
const numOptions = 7;
var gMFNService = Cc[mFNSContractID].getService(nsIMFNService);
@ -29,22 +30,40 @@ var gMFListener =
{
mReceived: 0,
itemAdded: function (aItem)
msgAdded: function (aMsg)
{
do_check_eq(this.mReceived & kItemAdded, 0);
this.mReceived |= kItemAdded;
do_check_eq(this.mReceived & kMsgAdded, 0);
this.mReceived |= kMsgAdded;
},
itemDeleted: function (aItem)
msgsDeleted: function (aMsgs)
{
do_check_eq(this.mReceived & kItemDeleted, 0);
this.mReceived |= kItemDeleted;
do_check_eq(this.mReceived & kMsgsDeleted, 0);
this.mReceived |= kMsgsDeleted;
},
itemMoveCopyCompleted: function (aMove, aSrcItems, aDestFolder)
msgsMoveCopyCompleted: function (aMove, aSrcMsgs, aDestFolder)
{
do_check_eq(this.mReceived & kItemMoveCopyCompleted, 0);
this.mReceived |= kItemMoveCopyCompleted;
do_check_eq(this.mReceived & kMsgsMoveCopyCompleted, 0);
this.mReceived |= kMsgsMoveCopyCompleted;
},
folderDeleted: function (aFolder)
{
do_check_eq(this.mReceived & kFolderDeleted, 0);
this.mReceived |= kFolderDeleted;
},
folderMoveCopyCompleted: function (aMove, aSrcFolder, aDestFolder)
{
do_check_eq(this.mReceived & kFolderMoveCopyCompleted, 0);
this.mReceived |= kFolderMoveCopyCompleted;
},
folderRenamed: function (aOrigFolder, aNewFolder)
{
do_check_eq(this.mReceived & kFolderRenamed, 0);
this.mReceived |= kFolderRenamed;
},
itemEvent: function (aItem, aEvent, aData)
@ -56,9 +75,12 @@ var gMFListener =
function NotifyMsgFolderListeners()
{
gMFNService.notifyItemAdded(null);
gMFNService.notifyItemDeleted(null);
gMFNService.notifyItemMoveCopyCompleted(null, null, null);
gMFNService.notifyMsgAdded(null);
gMFNService.notifyMsgsDeleted(null);
gMFNService.notifyMsgsMoveCopyCompleted(null, null, null);
gMFNService.notifyFolderDeleted(null);
gMFNService.notifyFolderMoveCopyCompleted(null, null, null);
gMFNService.notifyFolderRenamed(null, null);
gMFNService.notifyItemEvent(null, null, null);
}

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

@ -14,6 +14,7 @@
* - Copy messages from files into the db
* - Moving and copying one or more messages from one local folder to another
* - Moving folders, with and without subfolders
* - Renaming folders
* - Deleting messages and folders, to trash and from trash (permanently)
*/
@ -28,7 +29,7 @@ var gLocalTrashFolder;
function copyFileMessage(file, destFolder, isDraftOrTemplate)
{
copyListener.mFolderStoredIn = destFolder;
gExpectedEvents = [[kEvents.itemAdded, gHdrsReceived]];
gExpectedEvents = [[kEvents.msgAdded, gHdrsReceived]];
gCopyService.CopyFileMessage(file, destFolder, null, isDraftOrTemplate, 0, copyListener, null);
gCurrStatus |= kStatus.functionCallDone;
if (gCurrStatus == kStatus.everythingDone)
@ -41,7 +42,7 @@ function copyMessages(items, isMove, srcFolder, destFolder)
items.forEach(function (item) {
array.appendElement(item, false);
});
gExpectedEvents = [[kEvents.itemMoveCopyCompleted, isMove, items, destFolder]];
gExpectedEvents = [[kEvents.msgsMoveCopyCompleted, isMove, items, destFolder]];
gCopyService.CopyMessages(srcFolder, array, destFolder, isMove, copyListener, null, true);
gCurrStatus |= kStatus.functionCallDone;
if (gCurrStatus == kStatus.everythingDone)
@ -54,7 +55,7 @@ function copyFolders(items, isMove, destFolder)
items.forEach(function (item) {
array.appendElement(item, false);
});
gExpectedEvents = [[kEvents.itemMoveCopyCompleted, isMove, items, destFolder]];
gExpectedEvents = [[kEvents.folderMoveCopyCompleted, isMove, items, destFolder]];
gCopyService.CopyFolders(array, destFolder, isMove, copyListener, null);
gCurrStatus |= kStatus.functionCallDone;
if (gCurrStatus == kStatus.everythingDone)
@ -74,11 +75,11 @@ function deleteMessages(srcFolder, items, deleteStorage, isMove)
{
// We won't be getting any OnStopCopy notification in this case
gCurrStatus = kStatus.onStopCopyDone;
gExpectedEvents = [[kEvents.itemDeleted, items]];
gExpectedEvents = [[kEvents.msgsDeleted, items]];
}
else
// We have to be getting a move notification, even if isMove is false
gExpectedEvents = [[kEvents.itemMoveCopyCompleted, true, items, gLocalTrashFolder]];
gExpectedEvents = [[kEvents.msgsMoveCopyCompleted, true, items, gLocalTrashFolder]];
srcFolder.deleteMessages(array, null, deleteStorage, isMove, copyListener, true);
gCurrStatus |= kStatus.functionCallDone;
@ -86,6 +87,16 @@ function deleteMessages(srcFolder, items, deleteStorage, isMove)
resetStatusAndProceed();
}
function renameFolder(folder, newName)
{
gExpectedEvents = [[kEvents.folderRenamed, [folder], newName]];
gCurrStatus = kStatus.onStopCopyDone;
folder.rename(newName, null);
gCurrStatus |= kStatus.functionCallDone;
if (gCurrStatus == kStatus.everythingDone)
resetStatusAndProceed();
}
function deleteFolder(folder)
{
var array = Cc["@mozilla.org/array;1"]
@ -97,9 +108,9 @@ function deleteFolder(folder)
gCurrStatus = kStatus.onStopCopyDone;
// If ancestor is trash, expect an itemDeleted, otherwise expect an itemMoveCopyCompleted
if (gLocalTrashFolder.isAncestorOf(folder))
gExpectedEvents = [[kEvents.itemDeleted, [folder]]];
gExpectedEvents = [[kEvents.folderDeleted, [folder]]];
else
gExpectedEvents = [[kEvents.itemMoveCopyCompleted, true, [folder], gLocalTrashFolder]];
gExpectedEvents = [[kEvents.folderMoveCopyCompleted, true, [folder], gLocalTrashFolder]];
folder.parent.deleteSubFolders(array, null);
gCurrStatus |= kStatus.functionCallDone;
@ -158,9 +169,16 @@ const gTestArray =
// shift delete from trash
function testDeleteMessages4() { deleteMessages(gLocalTrashFolder, [gMsgHdrs[1].hdr], true, false); },
// Renaming folders
// XXX enable after working out bugs in rename folder
/*function testRename1() { renameFolder(gLocalFolder3, "folder4"); },
function testRename2() { renameFolder(gLocalFolder2.getChildNamed("folder4"), "folder3"); }
function testRename3() { renameFolder(gLocalFolder2, "folder4"); }
function testRename4() { renameFolder(gLocalInboxFolder.getChildNamed("folder4"), "folder2"); }*/
// Deleting folders (currently only one folder delete is supported through the UI)
function deleteFolder1() { deleteFolder(gLocalInboxFolder.getChildNamed("folder3")); },
function deleteFolder2() { deleteFolder(gLocalFolder2); },
function deleteFolder2() { deleteFolder(gLocalInboxFolder.getChildNamed("folder2")); },
function deleteFolder3() { deleteFolder(gLocalTrashFolder.getChildNamed("folder3")); } /*,
// XXX enable after making sure that only the topmost folder has its itemDeleted called
function deleteFolder4() { deleteFolder(gLocalTrashFolder.getChildNamed("folder2")); }*/
@ -199,12 +217,14 @@ function run_test()
function doTest(test)
{
// Set a limit of three seconds; if the notifications haven't arrived by then there's a problem.
do_timeout(3000, "if (gTest == "+test+") \
do_throw('Notifications not received in 3000 ms for operation '+gTest+', current status is '+gCurrStatus);");
if (test <= gTestArray.length)
gTestArray[test-1]();
{
var testFn = gTestArray[test-1];
// Set a limit of three seconds; if the notifications haven't arrived by then there's a problem.
do_timeout(3000, "if (gTest == "+test+") \
do_throw('Notifications not received in 3000 ms for operation "+testFn.name+", current status is '+gCurrStatus);");
testFn();
}
else
{
do_test_finished(); // for the one in run_test()

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

@ -2867,11 +2867,9 @@ NS_IMETHODIMP nsMsgDBFolder::RecursiveDelete(PRBool deleteStorage, nsIMsgWindow
if (deleteStorage && status == NS_OK)
{
status = Delete();
nsCOMPtr <nsISupports> supports;
QueryInterface(NS_GET_IID(nsISupports), getter_AddRefs(supports));
nsCOMPtr <nsIMsgFolderNotificationService> notifier = do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemDeleted(supports);
notifier->NotifyFolderDeleted(this);
}
return status;
}

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

@ -68,7 +68,6 @@
#include "nsIMsgFolderCacheElement.h"
#include "MailNewsTypes2.h"
#include "nsMsgUtils.h"
#include "nsIMsgFolderNotificationService.h"
#include "nsIMutableArray.h"
#include "nsICollation.h"

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

@ -2097,7 +2097,7 @@ NS_IMETHODIMP nsImapMailFolder::DeleteMessages(nsIArray *messages,
{
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemDeleted(messages);
notifier->NotifyMsgsDeleted(messages);
}
mDatabase->DeleteMessages(&srcKeyArray,nsnull);
EnableNotifications(allMessageCountNotifications, PR_TRUE, PR_TRUE /*dbBatching*/);
@ -2507,7 +2507,7 @@ NS_IMETHODIMP nsImapMailFolder::UpdateImapMailboxInfo(nsIImapProtocol* aProtocol
MsgGetHeadersFromKeys(mDatabase, keysToDelete, hdrsToDelete);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemDeleted(hdrsToDelete);
notifier->NotifyMsgsDeleted(hdrsToDelete);
// It would be nice to notify RDF or whoever of a mass delete here.
mDatabase->DeleteMessages(&keysToDelete, nsnull);
@ -2797,9 +2797,9 @@ nsresult nsImapMailFolder::NormalEndHeaderParseStream(nsIImapProtocol *aProtocol
if (mDatabase && (!m_msgMovedByFilter || ShowDeletedMessages()))
{
mDatabase->AddNewHdrToDB(newMsgHdr, PR_TRUE);
nsCOMPtr <nsIMsgFolderNotificationService> notifier = do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemAdded(newMsgHdr);
notifier->NotifyMsgAdded(newMsgHdr);
}
m_msgParser->Clear(); // clear out parser, because it holds onto a msg hdr.
m_msgParser->SetMailDB(nsnull); // tell it to let go of the db too.
@ -4345,11 +4345,11 @@ nsImapMailFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
if (notifier && m_copyState)
{
if (imapAction == nsIImapUrl::nsImapOnlineMove)
notifier->NotifyItemMoveCopyCompleted(PR_TRUE, m_copyState->m_messages, this);
notifier->NotifyMsgsMoveCopyCompleted(PR_TRUE, m_copyState->m_messages, this);
else if (imapAction == nsIImapUrl::nsImapOnlineCopy)
notifier->NotifyItemMoveCopyCompleted(PR_FALSE, m_copyState->m_messages, this);
notifier->NotifyMsgsMoveCopyCompleted(PR_FALSE, m_copyState->m_messages, this);
else if (imapAction == nsIImapUrl::nsImapDeleteMsg)
notifier->NotifyItemDeleted(m_copyState->m_messages);
notifier->NotifyMsgsDeleted(m_copyState->m_messages);
}
switch(imapAction)
@ -4500,7 +4500,7 @@ nsImapMailFolder::OnStopRunningUrl(nsIURI *aUrl, nsresult aExitCode)
PRUint32 numHdrs;
msgHdrs->GetLength(&numHdrs);
if (numHdrs)
notifier->NotifyItemDeleted(msgHdrs);
notifier->NotifyMsgsDeleted(msgHdrs);
}
db->DeleteMessages(&keyArray, nsnull);
@ -5763,7 +5763,7 @@ nsImapMailFolder::CopyNextStreamMessage(PRBool copySucceeded, nsISupports *copyS
PRUint32 numHdrs;
mailCopyState->m_messages->GetLength(&numHdrs);
if (numHdrs)
notifier->NotifyItemMoveCopyCompleted(mailCopyState->m_isMove, mailCopyState->m_messages, this);
notifier->NotifyMsgsMoveCopyCompleted(mailCopyState->m_isMove, mailCopyState->m_messages, this);
}
@ -6265,7 +6265,7 @@ nsresult nsImapMailFolder::CopyMessagesOffline(nsIMsgFolder* srcFolder,
{
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemMoveCopyCompleted(isMove, messages, this);
notifier->NotifyMsgsMoveCopyCompleted(isMove, messages, this);
}
nsCOMPtr<nsISupports> srcSupport = do_QueryInterface(srcFolder);
@ -7411,7 +7411,7 @@ NS_IMETHODIMP nsImapMailFolder::RenameClient(nsIMsgWindow *msgWindow, nsIMsgFold
nsCOMPtr <nsIMsgImapMailFolder> oldImapFolder = do_QueryInterface(msgFolder);
if (oldImapFolder)
oldImapFolder->SetVerifiedAsOnlineFolder(PR_FALSE);
nsCOMPtr <nsIMsgFolderNotificationService> notifier = do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyFolderRenamed(msgFolder, child);
NotifyItemAdded(child);

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

@ -1164,7 +1164,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::RenameSubFolders(nsIMsgWindow *msgWindow, ns
nsresult rv =NS_OK;
mInitialized = PR_TRUE;
nsCOMPtr <nsIMsgFolderNotificationService> notifier = do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyFolderRenamed(oldFolder, this);
@ -1404,9 +1404,9 @@ nsMsgLocalMailFolder::DeleteMessages(nsIArray *messages,
// notify on delete from trash and shift-delete
if (!isMove && (deleteStorage || isTrashFolder))
{
nsCOMPtr <nsIMsgFolderNotificationService> notifier = do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemDeleted(messages);
notifier->NotifyMsgsDeleted(messages);
}
if (!deleteStorage && !isTrashFolder)
@ -2567,7 +2567,7 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndCopy(PRBool copySucceeded)
// because deleting the source messages clears out the src msg db hdr.
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemMoveCopyCompleted(mCopyState->m_isMove, mCopyState->m_messages, this);
notifier->NotifyMsgsMoveCopyCompleted(mCopyState->m_isMove, mCopyState->m_messages, this);
}
if(!mCopyState->m_isMove)
@ -2597,9 +2597,9 @@ NS_IMETHODIMP nsMsgLocalMailFolder::EndCopy(PRBool copySucceeded)
// Send the itemAdded notification in case we didn't send the itemMoveCopyCompleted notification earlier.
if (!numHdrs)
{
nsCOMPtr <nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyItemAdded(newHdr);
notifier->NotifyMsgAdded(newHdr);
}
}
return rv;

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

@ -1761,7 +1761,9 @@ PRInt32 nsParseNewMailState::PublishMsgHeader(nsIMsgWindow *msgWindow)
m_newMsgHdr->OrFlags(MSG_FLAG_NEW, &newFlags);
m_mailDB->AddNewHdrToDB(m_newMsgHdr, PR_TRUE);
NotifyGlobalListeners(m_newMsgHdr);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyMsgAdded(m_newMsgHdr);
}
} // if it was moved by imap filter, m_parseMsgState->m_newMsgHdr == nsnull
m_newMsgHdr = nsnull;
@ -1769,14 +1771,6 @@ PRInt32 nsParseNewMailState::PublishMsgHeader(nsIMsgWindow *msgWindow)
return 0;
}
void nsParseNewMailState::NotifyGlobalListeners(nsIMsgDBHdr *newHdr)
{
if (!m_notificationService)
m_notificationService = do_GetService("@mozilla.org/messenger/msgnotificationservice;1");
if (m_notificationService)
m_notificationService->NotifyItemAdded(newHdr);
}
nsresult nsParseNewMailState::GetTrashFolder(nsIMsgFolder **pTrashFolder)
{
nsresult rv=NS_ERROR_UNEXPECTED;
@ -2389,7 +2383,9 @@ nsresult nsParseNewMailState::MoveIncorporatedMessage(nsIMsgDBHdr *mailHdr,
}
}
destMailDB->AddNewHdrToDB(newHdr, PR_TRUE);
NotifyGlobalListeners(newHdr);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyMsgAdded(newHdr);
m_msgToForwardOrReply = newHdr;
}
}

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

@ -255,7 +255,6 @@ public:
virtual void ApplyFilters(PRBool *pMoved, nsIMsgWindow *msgWindow,
PRUint32 msgOffset);
nsresult ApplyForwardAndReplyFilter(nsIMsgWindow *msgWindow);
void NotifyGlobalListeners(nsIMsgDBHdr *newHdr);
// this keeps track of how many messages we downloaded that
// aren't new - e.g., marked read, or moved to an other server.
@ -276,7 +275,6 @@ protected:
nsCOMPtr <nsIMsgWindow> m_msgWindow;
nsCOMPtr <nsIMsgFolder> m_downloadFolder;
nsCOMArray <nsIMsgFolder> m_filterTargetFolders;
nsCOMPtr <nsIMsgFolderNotificationService> m_notificationService;
nsImapMoveCoalescer *m_moveCoalescer; // strictly owned by nsParseNewMailState;

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

@ -868,7 +868,9 @@ nsPop3Sink::IncorporateComplete(nsIMsgWindow *aMsgWindow, PRInt32 aSize)
}
}
m_newMailParser->m_mailDB->AddNewHdrToDB(hdr, PR_TRUE);
m_newMailParser->NotifyGlobalListeners(hdr);
nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID));
if (notifier)
notifier->NotifyMsgAdded(hdr);
}
}
else