зеркало из https://github.com/mozilla/gecko-dev.git
more work on reading offline news, sr=sspitzer for mscott 15870
This commit is contained in:
Родитель
9a961598e2
Коммит
6f2568e88f
|
@ -295,6 +295,9 @@ nsresult nsMsgProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||||
|
|
||||||
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
if (NS_SUCCEEDED(rv) && aMsgUrl)
|
||||||
{
|
{
|
||||||
|
PRBool msgIsInLocalCache;
|
||||||
|
aMsgUrl->GetMsgIsInLocalCache(&msgIsInLocalCache);
|
||||||
|
|
||||||
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK); // set the url as a url currently being run...
|
rv = aMsgUrl->SetUrlState(PR_TRUE, NS_OK); // set the url as a url currently being run...
|
||||||
|
|
||||||
// if the url is given a stream consumer then we should use it to forward calls to...
|
// if the url is given a stream consumer then we should use it to forward calls to...
|
||||||
|
@ -325,7 +328,7 @@ nsresult nsMsgProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||||
m_socketIsOpen = PR_TRUE; // mark the channel as open
|
m_socketIsOpen = PR_TRUE; // mark the channel as open
|
||||||
}
|
}
|
||||||
} // if we got an event queue service
|
} // if we got an event queue service
|
||||||
else // the connection is already open so we should begin processing our new url...
|
else if (!msgIsInLocalCache) // the connection is already open so we should begin processing our new url...
|
||||||
rv = ProcessProtocolState(aURL, nsnull, 0, 0);
|
rv = ProcessProtocolState(aURL, nsnull, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,9 @@
|
||||||
#include "nsIMsgFolder.h"
|
#include "nsIMsgFolder.h"
|
||||||
#include "nsIMsgNewsFolder.h"
|
#include "nsIMsgNewsFolder.h"
|
||||||
|
|
||||||
|
// for the memory cache...
|
||||||
|
#include "nsICachedNetData.h"
|
||||||
|
|
||||||
#include "nsIPref.h"
|
#include "nsIPref.h"
|
||||||
|
|
||||||
#include "nsIMsgWindow.h"
|
#include "nsIMsgWindow.h"
|
||||||
|
@ -558,11 +561,15 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI * aURL, nsIMsgWindow *aMsgWindow
|
||||||
|
|
||||||
m_runningURL = do_QueryInterface(m_url);
|
m_runningURL = do_QueryInterface(m_url);
|
||||||
m_connectionBusy = PR_TRUE;
|
m_connectionBusy = PR_TRUE;
|
||||||
|
PRBool msgIsInLocalCache = PR_FALSE;
|
||||||
if (NS_SUCCEEDED(rv) && m_runningURL)
|
if (NS_SUCCEEDED(rv) && m_runningURL)
|
||||||
{
|
{
|
||||||
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningURL);
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningURL);
|
||||||
if (mailnewsUrl)
|
if (mailnewsUrl)
|
||||||
|
{
|
||||||
mailnewsUrl->SetMsgWindow(aMsgWindow);
|
mailnewsUrl->SetMsgWindow(aMsgWindow);
|
||||||
|
mailnewsUrl->GetMsgIsInLocalCache(&msgIsInLocalCache);
|
||||||
|
}
|
||||||
// okay, now fill in our event sinks...Note that each getter ref counts before
|
// okay, now fill in our event sinks...Note that each getter ref counts before
|
||||||
// it returns the interface to us...we'll release when we are done
|
// it returns the interface to us...we'll release when we are done
|
||||||
m_runningURL->GetNewsgroupList(getter_AddRefs(m_newsgroupList));
|
m_runningURL->GetNewsgroupList(getter_AddRefs(m_newsgroupList));
|
||||||
|
@ -570,6 +577,9 @@ NS_IMETHODIMP nsNNTPProtocol::Initialize(nsIURI * aURL, nsIMsgWindow *aMsgWindow
|
||||||
m_runningURL->GetNntpHost(getter_AddRefs(m_newsHost));
|
m_runningURL->GetNntpHost(getter_AddRefs(m_newsHost));
|
||||||
m_runningURL->GetNewsgroup(getter_AddRefs(m_newsgroup));
|
m_runningURL->GetNewsgroup(getter_AddRefs(m_newsgroup));
|
||||||
m_runningURL->GetOfflineNewsState(getter_AddRefs(m_offlineNewsState));
|
m_runningURL->GetOfflineNewsState(getter_AddRefs(m_offlineNewsState));
|
||||||
|
if (msgIsInLocalCache)
|
||||||
|
return NS_OK; // probably don't need to do anything else - definitely don't want
|
||||||
|
// to open the socket.
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return rv;
|
return rv;
|
||||||
|
@ -672,6 +682,161 @@ NS_IMETHODIMP nsNNTPProtocol::LoadNewsUrl(nsIURI * aURL, nsISupports * aConsumer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// WARNING: the cache stream listener is intended to be accessed from the UI thread!
|
||||||
|
// it will NOT create another proxy for the stream listener that gets passed in...
|
||||||
|
class nsNntpCacheStreamListener : public nsIStreamListener
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NS_DECL_ISUPPORTS
|
||||||
|
NS_DECL_NSISTREAMOBSERVER
|
||||||
|
NS_DECL_NSISTREAMLISTENER
|
||||||
|
|
||||||
|
nsNntpCacheStreamListener ();
|
||||||
|
virtual ~nsNntpCacheStreamListener();
|
||||||
|
|
||||||
|
nsresult Init(nsIStreamListener * aStreamListener, nsIChannel * aChannelToUse);
|
||||||
|
protected:
|
||||||
|
nsCOMPtr<nsIChannel> mChannelToUse;
|
||||||
|
nsCOMPtr<nsIStreamListener> mListener;
|
||||||
|
};
|
||||||
|
|
||||||
|
NS_IMPL_ADDREF(nsNntpCacheStreamListener);
|
||||||
|
NS_IMPL_RELEASE(nsNntpCacheStreamListener);
|
||||||
|
|
||||||
|
NS_INTERFACE_MAP_BEGIN(nsNntpCacheStreamListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIStreamListener)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIStreamObserver)
|
||||||
|
NS_INTERFACE_MAP_ENTRY(nsIStreamListener)
|
||||||
|
NS_INTERFACE_MAP_END
|
||||||
|
|
||||||
|
nsNntpCacheStreamListener::nsNntpCacheStreamListener()
|
||||||
|
{
|
||||||
|
NS_INIT_ISUPPORTS();
|
||||||
|
}
|
||||||
|
|
||||||
|
nsNntpCacheStreamListener::~nsNntpCacheStreamListener()
|
||||||
|
{}
|
||||||
|
|
||||||
|
nsresult nsNntpCacheStreamListener::Init(nsIStreamListener * aStreamListener, nsIChannel * aChannelToUse)
|
||||||
|
{
|
||||||
|
NS_ENSURE_ARG(aStreamListener);
|
||||||
|
NS_ENSURE_ARG(aChannelToUse);
|
||||||
|
|
||||||
|
mChannelToUse = aChannelToUse;
|
||||||
|
mListener = aStreamListener;
|
||||||
|
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsNntpCacheStreamListener::OnStartRequest(nsIChannel * aChannel, nsISupports * aCtxt)
|
||||||
|
{
|
||||||
|
nsCOMPtr <nsILoadGroup> loadGroup;
|
||||||
|
mChannelToUse->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (loadGroup)
|
||||||
|
loadGroup->AddChannel(mChannelToUse, nsnull /* context isupports */);
|
||||||
|
return mListener->OnStartRequest(mChannelToUse, aCtxt);
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsNntpCacheStreamListener::OnStopRequest(nsIChannel * aChannel, nsISupports * aCtxt, nsresult aStatus, const PRUnichar* aMsg)
|
||||||
|
{
|
||||||
|
nsresult rv = mListener->OnStopRequest(mChannelToUse, aCtxt, aStatus, aMsg);
|
||||||
|
nsCOMPtr <nsILoadGroup> loadGroup;
|
||||||
|
mChannelToUse->GetLoadGroup(getter_AddRefs(loadGroup));
|
||||||
|
if (loadGroup)
|
||||||
|
loadGroup->RemoveChannel(mChannelToUse, nsnull, aStatus, nsnull);
|
||||||
|
|
||||||
|
mListener = nsnull;
|
||||||
|
mChannelToUse = nsnull;
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
|
NS_IMETHODIMP
|
||||||
|
nsNntpCacheStreamListener::OnDataAvailable(nsIChannel * aChannel, nsISupports * aCtxt, nsIInputStream * aInStream, PRUint32 aSourceOffset, PRUint32 aCount)
|
||||||
|
{
|
||||||
|
return mListener->OnDataAvailable(mChannelToUse, aCtxt, aInStream, aSourceOffset, aCount);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
NS_IMETHODIMP nsNNTPProtocol::AsyncRead(nsIStreamListener *listener, nsISupports *ctxt)
|
||||||
|
{
|
||||||
|
nsresult rv;
|
||||||
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningURL, &rv);
|
||||||
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
|
SetNewsFolder(); // make sure m_newsFolder is set.
|
||||||
|
m_channelContext = ctxt;
|
||||||
|
m_channelListener = listener;
|
||||||
|
m_runningURL->GetNewsAction(&m_newsAction);
|
||||||
|
// first, check if this is a message load that should come from either
|
||||||
|
// the memory cache or the local msg cache.
|
||||||
|
if (mailnewsUrl && m_newsAction == nsINntpUrl::ActionDisplayArticle)
|
||||||
|
{
|
||||||
|
nsCOMPtr<nsICachedNetData> cacheEntry;
|
||||||
|
PRUint32 contentLength = 0;
|
||||||
|
PRBool partialFlag = PR_FALSE;
|
||||||
|
PRBool msgIsInLocalCache;
|
||||||
|
|
||||||
|
mailnewsUrl->GetMsgIsInLocalCache(&msgIsInLocalCache);
|
||||||
|
if (msgIsInLocalCache)
|
||||||
|
{
|
||||||
|
nsCOMPtr <nsIMsgFolder> folder = do_QueryInterface(m_newsFolder);
|
||||||
|
if (folder && NS_SUCCEEDED(rv))
|
||||||
|
{
|
||||||
|
// we want to create a file channel and read the msg from there.
|
||||||
|
nsMsgKey key = nsMsgKey_None;
|
||||||
|
rv = m_runningURL->GetMessageKey(&key);
|
||||||
|
nsCOMPtr<nsIFileChannel> fileChannel;
|
||||||
|
rv = folder->GetOfflineFileChannel(key, getter_AddRefs(fileChannel));
|
||||||
|
// get the file channel from the folder, somehow (through the message or
|
||||||
|
// folder sink?) We also need to set the transfer offset to the message offset
|
||||||
|
if (fileChannel && NS_SUCCEEDED(rv))
|
||||||
|
{
|
||||||
|
fileChannel->SetLoadGroup(m_loadGroup);
|
||||||
|
m_typeWanted = ARTICLE_WANTED;
|
||||||
|
nsNntpCacheStreamListener * cacheListener = new nsNntpCacheStreamListener();
|
||||||
|
NS_ADDREF(cacheListener);
|
||||||
|
cacheListener->Init(m_channelListener, NS_STATIC_CAST(nsIChannel *, this));
|
||||||
|
rv = fileChannel->AsyncRead(cacheListener, m_channelContext);
|
||||||
|
NS_RELEASE(cacheListener);
|
||||||
|
|
||||||
|
if (NS_SUCCEEDED(rv)) // ONLY if we succeeded in actually starting the read should we return
|
||||||
|
return NS_OK;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// look to see if this url should be added to the memory cache..
|
||||||
|
PRBool useMemoryCache = PR_FALSE;
|
||||||
|
mailnewsUrl->GetAddToMemoryCache(&useMemoryCache);
|
||||||
|
rv = mailnewsUrl->GetMemCacheEntry(getter_AddRefs(cacheEntry));
|
||||||
|
if (NS_SUCCEEDED(rv) && cacheEntry)
|
||||||
|
{
|
||||||
|
PRBool updateInProgress;
|
||||||
|
cacheEntry->GetPartialFlag(&partialFlag);
|
||||||
|
cacheEntry->GetUpdateInProgress(&updateInProgress);
|
||||||
|
cacheEntry->GetStoredContentLength(&contentLength);
|
||||||
|
// only try to update the cache entry if it isn't being used.
|
||||||
|
// We always want to try to write to the cache entry if we can
|
||||||
|
if (!updateInProgress)
|
||||||
|
{
|
||||||
|
// now we need to figure out if the entry is new / or partially unfinished...
|
||||||
|
// this determines if we are going to USE the cache entry for reading the data
|
||||||
|
// vs. if we need to write data into the cache entry...
|
||||||
|
if (!contentLength || partialFlag)
|
||||||
|
{
|
||||||
|
// we're going to fill up this cache entry,
|
||||||
|
// do we have a listener here?
|
||||||
|
nsIStreamListener *listener = m_channelListener;
|
||||||
|
rv = cacheEntry->InterceptAsyncRead(listener, 0, getter_AddRefs(m_channelListener));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nsMsgProtocol::AsyncRead(listener, ctxt);
|
||||||
|
}
|
||||||
|
|
||||||
nsresult nsNNTPProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
nsresult nsNNTPProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||||
{
|
{
|
||||||
NS_ENSURE_ARG_POINTER(aURL);
|
NS_ENSURE_ARG_POINTER(aURL);
|
||||||
|
@ -684,11 +849,12 @@ nsresult nsNNTPProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||||
nsCOMPtr <nsINNTPNewsgroupPost> message;
|
nsCOMPtr <nsINNTPNewsgroupPost> message;
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
|
|
||||||
// if this connection comes from the cache, we need to initialize the
|
m_runningURL = do_QueryInterface(aURL, &rv);
|
||||||
// load group here, by generating the start request notification. nsMsgProtocol::OnStartRequest
|
if (NS_FAILED(rv)) return rv;
|
||||||
// ignores the first parameter (which is supposed to be the channel) so we'll pass in null.
|
m_runningURL->GetNewsAction(&m_newsAction);
|
||||||
if (m_fromCache)
|
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(m_runningURL);
|
||||||
nsMsgProtocol::OnStartRequest(nsnull, aURL);
|
|
||||||
|
SetNewsFolder(); // make sure m_newsFolder is set.
|
||||||
|
|
||||||
m_articleNumber = -1;
|
m_articleNumber = -1;
|
||||||
rv = aURL->GetHost(getter_Copies(m_hostName));
|
rv = aURL->GetHost(getter_Copies(m_hostName));
|
||||||
|
@ -696,10 +862,7 @@ nsresult nsNNTPProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||||
rv = aURL->GetPreHost(getter_Copies(m_userName));
|
rv = aURL->GetPreHost(getter_Copies(m_userName));
|
||||||
if (NS_FAILED(rv)) return rv;
|
if (NS_FAILED(rv)) return rv;
|
||||||
|
|
||||||
m_runningURL = do_QueryInterface(aURL, &rv);
|
|
||||||
if (NS_FAILED(rv)) return rv;
|
|
||||||
m_connectionBusy = PR_TRUE;
|
m_connectionBusy = PR_TRUE;
|
||||||
m_runningURL->GetNewsAction(&m_newsAction);
|
|
||||||
|
|
||||||
// okay, now fill in our event sinks...Note that each getter ref counts before
|
// okay, now fill in our event sinks...Note that each getter ref counts before
|
||||||
// it returns the interface to us...we'll release when we are done
|
// it returns the interface to us...we'll release when we are done
|
||||||
|
@ -927,6 +1090,13 @@ nsresult nsNNTPProtocol::LoadUrl(nsIURI * aURL, nsISupports * aConsumer)
|
||||||
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// if this connection comes from the cache, we need to initialize the
|
||||||
|
// load group here, by generating the start request notification. nsMsgProtocol::OnStartRequest
|
||||||
|
// ignores the first parameter (which is supposed to be the channel) so we'll pass in null.
|
||||||
|
if (m_fromCache)
|
||||||
|
nsMsgProtocol::OnStartRequest(nsnull, aURL);
|
||||||
|
|
||||||
/* At this point, we're all done parsing the URL, and know exactly
|
/* At this point, we're all done parsing the URL, and know exactly
|
||||||
what we want to do with it.
|
what we want to do with it.
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -168,7 +168,7 @@ public:
|
||||||
|
|
||||||
NS_IMETHOD Cancel(nsresult status); // handle stop button
|
NS_IMETHOD Cancel(nsresult status); // handle stop button
|
||||||
NS_IMETHOD GetContentType(char * *aContentType);
|
NS_IMETHOD GetContentType(char * *aContentType);
|
||||||
|
NS_IMETHOD AsyncRead(nsIStreamListener *listener, nsISupports *ctxt);
|
||||||
nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer);
|
nsresult LoadUrl(nsIURI * aURL, nsISupports * aConsumer);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -202,7 +202,6 @@ private:
|
||||||
nsCOMPtr<nsIInputStream> mDisplayInputStream;
|
nsCOMPtr<nsIInputStream> mDisplayInputStream;
|
||||||
nsCOMPtr<nsIOutputStream> mDisplayOutputStream;
|
nsCOMPtr<nsIOutputStream> mDisplayOutputStream;
|
||||||
nsMsgLineStreamBuffer * m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
|
nsMsgLineStreamBuffer * m_lineStreamBuffer; // used to efficiently extract lines from the incoming data stream
|
||||||
|
|
||||||
// the nsINntpURL that is currently running
|
// the nsINntpURL that is currently running
|
||||||
nsCOMPtr<nsINntpUrl> m_runningURL;
|
nsCOMPtr<nsINntpUrl> m_runningURL;
|
||||||
PRBool m_connectionBusy;
|
PRBool m_connectionBusy;
|
||||||
|
|
|
@ -220,6 +220,7 @@ nsNntpService::DisplayMessage(const char* aMessageURI, nsISupports * aDisplayCon
|
||||||
{
|
{
|
||||||
folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
|
folder->ShouldStoreMsgOffline(key, &shouldStoreMsgOffline);
|
||||||
folder->HasMsgOffline(key, &hasMsgOffline);
|
folder->HasMsgOffline(key, &hasMsgOffline);
|
||||||
|
msgUrl->SetMsgIsInLocalCache(hasMsgOffline);
|
||||||
}
|
}
|
||||||
newsFolder->SetSaveArticleOffline(shouldStoreMsgOffline);
|
newsFolder->SetSaveArticleOffline(shouldStoreMsgOffline);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче