big-ass leak fix - stop leaking mail datasources by clearing ourselves out when the last

RDF observer goes away, and re-initializing if new RDF observers arrive on the scene.
r=putterman
fixes #45176, among other leaks


git-svn-id: svn://10.0.0.236/trunk@75828 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
alecf%netscape.com 2000-08-08 23:32:55 +00:00
parent ed5414a7fa
commit e385002b0a
8 changed files with 254 additions and 243 deletions

View File

@ -117,20 +117,39 @@ nsCOMPtr<nsISupportsArray> nsMsgAccountManagerDataSource::mAccountRootArcsOut;
nsMsgAccountManagerDataSource::nsMsgAccountManagerDataSource()
{
#ifdef DEBUG_amds
printf("nsMsgAccountManagerDataSource() being created\n");
#endif
// do per-class initialization here
if (gAccountManagerResourceRefCnt++ == 0) {
getRDFService()->GetResource(NC_RDF_CHILD, &kNC_Child);
getRDFService()->GetResource(NC_RDF_NAME, &kNC_Name);
getRDFService()->GetResource(NC_RDF_FOLDERTREENAME, &kNC_FolderTreeName);
getRDFService()->GetResource(NC_RDF_NAME_SORT, &kNC_NameSort);
getRDFService()->GetResource(NC_RDF_FOLDERTREENAME_SORT, &kNC_FolderTreeNameSort);
getRDFService()->GetResource(NC_RDF_PAGETAG, &kNC_PageTag);
getRDFService()->GetResource(NC_RDF_ISDEFAULTSERVER, &kNC_IsDefaultServer);
getRDFService()->GetResource(NC_RDF_ACCOUNT, &kNC_Account);
getRDFService()->GetResource(NC_RDF_SERVER, &kNC_Server);
getRDFService()->GetResource(NC_RDF_IDENTITY, &kNC_Identity);
getRDFService()->GetResource(NC_RDF_PAGETITLE_MAIN, &kNC_PageTitleMain);
getRDFService()->GetResource(NC_RDF_PAGETITLE_SERVER, &kNC_PageTitleServer);
getRDFService()->GetResource(NC_RDF_PAGETITLE_COPIES, &kNC_PageTitleCopies);
getRDFService()->GetResource(NC_RDF_PAGETITLE_ADVANCED, &kNC_PageTitleAdvanced);
getRDFService()->GetResource(NC_RDF_PAGETITLE_SMTP, &kNC_PageTitleSMTP);
getRDFService()->GetResource(NC_RDF_ACCOUNTROOT, &kNC_AccountRoot);
// XXX This call should be moved to a NS_NewMsgFooDataSource()
// method that the factory calls, so that failure to construct
// will return an error code instead of returning a partially
// initialized object.
nsresult rv = Init();
NS_ASSERTION(NS_SUCCEEDED(rv), "uh oh, initialization failed");
if (NS_FAILED(rv)) return /* rv */;
return /* NS_OK */;
getRDFService()->GetLiteral(NS_ConvertASCIItoUCS2("true").GetUnicode(),
&kTrueLiteral);
// eventually these need to exist in some kind of array
// that's easily extensible
getRDFService()->GetResource(NC_RDF_SETTINGS, &kNC_Settings);
kDefaultServerAtom = NS_NewAtom("DefaultServer");
}
}
nsMsgAccountManagerDataSource::~nsMsgAccountManagerDataSource()
@ -182,54 +201,32 @@ NS_INTERFACE_MAP_END_INHERITING(nsMsgRDFDataSource)
nsresult
nsMsgAccountManagerDataSource::Init()
{
nsresult rv=NS_OK;
if (!mAccountManager) {
nsCOMPtr<nsIMsgAccountManager> am =
do_GetService(NS_MSGACCOUNTMANAGER_PROGID, &rv);
nsresult rv;
mAccountManager = getter_AddRefs(NS_GetWeakReference(am));
if (NS_FAILED(rv)) return rv;
rv = nsMsgRDFDataSource::Init();
if (NS_FAILED(rv)) return rv;
nsCOMPtr<nsIMsgAccountManager> am;
// get a weak ref to the account manager
if (!mAccountManager) {
am = do_GetService(NS_MSGACCOUNTMANAGER_PROGID, &rv);
mAccountManager = getter_AddRefs(NS_GetWeakReference(am));
} else
am = do_QueryReferent(mAccountManager);
if (am) {
am->AddIncomingServerListener(this);
am->AddRootFolderListener(this);
}
if (gAccountManagerResourceRefCnt++ == 0) {
getRDFService()->GetResource(NC_RDF_CHILD, &kNC_Child);
getRDFService()->GetResource(NC_RDF_NAME, &kNC_Name);
getRDFService()->GetResource(NC_RDF_FOLDERTREENAME, &kNC_FolderTreeName);
getRDFService()->GetResource(NC_RDF_NAME_SORT, &kNC_NameSort);
getRDFService()->GetResource(NC_RDF_FOLDERTREENAME_SORT, &kNC_FolderTreeNameSort);
getRDFService()->GetResource(NC_RDF_PAGETAG, &kNC_PageTag);
getRDFService()->GetResource(NC_RDF_ISDEFAULTSERVER, &kNC_IsDefaultServer);
getRDFService()->GetResource(NC_RDF_ACCOUNT, &kNC_Account);
getRDFService()->GetResource(NC_RDF_SERVER, &kNC_Server);
getRDFService()->GetResource(NC_RDF_IDENTITY, &kNC_Identity);
getRDFService()->GetResource(NC_RDF_PAGETITLE_MAIN, &kNC_PageTitleMain);
getRDFService()->GetResource(NC_RDF_PAGETITLE_SERVER, &kNC_PageTitleServer);
getRDFService()->GetResource(NC_RDF_PAGETITLE_COPIES, &kNC_PageTitleCopies);
getRDFService()->GetResource(NC_RDF_PAGETITLE_ADVANCED, &kNC_PageTitleAdvanced);
getRDFService()->GetResource(NC_RDF_PAGETITLE_SMTP, &kNC_PageTitleSMTP);
getRDFService()->GetResource(NC_RDF_ACCOUNTROOT, &kNC_AccountRoot);
getRDFService()->GetLiteral(NS_ConvertASCIItoUCS2("true").GetUnicode(),
&kTrueLiteral);
// eventually these need to exist in some kind of array
// that's easily extensible
getRDFService()->GetResource(NC_RDF_SETTINGS, &kNC_Settings);
kDefaultServerAtom = NS_NewAtom("DefaultServer");
}
return NS_OK;
}
void nsMsgAccountManagerDataSource::Close()
void nsMsgAccountManagerDataSource::Cleanup()
{
printf("*** AccountManager Datasource cleanup\n");
nsCOMPtr<nsIMsgAccountManager> am =
do_QueryReferent(mAccountManager);
@ -238,7 +235,7 @@ void nsMsgAccountManagerDataSource::Close()
am->RemoveRootFolderListener(this);
}
nsMsgRDFDataSource::Close();
nsMsgRDFDataSource::Cleanup();
}
/* nsIRDFNode GetTarget (in nsIRDFResource aSource, in nsIRDFResource property, in boolean aTruthValue); */

View File

@ -50,7 +50,7 @@ public:
virtual ~nsMsgAccountManagerDataSource();
virtual nsresult Init();
virtual void Close();
virtual void Cleanup();
// service manager shutdown method
NS_DECL_ISUPPORTS_INHERITED

View File

@ -98,21 +98,62 @@ nsIAtom * nsMsgFolderDataSource::kTotalMessagesAtom = nsnull;
nsIAtom * nsMsgFolderDataSource::kTotalUnreadMessagesAtom = nsnull;
nsIAtom * nsMsgFolderDataSource::kNameAtom = nsnull;
nsMsgFolderDataSource::nsMsgFolderDataSource():
mInitialized(PR_FALSE)
nsMsgFolderDataSource::nsMsgFolderDataSource()
{
// one-time initialization here
nsIRDFService* rdf = getRDFService();
if (gFolderResourceRefCnt++ == 0) {
rdf->GetResource(NC_RDF_CHILD, &kNC_Child);
rdf->GetResource(NC_RDF_MESSAGECHILD, &kNC_MessageChild);
rdf->GetResource(NC_RDF_FOLDER, &kNC_Folder);
rdf->GetResource(NC_RDF_NAME, &kNC_Name);
rdf->GetResource(NC_RDF_FOLDERTREENAME, &kNC_FolderTreeName);
rdf->GetResource(NC_RDF_NAME_SORT, &kNC_NameSort);
rdf->GetResource(NC_RDF_FOLDERTREENAME_SORT, &kNC_FolderTreeNameSort);
rdf->GetResource(NC_RDF_SPECIALFOLDER, &kNC_SpecialFolder);
rdf->GetResource(NC_RDF_SERVERTYPE, &kNC_ServerType);
rdf->GetResource(NC_RDF_ISSERVER, &kNC_IsServer);
rdf->GetResource(NC_RDF_ISSECURE, &kNC_IsSecure);
rdf->GetResource(NC_RDF_CANSUBSCRIBE, &kNC_CanSubscribe);
rdf->GetResource(NC_RDF_CANFILEMESSAGES, &kNC_CanFileMessages);
rdf->GetResource(NC_RDF_CANCREATESUBFOLDERS, &kNC_CanCreateSubfolders);
rdf->GetResource(NC_RDF_CANRENAME, &kNC_CanRename);
rdf->GetResource(NC_RDF_TOTALMESSAGES, &kNC_TotalMessages);
rdf->GetResource(NC_RDF_TOTALUNREADMESSAGES, &kNC_TotalUnreadMessages);
rdf->GetResource(NC_RDF_CHARSET, &kNC_Charset);
rdf->GetResource(NC_RDF_BIFFSTATE, &kNC_BiffState);
rdf->GetResource(NC_RDF_HASUNREADMESSAGES, &kNC_HasUnreadMessages);
rdf->GetResource(NC_RDF_NEWMESSAGES, &kNC_NewMessages);
rdf->GetResource(NC_RDF_SUBFOLDERSHAVEUNREADMESSAGES, &kNC_SubfoldersHaveUnreadMessages);
rdf->GetResource(NC_RDF_NOSELECT, &kNC_NoSelect);
rdf->GetResource(NC_RDF_DELETE, &kNC_Delete);
rdf->GetResource(NC_RDF_REALLY_DELETE, &kNC_ReallyDelete);
rdf->GetResource(NC_RDF_NEWFOLDER, &kNC_NewFolder);
rdf->GetResource(NC_RDF_GETNEWMESSAGES, &kNC_GetNewMessages);
rdf->GetResource(NC_RDF_COPY, &kNC_Copy);
rdf->GetResource(NC_RDF_MOVE, &kNC_Move);
rdf->GetResource(NC_RDF_MARKALLMESSAGESREAD,
&kNC_MarkAllMessagesRead);
rdf->GetResource(NC_RDF_COMPACT, &kNC_Compact);
rdf->GetResource(NC_RDF_RENAME, &kNC_Rename);
rdf->GetResource(NC_RDF_EMPTYTRASH, &kNC_EmptyTrash);
kTotalMessagesAtom = NS_NewAtom("TotalMessages");
kTotalUnreadMessagesAtom = NS_NewAtom("TotalUnreadMessages");
kBiffStateAtom = NS_NewAtom("BiffState");
kNewMessagesAtom = NS_NewAtom("NewMessages");
kNameAtom = NS_NewAtom("Name");
}
CreateLiterals(rdf);
CreateArcsOutEnumerator();
}
nsMsgFolderDataSource::~nsMsgFolderDataSource (void)
{
nsresult rv;
if (!m_shuttingDown)
{
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
if(NS_SUCCEEDED(rv))
mailSession->RemoveFolderListener(this);
}
if (--gFolderResourceRefCnt == 0)
{
nsrefcnt refcnt;
@ -154,99 +195,54 @@ nsMsgFolderDataSource::~nsMsgFolderDataSource (void)
NS_RELEASE(kTotalMessagesAtom);
NS_RELEASE(kTotalUnreadMessagesAtom);
NS_RELEASE(kBiffStateAtom);
NS_RELEASE(kNewMessagesAtom);
NS_RELEASE(kNewMessagesAtom);
NS_RELEASE(kNameAtom);
}
}
nsresult nsMsgFolderDataSource::CreateLiterals(nsIRDFService *rdf)
{
createNode((const PRUnichar*)NS_LITERAL_STRING("true"),
getter_AddRefs(kTrueLiteral), rdf);
createNode((const PRUnichar*)NS_LITERAL_STRING("false"),
getter_AddRefs(kFalseLiteral), rdf);
return NS_OK;
}
nsresult nsMsgFolderDataSource::Init()
{
if (mInitialized)
return NS_ERROR_ALREADY_INITIALIZED;
nsresult rv;
rv = nsMsgRDFDataSource::Init();
if (NS_FAILED(rv))
return rv;
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
if(NS_SUCCEEDED(rv))
mailSession->AddFolderListener(this);
nsIRDFService *rdf = getRDFService();
if(!rdf)
return NS_ERROR_FAILURE;
return NS_OK;
}
if (gFolderResourceRefCnt++ == 0) {
rdf->GetResource(NC_RDF_CHILD, &kNC_Child);
rdf->GetResource(NC_RDF_MESSAGECHILD, &kNC_MessageChild);
rdf->GetResource(NC_RDF_FOLDER, &kNC_Folder);
rdf->GetResource(NC_RDF_NAME, &kNC_Name);
rdf->GetResource(NC_RDF_FOLDERTREENAME, &kNC_FolderTreeName);
rdf->GetResource(NC_RDF_NAME_SORT, &kNC_NameSort);
rdf->GetResource(NC_RDF_FOLDERTREENAME_SORT, &kNC_FolderTreeNameSort);
rdf->GetResource(NC_RDF_SPECIALFOLDER, &kNC_SpecialFolder);
rdf->GetResource(NC_RDF_SERVERTYPE, &kNC_ServerType);
rdf->GetResource(NC_RDF_ISSERVER, &kNC_IsServer);
rdf->GetResource(NC_RDF_ISSECURE, &kNC_IsSecure);
rdf->GetResource(NC_RDF_CANSUBSCRIBE, &kNC_CanSubscribe);
rdf->GetResource(NC_RDF_CANFILEMESSAGES, &kNC_CanFileMessages);
rdf->GetResource(NC_RDF_CANCREATESUBFOLDERS, &kNC_CanCreateSubfolders);
rdf->GetResource(NC_RDF_CANRENAME, &kNC_CanRename);
rdf->GetResource(NC_RDF_TOTALMESSAGES, &kNC_TotalMessages);
rdf->GetResource(NC_RDF_TOTALUNREADMESSAGES, &kNC_TotalUnreadMessages);
rdf->GetResource(NC_RDF_CHARSET, &kNC_Charset);
rdf->GetResource(NC_RDF_BIFFSTATE, &kNC_BiffState);
rdf->GetResource(NC_RDF_HASUNREADMESSAGES, &kNC_HasUnreadMessages);
rdf->GetResource(NC_RDF_NEWMESSAGES, &kNC_NewMessages);
rdf->GetResource(NC_RDF_SUBFOLDERSHAVEUNREADMESSAGES, &kNC_SubfoldersHaveUnreadMessages);
rdf->GetResource(NC_RDF_NOSELECT, &kNC_NoSelect);
void nsMsgFolderDataSource::Cleanup()
{
nsresult rv;
if (!m_shuttingDown)
{
nsCOMPtr<nsIMsgMailSession> mailSession =
do_GetService(kMsgMailSessionCID, &rv);
rdf->GetResource(NC_RDF_DELETE, &kNC_Delete);
rdf->GetResource(NC_RDF_REALLY_DELETE, &kNC_ReallyDelete);
rdf->GetResource(NC_RDF_NEWFOLDER, &kNC_NewFolder);
rdf->GetResource(NC_RDF_GETNEWMESSAGES, &kNC_GetNewMessages);
rdf->GetResource(NC_RDF_COPY, &kNC_Copy);
rdf->GetResource(NC_RDF_MOVE, &kNC_Move);
rdf->GetResource(NC_RDF_MARKALLMESSAGESREAD,
&kNC_MarkAllMessagesRead);
rdf->GetResource(NC_RDF_COMPACT, &kNC_Compact);
rdf->GetResource(NC_RDF_RENAME, &kNC_Rename);
rdf->GetResource(NC_RDF_EMPTYTRASH, &kNC_EmptyTrash);
kTotalMessagesAtom = NS_NewAtom("TotalMessages");
kTotalUnreadMessagesAtom = NS_NewAtom("TotalUnreadMessages");
kBiffStateAtom = NS_NewAtom("BiffState");
kNewMessagesAtom = NS_NewAtom("NewMessages");
kNameAtom = NS_NewAtom("Name");
if(NS_SUCCEEDED(rv))
mailSession->RemoveFolderListener(this);
}
CreateLiterals(rdf);
rv = CreateArcsOutEnumerator();
if(NS_FAILED(rv)) return rv;
mInitialized = PR_TRUE;
return nsMsgRDFDataSource::Init();
}
nsresult nsMsgFolderDataSource::CreateLiterals(nsIRDFService *rdf)
{
nsAutoString str; str.AssignWithConversion("true");
createNode(str, getter_AddRefs(kTrueLiteral), rdf);
str.AssignWithConversion("false");
createNode(str, getter_AddRefs(kFalseLiteral), rdf);
return NS_OK;
}
void nsMsgFolderDataSource::Close()
{
kFolderArcsOutArray = null_nsCOMPtr();
nsMsgRDFDataSource::Close();
nsMsgRDFDataSource::Cleanup();
}
nsresult nsMsgFolderDataSource::CreateArcsOutEnumerator()
{
nsCOMPtr<nsISupportsArray> folderArcsOut;
nsresult rv;
rv = getFolderArcLabelsOut(getter_AddRefs(kFolderArcsOutArray));
@ -503,14 +499,13 @@ NS_IMETHODIMP nsMsgFolderDataSource::ArcLabelsOut(nsIRDFResource* source,
if (NS_SUCCEEDED(rv)) {
arcsArray = kFolderArcsOutArray;
rv = NS_NewArrayEnumerator(labels, arcsArray);
}
else {
arcsArray = kEmptyArray;
rv = NS_NewEmptyEnumerator(labels);
}
rv = NS_NewArrayEnumerator(labels, arcsArray);
if(NS_FAILED(rv)) return rv;
return NS_OK;
return rv;
}
nsresult

View File

@ -34,10 +34,6 @@
class nsMsgFolderDataSource : public nsMsgRDFDataSource,
public nsIFolderListener
{
private:
PRBool mInitialized;
public:
NS_DECL_ISUPPORTS_INHERITED
@ -46,7 +42,7 @@ public:
nsMsgFolderDataSource(void);
virtual ~nsMsgFolderDataSource (void);
virtual nsresult Init();
virtual void Close();
virtual void Cleanup();
// nsIRDFDataSource methods
NS_IMETHOD GetURI(char* *uri);

View File

@ -90,25 +90,58 @@ nsIAtom * nsMsgMessageDataSource::kStatusAtom = nsnull;
nsMsgMessageDataSource::nsMsgMessageDataSource():
mInitialized(PR_FALSE),
mHeaderParser(nsnull)
nsMsgMessageDataSource::nsMsgMessageDataSource()
{
mStringBundle = nsnull;
mHeaderParser = do_CreateInstance(kMsgHeaderParserCID);
nsIRDFService *rdf = getRDFService();
if (gMessageResourceRefCnt++ == 0) {
rdf->GetResource(NC_RDF_SUBJECT, &kNC_Subject);
rdf->GetResource(NC_RDF_SUBJECT_COLLATION_SORT, &kNC_SubjectCollation);
rdf->GetResource(NC_RDF_SENDER, &kNC_Sender);
rdf->GetResource(NC_RDF_SENDER_COLLATION_SORT, &kNC_SenderCollation);
rdf->GetResource(NC_RDF_RECIPIENT, &kNC_Recipient);
rdf->GetResource(NC_RDF_RECIPIENT_COLLATION_SORT, &kNC_RecipientCollation);
rdf->GetResource(NC_RDF_DATE, &kNC_Date);
rdf->GetResource(NC_RDF_STATUS, &kNC_Status);
rdf->GetResource(NC_RDF_STATUS_STRING, &kNC_StatusString);
rdf->GetResource(NC_RDF_FLAGGED, &kNC_Flagged);
rdf->GetResource(NC_RDF_PRIORITY, &kNC_Priority);
rdf->GetResource(NC_RDF_PRIORITY_STRING, &kNC_PriorityString);
rdf->GetResource(NC_RDF_PRIORITY_SORT, &kNC_PrioritySort);
rdf->GetResource(NC_RDF_SIZE, &kNC_Size);
rdf->GetResource(NC_RDF_SIZE_SORT, &kNC_SizeSort);
rdf->GetResource(NC_RDF_TOTALMESSAGES, &kNC_Total);
rdf->GetResource(NC_RDF_TOTALUNREADMESSAGES, &kNC_Unread);
rdf->GetResource(NC_RDF_MESSAGECHILD, &kNC_MessageChild);
rdf->GetResource(NC_RDF_ISUNREAD, &kNC_IsUnread);
rdf->GetResource(NC_RDF_HASATTACHMENT, &kNC_HasAttachment);
rdf->GetResource(NC_RDF_ISIMAPDELETED, &kNC_IsImapDeleted);
rdf->GetResource(NC_RDF_MESSAGETYPE, &kNC_MessageType);
rdf->GetResource(NC_RDF_ORDERRECEIVED, &kNC_OrderReceived);
rdf->GetResource(NC_RDF_ORDERRECEIVED_SORT, &kNC_OrderReceivedSort);
rdf->GetResource(NC_RDF_MARKREAD, &kNC_MarkRead);
rdf->GetResource(NC_RDF_MARKUNREAD, &kNC_MarkUnread);
rdf->GetResource(NC_RDF_TOGGLEREAD, &kNC_ToggleRead);
rdf->GetResource(NC_RDF_MARKFLAGGED, &kNC_MarkFlagged);
rdf->GetResource(NC_RDF_MARKUNFLAGGED, &kNC_MarkUnflagged);
rdf->GetResource(NC_RDF_MARKTHREADREAD, &kNC_MarkThreadRead);
kStatusAtom = NS_NewAtom("Status");
kFlaggedAtom = NS_NewAtom("Flagged");
}
CreateLiterals(rdf);
CreateArcsOutEnumerators();
}
nsMsgMessageDataSource::~nsMsgMessageDataSource (void)
{
nsresult rv;
if (!m_shuttingDown)
{
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
if(NS_SUCCEEDED(rv))
mailSession->RemoveFolderListener(this);
}
if (--gMessageResourceRefCnt == 0)
{
nsrefcnt refcnt;
@ -149,77 +182,35 @@ nsMsgMessageDataSource::~nsMsgMessageDataSource (void)
NS_RELEASE(kFlaggedAtom);
}
NS_IF_RELEASE(mHeaderParser);
}
void nsMsgMessageDataSource::Cleanup()
{
nsresult rv;
if (!m_shuttingDown) {
nsCOMPtr<nsIMsgMailSession> mailSession =
do_GetService(kMsgMailSessionCID, &rv);
if(NS_SUCCEEDED(rv))
mailSession->RemoveFolderListener(this);
}
nsMsgRDFDataSource::Cleanup();
}
nsresult nsMsgMessageDataSource::Init()
{
if (mInitialized)
return NS_ERROR_ALREADY_INITIALIZED;
nsresult rv;
nsIRDFService *rdf = getRDFService();
if(!rdf)
return NS_ERROR_FAILURE;
rv = nsMsgRDFDataSource::Init();
if (NS_FAILED(rv)) return rv;
rv = nsComponentManager::CreateInstance(kMsgHeaderParserCID,
NULL,
NS_GET_IID(nsIMsgHeaderParser),
(void **) &mHeaderParser);
if(NS_FAILED(rv))
return rv;
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
NS_WITH_SERVICE(nsIMsgMailSession, mailSession, kMsgMailSessionCID, &rv);
if(NS_SUCCEEDED(rv))
mailSession->AddFolderListener(this);
PR_ASSERT(NS_SUCCEEDED(rv));
if (gMessageResourceRefCnt++ == 0) {
rdf->GetResource(NC_RDF_SUBJECT, &kNC_Subject);
rdf->GetResource(NC_RDF_SUBJECT_COLLATION_SORT, &kNC_SubjectCollation);
rdf->GetResource(NC_RDF_SENDER, &kNC_Sender);
rdf->GetResource(NC_RDF_SENDER_COLLATION_SORT, &kNC_SenderCollation);
rdf->GetResource(NC_RDF_RECIPIENT, &kNC_Recipient);
rdf->GetResource(NC_RDF_RECIPIENT_COLLATION_SORT, &kNC_RecipientCollation);
rdf->GetResource(NC_RDF_DATE, &kNC_Date);
rdf->GetResource(NC_RDF_STATUS, &kNC_Status);
rdf->GetResource(NC_RDF_STATUS_STRING, &kNC_StatusString);
rdf->GetResource(NC_RDF_FLAGGED, &kNC_Flagged);
rdf->GetResource(NC_RDF_PRIORITY, &kNC_Priority);
rdf->GetResource(NC_RDF_PRIORITY_STRING, &kNC_PriorityString);
rdf->GetResource(NC_RDF_PRIORITY_SORT, &kNC_PrioritySort);
rdf->GetResource(NC_RDF_SIZE, &kNC_Size);
rdf->GetResource(NC_RDF_SIZE_SORT, &kNC_SizeSort);
rdf->GetResource(NC_RDF_TOTALMESSAGES, &kNC_Total);
rdf->GetResource(NC_RDF_TOTALUNREADMESSAGES, &kNC_Unread);
rdf->GetResource(NC_RDF_MESSAGECHILD, &kNC_MessageChild);
rdf->GetResource(NC_RDF_ISUNREAD, &kNC_IsUnread);
rdf->GetResource(NC_RDF_HASATTACHMENT, &kNC_HasAttachment);
rdf->GetResource(NC_RDF_ISIMAPDELETED, &kNC_IsImapDeleted);
rdf->GetResource(NC_RDF_MESSAGETYPE, &kNC_MessageType);
rdf->GetResource(NC_RDF_ORDERRECEIVED, &kNC_OrderReceived);
rdf->GetResource(NC_RDF_ORDERRECEIVED_SORT, &kNC_OrderReceivedSort);
rdf->GetResource(NC_RDF_MARKREAD, &kNC_MarkRead);
rdf->GetResource(NC_RDF_MARKUNREAD, &kNC_MarkUnread);
rdf->GetResource(NC_RDF_TOGGLEREAD, &kNC_ToggleRead);
rdf->GetResource(NC_RDF_MARKFLAGGED, &kNC_MarkFlagged);
rdf->GetResource(NC_RDF_MARKUNFLAGGED, &kNC_MarkUnflagged);
rdf->GetResource(NC_RDF_MARKTHREADREAD, &kNC_MarkThreadRead);
kStatusAtom = NS_NewAtom("Status");
kFlaggedAtom = NS_NewAtom("Flagged");
}
CreateLiterals(rdf);
rv = CreateArcsOutEnumerators();
if(NS_FAILED(rv)) return rv;
mInitialized = PR_TRUE;
return nsMsgRDFDataSource::Init();
return NS_OK;
}
nsresult nsMsgMessageDataSource::CreateLiterals(nsIRDFService *rdf)
@ -569,13 +560,13 @@ NS_IMETHODIMP nsMsgMessageDataSource::ArcLabelsOut(nsIRDFResource* source,
{
arcsArray = kNoThreadsArcsOutArray;
}
rv = NS_NewArrayEnumerator(labels, arcsArray);
}
else
{
arcsArray = kEmptyArray;
rv = NS_NewEmptyEnumerator(labels);
}
rv = NS_NewArrayEnumerator(labels, arcsArray);
NS_ENSURE_SUCCESS(rv, rv);
return NS_OK;

View File

@ -45,7 +45,7 @@ private:
PRBool mInitialized;
// The cached service managers
nsIMsgHeaderParser *mHeaderParser;
nsCOMPtr<nsIMsgHeaderParser> mHeaderParser;
public:
@ -216,6 +216,8 @@ protected:
nsresult GetUnreadChildrenNode(nsIMsgThread *thread, nsIRDFNode **target);
nsresult GetTotalChildrenNode(nsIMsgThread *thread, nsIRDFNode **target);
virtual void Cleanup();
static nsIRDFResource* kNC_Subject;
static nsIRDFResource* kNC_SubjectCollation;
static nsIRDFResource* kNC_Sender;

View File

@ -32,47 +32,68 @@
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
nsMsgRDFDataSource::nsMsgRDFDataSource():
mInitialized(PR_FALSE),
m_shuttingDown(PR_FALSE),
mRDFService(nsnull)
{
NS_INIT_REFCNT();
m_shuttingDown = PR_FALSE;
// do one-time initialization here
NS_NewISupportsArray(getter_AddRefs(mObservers));
}
nsMsgRDFDataSource::~nsMsgRDFDataSource()
{
// final shutdown happens here
NS_ASSERTION(!mInitialized, "Object going away without cleanup, possibly dangerous!");
if (mInitialized) Cleanup();
}
/* void Init (); */
/* initialization happens here - object is constructed,
but possibly partially shut down
*/
nsresult
nsMsgRDFDataSource::Init()
{
nsresult rv=NS_OK;
if (mInitialized)
return NS_ERROR_ALREADY_INITIALIZED;
/* Add an observer to XPCOM shutdown */
nsCOMPtr<nsIObserverService> obs = do_GetService(NS_OBSERVERSERVICE_PROGID,
&rv);
if (NS_FAILED(rv)) return rv;
nsAutoString topic; topic.AssignWithConversion(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
nsAutoString topic = NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
rv = obs->AddObserver(NS_STATIC_CAST(nsIObserver*, this), topic.GetUnicode());
if (NS_FAILED(rv)) return rv;
/* Get and keep the rdf service. Will be released by the observer */
getRDFService();
//Create Empty Enumerator
rv = NS_NewISupportsArray(getter_AddRefs(kEmptyArray));
if(NS_FAILED(rv)) return rv;
mInitialized=PR_TRUE;
return rv;
}
void nsMsgRDFDataSource::Close()
// clean yourself up - undo anything you did in Init()
void nsMsgRDFDataSource::Cleanup()
{
mWindow = null_nsCOMPtr();
kEmptyArray = null_nsCOMPtr();
nsresult rv;
mRDFService = nsnull;
// release ourselves from the observer service
nsCOMPtr<nsIObserverService> obs = do_GetService(NS_OBSERVERSERVICE_PROGID,
&rv);
if (NS_SUCCEEDED(rv)) {
rv = obs->RemoveObserver(NS_STATIC_CAST(nsIObserver*, this),
(const PRUnichar*)NS_LITERAL_STRING(NS_XPCOM_SHUTDOWN_OBSERVER_ID));
}
// release the window
mWindow = nsnull;
mInitialized = PR_FALSE;
}
NS_IMPL_ADDREF(nsMsgRDFDataSource)
@ -176,15 +197,15 @@ nsMsgRDFDataSource::HasAssertion(nsIRDFResource *aSource, nsIRDFResource *aPrope
NS_IMETHODIMP
nsMsgRDFDataSource::AddObserver(nsIRDFObserver *aObserver)
{
if (! mObservers) {
nsresult rv;
rv = NS_NewISupportsArray(getter_AddRefs(mObservers));
if (NS_FAILED(rv)) return rv;
}
NS_ASSERTION(mObservers->IndexOf(aObserver) == -1, "better not already be observing this");
// make sure we're initialized
if (!mInitialized)
Init();
NS_ASSERTION(mObservers->IndexOf(aObserver) == -1,
"better not already be observing this");
mObservers->AppendElement(aObserver);
return NS_OK;
mObservers->AppendElement(aObserver);
return NS_OK;
}
@ -195,6 +216,14 @@ nsMsgRDFDataSource::RemoveObserver(nsIRDFObserver *aObserver)
if (! mObservers)
return NS_OK;
mObservers->RemoveElement(aObserver);
// when we hit 0 observers, then it's probably time
// to go away - clean ourselves up now
PRUint32 count;
mObservers->Count(&count);
if (count == 0)
Cleanup();
return NS_OK;
}
@ -280,9 +309,8 @@ nsMsgRDFDataSource::DoCommand(nsISupportsArray *aSources, nsIRDFResource *aComma
NS_IMETHODIMP
nsMsgRDFDataSource::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData )
{
mRDFService = nsnull;
m_shuttingDown = PR_TRUE;
Close();
Cleanup();
return NS_OK;
}

View File

@ -50,7 +50,9 @@ class nsMsgRDFDataSource : public nsIRDFDataSource,
NS_DECL_NSIRDFDATASOURCE
NS_DECL_NSIOBSERVER
virtual void Close();
// called to reset the datasource to an empty state
// if you need to release yourself as an observer/listener, do it here
virtual void Cleanup();
protected:
nsIRDFService *getRDFService();
@ -69,8 +71,8 @@ class nsMsgRDFDataSource : public nsIRDFDataSource,
nsCOMPtr<nsIMsgWindow> mWindow;
nsCOMPtr<nsISupportsArray> kEmptyArray;
PRBool m_shuttingDown;
PRBool mInitialized;
nsresult GetIsThreaded(PRBool *threaded);
nsresult GetViewType(PRUint32 *viewType);
nsresult GetMessageView(nsIMessageView **messageView);