Back to index

lightning-sunbird  0.9+nobinonly
nsRssIncomingServer.cpp
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is mozilla mailnews.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Seth Spitzer <sspitzer@mozilla.org>.
00018  * Portions created by the Initial Developer are Copyright (C) 2004
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *   David Bienvenu <bienvenu@nventure.com>
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 #include "nsIRssService.h"
00039 #include "nsRssIncomingServer.h"
00040 #include "nsMsgFolderFlags.h"
00041 #include "nsINewsBlogFeedDownloader.h"
00042 #include "nsIMsgMailSession.h"
00043 #include "nsMsgBaseCID.h"
00044 
00045 #include "nsIMsgLocalMailFolder.h"
00046 #include "nsIDBFolderInfo.h"
00047 
00048 nsrefcnt nsRssIncomingServer::gInstanceCount    = 0;
00049 
00050 NS_IMPL_ISUPPORTS_INHERITED3(nsRssIncomingServer,
00051                              nsMsgIncomingServer,
00052                              nsIRssIncomingServer,
00053                              nsIFolderListener, 
00054                              nsILocalMailIncomingServer)
00055 
00056 nsRssIncomingServer::nsRssIncomingServer() 
00057 {
00058   m_canHaveFilters = PR_TRUE;
00059 
00060   if (gInstanceCount == 0) 
00061   {
00062     nsresult rv;
00063     nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); 
00064 
00065     if (NS_SUCCEEDED(rv))
00066       mailSession->AddFolderListener(this, nsIFolderListener::added);
00067   }
00068 
00069   gInstanceCount++;
00070 }
00071 
00072 nsRssIncomingServer::~nsRssIncomingServer()
00073 {
00074   gInstanceCount--;
00075   
00076   // I used to have code here which unregistered the global rss folder listener with the
00077   // mail session. But the rss incoming server is held until shutdown when we shut down the 
00078   // account datasource. And at shutdown the mail session explicitly releases all of its folder listeners
00079   // anyway so this was effectively a no-op...
00080 }
00081 
00082 nsresult nsRssIncomingServer::FillInDataSourcePath(const nsAString& aDataSourceName, nsILocalFile ** aLocation)
00083 {
00084   nsresult rv;
00085   // start by gettting the local path for this server
00086   nsCOMPtr<nsIFileSpec> localPathForServer;
00087   rv = GetLocalPath(getter_AddRefs(localPathForServer));
00088   NS_ENSURE_SUCCESS(rv, rv);
00089 
00090   // convert to a nsIFile
00091   nsCOMPtr<nsILocalFile> localFile;
00092   nsFileSpec pathSpec;
00093   localPathForServer->GetFileSpec(&pathSpec);
00094   rv = NS_FileSpecToIFile(&pathSpec, getter_AddRefs(localFile));
00095   NS_ENSURE_SUCCESS(rv, rv);
00096 
00097   // now append the name of the subscriptions data source
00098   rv = localFile->Append(aDataSourceName);
00099   NS_IF_ADDREF(*aLocation = localFile);
00100   return rv;
00101 }
00102 
00103 // nsIRSSIncomingServer methods
00104 NS_IMETHODIMP nsRssIncomingServer::GetSubscriptionsDataSourcePath(nsILocalFile ** aLocation)
00105 {
00106   return FillInDataSourcePath(NS_LITERAL_STRING("feeds.rdf"), aLocation);
00107 }
00108 
00109 NS_IMETHODIMP nsRssIncomingServer::GetFeedItemsDataSourcePath(nsILocalFile ** aLocation)
00110 {
00111   return FillInDataSourcePath(NS_LITERAL_STRING("feeditems.rdf"), aLocation);
00112 }
00113 
00114 NS_IMETHODIMP nsRssIncomingServer::CreateDefaultMailboxes(nsIFileSpec *path)
00115 {
00116     NS_ENSURE_ARG_POINTER(path);
00117     
00118     // for RSS, all we have is Trash
00119     // XXX or should we be use Local Folders/Trash?
00120     nsresult rv = path->AppendRelativeUnixPath("Trash");
00121     if (NS_FAILED(rv)) 
00122         return rv;
00123     
00124     PRBool exists;
00125     rv = path->Exists(&exists);
00126     if (!exists) 
00127     {
00128         rv = path->Touch();
00129         if (NS_FAILED(rv)) 
00130             return rv;
00131     }
00132     
00133     return NS_OK;
00134 }
00135 
00136 NS_IMETHODIMP nsRssIncomingServer::SetFlagsOnDefaultMailboxes()
00137 {
00138     nsCOMPtr<nsIMsgFolder> rootFolder;
00139     nsresult rv = GetRootFolder(getter_AddRefs(rootFolder));
00140     NS_ENSURE_SUCCESS(rv, rv);
00141 
00142     nsCOMPtr<nsIMsgLocalMailFolder> localFolder =
00143         do_QueryInterface(rootFolder, &rv);
00144     NS_ENSURE_SUCCESS(rv, rv);
00145 
00146     localFolder->SetFlagsOnDefaultMailboxes(MSG_FOLDER_FLAG_TRASH);
00147     return NS_OK;
00148 }
00149 
00150 NS_IMETHODIMP nsRssIncomingServer::PerformBiff(nsIMsgWindow *aMsgWindow)
00151 {
00152   // do we need to do anything here besides download articles
00153   // for each feed? I don't think we have a way to check a feed for new articles without actually
00154   // getting the articles. Do we need to SetPerformingBiff to true for this server? 
00155   nsresult rv;
00156   nsCOMPtr<nsIMsgFolder> rootRSSFolder;
00157   GetRootMsgFolder(getter_AddRefs(rootRSSFolder));
00158 
00159   // enumerate over the RSS folders and ping each one
00160   nsCOMPtr<nsISupportsArray> allDescendents;
00161   NS_NewISupportsArray(getter_AddRefs(allDescendents));
00162   rv = rootRSSFolder->ListDescendents(allDescendents);
00163   NS_ENSURE_SUCCESS(rv, rv);
00164   
00165   PRUint32 cnt =0;  
00166   allDescendents->Count(&cnt);
00167 
00168   nsCOMPtr<nsISupports> supports;
00169   nsCOMPtr<nsIUrlListener> urlListener;
00170   nsCOMPtr<nsIMsgFolder> rssFolder;
00171 
00172   for (PRUint32 index = 0; index < cnt; index++)
00173   {
00174     supports = getter_AddRefs(allDescendents->ElementAt(index));
00175     rssFolder = do_QueryInterface(supports, &rv);
00176     if (rssFolder)
00177     {
00178       urlListener = do_QueryInterface(rssFolder);
00179       // WARNING: Never call GetNewMail with the root folder or you will trigger an infinite loop...
00180       GetNewMail(aMsgWindow, urlListener, rssFolder, nsnull);
00181     }
00182   }
00183 
00184   return NS_OK;
00185 }
00186 
00187 NS_IMETHODIMP nsRssIncomingServer::GetNewMail(nsIMsgWindow *aMsgWindow, nsIUrlListener *aUrlListener, nsIMsgFolder *aFolder, nsIURI **_retval)
00188 {
00189   NS_ENSURE_ARG_POINTER(aFolder);
00190 
00191   // before we even try to get New Mail, check to see if the passed in folder was the root folder.
00192   // If it was, then call PerformBiff which will properly walk through each RSS folder, asking it to check for new Mail.
00193   PRBool rootFolder = PR_FALSE;
00194   aFolder->GetIsServer(&rootFolder);
00195   if (rootFolder)
00196     return PerformBiff(aMsgWindow);
00197   
00198   PRBool valid = PR_FALSE;
00199   nsCOMPtr <nsIMsgDatabase> db;
00200   nsresult rv;
00201   nsCOMPtr <nsINewsBlogFeedDownloader> rssDownloader = do_GetService("@mozilla.org/newsblog-feed-downloader;1", &rv);
00202   NS_ENSURE_SUCCESS(rv, rv);
00203   rv = aFolder->GetMsgDatabase(aMsgWindow, getter_AddRefs(db));
00204   if (NS_SUCCEEDED(rv) && db)
00205   {
00206     rv = db->GetSummaryValid(&valid);
00207     NS_ASSERTION(valid, "db is invalid");
00208     if (valid)
00209     {
00210       nsCOMPtr <nsIDBFolderInfo> folderInfo;
00211       rv = db->GetDBFolderInfo(getter_AddRefs(folderInfo));
00212       if (folderInfo)
00213       {
00214         nsXPIDLCString url;
00215         nsXPIDLString folderName;
00216         aFolder->GetName(getter_Copies(folderName));
00217         folderInfo->GetCharPtrProperty("feedUrl", getter_Copies(url));
00218 
00219         rv = rssDownloader->DownloadFeed(url.get(), 
00220                                          aFolder, PR_FALSE, folderName.get(), aUrlListener, aMsgWindow);
00221       }
00222     }
00223   }
00224   return NS_OK;
00225 }
00226 
00227 NS_IMETHODIMP nsRssIncomingServer::GetLocalStoreType(char **type)
00228 {
00229     NS_ENSURE_ARG_POINTER(type);
00230     *type = strdup("mailbox");
00231     return NS_OK;
00232 }
00233 
00234 NS_IMETHODIMP nsRssIncomingServer::GetAccountManagerChrome(nsAString& aResult)
00235 {
00236     aResult.AssignLiteral("am-newsblog.xul");
00237     return NS_OK;
00238 }
00239 
00240 NS_IMETHODIMP nsRssIncomingServer::GetOfflineSupportLevel(PRInt32 *aSupportLevel)
00241 {
00242   NS_ENSURE_ARG_POINTER(aSupportLevel);
00243   *aSupportLevel = OFFLINE_SUPPORT_LEVEL_NONE;
00244   return NS_OK;
00245 }
00246 
00247 NS_IMETHODIMP nsRssIncomingServer::GetSupportsDiskSpace(PRBool *aSupportsDiskSpace)
00248 {
00249   NS_ENSURE_ARG_POINTER(aSupportsDiskSpace);
00250   *aSupportsDiskSpace = PR_FALSE;
00251   return NS_OK;
00252 }
00253 
00254 NS_IMETHODIMP nsRssIncomingServer::GetServerRequiresPasswordForBiff(PRBool *aServerRequiresPasswordForBiff)
00255 {
00256   NS_ENSURE_ARG_POINTER(aServerRequiresPasswordForBiff);
00257   *aServerRequiresPasswordForBiff = PR_FALSE;  // for rss folders, we don't require a password
00258   return NS_OK;
00259 }
00260 
00261 NS_IMETHODIMP nsRssIncomingServer::GetCanSearchMessages(PRBool *canSearchMessages)
00262 {
00263   NS_ENSURE_ARG_POINTER(canSearchMessages);
00264   *canSearchMessages = PR_TRUE;
00265   return NS_OK;
00266 }
00267 
00268 NS_IMETHODIMP nsRssIncomingServer::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item)
00269 {
00270   nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(item);
00271   // just kick out with a success code if the item in question is not a folder
00272   if (!folder)
00273     return NS_OK;
00274 
00275   nsCOMPtr<nsIMsgIncomingServer> server;
00276   nsresult rv = folder->GetServer(getter_AddRefs(server));
00277   NS_ENSURE_SUCCESS(rv, rv);
00278 
00279   nsXPIDLCString type; 
00280   rv = server->GetType(getter_Copies(type));
00281   NS_ENSURE_SUCCESS(rv, rv);
00282  
00283   if (type.Equals("rss"))
00284   {
00285     nsCOMPtr <nsINewsBlogFeedDownloader> rssDownloader = do_GetService("@mozilla.org/newsblog-feed-downloader;1", &rv);
00286     NS_ENSURE_SUCCESS(rv, rv);
00287 
00288     // did the user just delete this folder (adding it to trash?) 
00289     nsCOMPtr<nsIMsgFolder> rootMsgFolder;
00290     nsCOMPtr<nsIMsgFolder> trashFolder;
00291     rv = GetRootFolder(getter_AddRefs(rootMsgFolder));
00292     NS_ENSURE_SUCCESS(rv, rv);
00293 
00294     PRUint32 numFolders;
00295     rv = rootMsgFolder->GetFoldersWithFlag(MSG_FOLDER_FLAG_TRASH, 1, &numFolders, getter_AddRefs(trashFolder));
00296     
00297     PRBool unsubscribe = PR_FALSE;
00298     if (trashFolder)
00299       trashFolder->IsAncestorOf(folder, &unsubscribe);
00300 
00301     rssDownloader->UpdateSubscriptionsDS(folder, unsubscribe);
00302 
00303     // if the user was moving or deleting a set of nested folders, we only seem to get a single OnItemAdded
00304     // notification. So we need to iterate over all of the descedent folders of the folder whose location has
00305     // changed.
00306 
00307     nsCOMPtr<nsISupportsArray> allDescendents;
00308     NS_NewISupportsArray(getter_AddRefs(allDescendents));
00309     rv = folder->ListDescendents(allDescendents);
00310     NS_ENSURE_SUCCESS(rv, rv);
00311 
00312     PRUint32 cnt =0;  
00313     allDescendents->Count(&cnt);
00314 
00315     nsCOMPtr<nsISupports> supports;
00316     nsCOMPtr<nsIMsgFolder> rssFolder;
00317 
00318     for (PRUint32 index = 0; index < cnt; index++)
00319     {
00320       supports = getter_AddRefs(allDescendents->ElementAt(index));
00321       rssFolder = do_QueryInterface(supports, &rv);
00322       if (rssFolder)
00323         rssDownloader->UpdateSubscriptionsDS(rssFolder, unsubscribe);
00324     }
00325   }
00326          
00327   return rv;
00328 }
00329 
00330 NS_IMETHODIMP nsRssIncomingServer::OnItemRemoved(nsIRDFResource *parentItem, nsISupports *item)
00331 {
00332  return NS_ERROR_NOT_IMPLEMENTED;
00333 }
00334 
00335 NS_IMETHODIMP nsRssIncomingServer::OnItemPropertyChanged(nsIRDFResource *item, nsIAtom *property, const char *oldValue, const char *newValue)
00336 {
00337   return NS_ERROR_NOT_IMPLEMENTED;
00338 }
00339 
00340 NS_IMETHODIMP nsRssIncomingServer::OnItemIntPropertyChanged(nsIRDFResource *item, nsIAtom *property, PRInt32 oldValue, PRInt32 newValue)
00341 {
00342   return NS_ERROR_NOT_IMPLEMENTED;
00343 }
00344 
00345 NS_IMETHODIMP nsRssIncomingServer::OnItemBoolPropertyChanged(nsIRDFResource *item, nsIAtom *property, PRBool oldValue, PRBool newValue)
00346 {
00347   return NS_ERROR_NOT_IMPLEMENTED;
00348 }
00349 
00350 NS_IMETHODIMP nsRssIncomingServer::OnItemUnicharPropertyChanged(nsIRDFResource *item, nsIAtom *property, const PRUnichar *oldValue, const PRUnichar *newValue)
00351 {
00352   return NS_ERROR_NOT_IMPLEMENTED;
00353 }
00354 
00355 
00356 NS_IMETHODIMP nsRssIncomingServer::OnItemPropertyFlagChanged(nsIMsgDBHdr *item, nsIAtom *property, PRUint32 oldFlag, PRUint32 newFlag)
00357 {
00358   return NS_ERROR_NOT_IMPLEMENTED;
00359 }
00360 
00361 NS_IMETHODIMP nsRssIncomingServer::OnItemEvent(nsIMsgFolder *aFolder, nsIAtom *aEvent)
00362 {
00363   return NS_ERROR_NOT_IMPLEMENTED;
00364 }