Bug 226890 - Thunderbird doesn't handle news URIs properly, part 10: Make command-line news handling work. r=bienvenu, sr=neil
--- a/mail/components/nsMailDefaultHandler.js
+++ b/mail/components/nsMailDefaultHandler.js
@@ -151,18 +151,27 @@ function openURI(uri)
QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsIRequestObserver,
Components.interfaces.nsISupportsWeakReference])
};
loadgroup.groupObserver = loadlistener;
var listener = {
onStartURIOpen: function(uri) { return false; },
- doContent: function(ctype, preferred, request, handler) { return false; },
- isPreferred: function(ctype, desired) { return false; },
+ doContent: function(ctype, preferred, request, handler) {
+ var newHandler = Components.classes["@mozilla.org/uriloader/content-handler;1?type=application/x-message-display"]
+ .createInstance(Components.interfaces.nsIContentHandler);
+ newHandler.handleContent("application/x-message-display", this, request);
+ return true;
+ },
+ isPreferred: function(ctype, desired) {
+ if (ctype == "message/rfc822")
+ return true;
+ return false;
+ },
canHandleContent: function(ctype, preferred, desired) { return false; },
loadCookie: null,
parentContentListener: null,
getInterface: function(iid) {
if (iid.equals(Components.interfaces.nsIURIContentListener))
return this;
if (iid.equals(Components.interfaces.nsILoadGroup))
--- a/mailnews/base/util/nsMsgProtocol.cpp
+++ b/mailnews/base/util/nsMsgProtocol.cpp
@@ -550,16 +550,20 @@ nsresult nsMsgProtocol::LoadUrl(nsIURI *
nsCOMPtr<nsIInputStreamPump> pump;
rv = NS_NewInputStreamPump(getter_AddRefs(pump),
m_inputStream, -1, m_readCount);
if (NS_FAILED(rv)) return rv;
m_request = pump; // keep a reference to the pump so we can cancel it
+ // This helps when running URLs from the command line
+ rv = pump->SetLoadGroup(m_loadGroup);
+ NS_ENSURE_SUCCESS(rv, rv);
+
// put us in a state where we are always notified of incoming data
rv = pump->AsyncRead(this, urlSupports);
NS_ASSERTION(NS_SUCCEEDED(rv), "AsyncRead failed");
m_socketIsOpen = PR_TRUE; // mark the channel as open
}
} // if we got an event queue service
else if (!msgIsInLocalCache) // the connection is already open so we should begin processing our new url...
rv = ProcessProtocolState(aURL, nsnull, 0, 0);
--- a/mailnews/news/src/nsNntpIncomingServer.cpp
+++ b/mailnews/news/src/nsNntpIncomingServer.cpp
@@ -764,16 +764,27 @@ nsNntpIncomingServer::OnStopRunningUrl(n
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::ContainsNewsgroup(const nsACString &name,
bool *containsGroup)
{
if (name.IsEmpty()) return NS_ERROR_FAILURE;
+ if (mSubscribedNewsgroups.Length() == 0)
+ {
+ // If this is empty, we may need to discover folders
+ nsCOMPtr<nsIMsgFolder> rootFolder;
+ GetRootFolder(getter_AddRefs(rootFolder));
+ if (rootFolder)
+ {
+ nsCOMPtr<nsISimpleEnumerator> subfolders;
+ rootFolder->GetSubFolders(getter_AddRefs(subfolders));
+ }
+ }
nsCAutoString unescapedName;
MsgUnescapeString(name, 0, unescapedName);
*containsGroup = mSubscribedNewsgroups.Contains(name);
return NS_OK;
}
NS_IMETHODIMP
nsNntpIncomingServer::SubscribeToNewsgroup(const nsACString &aName)
--- a/mailnews/news/src/nsNntpService.cpp
+++ b/mailnews/news/src/nsNntpService.cpp
@@ -80,16 +80,18 @@
#include "prprf.h"
#include "nsICacheService.h"
#include "nsICacheEntryDescriptor.h"
#include "nsMsgUtils.h"
#include "nsNetUtil.h"
#include "nsIWindowWatcher.h"
#include "nsICommandLine.h"
#include "nsIMsgMailNewsUrl.h"
+#include "nsIMsgMailSession.h"
+#include "nsISupportsPrimitives.h"
#undef GetPort // XXX Windows!
#undef SetPort // XXX Windows!
#define PREF_MAIL_ROOT_NNTP "mail.root.nntp" // old - for backward compatibility only
#define PREF_MAIL_ROOT_NNTP_REL "mail.root.nntp-rel"
nsNntpService::nsNntpService()
@@ -1040,89 +1042,52 @@ nsNntpService::GetServerForUri(nsIURI *a
nsCOMPtr <nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv,rv);
// find the incoming server, it if exists.
// migrate if necessary, before searching for it.
// if it doesn't exist, create it.
nsCOMPtr<nsIMsgIncomingServer> server;
- nsCOMPtr<nsINntpIncomingServer> nntpServer;
- nsCOMPtr <nsISupportsArray> accounts;
- rv = accountManager->GetAccounts(getter_AddRefs(accounts));
- if (NS_FAILED(rv)) return rv;
+ // Grab all servers for if this is a no-authority URL. This also loads
+ // accounts if they haven't been loaded, i.e., we're running this straight
+ // from the command line
+ nsCOMPtr <nsISupportsArray> servers;
+ rv = accountManager->GetAllServers(getter_AddRefs(servers));
+ NS_ENSURE_SUCCESS(rv, rv);
- // news:group becomes news://group, so we have three types of urls:
- // news://group (autosubscribing without a host)
- // news://host/group (autosubscribing with a host)
- // news://host (updating the unread message counts on a server)
- //
- // first, check if hostName is really a server or a group
- // by looking for a server with hostName
- //
- // xxx todo what if we have two servers on the same host, but different ports?
- // Or no port, but scheme (snews:// vs news://) is different?
- rv = accountManager->FindServerByURI(aUri, PR_FALSE,
- getter_AddRefs(server));
+ nsCOMPtr<nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(aUri, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
- if (!server)
- {
- // try the "real" settings ("realservername" and "realusername")
- rv = accountManager->FindServerByURI(aUri, PR_TRUE,
- getter_AddRefs(server));
- }
+ rv = mailUrl->GetServer(getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
- // if we didn't find the server, and path was "/", this is a news://group url
- if (!server && !strcmp("/",path.get()))
+ if (!server && !hostName.IsEmpty())
{
- // the uri was news://group and we want to turn that into news://host/group
- // step 1, set the path to be the hostName;
- rv = aUri->SetPath(hostName);
- NS_ENSURE_SUCCESS(rv,rv);
-
- // until we support default news servers, use the first nntp server we find
- rv = accountManager->FindServerByURI(aUri, PR_FALSE, getter_AddRefs(server));
- if (NS_FAILED(rv) || !server)
- {
- // step 2, set the uri's hostName and the local variable hostName
- // to be "news"
- rv = aUri->SetHost(NS_LITERAL_CSTRING("news"));
- NS_ENSURE_SUCCESS(rv,rv);
-
- rv = aUri->GetAsciiHost(hostName);
- NS_ENSURE_SUCCESS(rv,rv);
- }
- else
- {
- // step 2, set the uri's hostName and the local variable hostName
- // to be the host name of the server we found
- rv = server->GetHostName(hostName);
- NS_ENSURE_SUCCESS(rv,rv);
-
- rv = aUri->SetHost(hostName);
- NS_ENSURE_SUCCESS(rv,rv);
- }
- }
-
- if (NS_FAILED(rv) || !server)
- {
+ // If we don't have this server but it isn't no-auth, add it.
+ // Ideally, we should remove this account quickly (see bug 41133)
bool useSSL = false;
- if (PL_strcasecmp("snews", scheme.get()) == 0)
+ if (scheme.EqualsLiteral("snews") || scheme.EqualsLiteral("nntps"))
{
useSSL = PR_TRUE;
if ((port == 0) || (port == -1))
port = nsINntpUrl::DEFAULT_NNTPS_PORT;
}
rv = CreateNewsAccount(hostName.get(), useSSL, port, getter_AddRefs(server));
+ NS_ENSURE_SUCCESS(rv, rv);
}
- if (NS_FAILED(rv)) return rv;
+ if (!server && hostName.IsEmpty())
+ // XXX: Until we support no-auth uris, bail
+ return NS_ERROR_FAILURE;
+
if (!server) return NS_ERROR_FAILURE;
+ nsCOMPtr<nsINntpIncomingServer> nntpServer;
nntpServer = do_QueryInterface(server, &rv);
if (!nntpServer || NS_FAILED(rv))
return rv;
NS_IF_ADDREF(*aServer = nntpServer);
nsCAutoString spec;
@@ -1743,52 +1708,68 @@ nsNntpService::HandleContent(const char
NS_ENSURE_SUCCESS(rv, rv);
// check for x-application-newsgroup or x-application-newsgroup-listids
if (PL_strncasecmp(aContentType, "x-application-newsgroup", 23) == 0)
{
nsCOMPtr<nsIURI> uri;
rv = aChannel->GetURI(getter_AddRefs(uri));
NS_ENSURE_SUCCESS(rv, rv);
- if (uri)
+
+ nsCOMPtr<nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(uri);
+ if (mailUrl)
{
- nsCString uriStr;
- rv = uri->GetSpec(uriStr);
+ nsCOMPtr<nsIMsgFolder> msgFolder;
+ rv = mailUrl->GetFolder(getter_AddRefs(msgFolder));
NS_ENSURE_SUCCESS(rv, rv);
- PRInt32 cutChar = uriStr.FindChar('?');
- if (cutChar > 0)
- uriStr.SetLength(cutChar);
+ // No folder means we can't handle this
+ if (!msgFolder)
+ return NS_ERROR_WONT_HANDLE_CONTENT;
- // Try to get a valid folder...
- nsCOMPtr <nsIMsgFolder> msgFolder;
- GetFolderFromUri(uriStr.get(), getter_AddRefs(msgFolder));
-
- // ... and only go on if we have a valid URI (i.e., valid folder)
- if (msgFolder)
+ nsCString folderURL;
+ rv = msgFolder->GetURI(folderURL);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsIMsgWindow> msgWindow;
+ mailUrl->GetMsgWindow(getter_AddRefs(msgWindow));
+ if (!msgWindow)
{
- nsCOMPtr <nsIURI> originalUri;
- aChannel->GetOriginalURI(getter_AddRefs(originalUri));
- if (originalUri)
+ // This came from a docshell that didn't set msgWindow, so find one
+ nsCOMPtr<nsIMsgMailSession> mailSession =
+ do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ mailSession->GetTopmostMsgWindow(getter_AddRefs(msgWindow));
+
+ if (!msgWindow)
{
- nsCOMPtr <nsIMsgMailNewsUrl> mailUrl = do_QueryInterface(originalUri);
- if (mailUrl)
- {
- nsCOMPtr <nsIMsgWindow> msgWindow;
- mailUrl->GetMsgWindow(getter_AddRefs(msgWindow));
- if (msgWindow)
- {
- nsCOMPtr <nsIMsgWindowCommands> windowCommands;
- msgWindow->GetWindowCommands(getter_AddRefs(windowCommands));
- if (windowCommands)
- windowCommands->SelectFolder(uriStr);
- }
- }
+ // We need to create a 3-pane window, then
+ nsCOMPtr<nsIWindowWatcher> wwatcher =
+ do_GetService(NS_WINDOWWATCHER_CONTRACTID, &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsCOMPtr<nsISupportsCString> arg =
+ do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID);
+ arg->SetData(folderURL);
+
+ nsCOMPtr<nsIDOMWindow> newWindow;
+ rv = wwatcher->OpenWindow(nsnull, "chrome://messenger/content/",
+ "_blank", "chome,all,dialog=no", arg, getter_AddRefs(newWindow));
+ NS_ENSURE_SUCCESS(rv, rv);
}
}
+ if (msgWindow)
+ {
+ nsCOMPtr<nsIMsgWindowCommands> windowCommands;
+ msgWindow->GetWindowCommands(getter_AddRefs(windowCommands));
+ if (windowCommands)
+ windowCommands->SelectFolder(folderURL);
+ }
+ request->Cancel(NS_BINDING_ABORTED);
}
} else // The content-type was not x-application-newsgroup.
rv = NS_ERROR_WONT_HANDLE_CONTENT;
return rv;
}
NS_IMETHODIMP
nsNntpService::MessageURIToMsgHdr(const char *uri, nsIMsgDBHdr **_retval)