fixed bug 33986 -- IMAP: Quit with unsaved draft, save to draft crashes & bug 44203 -- Closing last mail compose crashes the app; r=alecf

git-svn-id: svn://10.0.0.236/trunk@73706 18797224-902f-48f8-a5cc-f745e15eee43
This commit is contained in:
jefft%netscape.com
2000-07-05 23:19:24 +00:00
parent af868ff566
commit 88334e2247
10 changed files with 134 additions and 10 deletions

View File

@@ -92,6 +92,10 @@ interface nsIMsgAccountManager : nsISupports {
/* summary of summary files folder cache */
readonly attribute nsIMsgFolderCache folderCache;
/* are we shutting down */
readonly attribute boolean shutdownInProgress;
/*
* search for the server with the given username, hostname, and type
* the type is the same as is specified in the preferences,

View File

@@ -230,5 +230,40 @@ function MsgToggleSplitter(id)
}
function NotifyQuitApplication()
{
var ObserverService = Components.classes["component://netscape/observer-service"].getService();
ObserverService = ObserverService.QueryInterface(Components.interfaces.nsIObserverService);
if (ObserverService)
{
try
{
ObserverService.Notify(null, "quit-application", null);
}
catch (ex)
{
// dump("no observer found \n");
}
}
}
function LastToClose()
{
var windowManager = Components.classes['component://netscape/rdf/datasource?name=window-mediator'].getService();
var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator);
var enumerator = windowManagerInterface.getEnumerator( null );
var count = 0;
while ( enumerator.hasMoreElements() && count < 2 )
{
var windowToClose = enumerator.getNext();
count++;
}
if (count == 1)
return true;
else
return false;
}

View File

@@ -128,6 +128,7 @@ nsMsgAccountManager::nsMsgAccountManager() :
m_accountsLoaded(PR_FALSE),
m_defaultAccount(null_nsCOMPtr()),
m_haveShutdown(PR_FALSE),
m_shutdownInProgress(PR_FALSE),
m_emptyTrashInProgress(PR_FALSE),
m_prefs(0)
{
@@ -170,6 +171,8 @@ nsresult nsMsgAccountManager::Init()
{
nsAutoString topic; topic.AssignWithConversion(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
observerService->AddObserver(this, topic.GetUnicode());
topic.AssignWithConversion("quit-application");
observerService->AddObserver(this, topic.GetUnicode());
}
return NS_OK;
@@ -191,15 +194,30 @@ nsresult nsMsgAccountManager::Shutdown()
return NS_OK;
}
NS_IMETHODIMP
nsMsgAccountManager::GetShutdownInProgress(PRBool *_retval)
{
NS_ENSURE_ARG_POINTER(_retval);
*_retval = m_shutdownInProgress;
return NS_OK;
}
NS_IMETHODIMP nsMsgAccountManager::Observe(nsISupports *aSubject, const PRUnichar *aTopic, const PRUnichar *someData)
{
nsAutoString topicString(aTopic);
nsAutoString shutdownString; shutdownString.AssignWithConversion(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
nsAutoString shutdownString;
shutdownString.AssignWithConversion(NS_XPCOM_SHUTDOWN_OBSERVER_ID);
nsAutoString quitApplicationString;
quitApplicationString.AssignWithConversion("quit-application");
if(topicString == shutdownString)
{
Shutdown();
}
else if (topicString == quitApplicationString)
{
m_shutdownInProgress = PR_TRUE;
}
return NS_OK;
}

View File

@@ -77,6 +77,7 @@ private:
nsCAutoString mAccountKeyList;
PRBool m_haveShutdown;
PRBool m_shutdownInProgress;
/* internal creation routines - updates m_identities and m_incomingServers */

View File

@@ -962,6 +962,8 @@ function ComposeCanClose()
switch (result.value)
{
case 0: //Save
if (LastToClose())
NotifyQuitApplication();
SaveAsDraft();
break;
case 1: //Cancel

View File

@@ -1138,15 +1138,12 @@ m_compFields->SetCc(recipStrCStr);
////////////////////////////////////////////////////////////////////////////////////
QuotingOutputStreamListener::~QuotingOutputStreamListener()
{
if (mComposeObj)
NS_RELEASE(mComposeObj);
}
QuotingOutputStreamListener::QuotingOutputStreamListener(const PRUnichar * originalMsgURI,
PRBool quoteHeaders,
nsIMsgIdentity *identity)
{
mComposeObj = nsnull;
mQuoteHeaders = quoteHeaders;
mIdentity = identity;
@@ -1450,7 +1447,7 @@ NS_IMETHODIMP QuotingOutputStreamListener::OnStopRequest(nsIChannel *aChannel, n
}
}
NS_IF_RELEASE(mComposeObj); //We are done with it, therefore release it.
mComposeObj = null_nsCOMPtr(); //We are done with it, therefore release it.
return rv;
}
@@ -1624,7 +1621,6 @@ NS_IMPL_QUERY_INTERFACE2(nsMsgComposeSendListener,
nsMsgComposeSendListener::nsMsgComposeSendListener(void)
{
mComposeObj = nsnull;
mDeliverMode = 0;
NS_INIT_REFCNT();
@@ -1801,7 +1797,6 @@ NS_IMPL_ISUPPORTS(nsMsgDocumentStateListener, NS_GET_IID(nsIDocumentStateListene
nsMsgDocumentStateListener::nsMsgDocumentStateListener(void)
{
NS_INIT_REFCNT();
mComposeObj = nsnull;
}
nsMsgDocumentStateListener::~nsMsgDocumentStateListener(void)

View File

@@ -151,7 +151,7 @@ public:
NS_IMETHOD SetMimeHeaders(nsIMimeHeaders * headers);
private:
nsMsgCompose *mComposeObj;
nsCOMPtr<nsMsgCompose> mComposeObj;
nsString mMsgBody;
nsString mCitePrefix;
nsString mSignature;
@@ -202,7 +202,7 @@ public:
private:
nsMsgCompose *mComposeObj;
nsCOMPtr<nsMsgCompose> mComposeObj;
MSG_DeliverMode mDeliverMode;
};

View File

@@ -39,10 +39,14 @@
#include "nsIURL.h"
#include "nsMsgComposeStringBundle.h"
#include "nsMsgCompUtils.h"
#include "prcmon.h"
#include "nsIMsgImapMailFolder.h"
#include "nsIEventQueueService.h"
static NS_DEFINE_CID(kStandardUrlCID, NS_STANDARDURL_CID);
static NS_DEFINE_CID(kMsgCopyServiceCID,NS_MSGCOPYSERVICE_CID);
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
////////////////////////////////////////////////////////////////////////////////////
// This is the listener class for the copy operation. We have to create this class
@@ -59,6 +63,8 @@ NS_INTERFACE_MAP_END_THREADSAFE
CopyListener::CopyListener(void)
{
mComposeAndSend = nsnull;
mCopyObject = nsnull;
mCopyInProgress = PR_FALSE;
NS_INIT_REFCNT();
}
@@ -123,6 +129,13 @@ CopyListener::OnStopCopy(nsresult aStatus)
#endif
}
if (mCopyObject)
{
PR_CEnterMonitor(mCopyObject);
PR_CNotifyAll(mCopyObject);
mCopyInProgress = PR_FALSE;
PR_CExitMonitor(mCopyObject);
}
if (mComposeAndSend)
mComposeAndSend->NotifyListenersOnStopCopy(aStatus);
@@ -246,8 +259,47 @@ nsMsgCopy::DoCopy(nsIFileSpec *aDiskFile, nsIMsgFolder *dstFolder,
return NS_ERROR_OUT_OF_MEMORY;
mCopyListener->SetMsgComposeAndSendObject(aMsgSendObj);
nsCOMPtr<nsIEventQueue> eventQueue;
if (aIsDraft)
{
nsCOMPtr<nsIMsgImapMailFolder> imapFolder =
do_QueryInterface(dstFolder);
NS_WITH_SERVICE(nsIMsgAccountManager, accountManager,
NS_MSGACCOUNTMANAGER_PROGID, &rv);
if (NS_FAILED(rv)) return rv;
PRBool shutdownInProgress = PR_FALSE;
rv = accountManager->GetShutdownInProgress(&shutdownInProgress);
if (NS_SUCCEEDED(rv) && shutdownInProgress && imapFolder)
{
// set the following only when we were in the middle of shutdown
// process
mCopyListener->mCopyObject = do_QueryInterface(tPtr);
mCopyListener->mCopyInProgress = PR_TRUE;
NS_WITH_SERVICE(nsIEventQueueService, pEventQService,
kEventQueueServiceCID, &rv);
if (NS_FAILED(rv)) return rv;
pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD,
getter_AddRefs(eventQueue));
}
}
// ** make sure we have a valid copy listener while waiting for copy
// server to finish
nsCOMPtr<CopyListener> aCopyListener = do_QueryInterface(tPtr);
rv = copyService->CopyFileMessage(aDiskFile, dstFolder, aMsgToReplace,
aIsDraft, mCopyListener, msgWindow);
// aCopyListener->mCopyInProgress can only be set when we are in the
// middle of the shutdown process
while (aCopyListener->mCopyInProgress)
{
PR_CEnterMonitor(aCopyListener);
PR_CWait(aCopyListener, 1000UL);
PR_CExitMonitor(aCopyListener);
if (eventQueue)
eventQueue->ProcessPendingEvents();
}
}
return rv;

View File

@@ -63,6 +63,9 @@ public:
NS_IMETHOD OnStopCopy(nsresult aStatus);
NS_IMETHOD SetMsgComposeAndSendObject(nsMsgComposeAndSend *obj);
nsCOMPtr<nsISupports> mCopyObject;
PRBool mCopyInProgress;
private:
nsCOMPtr<nsMsgComposeAndSend> mComposeAndSend;

View File

@@ -1,9 +1,23 @@
function goQuitApplication()
{
var ObserverService = Components.classes["component://netscape/observer-service"].getService();
ObserverService = ObserverService.QueryInterface(Components.interfaces.nsIObserverService);
if (ObserverService)
{
try
{
ObserverService.Notify(null, "quit-application", null);
}
catch (ex)
{
// dump("no observer found \n");
}
}
var windowManager = Components.classes['component://netscape/rdf/datasource?name=window-mediator'].getService();
var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator);
var enumerator = windowManagerInterface.getEnumerator( null );
while ( enumerator.hasMoreElements() )
{
var windowToClose = enumerator.getNext();