mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-26 19:55:39 +00:00
more work on offline, especially handling being offline re loading folders and messages w/o offline bodies 15865
This commit is contained in:
parent
2a48d3c1f2
commit
a7dda2acff
@ -331,3 +331,18 @@
|
||||
## @loc None
|
||||
5058=Deleting this folder is not undoable and will delete all of the messages it contains. Are you sure you still want to delete this folder?
|
||||
|
||||
## @name IMAP_HTML_NO_CACHED_BODY_TITLE
|
||||
## @loc None
|
||||
5059=<TITLE>Go Online to View This Message</TITLE>\n\
|
||||
## @name IMAP_HTML_NO_CACHED_BODY_BODY
|
||||
## @loc None
|
||||
5060=The body of this message has not been downloaded from \n\
|
||||
the server for reading offline. To read this message, \n\
|
||||
you must reconnect to the network, choose Offline from \n\
|
||||
the File menu and then select Work Online.\n\
|
||||
In the future, you can select which messages or folders to read offline. To do \n\
|
||||
this, choose Offline from the file menu and then select Synchronize. You can \n\
|
||||
adjust the Disk Space preference to prevent the downloading of large messages.
|
||||
|
||||
|
||||
|
||||
|
@ -55,6 +55,9 @@
|
||||
#include "nsIDirectoryService.h"
|
||||
#include "nsAppDirectoryServiceDefs.h"
|
||||
#include "nsIWebNavigation.h"
|
||||
#include "nsIIOService.h"
|
||||
#include "nsImapStringBundle.h"
|
||||
#include "plbase64.h"
|
||||
|
||||
#define PREF_MAIL_ROOT_IMAP "mail.root.imap"
|
||||
|
||||
@ -62,6 +65,7 @@ static NS_DEFINE_CID(kPrefCID, NS_PREF_CID);
|
||||
static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
|
||||
static NS_DEFINE_CID(kEventQueueServiceCID, NS_EVENTQUEUESERVICE_CID);
|
||||
static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
|
||||
static NS_DEFINE_CID(kIOServiceCID, NS_IOSERVICE_CID);
|
||||
|
||||
|
||||
static const char *sequenceString = "SEQUENCE";
|
||||
@ -114,6 +118,18 @@ PRUnichar nsImapService::GetHierarchyDelimiter(nsIMsgFolder* aMsgFolder)
|
||||
return delimiter;
|
||||
}
|
||||
|
||||
PRBool nsImapService::WeAreOffline()
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
PRBool offline = PR_FALSE;
|
||||
|
||||
NS_WITH_SERVICE(nsIIOService, netService, kIOServiceCID, &rv);
|
||||
if (NS_SUCCEEDED(rv) && netService)
|
||||
{
|
||||
netService->GetOffline(&offline);
|
||||
}
|
||||
return offline;
|
||||
}
|
||||
// N.B., this returns an escaped folder name, appropriate for putting in a url.
|
||||
nsresult
|
||||
nsImapService::GetFolderName(nsIMsgFolder* aImapFolder,
|
||||
@ -167,15 +183,18 @@ nsImapService::SelectFolder(nsIEventQueue * aClientEventQueue,
|
||||
// create a protocol instance to handle the request.
|
||||
// NOTE: once we start working with multiple connections, this step will be much more complicated...but for now
|
||||
// just create a connection and process the request.
|
||||
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
||||
"Oops ... null pointer");
|
||||
if (!aImapMailFolder || !aClientEventQueue)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_ASSERTION (aImapMailFolder && aClientEventQueue,
|
||||
"Oops ... null pointer");
|
||||
if (!aImapMailFolder || !aClientEventQueue)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
PRBool noSelect = PR_FALSE;
|
||||
aImapMailFolder->GetFlag(MSG_FOLDER_FLAG_IMAP_NOSELECT, &noSelect);
|
||||
if (WeAreOffline())
|
||||
return NS_MSG_ERROR_OFFLINE;
|
||||
|
||||
if (noSelect) return NS_OK;
|
||||
PRBool noSelect = PR_FALSE;
|
||||
aImapMailFolder->GetFlag(MSG_FOLDER_FLAG_IMAP_NOSELECT, &noSelect);
|
||||
|
||||
if (noSelect) return NS_OK;
|
||||
|
||||
nsCOMPtr<nsIImapUrl> imapUrl;
|
||||
nsCAutoString urlSpec;
|
||||
@ -915,113 +934,140 @@ nsImapService::FetchMessage(nsIImapUrl * aImapUrl,
|
||||
// create a protocol instance to handle the request.
|
||||
// NOTE: once we start working with multiple connections, this step will be much more complicated...but for now
|
||||
// just create a connection and process the request.
|
||||
NS_ASSERTION (aImapUrl && aImapMailFolder && aImapMessage,"Oops ... null pointer");
|
||||
if (!aImapUrl || !aImapMailFolder || !aImapMessage)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
NS_ASSERTION (aImapUrl && aImapMailFolder && aImapMessage,"Oops ... null pointer");
|
||||
if (!aImapUrl || !aImapMailFolder || !aImapMessage)
|
||||
return NS_ERROR_NULL_POINTER;
|
||||
|
||||
nsCAutoString urlSpec;
|
||||
nsresult rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
|
||||
|
||||
rv = aImapUrl->SetImapMessageSink(aImapMessage);
|
||||
if (NS_SUCCEEDED(rv))
|
||||
{
|
||||
nsXPIDLCString currentSpec;
|
||||
nsCOMPtr<nsIURI> url = do_QueryInterface(aImapUrl);
|
||||
url->GetSpec(getter_Copies(currentSpec));
|
||||
urlSpec.Assign(currentSpec);
|
||||
|
||||
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
||||
|
||||
urlSpec.Append("fetch>");
|
||||
urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
|
||||
urlSpec.Append(">");
|
||||
urlSpec.AppendWithConversion(hierarchySeparator);
|
||||
|
||||
nsXPIDLCString folderName;
|
||||
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
||||
urlSpec.Append((const char *) folderName);
|
||||
urlSpec.Append(">");
|
||||
urlSpec.Append(messageIdentifierList);
|
||||
|
||||
|
||||
// rhp: If we are displaying this message for the purpose of printing, we
|
||||
// need to append the header=print option.
|
||||
//
|
||||
if (mPrintingOperation)
|
||||
urlSpec.Append("?header=print");
|
||||
|
||||
// mscott - this cast to a char * is okay...there's a bug in the XPIDL
|
||||
// compiler that is preventing in string parameters from showing up as
|
||||
// const char *. hopefully they will fix it soon.
|
||||
rv = url->SetSpec((char *) urlSpec.GetBuffer());
|
||||
|
||||
rv = aImapUrl->SetImapAction(aImapAction);
|
||||
if (aImapMailFolder && aDisplayConsumer)
|
||||
{
|
||||
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
||||
rv = aImapMailFolder->GetServer(getter_AddRefs(aMsgIncomingServer));
|
||||
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
||||
{
|
||||
PRBool interrupted;
|
||||
nsCOMPtr<nsIImapIncomingServer>
|
||||
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && aImapServer)
|
||||
aImapServer->PseudoInterruptMsgLoad(aImapUrl, &interrupted);
|
||||
}
|
||||
}
|
||||
// if the display consumer is a docshell, then we should run the url in the docshell.
|
||||
// otherwise, it should be a stream listener....so open a channel using AsyncRead
|
||||
// and the provided stream listener....
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aDisplayConsumer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && docShell)
|
||||
{
|
||||
rv = docShell->LoadURI(url, nsnull, nsIWebNavigation::LOAD_FLAGS_NONE);
|
||||
}
|
||||
else
|
||||
nsresult rv;
|
||||
nsXPIDLCString currentSpec;
|
||||
nsCOMPtr<nsIURI> url = do_QueryInterface(aImapUrl);
|
||||
if (WeAreOffline())
|
||||
{
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> msgurl (do_QueryInterface(aImapUrl));
|
||||
if (msgurl)
|
||||
{
|
||||
PRBool msgIsInLocalCache = PR_FALSE;
|
||||
msgurl->GetMsgIsInLocalCache(&msgIsInLocalCache);
|
||||
if (!msgIsInLocalCache)
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> aStreamListener = do_QueryInterface(aDisplayConsumer, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aStreamListener)
|
||||
nsCOMPtr<nsIMsgIncomingServer> server;
|
||||
nsCOMPtr<nsIImapServerSink> imapServer;
|
||||
|
||||
rv = aImapMailFolder->GetServer(getter_AddRefs(server));
|
||||
if (server)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> aChannel;
|
||||
nsCOMPtr<nsILoadGroup> aLoadGroup;
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl, &rv);
|
||||
if (NS_SUCCEEDED(rv) && mailnewsUrl)
|
||||
imapServer = do_QueryInterface(server);
|
||||
if (imapServer)
|
||||
{
|
||||
if (aMsgWindow)
|
||||
mailnewsUrl->SetMsgWindow(aMsgWindow);
|
||||
mailnewsUrl->GetLoadGroup(getter_AddRefs(aLoadGroup));
|
||||
nsXPIDLString errorMsgTitle;
|
||||
nsXPIDLString errorMsgBody;
|
||||
|
||||
imapServer->GetImapStringByID(IMAP_HTML_NO_CACHED_BODY_BODY, getter_Copies(errorMsgBody));
|
||||
imapServer->GetImapStringByID(IMAP_HTML_NO_CACHED_BODY_TITLE, getter_Copies(errorMsgTitle));
|
||||
return aMsgWindow->DisplayHTMLInMessagePane(errorMsgTitle, errorMsgBody);
|
||||
}
|
||||
rv = NewChannel(url, getter_AddRefs(aChannel));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aChannel->SetLoadGroup(aLoadGroup);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsISupports> aCtxt = do_QueryInterface(url);
|
||||
// now try to open the channel passing in our display consumer as the listener
|
||||
rv = aChannel->AsyncRead(aStreamListener, aCtxt);
|
||||
}
|
||||
else // do what we used to do before
|
||||
{
|
||||
// I'd like to get rid of this code as I believe that we always get a docshell
|
||||
// or stream listener passed into us in this method but i'm not sure yet...
|
||||
// I'm going to use an assert for now to figure out if this is ever getting called
|
||||
#ifdef DEBUG_mscott
|
||||
NS_ASSERTION(0, "oops...someone still is reaching this part of the code");
|
||||
#endif
|
||||
nsCOMPtr<nsIEventQueue> queue;
|
||||
// get the Event Queue for this thread...
|
||||
NS_WITH_SERVICE(nsIEventQueueService, pEventQService, kEventQueueServiceCID, &rv);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = GetImapConnectionAndLoadUrl(queue, aImapUrl, aDisplayConsumer, aURL);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
nsCAutoString urlSpec;
|
||||
rv = SetImapUrlSink(aImapMailFolder, aImapUrl);
|
||||
|
||||
rv = aImapUrl->SetImapMessageSink(aImapMessage);
|
||||
url->GetSpec(getter_Copies(currentSpec));
|
||||
urlSpec.Assign(currentSpec);
|
||||
|
||||
PRUnichar hierarchySeparator = GetHierarchyDelimiter(aImapMailFolder);
|
||||
|
||||
urlSpec.Append("fetch>");
|
||||
urlSpec.Append(messageIdsAreUID ? uidString : sequenceString);
|
||||
urlSpec.Append(">");
|
||||
urlSpec.AppendWithConversion(hierarchySeparator);
|
||||
|
||||
nsXPIDLCString folderName;
|
||||
GetFolderName(aImapMailFolder, getter_Copies(folderName));
|
||||
urlSpec.Append((const char *) folderName);
|
||||
urlSpec.Append(">");
|
||||
urlSpec.Append(messageIdentifierList);
|
||||
|
||||
// rhp: If we are displaying this message for the purpose of printing, we
|
||||
// need to append the header=print option.
|
||||
//
|
||||
if (mPrintingOperation)
|
||||
urlSpec.Append("?header=print");
|
||||
|
||||
// mscott - this cast to a char * is okay...there's a bug in the XPIDL
|
||||
// compiler that is preventing in string parameters from showing up as
|
||||
// const char *. hopefully they will fix it soon.
|
||||
rv = url->SetSpec((char *) urlSpec.GetBuffer());
|
||||
|
||||
rv = aImapUrl->SetImapAction(aImapAction);
|
||||
if (aImapMailFolder && aDisplayConsumer)
|
||||
{
|
||||
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
||||
rv = aImapMailFolder->GetServer(getter_AddRefs(aMsgIncomingServer));
|
||||
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
||||
{
|
||||
PRBool interrupted;
|
||||
nsCOMPtr<nsIImapIncomingServer>
|
||||
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && aImapServer)
|
||||
aImapServer->PseudoInterruptMsgLoad(aImapUrl, &interrupted);
|
||||
}
|
||||
}
|
||||
// if the display consumer is a docshell, then we should run the url in the docshell.
|
||||
// otherwise, it should be a stream listener....so open a channel using AsyncRead
|
||||
// and the provided stream listener....
|
||||
|
||||
nsCOMPtr<nsIDocShell> docShell(do_QueryInterface(aDisplayConsumer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && docShell)
|
||||
{
|
||||
rv = docShell->LoadURI(url, nsnull, nsIWebNavigation::LOAD_FLAGS_NONE);
|
||||
}
|
||||
else
|
||||
{
|
||||
nsCOMPtr<nsIStreamListener> aStreamListener = do_QueryInterface(aDisplayConsumer, &rv);
|
||||
if (NS_SUCCEEDED(rv) && aStreamListener)
|
||||
{
|
||||
nsCOMPtr<nsIChannel> aChannel;
|
||||
nsCOMPtr<nsILoadGroup> aLoadGroup;
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsUrl = do_QueryInterface(aImapUrl, &rv);
|
||||
if (NS_SUCCEEDED(rv) && mailnewsUrl)
|
||||
{
|
||||
if (aMsgWindow)
|
||||
mailnewsUrl->SetMsgWindow(aMsgWindow);
|
||||
mailnewsUrl->GetLoadGroup(getter_AddRefs(aLoadGroup));
|
||||
}
|
||||
rv = NewChannel(url, getter_AddRefs(aChannel));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = aChannel->SetLoadGroup(aLoadGroup);
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
nsCOMPtr<nsISupports> aCtxt = do_QueryInterface(url);
|
||||
// now try to open the channel passing in our display consumer as the listener
|
||||
rv = aChannel->AsyncRead(aStreamListener, aCtxt);
|
||||
}
|
||||
else // do what we used to do before
|
||||
{
|
||||
// I'd like to get rid of this code as I believe that we always get a docshell
|
||||
// or stream listener passed into us in this method but i'm not sure yet...
|
||||
// I'm going to use an assert for now to figure out if this is ever getting called
|
||||
#ifdef DEBUG_mscott
|
||||
NS_ASSERTION(0, "oops...someone still is reaching this part of the code");
|
||||
#endif
|
||||
nsCOMPtr<nsIEventQueue> queue;
|
||||
// get the Event Queue for this thread...
|
||||
NS_WITH_SERVICE(nsIEventQueueService, pEventQService, kEventQueueServiceCID, &rv);
|
||||
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
|
||||
rv = pEventQService->GetThreadEventQueue(NS_CURRENT_THREAD, getter_AddRefs(queue));
|
||||
if (NS_FAILED(rv)) return rv;
|
||||
rv = GetImapConnectionAndLoadUrl(queue, aImapUrl, aDisplayConsumer, aURL);
|
||||
}
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
@ -1928,27 +1974,40 @@ nsImapService::GetImapConnectionAndLoadUrl(nsIEventQueue* aClientEventQueue,
|
||||
nsISupports* aConsumer,
|
||||
nsIURI** aURL)
|
||||
{
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(aImapUrl);
|
||||
rv = msgUrl->GetServer(getter_AddRefs(aMsgIncomingServer));
|
||||
|
||||
if (aURL)
|
||||
{
|
||||
*aURL = msgUrl;
|
||||
NS_IF_ADDREF(*aURL);
|
||||
}
|
||||
NS_ENSURE_ARG(aImapUrl);
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
||||
{
|
||||
nsCOMPtr<nsIImapIncomingServer>
|
||||
aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && aImapServer)
|
||||
rv = aImapServer->GetImapConnectionAndLoadUrl(aClientEventQueue,
|
||||
aImapUrl,
|
||||
aConsumer);
|
||||
}
|
||||
return rv;
|
||||
if (WeAreOffline())
|
||||
{
|
||||
nsImapAction imapAction;
|
||||
|
||||
// the only thing we can do offline is fetch messages.
|
||||
// ### TODO - need to look at msg copy, save attachment, etc. when we
|
||||
// have offline message bodies.
|
||||
aImapUrl->GetImapAction(&imapAction);
|
||||
if (imapAction != nsIImapUrl::nsImapMsgFetch)
|
||||
return NS_MSG_ERROR_OFFLINE;
|
||||
}
|
||||
|
||||
nsresult rv = NS_OK;
|
||||
nsCOMPtr<nsIMsgIncomingServer> aMsgIncomingServer;
|
||||
nsCOMPtr<nsIMsgMailNewsUrl> msgUrl = do_QueryInterface(aImapUrl);
|
||||
rv = msgUrl->GetServer(getter_AddRefs(aMsgIncomingServer));
|
||||
|
||||
if (aURL)
|
||||
{
|
||||
*aURL = msgUrl;
|
||||
NS_IF_ADDREF(*aURL);
|
||||
}
|
||||
|
||||
if (NS_SUCCEEDED(rv) && aMsgIncomingServer)
|
||||
{
|
||||
nsCOMPtr<nsIImapIncomingServer> aImapServer(do_QueryInterface(aMsgIncomingServer, &rv));
|
||||
if (NS_SUCCEEDED(rv) && aImapServer)
|
||||
rv = aImapServer->GetImapConnectionAndLoadUrl(aClientEventQueue,
|
||||
aImapUrl,
|
||||
aConsumer);
|
||||
}
|
||||
return rv;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
|
@ -69,6 +69,8 @@ public:
|
||||
NS_DECL_NSIMSGMESSAGEFETCHPARTSERVICE
|
||||
|
||||
protected:
|
||||
PRBool WeAreOffline();
|
||||
|
||||
PRUnichar GetHierarchyDelimiter(nsIMsgFolder* aMsgFolder);
|
||||
nsresult GetFolderName(nsIMsgFolder* aImapFolder,
|
||||
char **folderName);
|
||||
|
@ -89,5 +89,7 @@ NS_END_EXTERN_C
|
||||
#define IMAP_MOVE_FOLDER_TO_TRASH 5055
|
||||
#define IMAP_NO_NEW_MESSAGES 5056
|
||||
#define IMAP_DEFAULT_ACCOUNT_NAME 5057
|
||||
#define IMAP_DELETE_NO_TRASH 5058
|
||||
#define IMAP_DELETE_NO_TRASH 5058
|
||||
#define IMAP_HTML_NO_CACHED_BODY_TITLE 5059
|
||||
#define IMAP_HTML_NO_CACHED_BODY_BODY 5060
|
||||
#endif /* _nsImapStringBundle_H__ */
|
||||
|
Loading…
Reference in New Issue
Block a user