зеркало из https://github.com/mozilla/gecko-dev.git
more on cached connections work -- urlQueue now implemented on nsImapIncomingServer instead of nsImapService; LoadNextQueuedUrl() will be triggered when finishing a running url
This commit is contained in:
Родитель
7b3ef9ea03
Коммит
9bd44c06b5
|
@ -22,8 +22,15 @@
|
|||
|
||||
#include "nsIImapIncomingServer.h"
|
||||
#include "nsIMAPHostSessionList.h"
|
||||
#include "nsImapIncomingServer.h"
|
||||
#include "nsMsgIncomingServer.h"
|
||||
#include "nsImapIncomingServer.h"
|
||||
#include "nsIImapUrl.h"
|
||||
#include "nsIUrlListener.h"
|
||||
#include "nsIEventQueue.h"
|
||||
#include "nsIImapProtocol.h"
|
||||
#include "nsISupportsArray.h"
|
||||
#include "nsVoidArray.h"
|
||||
#include "nsCOMPtr.h"
|
||||
|
||||
#include "nsIPref.h"
|
||||
|
||||
|
@ -31,6 +38,7 @@
|
|||
#include "plstr.h"
|
||||
|
||||
static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID);
|
||||
static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID);
|
||||
|
||||
/* get some implementation from nsMsgIncomingServer */
|
||||
class nsImapIncomingServer : public nsMsgIncomingServer,
|
||||
|
@ -43,12 +51,30 @@ public:
|
|||
nsImapIncomingServer();
|
||||
virtual ~nsImapIncomingServer();
|
||||
|
||||
// we support the nsIImapIncomingServer interface
|
||||
// overriding nsMsgIncomingServer methods
|
||||
NS_IMETHOD SetKey(char * aKey); // override nsMsgIncomingServer's implementation...
|
||||
NS_IMETHOD GetServerURI(char * *aServerURI);
|
||||
|
||||
// we support the nsIImapIncomingServer interface
|
||||
NS_IMETHOD GetMaximumConnectionsNumber(PRInt32* maxConnections);
|
||||
NS_IMETHOD SetMaximumConnectionsNumber(PRInt32 maxConnections);
|
||||
|
||||
NS_IMETHOD GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue,
|
||||
nsIImapUrl* aImapUrl,
|
||||
nsIUrlListener* aUrlListener = 0,
|
||||
nsISupports* aConsumer = 0,
|
||||
nsIURL** aURL = 0);
|
||||
NS_IMETHOD LoadNextQueuedUrl();
|
||||
NS_IMETHOD RemoveConnection(nsIImapProtocol* aImapConnection);
|
||||
|
||||
private:
|
||||
nsresult CreateImapConnection (nsIEventQueue* aEventQueue,
|
||||
nsIImapUrl* aImapUrl,
|
||||
nsIImapProtocol** aImapConnection);
|
||||
char *m_rootFolderPath;
|
||||
nsCOMPtr<nsISupportsArray> m_connectionCache;
|
||||
nsCOMPtr<nsISupportsArray> m_urlQueue;
|
||||
nsVoidArray m_urlConsumers;
|
||||
};
|
||||
|
||||
NS_IMPL_ISUPPORTS_INHERITED(nsImapIncomingServer,
|
||||
|
@ -59,6 +85,9 @@ NS_IMPL_ISUPPORTS_INHERITED(nsImapIncomingServer,
|
|||
nsImapIncomingServer::nsImapIncomingServer() : m_rootFolderPath(nsnull)
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
nsresult rv;
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(m_connectionCache));
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(m_urlQueue));
|
||||
}
|
||||
|
||||
nsImapIncomingServer::~nsImapIncomingServer()
|
||||
|
@ -112,6 +141,197 @@ NS_IMETHODIMP nsImapIncomingServer::GetServerURI(char ** aServerURI)
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMPL_SERVERPREF_INT(nsImapIncomingServer, MaximumConnectionsNumber,
|
||||
"max_cached_connections");
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapIncomingServer::GetImapConnectionAndLoadUrl(nsIEventQueue*
|
||||
aClientEventQueue,
|
||||
nsIImapUrl* aImapUrl,
|
||||
nsIUrlListener*
|
||||
aUrlListener,
|
||||
nsISupports* aConsumer,
|
||||
nsIURL** aURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsIImapProtocol* aProtocol = nsnull;
|
||||
|
||||
rv = CreateImapConnection(aClientEventQueue, aImapUrl, &aProtocol);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
if (aUrlListener)
|
||||
aImapUrl->RegisterListener(aUrlListener);
|
||||
|
||||
if (aProtocol)
|
||||
{
|
||||
rv = aProtocol->LoadUrl(aImapUrl, aConsumer);
|
||||
}
|
||||
else
|
||||
{ // unable to get an imap connection to run the url; add to the url
|
||||
// queue
|
||||
PR_CEnterMonitor(this);
|
||||
m_urlQueue->AppendElement(aImapUrl);
|
||||
m_urlConsumers.AppendElement((void*)aConsumer);
|
||||
NS_IF_ADDREF(aConsumer);
|
||||
PR_CExitMonitor(this);
|
||||
}
|
||||
if (aURL)
|
||||
{
|
||||
*aURL = aImapUrl;
|
||||
NS_IF_RELEASE(*aURL);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapIncomingServer::LoadNextQueuedUrl()
|
||||
{
|
||||
PRUint32 cnt = 0;
|
||||
nsresult rv = NS_OK;
|
||||
|
||||
PR_CEnterMonitor(this);
|
||||
m_urlQueue->Count(&cnt);
|
||||
if (cnt > 0)
|
||||
{
|
||||
nsCOMPtr<nsIImapUrl>
|
||||
aImapUrl(do_QueryInterface(m_urlQueue->ElementAt(0)));
|
||||
|
||||
if (aImapUrl)
|
||||
{
|
||||
nsISupports *aConsumer =
|
||||
(nsISupports*)m_urlConsumers.ElementAt(0);
|
||||
|
||||
NS_IF_ADDREF(aConsumer);
|
||||
|
||||
nsIImapProtocol * protocolInstance = nsnull;
|
||||
rv = CreateImapConnection(nsnull, aImapUrl,
|
||||
&protocolInstance);
|
||||
if (NS_SUCCEEDED(rv) && protocolInstance)
|
||||
{
|
||||
rv = protocolInstance->LoadUrl(aImapUrl, aConsumer);
|
||||
m_urlQueue->RemoveElementAt(0);
|
||||
m_urlConsumers.RemoveElementAt(0);
|
||||
}
|
||||
|
||||
NS_IF_RELEASE(aConsumer);
|
||||
}
|
||||
}
|
||||
PR_CExitMonitor(this);
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapIncomingServer::RemoveConnection(nsIImapProtocol* aImapConnection)
|
||||
{
|
||||
PRInt32 elementIndex = -1;
|
||||
nsresult rv;
|
||||
PR_CEnterMonitor(this);
|
||||
|
||||
if (aImapConnection)
|
||||
{
|
||||
// preventing earlier release of the protocol
|
||||
nsCOMPtr<nsIImapProtocol>
|
||||
aConnection(do_QueryInterface(aImapConnection,&rv));
|
||||
aImapConnection->TellThreadToDie(PR_TRUE);
|
||||
|
||||
m_connectionCache->RemoveElement(aImapConnection);
|
||||
}
|
||||
|
||||
PR_CExitMonitor(this);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImapIncomingServer::CreateImapConnection(nsIEventQueue *aEventQueue,
|
||||
nsIImapUrl * aImapUrl,
|
||||
nsIImapProtocol ** aImapConnection)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool canRunUrl = PR_FALSE;
|
||||
PRBool hasToWait = PR_FALSE;
|
||||
nsCOMPtr<nsIImapProtocol> connection;
|
||||
nsCOMPtr<nsIImapProtocol> freeConnection;
|
||||
PRBool isBusy = PR_FALSE;
|
||||
PRBool isInboxConnection = PR_FALSE;
|
||||
|
||||
PR_CEnterMonitor(this);
|
||||
|
||||
PRInt32 maxConnections = 2; // default to be two
|
||||
rv = GetMaximumConnectionsNumber(&maxConnections);
|
||||
if (NS_FAILED(rv) || maxConnections < 2)
|
||||
{
|
||||
maxConnections = 2;
|
||||
rv = SetMaximumConnectionsNumber(maxConnections);
|
||||
}
|
||||
|
||||
*aImapConnection = nsnull;
|
||||
// iterate through the connection cache for a connection that can handle this url.
|
||||
PRUint32 cnt;
|
||||
rv = m_connectionCache->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
for (PRUint32 i = 0; i < cnt && !canRunUrl && !hasToWait; i++)
|
||||
{
|
||||
connection = do_QueryInterface(m_connectionCache->ElementAt(i));
|
||||
if (connection)
|
||||
connection->CanHandleUrl(aImapUrl, canRunUrl, hasToWait);
|
||||
|
||||
if (!freeConnection && !canRunUrl && !hasToWait && connection)
|
||||
{
|
||||
connection->IsBusy(isBusy, isInboxConnection);
|
||||
if (!isBusy && !isInboxConnection)
|
||||
freeConnection = connection;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here and we have a connection, then we should return it!
|
||||
if (canRunUrl && connection)
|
||||
{
|
||||
*aImapConnection = connection;
|
||||
NS_IF_ADDREF(*aImapConnection);
|
||||
}
|
||||
else if (hasToWait)
|
||||
{
|
||||
// do nothing; return NS_OK; for queuing
|
||||
}
|
||||
else if (cnt < maxConnections && aEventQueue)
|
||||
{
|
||||
// create a new connection and add it to the connection cache
|
||||
// we may need to flag the protocol connection as busy so we don't get
|
||||
// a race
|
||||
// condition where someone else goes through this code
|
||||
nsIImapProtocol * protocolInstance = nsnull;
|
||||
rv = nsComponentManager::CreateInstance(kImapProtocolCID, nsnull,
|
||||
nsIImapProtocol::GetIID(),
|
||||
(void **) &protocolInstance);
|
||||
if (NS_SUCCEEDED(rv) && protocolInstance)
|
||||
{
|
||||
NS_WITH_SERVICE(nsIImapHostSessionList, hostSession,
|
||||
kCImapHostSessionList, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
rv = protocolInstance->Initialize(hostSession, aEventQueue);
|
||||
}
|
||||
|
||||
// take the protocol instance and add it to the connectionCache
|
||||
if (protocolInstance)
|
||||
m_connectionCache->AppendElement(protocolInstance);
|
||||
*aImapConnection = protocolInstance; // this is already ref counted.
|
||||
|
||||
}
|
||||
else if (freeConnection)
|
||||
{
|
||||
*aImapConnection = freeConnection;
|
||||
NS_IF_ADDREF(*aImapConnection);
|
||||
}
|
||||
else // cannot get anyone to handle the url queue it
|
||||
{
|
||||
// queue the url
|
||||
}
|
||||
|
||||
PR_CExitMonitor(this);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult NS_NewImapIncomingServer(const nsIID& iid,
|
||||
void **result)
|
||||
|
|
|
@ -47,6 +47,7 @@ PRLogModuleInfo *IMAP;
|
|||
#include "nsString2.h"
|
||||
|
||||
#include "nsIMsgIncomingServer.h"
|
||||
#include "nsIImapIncomingServer.h"
|
||||
|
||||
// for temp message hack
|
||||
#ifdef XP_UNIX
|
||||
|
@ -363,8 +364,6 @@ nsImapProtocol::SetupSinkProxy()
|
|||
"fatal... null sink event queue or thread");
|
||||
nsresult res;
|
||||
|
||||
if (!m_server)
|
||||
m_runningUrl->GetServer(getter_AddRefs(m_server));
|
||||
if (!m_imapLog)
|
||||
{
|
||||
nsCOMPtr<nsIImapLog> aImapLog;
|
||||
|
@ -436,35 +435,17 @@ nsImapProtocol::SetupSinkProxy()
|
|||
// Setup With Url is intended to set up data which is held on a PER URL basis and not
|
||||
// a per connection basis. If you have data which is independent of the url we are currently
|
||||
// running, then you should put it in Initialize().
|
||||
void nsImapProtocol::SetupWithUrl(nsIURL * aURL)
|
||||
nsresult nsImapProtocol::SetupWithUrl(nsIURL * aURL, nsISupports* aConsumer)
|
||||
{
|
||||
NS_PRECONDITION(aURL, "null URL passed into Imap Protocol");
|
||||
if (aURL)
|
||||
{
|
||||
nsresult rv = aURL->QueryInterface(nsIImapUrl::GetIID(),
|
||||
nsresult rv = aURL->QueryInterface(nsIImapUrl::GetIID(),
|
||||
(void **)&m_runningUrl);
|
||||
if (NS_FAILED(rv)) return;
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsIMsgIncomingServer> aServer;
|
||||
rv = m_runningUrl->GetServer(getter_AddRefs(aServer));
|
||||
if (NS_FAILED(rv)) return;
|
||||
|
||||
char *username = nsnull;
|
||||
const char* hostname = nsnull;
|
||||
aServer->GetUserName(&username);
|
||||
m_runningUrl->GetHost(&hostname);
|
||||
|
||||
if (PL_strcmp(GetImapHostName(), hostname) ||
|
||||
PL_strcmp(GetImapUserName(), username))
|
||||
{
|
||||
// ** jt - we might want to check for the port number too.
|
||||
// wrong hostname and username, must be reusing the connection for
|
||||
// different account -- *** jt
|
||||
m_transport = null_nsCOMPtr();
|
||||
m_outputStream = null_nsCOMPtr();
|
||||
m_outputConsumer = null_nsCOMPtr();
|
||||
}
|
||||
PR_FREEIF(username);
|
||||
if (!m_server)
|
||||
m_runningUrl->GetServer(getter_AddRefs(m_server));
|
||||
|
||||
if ( m_runningUrl && !m_transport /* and we don't have a transport yet */)
|
||||
{
|
||||
|
@ -547,9 +528,15 @@ void nsImapProtocol::ImapThreadMain(void *aParm)
|
|||
|
||||
me->m_eventQueue = null_nsCOMPtr();
|
||||
|
||||
// ***** Important need to remove the connection out from the connection
|
||||
// pool - nsImapService **********
|
||||
delete me;
|
||||
if (me->m_server)
|
||||
{
|
||||
nsCOMPtr<nsIImapIncomingServer>
|
||||
aImapServer(do_QueryInterface(me->m_server, &result));
|
||||
if (NS_SUCCEEDED(result))
|
||||
aImapServer->RemoveConnection(me);
|
||||
}
|
||||
|
||||
NS_RELEASE(me);
|
||||
}
|
||||
|
||||
PRBool
|
||||
|
@ -596,11 +583,38 @@ nsImapProtocol::WaitForFEEventCompletion()
|
|||
PR_ExitMonitor(m_eventCompletionMonitor);
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapProtocol::TellThreadToDie(PRBool isSafeToDie)
|
||||
{
|
||||
// **** jt - This routine should only be called by imap service.
|
||||
static char logoutString[] = "???? logout\r\n";
|
||||
SendData(logoutString);
|
||||
// GetServerStateParser().ParseIMAPServerResponse(logoutString);
|
||||
|
||||
m_transport = null_nsCOMPtr();
|
||||
m_outputStream = null_nsCOMPtr();
|
||||
m_outputConsumer = null_nsCOMPtr();
|
||||
|
||||
PR_EnterMonitor(m_threadDeathMonitor);
|
||||
m_threadShouldDie = PR_TRUE;
|
||||
PR_ExitMonitor(m_threadDeathMonitor);
|
||||
|
||||
PR_EnterMonitor(m_eventCompletionMonitor);
|
||||
PR_NotifyAll(m_eventCompletionMonitor);
|
||||
PR_ExitMonitor(m_eventCompletionMonitor);
|
||||
|
||||
PR_EnterMonitor(m_urlReadyToRunMonitor);
|
||||
PR_NotifyAll(m_urlReadyToRunMonitor);
|
||||
PR_ExitMonitor(m_urlReadyToRunMonitor);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
nsImapProtocol::ImapThreadMainLoop()
|
||||
{
|
||||
// ****** please implement PR_LOG 'ing ******
|
||||
while (ImapThreadIsRunning())
|
||||
while (ImapThreadIsRunning() && !DeathSignalReceived())
|
||||
{
|
||||
// if we are making our first pass through this loop and
|
||||
// we already have a url to process then jump right in and
|
||||
|
@ -620,6 +634,7 @@ nsImapProtocol::ImapThreadMainLoop()
|
|||
|
||||
PR_ExitMonitor(m_urlReadyToRunMonitor);
|
||||
}
|
||||
m_imapThreadIsRunning = PR_FALSE;
|
||||
}
|
||||
|
||||
void nsImapProtocol::EstablishServerConnection()
|
||||
|
@ -803,7 +818,20 @@ void nsImapProtocol::ProcessCurrentURL()
|
|||
SetCurrentEntryStatus(0);
|
||||
#endif
|
||||
if (DeathSignalReceived())
|
||||
{
|
||||
HandleCurrentUrlError();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_server)
|
||||
{
|
||||
nsresult rv;
|
||||
nsCOMPtr<nsIImapIncomingServer>
|
||||
aImapServer(do_QueryInterface(m_server, &rv));
|
||||
if (NS_SUCCEEDED(rv))
|
||||
aImapServer->LoadNextQueuedUrl();
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (!logonFailed)
|
||||
HandleCurrentUrlError();
|
||||
|
@ -813,11 +841,6 @@ void nsImapProtocol::ProcessCurrentURL()
|
|||
|
||||
// release the url as we are done with it...
|
||||
ReleaseUrlState();
|
||||
|
||||
nsresult rv;
|
||||
NS_WITH_SERVICE(nsIImapService, imapService, kCImapService, &rv);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
imapService->LoadNextQueuedUrl();
|
||||
}
|
||||
|
||||
void nsImapProtocol::ParseIMAPandCheckForNewMail(const char* commandString)
|
||||
|
@ -862,14 +885,16 @@ NS_IMETHODIMP nsImapProtocol::OnDataAvailable(nsIURL* aURL, nsIInputStream *aISt
|
|||
|
||||
NS_IMETHODIMP nsImapProtocol::OnStartBinding(nsIURL* aURL, const char *aContentType)
|
||||
{
|
||||
m_runningUrl->SetUrlState(PR_TRUE, NS_OK);
|
||||
if (m_runningUrl)
|
||||
m_runningUrl->SetUrlState(PR_TRUE, NS_OK);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
// stop binding is a "notification" informing us that the stream associated with aURL is going away.
|
||||
NS_IMETHODIMP nsImapProtocol::OnStopBinding(nsIURL* aURL, nsresult aStatus, const PRUnichar* aMsg)
|
||||
{
|
||||
m_runningUrl->SetUrlState(PR_FALSE, aStatus); // set change in url
|
||||
if (m_runningUrl)
|
||||
m_runningUrl->SetUrlState(PR_FALSE, aStatus); // set change in url
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -937,7 +962,8 @@ nsresult nsImapProtocol::LoadUrl(nsIURL * aURL, nsISupports * aConsumer)
|
|||
if (aConsumer)
|
||||
m_displayConsumer = do_QueryInterface(aConsumer);
|
||||
|
||||
SetupWithUrl(aURL);
|
||||
rv = SetupWithUrl(aURL, aConsumer);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
SetupSinkProxy(); // generate proxies for all of the event sinks in the url
|
||||
|
||||
if (m_transport && m_runningUrl)
|
||||
|
|
|
@ -108,6 +108,8 @@ public:
|
|||
NS_IMETHOD GetSupportedUserFlags(PRUint16 *flags);
|
||||
|
||||
NS_IMETHOD GetDisplayStream (nsIWebShell **webShell);
|
||||
// Tell thread to die. This can only be called by imap service
|
||||
NS_IMETHOD TellThreadToDie(PRBool isSafeToDie);
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
// End of nsIStreamListenerSupport
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -359,7 +361,7 @@ private:
|
|||
PRUint32 *m_fetchBodyIdList;
|
||||
|
||||
// initialization function given a new url and transport layer
|
||||
void SetupWithUrl(nsIURL * aURL);
|
||||
nsresult SetupWithUrl(nsIURL * aURL, nsISupports* aConsumer);
|
||||
void ReleaseUrlState(); // release any state that is stored on a per action basis.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -2298,4 +2298,3 @@ nsImapServerResponseParser::GetHostSessionList()
|
|||
return fHostSessionList;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
|
||||
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
||||
*
|
||||
* The contents of this file are subject to the Netscape Public License
|
||||
* Version 1.0 (the "NPL"); you may not use this file except in
|
||||
|
@ -28,9 +28,9 @@
|
|||
#include "nsIIMAPHostSessionList.h"
|
||||
#include "nsImapService.h"
|
||||
#include "nsImapUrl.h"
|
||||
#include "nsImapProtocol.h"
|
||||
#include "nsCOMPtr.h"
|
||||
#include "nsIMsgFolder.h"
|
||||
#include "nsIImapIncomingServer.h"
|
||||
|
||||
#include "nsImapUtils.h"
|
||||
|
||||
|
@ -45,15 +45,11 @@ static NS_DEFINE_IID(kISupportsIID, NS_ISUPPORTS_IID);
|
|||
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kCImapHostSessionList, NS_IIMAPHOSTSESSIONLIST_CID);
|
||||
static NS_DEFINE_CID(kImapProtocolCID, NS_IMAPPROTOCOL_CID);
|
||||
static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
|
||||
|
||||
static const char *sequenceString = "SEQUENCE";
|
||||
static const char *uidString = "UID";
|
||||
|
||||
#define MAXIMUM_CONNECTION 5
|
||||
|
||||
NS_IMPL_THREADSAFE_ADDREF(nsImapService);
|
||||
NS_IMPL_THREADSAFE_RELEASE(nsImapService);
|
||||
|
||||
|
@ -61,22 +57,10 @@ NS_IMPL_THREADSAFE_RELEASE(nsImapService);
|
|||
nsImapService::nsImapService()
|
||||
{
|
||||
NS_INIT_REFCNT();
|
||||
|
||||
// mscott - the imap service really needs to be a service listener
|
||||
// on the host session list...
|
||||
nsresult rv = nsServiceManager::GetService(kCImapHostSessionList, nsIImapHostSessionList::GetIID(),
|
||||
(nsISupports**)&m_sessionList);
|
||||
|
||||
// I don't know how we're going to report this error if we failed to create the isupports array...
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(m_connectionCache));
|
||||
rv = NS_NewISupportsArray(getter_AddRefs(m_urlQueue));
|
||||
}
|
||||
|
||||
nsImapService::~nsImapService()
|
||||
{
|
||||
// release the host session list
|
||||
if (m_sessionList)
|
||||
(void)nsServiceManager::ReleaseService(kCImapHostSessionList, m_sessionList);
|
||||
}
|
||||
|
||||
nsresult nsImapService::QueryInterface(const nsIID &aIID, void** aInstancePtr)
|
||||
|
@ -109,83 +93,6 @@ nsresult nsImapService::QueryInterface(const nsIID &aIID, void** aInstancePtr)
|
|||
return NS_NOINTERFACE;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapService::CreateImapConnection(nsIEventQueue *aEventQueue, nsIImapUrl * aImapUrl,
|
||||
nsIImapProtocol ** aImapConnection)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool canRunUrl = PR_FALSE;
|
||||
PRBool hasToWait = PR_FALSE;
|
||||
nsCOMPtr<nsIImapProtocol> connection;
|
||||
nsCOMPtr<nsIImapProtocol> freeConnection;
|
||||
PRBool isBusy = PR_FALSE;
|
||||
PRBool isInboxConnection = PR_FALSE;
|
||||
|
||||
PR_CEnterMonitor(this);
|
||||
|
||||
*aImapConnection = nsnull;
|
||||
|
||||
// iterate through the connection cache for a connection that can handle this url.
|
||||
PRUint32 cnt;
|
||||
rv = m_connectionCache->Count(&cnt);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
for (PRUint32 i = 0; i < cnt && !canRunUrl && !hasToWait; i++)
|
||||
{
|
||||
connection = do_QueryInterface(m_connectionCache->ElementAt(i));
|
||||
if (connection)
|
||||
connection->CanHandleUrl(aImapUrl, canRunUrl, hasToWait);
|
||||
|
||||
if (!freeConnection && !canRunUrl && !hasToWait && connection)
|
||||
{
|
||||
connection->IsBusy(isBusy, isInboxConnection);
|
||||
if (!isBusy && !isInboxConnection)
|
||||
freeConnection = connection;
|
||||
}
|
||||
}
|
||||
|
||||
// if we got here and we have a connection, then we should return it!
|
||||
if (canRunUrl && connection)
|
||||
{
|
||||
*aImapConnection = connection;
|
||||
NS_IF_ADDREF(*aImapConnection);
|
||||
}
|
||||
else if (hasToWait)
|
||||
{
|
||||
// do nothing; return NS_OK; for queuing
|
||||
}
|
||||
else if (cnt < MAXIMUM_CONNECTION && aEventQueue)
|
||||
{
|
||||
// create a new connection and add it to the connection cache
|
||||
// we may need to flag the protocol connection as busy so we don't get
|
||||
// a race
|
||||
// condition where someone else goes through this code
|
||||
nsIImapProtocol * protocolInstance = nsnull;
|
||||
rv = nsComponentManager::CreateInstance(kImapProtocolCID, nsnull,
|
||||
nsIImapProtocol::GetIID(),
|
||||
(void **) &protocolInstance);
|
||||
if (NS_SUCCEEDED(rv) && protocolInstance)
|
||||
rv = protocolInstance->Initialize(m_sessionList, aEventQueue);
|
||||
|
||||
// take the protocol instance and add it to the connectionCache
|
||||
if (protocolInstance)
|
||||
m_connectionCache->AppendElement(protocolInstance);
|
||||
*aImapConnection = protocolInstance; // this is already ref counted.
|
||||
|
||||
}
|
||||
else if (freeConnection)
|
||||
{
|
||||
*aImapConnection = freeConnection;
|
||||
NS_IF_ADDREF(*aImapConnection);
|
||||
}
|
||||
else // cannot get anyone to handle the url queue it
|
||||
{
|
||||
// queue the url
|
||||
}
|
||||
|
||||
PR_CExitMonitor(this);
|
||||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImapService::GetFolderName(nsIMsgFolder* aImapFolder,
|
||||
nsString2& folderName)
|
||||
|
@ -208,42 +115,6 @@ nsImapService::GetFolderName(nsIMsgFolder* aImapFolder,
|
|||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapService::LoadNextQueuedUrl()
|
||||
{
|
||||
PRUint32 cnt = 0;
|
||||
nsresult rv = NS_OK;
|
||||
m_urlQueue->Count(&cnt);
|
||||
if (cnt > 0)
|
||||
{
|
||||
nsCOMPtr<nsIImapUrl>
|
||||
aImapUrl(do_QueryInterface(m_urlQueue->ElementAt(0)));
|
||||
|
||||
if (aImapUrl)
|
||||
{
|
||||
nsISupports *aConsumer =
|
||||
(nsISupports*)m_urlConsumers.ElementAt(0);
|
||||
|
||||
NS_IF_ADDREF(aConsumer);
|
||||
|
||||
nsIImapProtocol * protocolInstance = nsnull;
|
||||
rv = CreateImapConnection(nsnull, aImapUrl,
|
||||
&protocolInstance);
|
||||
if (NS_SUCCEEDED(rv) && protocolInstance)
|
||||
{
|
||||
rv = protocolInstance->LoadUrl(aImapUrl, aConsumer);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
m_urlQueue->RemoveElementAt(0);
|
||||
m_urlConsumers.RemoveElementAt(0);
|
||||
}
|
||||
}
|
||||
NS_IF_RELEASE(aConsumer);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue,
|
||||
nsIMsgFolder * aImapMailFolder,
|
||||
|
@ -490,38 +361,6 @@ nsImapService::CreateStartOfImapUrl(nsIImapUrl * &imapUrl,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImapService::GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue,
|
||||
nsIImapUrl* aImapUrl,
|
||||
nsIUrlListener* aUrlListener,
|
||||
nsISupports* aConsumer,
|
||||
nsIURL** aURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsIImapProtocol* aProtocol = nsnull;
|
||||
|
||||
rv = CreateImapConnection(aClientEventQueue, aImapUrl, &aProtocol);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
aImapUrl->RegisterListener(aUrlListener);
|
||||
if (aProtocol)
|
||||
{
|
||||
rv = aProtocol->LoadUrl(aImapUrl, aConsumer);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_urlQueue->AppendElement(aImapUrl);
|
||||
m_urlConsumers.AppendElement((void*)aConsumer);
|
||||
NS_IF_ADDREF(aConsumer);
|
||||
}
|
||||
if (aURL)
|
||||
{
|
||||
*aURL = aImapUrl;
|
||||
NS_IF_RELEASE(*aURL);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/* fetching the headers of RFC822 messages */
|
||||
/* imap4://HOST>header><UID/SEQUENCE>>MAILBOXPATH>x */
|
||||
/* 'x' is the message UID or sequence number list */
|
||||
|
@ -1218,6 +1057,30 @@ nsImapService::OnlineMessageCopy(nsIEventQueue* aClientEventQueue,
|
|||
return rv;
|
||||
}
|
||||
|
||||
nsresult
|
||||
nsImapService::GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue,
|
||||
nsIImapUrl* aImapUrl,
|
||||
nsIUrlListener* aUrlListener,
|
||||
nsISupports* aConsumer,
|
||||
nsIURL** aURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
||||
rv = aImapUrl->GetServer(getter_AddRefs(aMsgIncomingServer));
|
||||
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
||||
{
|
||||
nsCOMPtr<nsIImapIncomingServer>
|
||||
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && aImapServer)
|
||||
rv = aImapServer->GetImapConnectionAndLoadUrl(aClientEventQueue,
|
||||
aImapUrl,
|
||||
aUrlListener,
|
||||
aConsumer,
|
||||
aURL);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
#ifdef HAVE_PORT
|
||||
|
||||
/* fetching the headers of RFC822 messages */
|
||||
|
|
|
@ -42,10 +42,6 @@ public:
|
|||
// we suppport the nsIImapService interface
|
||||
////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
NS_IMETHOD CreateImapConnection (nsIEventQueue *aEventQueue, nsIImapUrl * aImapUrl,
|
||||
nsIImapProtocol ** aImapConnection);
|
||||
NS_IMETHOD LoadNextQueuedUrl();
|
||||
|
||||
NS_IMETHOD SelectFolder(nsIEventQueue * aClientEventQueue,
|
||||
nsIMsgFolder *aImapMailFolder,
|
||||
nsIUrlListener * aUrlListener,
|
||||
|
@ -172,14 +168,7 @@ protected:
|
|||
const char *howToDiddle,
|
||||
imapMessageFlagsType flags,
|
||||
PRBool messageIdsAreUID);
|
||||
nsIImapHostSessionList * m_sessionList; // the one and only list of all host sessions...
|
||||
|
||||
// the connection cache right now is just a simple array of open nsIImapProtocol instances.
|
||||
// we just iterate over all known connections and see if one of the connections can run
|
||||
// our current request...we can look into making a more sophisticated cache later...
|
||||
nsCOMPtr<nsISupportsArray> m_connectionCache;
|
||||
nsCOMPtr<nsISupportsArray> m_urlQueue;
|
||||
nsVoidArray m_urlConsumers;
|
||||
};
|
||||
|
||||
#endif /* nsImapService_h___ */
|
||||
|
|
Загрузка…
Ссылка в новой задаче