148 lines
5.0 KiB
Diff
148 lines
5.0 KiB
Diff
|
# vim: se ft=diff :
|
||
|
# HG changeset patch
|
||
|
# User Jan Horak <jhorak>
|
||
|
# Date 2017-04-26 02:36
|
||
|
# Parent 540cd06b1aea0bfa6f906b86393f5480914c01c2
|
||
|
Bug 1158578 - fix crash when compacting IMAP account. r=jorgk
|
||
|
|
||
|
diff --git a/mailnews/base/src/nsMsgFolderCompactor.cpp b/mailnews/base/src/nsMsgFolderCompactor.cpp
|
||
|
--- a/mailnews/base/src/nsMsgFolderCompactor.cpp
|
||
|
+++ b/mailnews/base/src/nsMsgFolderCompactor.cpp
|
||
|
@@ -31,16 +31,17 @@
|
||
|
#include "nsIMsgStatusFeedback.h"
|
||
|
#include "nsMsgBaseCID.h"
|
||
|
#include "nsIMsgFolderNotificationService.h"
|
||
|
#include "nsIMsgPluggableStore.h"
|
||
|
#include "nsMsgFolderCompactor.h"
|
||
|
#include <algorithm>
|
||
|
#include "nsIOutputStream.h"
|
||
|
#include "nsIInputStream.h"
|
||
|
+#include "nsPrintfCString.h"
|
||
|
|
||
|
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
// nsFolderCompactState
|
||
|
//////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
NS_IMPL_ISUPPORTS(nsFolderCompactState, nsIMsgFolderCompactor, nsIRequestObserver, nsIStreamListener, nsICopyMessageStreamListener, nsIUrlListener)
|
||
|
|
||
|
@@ -1096,16 +1097,24 @@ nsOfflineStoreCompactState::OnStopReques
|
||
|
// check for it specifically and don't terminate the compaction.
|
||
|
if (NS_FAILED(rv) && rv != NS_MSG_ERROR_MSG_NOT_OFFLINE)
|
||
|
goto done;
|
||
|
uri = do_QueryInterface(ctxt, &rv);
|
||
|
if (NS_FAILED(rv)) goto done;
|
||
|
rv = GetMessage(getter_AddRefs(msgHdr));
|
||
|
if (NS_FAILED(rv)) goto done;
|
||
|
|
||
|
+ // This is however an unexpected condition, so let's print a warning.
|
||
|
+ if (rv == NS_MSG_ERROR_MSG_NOT_OFFLINE) {
|
||
|
+ nsAutoCString spec;
|
||
|
+ uri->GetSpec(spec);
|
||
|
+ nsPrintfCString msg("Message expectedly not available offline: %s", spec.get());
|
||
|
+ NS_WARNING(msg.get());
|
||
|
+ }
|
||
|
+
|
||
|
if (msgHdr)
|
||
|
{
|
||
|
if (NS_SUCCEEDED(status))
|
||
|
{
|
||
|
msgHdr->SetMessageOffset(m_startOfNewMsg);
|
||
|
char storeToken[100];
|
||
|
PR_snprintf(storeToken, sizeof(storeToken), "%lld", m_startOfNewMsg);
|
||
|
msgHdr->SetStringProperty("storeToken", storeToken);
|
||
|
diff --git a/mailnews/imap/src/nsImapProtocol.cpp b/mailnews/imap/src/nsImapProtocol.cpp
|
||
|
--- a/mailnews/imap/src/nsImapProtocol.cpp
|
||
|
+++ b/mailnews/imap/src/nsImapProtocol.cpp
|
||
|
@@ -9500,35 +9500,66 @@ nsresult nsImapMockChannel::ReadFromMemC
|
||
|
// Content is modified so return an error so we try to open it the
|
||
|
// old fashioned way.
|
||
|
rv = NS_ERROR_FAILURE;
|
||
|
}
|
||
|
|
||
|
return rv;
|
||
|
}
|
||
|
|
||
|
+class nsReadFromImapConnectionFailure : public mozilla::Runnable
|
||
|
+{
|
||
|
+public:
|
||
|
+ nsReadFromImapConnectionFailure(nsImapMockChannel *aChannel)
|
||
|
+ : mImapMockChannel(aChannel)
|
||
|
+ {}
|
||
|
+
|
||
|
+ NS_IMETHOD Run()
|
||
|
+ {
|
||
|
+ if (mImapMockChannel) {
|
||
|
+ mImapMockChannel->RunOnStopRequestFailure();
|
||
|
+ }
|
||
|
+ return NS_OK;
|
||
|
+ }
|
||
|
+private:
|
||
|
+ RefPtr<nsImapMockChannel> mImapMockChannel;
|
||
|
+};
|
||
|
+
|
||
|
+
|
||
|
+nsresult nsImapMockChannel::RunOnStopRequestFailure()
|
||
|
+{
|
||
|
+ if (m_channelListener) {
|
||
|
+ m_channelListener->OnStopRequest(this, m_channelContext,
|
||
|
+ NS_MSG_ERROR_MSG_NOT_OFFLINE);
|
||
|
+ }
|
||
|
+ return NS_OK;
|
||
|
+}
|
||
|
+
|
||
|
// the requested url isn't in any of our caches so create an imap connection
|
||
|
// to process it.
|
||
|
nsresult nsImapMockChannel::ReadFromImapConnection()
|
||
|
{
|
||
|
nsresult rv = NS_OK;
|
||
|
nsCOMPtr<nsIImapUrl> imapUrl = do_QueryInterface(m_url);
|
||
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_url);
|
||
|
|
||
|
bool localOnly = false;
|
||
|
imapUrl->GetLocalFetchOnly(&localOnly);
|
||
|
if (localOnly)
|
||
|
{
|
||
|
// This will cause an OnStartRunningUrl, and the subsequent close
|
||
|
// will then cause an OnStopRunningUrl with the cancel status.
|
||
|
NotifyStartEndReadFromCache(true);
|
||
|
Cancel(NS_MSG_ERROR_MSG_NOT_OFFLINE);
|
||
|
- if (m_channelListener)
|
||
|
- m_channelListener->OnStopRequest(this, m_channelContext,
|
||
|
- NS_MSG_ERROR_MSG_NOT_OFFLINE);
|
||
|
+
|
||
|
+ // Dispatch error notification, so ReadFromImapConnection() returns *before*
|
||
|
+ // the error is sent to the listener's OnStopRequest(). This avoids
|
||
|
+ // endless recursion where the caller relies on async execution.
|
||
|
+ nsCOMPtr<nsIRunnable> event = new nsReadFromImapConnectionFailure(this);
|
||
|
+ NS_DispatchToCurrentThread(event);
|
||
|
return NS_MSG_ERROR_MSG_NOT_OFFLINE;
|
||
|
}
|
||
|
|
||
|
nsCOMPtr <nsILoadGroup> loadGroup;
|
||
|
GetLoadGroup(getter_AddRefs(loadGroup));
|
||
|
if (!loadGroup) // if we don't have one, the url will snag one from the msg window...
|
||
|
mailnewsUrl->GetLoadGroup(getter_AddRefs(loadGroup));
|
||
|
|
||
|
diff --git a/mailnews/imap/src/nsImapProtocol.h b/mailnews/imap/src/nsImapProtocol.h
|
||
|
--- a/mailnews/imap/src/nsImapProtocol.h
|
||
|
+++ b/mailnews/imap/src/nsImapProtocol.h
|
||
|
@@ -714,16 +714,17 @@ public:
|
||
|
NS_DECL_NSIIMAPMOCKCHANNEL
|
||
|
NS_DECL_NSICHANNEL
|
||
|
NS_DECL_NSIREQUEST
|
||
|
NS_DECL_NSICACHEENTRYOPENCALLBACK
|
||
|
NS_DECL_NSITRANSPORTEVENTSINK
|
||
|
|
||
|
nsImapMockChannel();
|
||
|
static nsresult Create (const nsIID& iid, void **result);
|
||
|
+ nsresult RunOnStopRequestFailure();
|
||
|
|
||
|
protected:
|
||
|
virtual ~nsImapMockChannel();
|
||
|
nsCOMPtr <nsIURI> m_url;
|
||
|
|
||
|
nsCOMPtr<nsIURI> m_originalUrl;
|
||
|
nsCOMPtr<nsILoadGroup> m_loadGroup;
|
||
|
nsCOMPtr<nsILoadInfo> m_loadInfo;
|