Bug 409458 - nsIMsgFolder.AddFolderListener should hold a reference to the listener. r=standard8,neil,darktrojan,jorgk
This commit is contained in:
Родитель
210561200a
Коммит
2329776de1
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* Test that adding nsIFolderListener in js does not cause any crash.
|
||||
*/
|
||||
|
||||
ChromeUtils.import("resource:///modules/MailServices.jsm");
|
||||
load("../../../resources/logHelper.js");
|
||||
load("../../../resources/asyncTestUtils.js");
|
||||
load("../../../resources/messageModifier.js");
|
||||
load("../../../resources/messageGenerator.js");
|
||||
load("../../../resources/messageInjection.js");
|
||||
|
||||
var folderListener = {
|
||||
OnItemAdded: function() {},
|
||||
OnItemRemoved: function() {},
|
||||
OnItemPropertyChanged: function() {},
|
||||
OnItemIntPropertyChanged: function() {},
|
||||
OnItemBoolPropertyChanged: function() {},
|
||||
OnItemUnicharPropertyChanged: function() {},
|
||||
OnItemPropertyFlagChanged: function() {},
|
||||
OnItemEvent: function() {},
|
||||
}
|
||||
|
||||
var targetFolder;
|
||||
|
||||
var tests = [
|
||||
function setup() {
|
||||
gMessageGenerator = new MessageGenerator();
|
||||
|
||||
configure_message_injection({mode: "local"});
|
||||
|
||||
targetFolder = make_empty_folder();
|
||||
targetFolder.AddFolderListener(folderListener);
|
||||
registerCleanupFunction(function() {
|
||||
targetFolder.RemoveFolderListener(folderListener);
|
||||
});
|
||||
},
|
||||
async function create_new_message() {
|
||||
let [msgSet] = make_new_sets_in_folder(targetFolder, [{count: 1}]);
|
||||
await wait_for_message_injection();
|
||||
}
|
||||
];
|
||||
|
||||
function run_test() {
|
||||
async_run_tests(tests);
|
||||
}
|
|
@ -78,3 +78,4 @@ skip-if = true # See bug 1418063.
|
|||
[test_testsuite_fakeserverAuth.js]
|
||||
[test_viewSortByAddresses.js]
|
||||
[test_formatFileSize.js]
|
||||
[test_nsIFolderListener.js]
|
||||
|
|
|
@ -4929,16 +4929,25 @@ NS_IMETHODIMP nsMsgDBFolder::CopyDataDone()
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
#define NOTIFY_LISTENERS(propertyfunc_, params_) \
|
||||
PR_BEGIN_MACRO \
|
||||
nsTObserverArray<nsCOMPtr<nsIFolderListener>>::ForwardIterator iter(mListeners); \
|
||||
nsCOMPtr<nsIFolderListener> listener; \
|
||||
while (iter.HasMore()) { \
|
||||
listener = iter.GetNext(); \
|
||||
listener->propertyfunc_ params_; \
|
||||
} \
|
||||
PR_END_MACRO
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgDBFolder::NotifyPropertyChanged(const nsACString &aProperty,
|
||||
const nsACString& aOldValue,
|
||||
const nsACString& aNewValue)
|
||||
{
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemPropertyChanged,
|
||||
(this, aProperty,
|
||||
nsCString(aOldValue).get(),
|
||||
nsCString(aNewValue).get()));
|
||||
NOTIFY_LISTENERS(OnItemPropertyChanged,
|
||||
(this, aProperty,
|
||||
nsCString(aOldValue).get(),
|
||||
nsCString(aNewValue).get()));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -4955,11 +4964,10 @@ nsMsgDBFolder::NotifyUnicharPropertyChanged(const nsACString &aProperty,
|
|||
const nsAString& aOldValue,
|
||||
const nsAString& aNewValue)
|
||||
{
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemUnicharPropertyChanged,
|
||||
(this, aProperty,
|
||||
nsString(aOldValue).get(),
|
||||
nsString(aNewValue).get()));
|
||||
NOTIFY_LISTENERS(OnItemUnicharPropertyChanged,
|
||||
(this, aProperty,
|
||||
nsString(aOldValue).get(),
|
||||
nsString(aNewValue).get()));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -4982,9 +4990,8 @@ nsMsgDBFolder::NotifyIntPropertyChanged(const nsACString &aProperty, int64_t aOl
|
|||
aProperty.Equals(kTotalUnreadMessages)))
|
||||
return NS_OK;
|
||||
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemIntPropertyChanged,
|
||||
(this, aProperty, aOldValue, aNewValue));
|
||||
NOTIFY_LISTENERS(OnItemIntPropertyChanged,
|
||||
(this, aProperty, aOldValue, aNewValue));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -4999,9 +5006,8 @@ NS_IMETHODIMP
|
|||
nsMsgDBFolder::NotifyBoolPropertyChanged(const nsACString &aProperty,
|
||||
bool aOldValue, bool aNewValue)
|
||||
{
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemBoolPropertyChanged,
|
||||
(this, aProperty, aOldValue, aNewValue));
|
||||
NOTIFY_LISTENERS(OnItemBoolPropertyChanged,
|
||||
(this, aProperty, aOldValue, aNewValue));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -5016,9 +5022,8 @@ NS_IMETHODIMP
|
|||
nsMsgDBFolder::NotifyPropertyFlagChanged(nsIMsgDBHdr *aItem, const nsACString &aProperty,
|
||||
uint32_t aOldValue, uint32_t aNewValue)
|
||||
{
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemPropertyFlagChanged,
|
||||
(aItem, aProperty, aOldValue, aNewValue));
|
||||
NOTIFY_LISTENERS(OnItemPropertyFlagChanged,
|
||||
(aItem, aProperty, aOldValue, aNewValue));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -5036,9 +5041,8 @@ NS_IMETHODIMP nsMsgDBFolder::NotifyItemAdded(nsISupports *aItem)
|
|||
if (!notify)
|
||||
return NS_OK;
|
||||
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemAdded,
|
||||
(this, aItem));
|
||||
NOTIFY_LISTENERS(OnItemAdded,
|
||||
(this, aItem));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -5050,9 +5054,8 @@ NS_IMETHODIMP nsMsgDBFolder::NotifyItemAdded(nsISupports *aItem)
|
|||
|
||||
nsresult nsMsgDBFolder::NotifyItemRemoved(nsISupports *aItem)
|
||||
{
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemRemoved,
|
||||
(this, aItem));
|
||||
NOTIFY_LISTENERS(OnItemRemoved,
|
||||
(this, aItem));
|
||||
|
||||
// Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
@ -5064,9 +5067,8 @@ nsresult nsMsgDBFolder::NotifyItemRemoved(nsISupports *aItem)
|
|||
|
||||
nsresult nsMsgDBFolder::NotifyFolderEvent(const nsACString &aEvent)
|
||||
{
|
||||
NS_OBSERVER_ARRAY_NOTIFY_OBSERVERS(mListeners, nsIFolderListener,
|
||||
OnItemEvent,
|
||||
(this, aEvent));
|
||||
NOTIFY_LISTENERS(OnItemEvent,
|
||||
(this, aEvent));
|
||||
|
||||
//Notify listeners who listen to every folder
|
||||
nsresult rv;
|
||||
|
|
|
@ -214,8 +214,7 @@ protected:
|
|||
bool mNotifyCountChanges;
|
||||
int64_t mExpungedBytes;
|
||||
nsCOMArray<nsIMsgFolder> mSubFolders;
|
||||
// This can't be refcounted due to ownsership issues
|
||||
nsTObserverArray<nsIFolderListener*> mListeners;
|
||||
nsTObserverArray<nsCOMPtr<nsIFolderListener>> mListeners;
|
||||
|
||||
bool mInitializedFromCache;
|
||||
nsISupports *mSemaphoreHolder; // set when the folder is being written to
|
||||
|
|
|
@ -117,12 +117,13 @@ nsMsgSendLater::Init()
|
|||
// Subscribe to the unsent messages folder
|
||||
// XXX This code should be set up for multiple unsent folders, however we
|
||||
// don't support that at the moment, so for now just assume one folder.
|
||||
rv = GetUnsentMessagesFolder(nullptr, getter_AddRefs(mMessageFolder));
|
||||
nsCOMPtr<nsIMsgFolder> folder;
|
||||
rv = GetUnsentMessagesFolder(nullptr, getter_AddRefs(folder));
|
||||
// There doesn't have to be a nsMsgQueueForLater flagged folder.
|
||||
if (NS_FAILED(rv) || !mMessageFolder)
|
||||
if (NS_FAILED(rv) || !folder)
|
||||
return NS_OK;
|
||||
|
||||
rv = mMessageFolder->AddFolderListener(this);
|
||||
rv = folder->AddFolderListener(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// XXX may want to send messages X seconds after startup if there are any.
|
||||
|
@ -164,8 +165,12 @@ nsMsgSendLater::Observe(nsISupports *aSubject, const char* aTopic,
|
|||
nsresult rv;
|
||||
if (mMessageFolder)
|
||||
{
|
||||
rv = mMessageFolder->RemoveFolderListener(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder, &rv);
|
||||
if (folder)
|
||||
{
|
||||
rv = folder->RemoveFolderListener(this);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
}
|
||||
}
|
||||
|
||||
// Now remove ourselves from the observer service as well.
|
||||
|
@ -610,7 +615,9 @@ nsMsgSendLater::StartNextMailFileSend(nsresult prevStatus)
|
|||
return NS_ERROR_UNEXPECTED;
|
||||
|
||||
nsCString messageURI;
|
||||
mMessageFolder->GetUriForMsg(mMessage, messageURI);
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
folder->GetUriForMsg(mMessage, messageURI);
|
||||
|
||||
rv = nsMsgCreateTempFile("nsqmail.tmp", getter_AddRefs(mTempFile));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
@ -657,12 +664,21 @@ nsMsgSendLater::StartNextMailFileSend(nsresult prevStatus)
|
|||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsMsgSendLater::GetUnsentMessagesFolder(nsIMsgIdentity *aIdentity, nsIMsgFolder **folder)
|
||||
nsMsgSendLater::GetUnsentMessagesFolder(nsIMsgIdentity *aIdentity, nsIMsgFolder **aFolder)
|
||||
{
|
||||
nsCString uri;
|
||||
GetFolderURIFromUserPrefs(nsIMsgSend::nsMsgQueueForLater, aIdentity, uri);
|
||||
return LocateMessageFolder(aIdentity, nsIMsgSend::nsMsgQueueForLater,
|
||||
uri.get(), folder);
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder);
|
||||
if (!folder) {
|
||||
nsCString uri;
|
||||
GetFolderURIFromUserPrefs(nsIMsgSend::nsMsgQueueForLater, aIdentity, uri);
|
||||
rv = LocateMessageFolder(aIdentity, nsIMsgSend::nsMsgQueueForLater, uri.get(), getter_AddRefs(folder));
|
||||
mMessageFolder = do_GetWeakReference(folder);
|
||||
if (!mMessageFolder)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
if (folder)
|
||||
folder.forget(aFolder);
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -689,16 +705,19 @@ nsMsgSendLater::HasUnsentMessages(nsIMsgIdentity *aIdentity, bool *aResult)
|
|||
// don't support that at the moment, so for now just assume one folder.
|
||||
if (!mMessageFolder)
|
||||
{
|
||||
rv = GetUnsentMessagesFolder(nullptr, getter_AddRefs(mMessageFolder));
|
||||
nsCOMPtr<nsIMsgFolder> folder;
|
||||
rv = GetUnsentMessagesFolder(nullptr, getter_AddRefs(folder));
|
||||
// There doesn't have to be a nsMsgQueueForLater flagged folder.
|
||||
if (NS_FAILED(rv) || !mMessageFolder)
|
||||
if (NS_FAILED(rv) || !folder)
|
||||
return NS_OK;
|
||||
}
|
||||
rv = ReparseDBIfNeeded(nullptr);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
int32_t totalMessages;
|
||||
rv = mMessageFolder->GetTotalMessages(false, &totalMessages);
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = folder->GetTotalMessages(false, &totalMessages);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
*aResult = totalMessages > 0;
|
||||
|
@ -741,7 +760,7 @@ nsresult nsMsgSendLater::ReparseDBIfNeeded(nsIUrlListener *aListener)
|
|||
// there are unsent messages, the db will be up to date.
|
||||
nsCOMPtr<nsIMsgDatabase> unsentDB;
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgLocalMailFolder> locFolder(do_QueryInterface(mMessageFolder, &rv));
|
||||
nsCOMPtr<nsIMsgLocalMailFolder> locFolder(do_QueryReferent(mMessageFolder, &rv));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
return locFolder->GetDatabaseWithReparse(aListener, nullptr,
|
||||
getter_AddRefs(unsentDB));
|
||||
|
@ -767,9 +786,10 @@ nsMsgSendLater::InternalSendMessages(bool aUserInitiated,
|
|||
// don't support that at the moment, so for now just assume one folder.
|
||||
if (!mMessageFolder)
|
||||
{
|
||||
rv = GetUnsentMessagesFolder(nullptr,
|
||||
getter_AddRefs(mMessageFolder));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
nsCOMPtr<nsIMsgFolder> folder;
|
||||
rv = GetUnsentMessagesFolder(nullptr, getter_AddRefs(folder));
|
||||
if (NS_FAILED(rv) || !folder)
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
nsCOMPtr<nsIMsgDatabase> unsentDB;
|
||||
// Remember these in case we need to reparse the db.
|
||||
|
@ -780,7 +800,9 @@ nsMsgSendLater::InternalSendMessages(bool aUserInitiated,
|
|||
mIdentity = nullptr; // don't hold onto the identity since we're a service.
|
||||
|
||||
nsCOMPtr<nsISimpleEnumerator> enumerator;
|
||||
rv = mMessageFolder->GetMessages(getter_AddRefs(enumerator));
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = folder->GetMessages(getter_AddRefs(enumerator));
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
|
||||
// copy all the elements in the enumerator into our isupports array....
|
||||
|
@ -886,8 +908,11 @@ nsMsgSendLater::DeleteCurrentMessage()
|
|||
|
||||
msgArray->InsertElementAt(mMessage, 0);
|
||||
|
||||
nsresult res = mMessageFolder->DeleteMessages(msgArray, nullptr, true, false, nullptr, false /*allowUndo*/);
|
||||
if (NS_FAILED(res))
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
rv = folder->DeleteMessages(msgArray, nullptr, true, false, nullptr, false /*allowUndo*/);
|
||||
if (NS_FAILED(rv))
|
||||
return NS_ERROR_FAILURE;
|
||||
|
||||
// Null out the message so we don't try and delete it again.
|
||||
|
@ -1313,8 +1338,11 @@ nsMsgSendLater::EndSendMessages(nsresult aStatus, const char16_t *aMsg,
|
|||
// Clear out our array of messages.
|
||||
mMessagesToSend.Clear();
|
||||
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIMsgFolder> folder = do_QueryReferent(mMessageFolder, &rv);
|
||||
NS_ENSURE_SUCCESS(rv,);
|
||||
// We don't need to keep hold of the database now we've finished sending.
|
||||
(void)mMessageFolder->SetMsgDatabase(nullptr);
|
||||
(void)folder->SetMsgDatabase(nullptr);
|
||||
|
||||
// or the enumerator, temp file or output stream
|
||||
mEnumerator = nullptr;
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "nsITimer.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgShutdown.h"
|
||||
#include "nsWeakPtr.h"
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////
|
||||
// This is the listener class for the send operation. We have to create this class
|
||||
|
@ -94,7 +95,7 @@ public:
|
|||
uint32_t mTotalSendCount;
|
||||
nsCOMArray<nsIMsgDBHdr> mMessagesToSend;
|
||||
nsCOMPtr<nsISimpleEnumerator> mEnumerator;
|
||||
nsCOMPtr<nsIMsgFolder> mMessageFolder;
|
||||
nsWeakPtr mMessageFolder;
|
||||
nsCOMPtr<nsIMsgStatusFeedback> mFeedback;
|
||||
|
||||
// Private Information
|
||||
|
|
Загрузка…
Ссылка в новой задаче