Fix for 17712. Reviewed by bienvenu and alecf. Mailnews shuts down accounts, biff,

and folders properly as an xpcom shutdown observer.
This commit is contained in:
putterman%netscape.com 1999-11-14 20:36:22 +00:00
Родитель fc0b3a7bf4
Коммит 46acd7660f
13 изменённых файлов: 192 добавлений и 109 удалений

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

@ -126,7 +126,7 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMessengerBootstrap)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsUrlListenerManager)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgMailSession, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMessenger)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgAccountManager)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgAccountManager, Init)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgAccount)
NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgIdentity)
NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMsgFolderDataSource, Init)

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

@ -26,19 +26,21 @@
[scriptable, uuid(75621650-0fce-11d3-8b49-006008948010)]
interface nsIFolder : nsICollection {
readonly attribute string URI;
attribute wstring name;
attribute wstring prettyName;
readonly attribute wstring abbreviatedName;
readonly attribute string URI;
attribute wstring name;
attribute wstring prettyName;
readonly attribute wstring abbreviatedName;
nsISupports GetChildNamed(in string name);
attribute nsIFolder parent;
nsISupports GetChildNamed(in string name);
attribute nsIFolder parent;
nsIEnumerator GetSubFolders();
readonly attribute boolean hasSubFolders;
nsIEnumerator GetSubFolders();
readonly attribute boolean hasSubFolders;
void AddFolderListener(in nsIFolderListener listener);
void RemoveFolderListener(in nsIFolderListener listener);
nsIFolder FindSubFolder(in string subFolderName);
void AddFolderListener(in nsIFolderListener listener);
void RemoveFolderListener(in nsIFolderListener listener);
nsIFolder FindSubFolder(in string subFolderName);
void Shutdown(in boolean shutdownChildren);
};

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

@ -22,12 +22,6 @@
[scriptable, uuid(E6B64B86-90CB-11d3-8B02-0060B0FC04D2)]
interface nsIIncomingServerListener : nsISupports {
/* Notification sent when a new server is created */
void OnServerAdded(in nsIMsgIncomingServer server);
/* Notification sent when a server is deleted */
void OnServerRemoved(in nsIMsgIncomingServer server);
/* Notification sent when a server is first loaded into the account manager */
void OnServerLoaded(in nsIMsgIncomingServer server);

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

@ -134,8 +134,6 @@ interface nsIMsgAccountManager : nsISupports {
void RemoveIncomingServerListener(in nsIIncomingServerListener serverListener);
void NotifyServerLoaded(in nsIMsgIncomingServer server);
void NotifyServerUnloaded(in nsIMsgIncomingServer server);
void NotifyServerAdded(in nsIMsgIncomingServer server);
void NotifyServerRemoved(in nsIMsgIncomingServer server);
void createLocalMailAccount(in nsIMsgIdentity identity);
};

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

@ -57,31 +57,8 @@ nsMessengerBootstrap::Initialize(nsIAppShellService*,
nsresult
nsMessengerBootstrap::Shutdown()
{
nsresult finalrv = NS_OK;
nsresult rv;
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager, kMsgAccountManagerCID, &rv);
if (NS_SUCCEEDED(rv) && accountManager)
{
// we should really move the folder cache completely to
// the account manager, but I'll wait for m12.
nsCOMPtr <nsIMsgFolderCache> folderCache;
accountManager->GetFolderCache(getter_AddRefs(folderCache));
if (folderCache)
accountManager->WriteToFolderCache(folderCache);
accountManager->CloseCachedConnections();
accountManager->UnloadAccounts();
}
rv = nsServiceManager::UnregisterService("component://netscape/appshell/component/messenger");
if(NS_FAILED(rv)) finalrv = rv;
rv = nsServiceManager::UnregisterService("component://netscape/messenger/services/session");
if(NS_FAILED(rv)) finalrv = rv;
rv = nsServiceManager::UnregisterService("component://netscape/messenger/biffManager");
if(NS_FAILED(rv)) finalrv = rv;
return finalrv;
return NS_OK;
}

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

@ -48,6 +48,7 @@
#include "nsISmtpService.h"
#include "nsString.h"
#include "nsIMsgBiffManager.h"
#include "nsIObserverService.h"
// this should eventually be moved to the pop3 server for upgrading
#include "nsIPop3IncomingServer.h"
@ -308,16 +309,15 @@ typedef struct _findAccountByKeyEntry {
NS_IMPL_ISUPPORTS1(nsMsgAccountManager, nsIMsgAccountManager)
NS_IMPL_ISUPPORTS2(nsMsgAccountManager, nsIMsgAccountManager, nsIObserver)
nsMsgAccountManager::nsMsgAccountManager() :
m_accountsLoaded(PR_FALSE),
m_defaultAccount(null_nsCOMPtr()),
m_prefs(0)
m_prefs(0),
m_haveShutdown(PR_FALSE)
{
NS_INIT_REFCNT();
NS_NewISupportsArray(&m_accounts);
NS_NewISupportsArray(getter_AddRefs(m_incomingServerListeners));
m_alreadySetImapDefaultLocalPath = PR_FALSE;
m_alreadySetNntpDefaultLocalPath = PR_FALSE;
@ -325,12 +325,72 @@ nsMsgAccountManager::nsMsgAccountManager() :
nsMsgAccountManager::~nsMsgAccountManager()
{
CloseCachedConnections();
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID, m_prefs);
UnloadAccounts();
nsresult rv;
if(!m_haveShutdown)
{
Shutdown();
//Don't remove from Observer service in Shutdown because Shutdown also gets called
//from xpcom shutdown observer. And we don't want to remove from the service in that case.
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->RemoveObserver(this, topic.GetUnicode());
}
}
NS_IF_RELEASE(m_accounts);
}
nsresult nsMsgAccountManager::Init()
{
nsresult rv;
rv = NS_NewISupportsArray(&m_accounts);
if(NS_FAILED(rv)) return rv;
rv = NS_NewISupportsArray(getter_AddRefs(m_incomingServerListeners));
if(NS_FAILED(rv)) return rv;
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->AddObserver(this, topic.GetUnicode());
}
return NS_OK;
}
nsresult nsMsgAccountManager::Shutdown()
{
WriteToFolderCache(m_msgFolderCache);
CloseCachedConnections();
UnloadAccounts();
if (m_prefs) nsServiceManager::ReleaseService(kPrefServiceCID, m_prefs);
m_haveShutdown = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData)
{
nsAutoString topicString(aTopic);
nsAutoString shutdownString(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
if(topicString == shutdownString)
{
Shutdown();
}
return NS_OK;
}
nsresult
nsMsgAccountManager::getPrefService()
{
@ -632,7 +692,12 @@ nsMsgAccountManager::hashUnloadServer(nsHashKey *aKey, void *aData,
nsMsgAccountManager *accountManager = (nsMsgAccountManager*)closure;
accountManager->NotifyServerUnloaded(server);
nsCOMPtr<nsIFolder> rootFolder;
rv = server->GetRootFolder(getter_AddRefs(rootFolder));
if(NS_SUCCEEDED(rv))
rootFolder->Shutdown(PR_TRUE);
return PR_TRUE;
}
@ -1282,40 +1347,6 @@ NS_IMETHODIMP nsMsgAccountManager::NotifyServerUnloaded(nsIMsgIncomingServer *se
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::NotifyServerAdded(nsIMsgIncomingServer *server)
{
nsresult rv;
PRUint32 count;
rv = m_incomingServerListeners->Count(&count);
if (NS_FAILED(rv)) return rv;
for(PRUint32 i = 0; i < count; i++)
{
nsCOMPtr<nsIIncomingServerListener> listener =
getter_AddRefs((nsIIncomingServerListener*)m_incomingServerListeners->ElementAt(i));
listener->OnServerAdded(server);
}
return NS_OK;}
NS_IMETHODIMP nsMsgAccountManager::NotifyServerRemoved(nsIMsgIncomingServer *server)
{
nsresult rv;
PRUint32 count;
rv = m_incomingServerListeners->Count(&count);
if (NS_FAILED(rv)) return rv;
for(PRUint32 i = 0; i < count; i++)
{
nsCOMPtr<nsIIncomingServerListener> listener =
getter_AddRefs((nsIIncomingServerListener*)m_incomingServerListeners->ElementAt(i));
listener->OnServerRemoved(server);
}
return NS_OK;
}
nsresult
nsMsgAccountManager::MigrateIdentity(nsIMsgIdentity *identity)

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

@ -27,6 +27,8 @@
#include "nsISmtpServer.h"
#include "nsIPref.h"
#include "nsIMsgFolderCache.h"
#include "nsIObserver.h"
/*
* some platforms (like Windows and Mac) use a map file, because of
* file name length limitations.
@ -55,7 +57,7 @@
#endif /* XP_UNIX || XP_BEOS */
class nsMsgAccountManager : public nsIMsgAccountManager
class nsMsgAccountManager : public nsIMsgAccountManager, public nsIObserver
{
public:
@ -67,7 +69,11 @@ public:
/* nsIMsgAccountManager methods */
NS_DECL_NSIMSGACCOUNTMANAGER
NS_DECL_NSIOBSERVER
nsresult Init();
nsresult Shutdown();
private:
PRBool m_accountsLoaded;
@ -83,6 +89,9 @@ private:
nsCAutoString accountKeyList;
PRBool m_haveShutdown;
/* internal creation routines - updates m_identities and m_incomingServers */
nsresult createKeyedAccount(const char* key,
nsIMsgAccount **_retval);

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

@ -180,7 +180,7 @@ nsMsgAccountManagerDataSource::Init()
void nsMsgAccountManagerDataSource::Close()
{
mAccountManager = null_nsCOMPtr();
// mAccountManager = null_nsCOMPtr();
nsMsgRDFDataSource::Close();
}

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

@ -24,10 +24,11 @@
#include "nsCRT.h"
#include "nsIMsgMailSession.h"
#include "nsMsgBaseCID.h"
#include "nsIObserverService.h"
static NS_DEFINE_CID(kMsgAccountManagerCID, NS_MSGACCOUNTMANAGER_CID);
NS_IMPL_ISUPPORTS2(nsMsgBiffManager, nsIMsgBiffManager, nsIIncomingServerListener)
NS_IMPL_ISUPPORTS3(nsMsgBiffManager, nsIMsgBiffManager, nsIIncomingServerListener, nsIObserver)
void OnBiffTimer(nsITimer *timer, void *aBiffManager)
{
@ -41,10 +42,13 @@ nsMsgBiffManager::nsMsgBiffManager()
mBiffTimer = nsnull;
mBiffArray = nsnull;
mHaveShutdown = PR_FALSE;
}
nsMsgBiffManager::~nsMsgBiffManager()
{
nsresult rv;
if (mBiffTimer) {
mBiffTimer->Cancel();
}
@ -59,13 +63,18 @@ nsMsgBiffManager::~nsMsgBiffManager()
}
delete mBiffArray;
nsresult rv;
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager, kMsgAccountManagerCID, &rv);
if(NS_SUCCEEDED(rv))
if(!mHaveShutdown)
{
rv = accountManager->RemoveIncomingServerListener(this);
Shutdown();
//Don't remove from Observer service in Shutdown because Shutdown also gets called
//from xpcom shutdown observer. And we don't want to remove from the service in that case.
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->RemoveObserver(this, topic.GetUnicode());
}
}
}
nsresult nsMsgBiffManager::Init()
@ -77,10 +86,32 @@ nsresult nsMsgBiffManager::Init()
return NS_ERROR_OUT_OF_MEMORY;
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager, kMsgAccountManagerCID, &rv);
if (NS_FAILED(rv)) return rv;
if (NS_SUCCEEDED(rv))
{
accountManager->AddIncomingServerListener(this);
}
rv = accountManager->AddIncomingServerListener(this);
return rv;
NS_WITH_SERVICE (nsIObserverService, observerService, NS_OBSERVERSERVICE_PROGID, &rv);
if (NS_SUCCEEDED(rv))
{
nsAutoString topic(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->AddObserver(this, topic.GetUnicode());
}
return NS_OK;
}
nsresult nsMsgBiffManager::Shutdown()
{
nsresult rv;
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager, kMsgAccountManagerCID, &rv);
if (NS_SUCCEEDED(rv))
{
accountManager->RemoveIncomingServerListener(this);
}
mHaveShutdown = PR_TRUE;
return NS_OK;
}
NS_IMETHODIMP nsMsgBiffManager::AddServerBiff(nsIMsgIncomingServer *server)
@ -130,16 +161,6 @@ NS_IMETHODIMP nsMsgBiffManager::ForceBiffAll()
return NS_OK;
}
NS_IMETHODIMP nsMsgBiffManager::OnServerAdded(nsIMsgIncomingServer *server)
{
return NS_OK;
}
NS_IMETHODIMP nsMsgBiffManager::OnServerRemoved(nsIMsgIncomingServer *server)
{
return NS_OK;
}
NS_IMETHODIMP nsMsgBiffManager::OnServerLoaded(nsIMsgIncomingServer *server)
{
nsresult rv;
@ -170,6 +191,19 @@ NS_IMETHODIMP nsMsgBiffManager::OnServerUnloaded(nsIMsgIncomingServer *server)
return rv;
}
NS_IMETHODIMP nsMsgBiffManager::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData)
{
nsAutoString topicString(aTopic);
nsAutoString shutdownString(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
if(topicString == shutdownString)
{
Shutdown();
}
return NS_OK;
}
PRInt32 nsMsgBiffManager::FindServer(nsIMsgIncomingServer *server)
{
PRInt32 count = mBiffArray->Count();

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

@ -31,6 +31,7 @@
#include "nsTime.h"
#include "nsCOMPtr.h"
#include "nsIIncomingServerListener.h"
#include "nsIObserver.h"
typedef struct {
nsCOMPtr<nsIMsgIncomingServer> server;
@ -38,7 +39,7 @@ typedef struct {
} nsBiffEntry;
class nsMsgBiffManager: public nsIMsgBiffManager, public nsIIncomingServerListener
class nsMsgBiffManager: public nsIMsgBiffManager, public nsIIncomingServerListener, public nsIObserver
{
public:
nsMsgBiffManager();
@ -47,8 +48,10 @@ public:
NS_DECL_ISUPPORTS
NS_DECL_NSIMSGBIFFMANAGER
NS_DECL_NSIINCOMINGSERVERLISTENER
NS_DECL_NSIOBSERVER
nsresult Init();
nsresult Shutdown();
nsresult PerformBiff();
protected:
@ -60,6 +63,7 @@ protected:
protected:
nsITimer *mBiffTimer;
nsVoidArray *mBiffArray;
PRBool mHaveShutdown;
};

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

@ -66,12 +66,40 @@ nsMsgDBFolder::nsMsgDBFolder(void)
}
nsMsgDBFolder::~nsMsgDBFolder(void)
{
//shutdown but don't shutdown children.
Shutdown(PR_FALSE);
}
NS_IMETHODIMP nsMsgDBFolder::Shutdown(PRBool shutdownChildren)
{
if(mDatabase)
{
mDatabase->RemoveListener(this);
mDatabase->Close(PR_TRUE);
mDatabase = null_nsCOMPtr();
}
if(shutdownChildren)
{
PRUint32 count;
nsresult rv = mSubFolders->Count(&count);
if(NS_SUCCEEDED(rv))
{
for (PRUint32 i = 0; i < count; i++)
{
nsCOMPtr<nsISupports> childFolderSupports = getter_AddRefs(mSubFolders->ElementAt(i));
if(childFolderSupports)
{
nsCOMPtr<nsIFolder> childFolder = do_QueryInterface(childFolderSupports);
if(childFolder)
childFolder->Shutdown(PR_TRUE);
}
}
}
}
return NS_OK;
}
NS_IMETHODIMP nsMsgDBFolder::StartFolderLoading(void)

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

@ -67,6 +67,8 @@ public:
NS_IMETHOD MarkAllMessagesRead(void);
NS_IMETHOD Shutdown(PRBool shutdownChildren);
protected:
virtual nsresult ReadDBFolderInfo(PRBool force);
virtual nsresult GetDatabase() = 0;

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

@ -190,6 +190,10 @@ nsMsgFolder::Init(const char* aURI)
return NS_OK;
}
NS_IMETHODIMP nsMsgFolder::Shutdown(PRBool shutdownChildren)
{
return NS_OK;
}
// nsICollection methods:
NS_IMETHODIMP