diff --git a/mailnews/imap/public/nsIImapMockChannel.idl b/mailnews/imap/public/nsIImapMockChannel.idl index a1f4cdd0293f..361f5b746af0 100644 --- a/mailnews/imap/public/nsIImapMockChannel.idl +++ b/mailnews/imap/public/nsIImapMockChannel.idl @@ -63,19 +63,19 @@ interface nsIStreamListener; interface nsIProgressEventSink; -interface nsILoadGroup; interface nsIURI; +interface nsIImapProtocol; -[scriptable, uuid(6EEC5ED3-670F-11d3-989A-001083010E9B)] +[scriptable, uuid(e0178cd5-d37b-4bde-9ab8-752083536225)] interface nsIImapMockChannel : nsIChannel { - attribute nsIProgressEventSink progressEventSink; - void GetChannelListener(out nsIStreamListener aChannelListener); - void GetChannelContext(out nsISupports aChannelContext); - void Close(); + attribute nsIProgressEventSink progressEventSink; + void GetChannelListener(out nsIStreamListener aChannelListener); + void GetChannelContext(out nsISupports aChannelContext); + void Close(); + void setImapProtocol(in nsIImapProtocol aProtocol); + [noscript] void setSecurityInfo(in nsISupports securityInfo); - [noscript] void setSecurityInfo(in nsISupports securityInfo); - - void setURI(in nsIURI uri); + void setURI(in nsIURI uri); }; diff --git a/mailnews/imap/src/nsImapProtocol.cpp b/mailnews/imap/src/nsImapProtocol.cpp index db0507e69d6f..b36cd32840f1 100644 --- a/mailnews/imap/src/nsImapProtocol.cpp +++ b/mailnews/imap/src/nsImapProtocol.cpp @@ -307,6 +307,7 @@ NS_INTERFACE_MAP_BEGIN(nsImapProtocol) NS_INTERFACE_MAP_ENTRY(nsIRunnable) NS_INTERFACE_MAP_ENTRY(nsIImapProtocol) NS_INTERFACE_MAP_ENTRY(nsIInputStreamCallback) + NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference) NS_INTERFACE_MAP_END_THREADSAFE static PRInt32 gTooFastTime = 2; @@ -702,6 +703,7 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer) m_runningUrl->GetMockChannel(getter_AddRefs(m_mockChannel)); if (m_mockChannel) { + m_mockChannel->SetImapProtocol(this); // if we have a listener from a mock channel, over-ride the consumer that was passed in nsCOMPtr channelListener; m_mockChannel->GetChannelListener(getter_AddRefs(channelListener)); @@ -800,8 +802,6 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer) // Ensure that the socket can get the notification callbacks SetSecurityCallbacksFromChannel(m_transport, m_mockChannel); - m_transport->SetTimeout(nsISocketTransport::TIMEOUT_CONNECT, gResponseTimeout + 60); - m_transport->SetTimeout(nsISocketTransport::TIMEOUT_READ_WRITE, gResponseTimeout); // open buffered, blocking input stream rv = m_transport->OpenInputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(m_inputStream)); if (NS_FAILED(rv)) return rv; @@ -816,6 +816,8 @@ nsresult nsImapProtocol::SetupWithUrl(nsIURI * aURL, nsISupports* aConsumer) if (m_transport && m_mockChannel) { + m_transport->SetTimeout(nsISocketTransport::TIMEOUT_CONNECT, gResponseTimeout + 60); + m_transport->SetTimeout(nsISocketTransport::TIMEOUT_READ_WRITE, gResponseTimeout); // set the security info for the mock channel to be the security status for our underlying transport. nsCOMPtr securityInfo; m_transport->GetSecurityInfo(getter_AddRefs(securityInfo)); @@ -945,10 +947,6 @@ NS_IMETHODIMP nsImapProtocol::Run() // called from UI thread. void nsImapProtocol::CloseStreams() { - if (m_inputStream) - m_inputStream->Close(); - if (m_outputStream) - m_outputStream->Close(); if (m_transport) { // make sure the transport closes (even if someone is still indirectly @@ -1263,10 +1261,10 @@ PRBool nsImapProtocol::ProcessCurrentURL() m_runningUrl->GetRerunningUrl(&rerunningUrl); m_runningUrl->GetExternalLinkUrl(&isExternalUrl); m_runningUrl->GetValidUrl(&validUrl); + m_runningUrl->GetImapAction(&m_imapAction); if (isExternalUrl) { - m_runningUrl->GetImapAction(&m_imapAction); if (m_imapAction == nsIImapUrl::nsImapSelectFolder) { // we need to send a start request so that the doc loader @@ -4243,6 +4241,12 @@ char* nsImapProtocol::CreateNewLineFromSocket() char * newLine = nsnull; PRUint32 numBytesInLine = 0; nsresult rv = NS_OK; + // we hold a ref to the input stream in case we get cancelled from the + // ui thread, which releases our ref to the input stream, and can + // cause the pipe to get deleted before the monitor the read is + // blocked on gets notified. When that happens, the imap thread + // will stay blocked. + nsCOMPtr kungFuGrip = m_inputStream; do { newLine = m_inputStreamBuffer->ReadNextLine(m_inputStream, numBytesInLine, needMoreData, &rv); @@ -4251,6 +4255,7 @@ char* nsImapProtocol::CreateNewLineFromSocket() } while (!newLine && NS_SUCCEEDED(rv) && !DeathSignalReceived()); // until we get the next line and haven't been interrupted + kungFuGrip = nsnull; if (NS_FAILED(rv)) { @@ -8420,9 +8425,16 @@ NS_IMETHODIMP nsImapMockChannel::GetStatus(nsresult *status) return NS_OK; } +NS_IMETHODIMP nsImapMockChannel::SetImapProtocol(nsIImapProtocol *aProtocol) +{ + m_protocol = do_GetWeakReference(aProtocol); + return NS_OK; +} + NS_IMETHODIMP nsImapMockChannel::Cancel(nsresult status) { m_cancelStatus = status; + nsCOMPtr imapProtocol = do_QueryReferent(m_protocol); // if we aren't reading from the cache and we get canceled...doom our cache entry... if (m_url) @@ -8439,7 +8451,10 @@ NS_IMETHODIMP nsImapMockChannel::Cancel(nsresult status) cacheEntry->Doom(); } } - + + if (imapProtocol) + imapProtocol->TellThreadToDie(PR_FALSE); + return NS_OK; } diff --git a/mailnews/imap/src/nsImapProtocol.h b/mailnews/imap/src/nsImapProtocol.h index 2b2f7c422f7b..5d9cc06bed9b 100644 --- a/mailnews/imap/src/nsImapProtocol.h +++ b/mailnews/imap/src/nsImapProtocol.h @@ -151,7 +151,8 @@ public: #define IMAP_CLEAN_UP_URL_STATE 0x00000010 // processing clean up url state #define IMAP_ISSUED_LANGUAGE_REQUEST 0x00000020 // make sure we only issue the language request once per connection... -class nsImapProtocol : public nsIImapProtocol, public nsIRunnable, public nsIInputStreamCallback, public nsMsgProtocol +class nsImapProtocol : public nsIImapProtocol, public nsIRunnable, public nsIInputStreamCallback, + public nsSupportsWeakReference, public nsMsgProtocol { public: @@ -660,6 +661,7 @@ protected: nsCOMPtr mSecurityInfo; nsCOMPtr mCacheRequest; // the request associated with a read from the cache nsCString m_ContentType; + nsWeakPtr m_protocol; PRBool mChannelClosed; PRBool mReadingFromCache;