diff --git a/mozilla/mail/extensions/Makefile.in b/mozilla/mail/extensions/Makefile.in index 570ed01ea84..404155d0931 100644 --- a/mozilla/mail/extensions/Makefile.in +++ b/mozilla/mail/extensions/Makefile.in @@ -26,7 +26,7 @@ VPATH = @srcdir@ include $(DEPTH)/config/autoconf.mk -DIRS = offline +DIRS = offline newsblog ifdef MOZ_PSM BUILD_SMIME=1 diff --git a/mozilla/mail/extensions/newsblog/content/Feed.js b/mozilla/mail/extensions/newsblog/content/Feed.js index 89ff844be50..7c2ddebef9d 100755 --- a/mozilla/mail/extensions/newsblog/content/Feed.js +++ b/mozilla/mail/extensions/newsblog/content/Feed.js @@ -481,6 +481,10 @@ function storeNextItem() { item.feed.removeInvalidItems(); + // let's be sure to flush any feed item changes back to disk + var ds = getItemsDS(item.feed.server); + ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush(); // flush any changes + if (item.feed.downloadCallback) item.feed.downloadCallback.downloaded(item.feed, kNewsBlogSuccess); diff --git a/mozilla/mail/extensions/newsblog/content/feed-properties.xul b/mozilla/mail/extensions/newsblog/content/feed-properties.xul index 197248f9b9b..8645c692bd7 100644 --- a/mozilla/mail/extensions/newsblog/content/feed-properties.xul +++ b/mozilla/mail/extensions/newsblog/content/feed-properties.xul @@ -37,6 +37,7 @@ - - diff --git a/mozilla/mail/extensions/newsblog/content/utils.js b/mozilla/mail/extensions/newsblog/content/utils.js index 39a6617601e..f3ba1ef576a 100755 --- a/mozilla/mail/extensions/newsblog/content/utils.js +++ b/mozilla/mail/extensions/newsblog/content/utils.js @@ -109,6 +109,9 @@ function updateFolderFeedUrl(aFolder, aFeedUrl, aRemoveUrl) } else folderInfo.SetCharPtrProperty("feedUrl", oldFeedUrl + kFeedUrlDelimiter + aFeedUrl); + + // commit the db to preserve our changes + msgdb.Close(true); } function getNodeValue(node) { diff --git a/mozilla/mail/extensions/newsblog/js/newsblog.js b/mozilla/mail/extensions/newsblog/js/newsblog.js index cf69b9497ce..51d3a97f5ec 100755 --- a/mozilla/mail/extensions/newsblog/js/newsblog.js +++ b/mozilla/mail/extensions/newsblog/js/newsblog.js @@ -85,6 +85,48 @@ var nsNewsBlogFeedDownloader = feed.download(true, progressNotifier); }, + updateSubscriptionsDS: function(aFolder, aUnsubscribe) + { + if (!gExternalScriptsLoaded) + loadScripts(); + + // an rss folder was just renamed...we need to update our feed data source + var msgdb = aFolder.QueryInterface(Components.interfaces.nsIMsgFolder).getMsgDatabase(null); + var folderInfo = msgdb.dBFolderInfo; + var feedurls = {}; + folderInfo.GetCharPtrProperty("feedUrl", feedurls); + feedurls = feedurls.value; + + var feedUrlArray = feedurls.split("|"); + + var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); + var ds = getSubscriptionsDS(aFolder.server); + + for (url in feedUrlArray) + { + if (feedUrlArray[url]) + { + id = rdf.GetResource(feedUrlArray[url]); + // get the node for the current folder URI + var node = ds.GetTarget(id, FZ_DESTFOLDER, true); + + // we need to check and see if the folder is a child of the trash...if it is, then we can + // treat this as an unsubscribe action + if (aUnsubscribe) + { + var feeds = getSubscriptionsList(aFolder.server); + var index = feeds.IndexOf(id); + if (index != -1) + feeds.RemoveElementAt(index, false); + removeAssertions(ds, id); + } + ds.Change(id, FZ_DESTFOLDER, node, rdf.GetResource(aFolder.URI)); + } + } // for each feed url in the folder property + + ds.QueryInterface(Components.interfaces.nsIRDFRemoteDataSource).Flush(); // flush any changes + }, + QueryInterface: function(aIID) { if (aIID.equals(Components.interfaces.nsINewsBlogFeedDownloader) || diff --git a/mozilla/mailnews/local/public/nsINewsBlogFeedDownloader.idl b/mozilla/mailnews/local/public/nsINewsBlogFeedDownloader.idl index a12241fc52b..ec530988a8d 100755 --- a/mozilla/mailnews/local/public/nsINewsBlogFeedDownloader.idl +++ b/mozilla/mailnews/local/public/nsINewsBlogFeedDownloader.idl @@ -50,5 +50,10 @@ interface nsINewsBlogFeedDownloader : nsISupports /* A convient method to subscribe to feeds without going through the subscribe UI used by drag and drop */ void subscribeToFeed(in string aUrl, in nsIMsgFolder aFolder, in nsIMsgWindow aMsgWindow); + + /* called when the RSS Incoming Server detects a change to an RSS folder. For instance, the user just + deleted an RSS folder and we need to update the subscriptions data source. Or the user renamed an RSS folder... + */ + void updateSubscriptionsDS(in nsIMsgFolder aFolder, in boolean aUnsubscribe); }; diff --git a/mozilla/mailnews/local/src/nsRssIncomingServer.cpp b/mozilla/mailnews/local/src/nsRssIncomingServer.cpp index 602074ae8c7..11dd84668cf 100755 --- a/mozilla/mailnews/local/src/nsRssIncomingServer.cpp +++ b/mozilla/mailnews/local/src/nsRssIncomingServer.cpp @@ -39,22 +39,45 @@ #include "nsRssIncomingServer.h" #include "nsMsgFolderFlags.h" #include "nsINewsBlogFeedDownloader.h" +#include "nsIMsgMailSession.h" +#include "nsMsgBaseCID.h" +#include "nsIRDFResource.h" #include "nsIMsgLocalMailFolder.h" #include "nsIDBFolderInfo.h" -NS_IMPL_ISUPPORTS_INHERITED2(nsRssIncomingServer, +nsrefcnt nsRssIncomingServer::gInstanceCount = 0; + +NS_IMPL_ISUPPORTS_INHERITED3(nsRssIncomingServer, nsMsgIncomingServer, nsIRssIncomingServer, + nsIFolderListener, nsILocalMailIncomingServer) nsRssIncomingServer::nsRssIncomingServer() { m_canHaveFilters = PR_TRUE; + + if (gInstanceCount == 0) + { + nsresult rv; + nsCOMPtr mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); + + if (NS_SUCCEEDED(rv)) + mailSession->AddFolderListener(this, nsIFolderListener::added); + } + + gInstanceCount++; } nsRssIncomingServer::~nsRssIncomingServer() { + gInstanceCount--; + + // I used to have code here which unregistered the global rss folder listener with the + // mail session. But the rss incoming server is held until shutdown when we shut down the + // account datasource. And at shutdown the mail session explicitly releases all of its folder listeners + // anyway so this was effectively a no-op... } nsresult nsRssIncomingServer::FillInDataSourcePath(const nsAString& aDataSourceName, nsILocalFile ** aLocation) @@ -135,25 +158,28 @@ NS_IMETHODIMP nsRssIncomingServer::PerformBiff(nsIMsgWindow *aMsgWindow) GetRootMsgFolder(getter_AddRefs(rootRSSFolder)); // enumerate over the RSS folders and ping each one - nsCOMPtr folderEnumerator; - rv = rootRSSFolder->GetSubFolders(getter_AddRefs(folderEnumerator)); + nsCOMPtr allDescendents; + NS_NewISupportsArray(getter_AddRefs(allDescendents)); + rv = rootRSSFolder->ListDescendents(allDescendents); NS_ENSURE_SUCCESS(rv, rv); - nsresult more = folderEnumerator->First(); + PRUint32 cnt =0; + allDescendents->Count(&cnt); + nsCOMPtr supports; nsCOMPtr urlListener; + nsCOMPtr rssFolder; - while (NS_SUCCEEDED(more)) + for (PRUint32 index = 0; index < cnt; index++) { - rv = folderEnumerator->CurrentItem(getter_AddRefs(supports)); - nsCOMPtr rssFolder = do_QueryInterface(supports); + supports = getter_AddRefs(allDescendents->ElementAt(index)); + rssFolder = do_QueryInterface(supports, &rv); if (rssFolder) { urlListener = do_QueryInterface(rssFolder); // WARNING: Never call GetNewMail with the root folder or you will trigger an infinite loop... GetNewMail(aMsgWindow, urlListener, rssFolder, nsnull); } - more = folderEnumerator->Next(); } return NS_OK; @@ -226,3 +252,99 @@ NS_IMETHODIMP nsRssIncomingServer::GetSupportsDiskSpace(PRBool *aSupportsDiskSpa *aSupportsDiskSpace = PR_FALSE; return NS_OK; } + +NS_IMETHODIMP nsRssIncomingServer::OnItemAdded(nsISupports *parentItem, nsISupports *item, const char *viewString) +{ + nsCOMPtr folder = do_QueryInterface(item); + NS_ENSURE_TRUE(folder, NS_OK); // just kick out with a success code if the item in question is not a folder + + nsCOMPtr server; + nsresult rv = folder->GetServer(getter_AddRefs(server)); + NS_ENSURE_SUCCESS(rv, rv); + + nsXPIDLCString type; + rv = server->GetType(getter_Copies(type)); + NS_ENSURE_SUCCESS(rv, rv); + + if (type.Equals("rss")) + { + nsCOMPtr rssDownloader = do_GetService("@mozilla.org/newsblog-feed-downloader;1", &rv); + NS_ENSURE_SUCCESS(rv, rv); + + // did the user just delete this folder (adding it to trash?) + nsCOMPtr rootMsgFolder; + nsCOMPtr trashFolder; + rv = GetRootFolder(getter_AddRefs(rootMsgFolder)); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 numFolders; + rv = rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 1, &numFolders, getter_AddRefs(trashFolder)); + + PRBool unsubscribe = PR_FALSE; + if (trashFolder) + trashFolder->IsAncestorOf(folder, &unsubscribe); + + rssDownloader->UpdateSubscriptionsDS(folder, unsubscribe); + + // if the user was moving or deleting a set of nested folders, we only seem to get a single OnItemAdded + // notification. So we need to iterate over all of the descedent folders of the folder whose location has + // changed. + + nsCOMPtr allDescendents; + NS_NewISupportsArray(getter_AddRefs(allDescendents)); + rv = folder->ListDescendents(allDescendents); + NS_ENSURE_SUCCESS(rv, rv); + + PRUint32 cnt =0; + allDescendents->Count(&cnt); + + nsCOMPtr supports; + nsCOMPtr rssFolder; + + for (PRUint32 index = 0; index < cnt; index++) + { + supports = getter_AddRefs(allDescendents->ElementAt(index)); + rssFolder = do_QueryInterface(supports, &rv); + if (rssFolder) + rssDownloader->UpdateSubscriptionsDS(rssFolder, unsubscribe); + } + } + + return rv; +} + +NS_IMETHODIMP nsRssIncomingServer::OnItemRemoved(nsISupports *parentItem, nsISupports *item, const char *viewString) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsRssIncomingServer::OnItemPropertyChanged(nsISupports *item, nsIAtom *property, const char *oldValue, const char *newValue) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsRssIncomingServer::OnItemIntPropertyChanged(nsISupports *item, nsIAtom *property, PRInt32 oldValue, PRInt32 newValue) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsRssIncomingServer::OnItemBoolPropertyChanged(nsISupports *item, nsIAtom *property, PRBool oldValue, PRBool newValue) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsRssIncomingServer::OnItemUnicharPropertyChanged(nsISupports *item, nsIAtom *property, const PRUnichar *oldValue, const PRUnichar *newValue) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + + +NS_IMETHODIMP nsRssIncomingServer::OnItemPropertyFlagChanged(nsISupports *item, nsIAtom *property, PRUint32 oldFlag, PRUint32 newFlag) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} + +NS_IMETHODIMP nsRssIncomingServer::OnItemEvent(nsIMsgFolder *aFolder, nsIAtom *aEvent) +{ + return NS_ERROR_NOT_IMPLEMENTED; +} diff --git a/mozilla/mailnews/local/src/nsRssIncomingServer.h b/mozilla/mailnews/local/src/nsRssIncomingServer.h index 1f1381c5d77..bd07bdc80e9 100755 --- a/mozilla/mailnews/local/src/nsRssIncomingServer.h +++ b/mozilla/mailnews/local/src/nsRssIncomingServer.h @@ -40,17 +40,19 @@ #include "nsIRssIncomingServer.h" #include "nsILocalMailIncomingServer.h" #include "nsMsgIncomingServer.h" - +#include "nsIFolderListener.h" class nsRssIncomingServer : public nsMsgIncomingServer, public nsIRssIncomingServer, - public nsILocalMailIncomingServer + public nsILocalMailIncomingServer, + public nsIFolderListener { public: NS_DECL_ISUPPORTS_INHERITED NS_DECL_NSIRSSINCOMINGSERVER NS_DECL_NSILOCALMAILINCOMINGSERVER + NS_DECL_NSIFOLDERLISTENER NS_IMETHOD GetLocalStoreType(char **); NS_IMETHOD GetOfflineSupportLevel(PRInt32 *aSupportLevel); @@ -62,6 +64,7 @@ public: virtual ~nsRssIncomingServer(); protected: nsresult FillInDataSourcePath(const nsAString& aDataSourceName, nsILocalFile ** aLocation); + static nsrefcnt gInstanceCount; }; #endif /* __nsRssIncomingServer_h */