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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ private:
|
||||
nsCAutoString mAccountKeyList;
|
||||
|
||||
PRBool m_haveShutdown;
|
||||
PRBool m_shutdownInProgress;
|
||||
|
||||
|
||||
/* internal creation routines - updates m_identities and m_incomingServers */
|
||||
|
||||
@@ -962,6 +962,8 @@ function ComposeCanClose()
|
||||
switch (result.value)
|
||||
{
|
||||
case 0: //Save
|
||||
if (LastToClose())
|
||||
NotifyQuitApplication();
|
||||
SaveAsDraft();
|
||||
break;
|
||||
case 1: //Cancel
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -63,6 +63,9 @@ public:
|
||||
NS_IMETHOD OnStopCopy(nsresult aStatus);
|
||||
|
||||
NS_IMETHOD SetMsgComposeAndSendObject(nsMsgComposeAndSend *obj);
|
||||
|
||||
nsCOMPtr<nsISupports> mCopyObject;
|
||||
PRBool mCopyInProgress;
|
||||
|
||||
private:
|
||||
nsCOMPtr<nsMsgComposeAndSend> mComposeAndSend;
|
||||
|
||||
@@ -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();
|
||||
|
||||
Reference in New Issue
Block a user