Back to index

lightning-sunbird  0.9+nobinonly
nsMsgMailSession.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is mozilla.org code.
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either of the GNU General Public License Version 2 or later (the "GPL"),
00026  * or 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 "msgCore.h" // for pre-compiled headers
00039 #include "nsMsgBaseCID.h"
00040 #include "nsMsgMailSession.h"
00041 #include "nsCOMPtr.h"
00042 #include "nsIMsgStatusFeedback.h"
00043 #include "nsIMsgWindow.h"
00044 #include "nsIMsgMessageService.h"
00045 #include "nsMsgUtils.h"
00046 #include "nsIURI.h"
00047 #include "nsXPIDLString.h"
00048 #include "nsIMsgAccountManager.h"
00049 #include "nsIChromeRegistry.h"
00050 #include "nsIDirectoryService.h"
00051 #include "nsAppDirectoryServiceDefs.h"
00052 #include "nsReadableUtils.h"
00053 #include "nsIDOMWindowInternal.h"
00054 #include "nsIDOMDocument.h"
00055 #include "nsIDOMElement.h"
00056 #include "nsIWindowMediator.h"
00057 #include "nsIScriptGlobalObject.h"
00058 #include "nsIDocShell.h"
00059 
00060 NS_IMPL_THREADSAFE_ADDREF(nsMsgMailSession)
00061 NS_IMPL_THREADSAFE_RELEASE(nsMsgMailSession)
00062 NS_INTERFACE_MAP_BEGIN(nsMsgMailSession)
00063   NS_INTERFACE_MAP_ENTRY(nsIMsgMailSession)
00064   NS_INTERFACE_MAP_ENTRY(nsIFolderListener)
00065   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIMsgMailSession)
00066 NS_INTERFACE_MAP_END_THREADSAFE
00067   
00068 nsMsgMailSession::nsMsgMailSession()
00069 {
00070 }
00071 
00072 
00073 nsMsgMailSession::~nsMsgMailSession()
00074 {
00075   Shutdown();
00076 }
00077 
00078 nsresult nsMsgMailSession::Init()
00079 {
00080   m_desktopSearchService = do_GetService("@mozilla.org/desktop-search-integration;1");
00081   return NS_NewISupportsArray(getter_AddRefs(mWindows));
00082 }
00083 
00084 nsresult nsMsgMailSession::Shutdown()
00085 {
00086   return NS_OK;
00087 }
00088 
00089 NS_IMETHODIMP nsMsgMailSession::AddFolderListener(nsIFolderListener * listener, PRUint32 notifyFlags)
00090 {
00091   NS_ENSURE_ARG_POINTER(listener);
00092 
00093   mListeners.AppendObject(listener);
00094   mListenerNotifyFlags.Add(notifyFlags);
00095   return NS_OK;
00096 }
00097 
00098 NS_IMETHODIMP nsMsgMailSession::RemoveFolderListener(nsIFolderListener * listener)
00099 {
00100   NS_ENSURE_ARG_POINTER(listener);
00101 
00102   PRInt32 index = mListeners.IndexOf(listener);
00103   NS_ASSERTION(index >= 0, "removing non-existent listener");
00104   if (index >= 0)
00105   {
00106     mListenerNotifyFlags.RemoveAt(index);
00107     mListeners.RemoveObjectAt(index);
00108   }
00109 
00110   return NS_OK;
00111 }
00112 
00113 NS_IMETHODIMP
00114 nsMsgMailSession::OnItemPropertyChanged(nsIRDFResource *item,
00115                                         nsIAtom *property,
00116                                         const char* oldValue,
00117                                         const char* newValue)
00118 {
00119   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00120     if (mListenerNotifyFlags[i] & nsIFolderListener::propertyChanged)
00121       mListeners[i]->OnItemPropertyChanged(item, property, oldValue, newValue);
00122 
00123   return NS_OK;
00124 }
00125 
00126 NS_IMETHODIMP
00127 nsMsgMailSession::OnItemUnicharPropertyChanged(nsIRDFResource *item,
00128                                                nsIAtom *property,
00129                                                const PRUnichar* oldValue,
00130                                                const PRUnichar* newValue)
00131 {
00132   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00133     if (mListenerNotifyFlags[i] & nsIFolderListener::unicharPropertyChanged)
00134       mListeners[i]->OnItemUnicharPropertyChanged(item, property, oldValue, newValue);
00135 
00136   return NS_OK;
00137 }
00138 
00139 NS_IMETHODIMP
00140 nsMsgMailSession::OnItemIntPropertyChanged(nsIRDFResource *item,
00141                                            nsIAtom *property,
00142                                            PRInt32 oldValue,
00143                                            PRInt32 newValue)
00144 {
00145   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00146     if (mListenerNotifyFlags[i] & nsIFolderListener::intPropertyChanged)
00147       mListeners[i]->OnItemIntPropertyChanged(item, property, oldValue, newValue);
00148 
00149   return NS_OK;
00150 }
00151 
00152 NS_IMETHODIMP
00153 nsMsgMailSession::OnItemBoolPropertyChanged(nsIRDFResource *item,
00154                                             nsIAtom *property,
00155                                             PRBool oldValue,
00156                                             PRBool newValue)
00157 {
00158   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00159     if (mListenerNotifyFlags[i] & nsIFolderListener::boolPropertyChanged)
00160       mListeners[i]->OnItemBoolPropertyChanged(item, property, oldValue, newValue);
00161 
00162   return NS_OK;
00163 }
00164 NS_IMETHODIMP
00165 nsMsgMailSession::OnItemPropertyFlagChanged(nsIMsgDBHdr *item,
00166                                             nsIAtom *property,
00167                                             PRUint32 oldValue,
00168                                             PRUint32 newValue)
00169 {
00170   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00171     if (mListenerNotifyFlags[i] & nsIFolderListener::propertyFlagChanged)
00172       mListeners[i]->OnItemPropertyFlagChanged(item, property, oldValue, newValue);
00173 
00174   return NS_OK;
00175 }
00176 
00177 NS_IMETHODIMP nsMsgMailSession::OnItemAdded(nsIRDFResource *parentItem, nsISupports *item)
00178 {
00179   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00180     if (mListenerNotifyFlags[i] & nsIFolderListener::added)
00181       mListeners[i]->OnItemAdded(parentItem, item);
00182 
00183   return NS_OK;
00184 }
00185 
00186 NS_IMETHODIMP nsMsgMailSession::OnItemRemoved(nsIRDFResource *parentItem, nsISupports *item)
00187 {
00188   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00189     if (mListenerNotifyFlags[i] & nsIFolderListener::removed)
00190       mListeners[i]->OnItemRemoved(parentItem, item);
00191 
00192   return NS_OK;
00193 }
00194 
00195 NS_IMETHODIMP nsMsgMailSession::OnItemEvent(nsIMsgFolder *aFolder,
00196                                             nsIAtom *aEvent)
00197 {
00198   for (PRInt32 i = mListeners.Count() - 1; i >= 0; --i)
00199     if (mListenerNotifyFlags[i] & nsIFolderListener::event)
00200       mListeners[i]->OnItemEvent(aFolder, aEvent);
00201 
00202   return NS_OK;
00203 }
00204 
00205 nsresult nsMsgMailSession::GetTopmostMsgWindow(nsIMsgWindow* *aMsgWindow)
00206 {
00207   nsresult rv;
00208 
00209   if (!aMsgWindow) return NS_ERROR_NULL_POINTER;
00210   
00211   *aMsgWindow = nsnull;
00212  
00213   if (mWindows)
00214   {
00215     PRUint32 count;
00216     rv = mWindows->Count(&count);
00217     NS_ENSURE_SUCCESS(rv, rv);
00218 
00219     nsCOMPtr<nsIMsgWindow> msgWindow;
00220 
00221     if (count == 1)
00222     {
00223       msgWindow = do_QueryElementAt(mWindows, 0, &rv);
00224       NS_ENSURE_SUCCESS(rv, rv);
00225       NS_IF_ADDREF(*aMsgWindow = msgWindow);
00226     }
00227     // If multiple message windows then we have lots more work.
00228     else if (count > 1)
00229     {
00230       // The msgWindows array does not hold z-order info.
00231       // Use mediator to get the top most window then match that with the msgWindows array.
00232       nsCOMPtr<nsIWindowMediator> windowMediator = do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
00233       NS_ENSURE_SUCCESS(rv, rv);
00234 
00235       nsCOMPtr<nsISimpleEnumerator> windowEnum;
00236       rv = windowMediator->GetZOrderDOMWindowEnumerator(nsnull, PR_TRUE, getter_AddRefs(windowEnum));
00237       NS_ENSURE_SUCCESS(rv, rv);
00238 
00239       nsCOMPtr<nsISupports> windowSupports;
00240       nsCOMPtr<nsIDOMWindow> topMostWindow;
00241       nsCOMPtr<nsIDOMDocument> domDocument;
00242       nsCOMPtr<nsIDOMElement> domElement;
00243       nsAutoString windowType;
00244       PRBool more;
00245 
00246       // loop to get the top most with attibute "mail:3pane" or "mail:messageWindow"
00247       windowEnum->HasMoreElements(&more);
00248       while (more)
00249       {
00250         rv = windowEnum->GetNext(getter_AddRefs(windowSupports));
00251         NS_ENSURE_SUCCESS(rv, rv);
00252         NS_ENSURE_TRUE(windowSupports, NS_ERROR_FAILURE);
00253 
00254         topMostWindow = do_QueryInterface(windowSupports, &rv);
00255         NS_ENSURE_SUCCESS(rv, rv);
00256         NS_ENSURE_TRUE(topMostWindow, NS_ERROR_FAILURE);
00257 
00258         rv = topMostWindow->GetDocument(getter_AddRefs(domDocument));
00259         NS_ENSURE_SUCCESS(rv, rv);
00260         NS_ENSURE_TRUE(domDocument, NS_ERROR_FAILURE);
00261 
00262         rv = domDocument->GetDocumentElement(getter_AddRefs(domElement));
00263         NS_ENSURE_SUCCESS(rv, rv);
00264         NS_ENSURE_TRUE(domElement, NS_ERROR_FAILURE);
00265 
00266         rv = domElement->GetAttribute(NS_LITERAL_STRING("windowtype"), windowType);
00267         NS_ENSURE_SUCCESS(rv, rv);
00268 
00269         if (windowType.EqualsLiteral("mail:3pane") ||
00270             windowType.EqualsLiteral("mail:messageWindow"))
00271             break;
00272 
00273         windowEnum->HasMoreElements(&more);
00274       }
00275 
00276       // identified the top most window
00277       if (more)
00278       {
00279         nsCOMPtr<nsIScriptGlobalObject> globalObj = do_QueryInterface(topMostWindow, &rv);
00280         NS_ENSURE_SUCCESS(rv, rv);
00281   
00282         // use this for the match
00283         nsIDocShell *topDocShell = globalObj->GetDocShell();
00284 
00285         // loop for the msgWindow array to find the match
00286         nsCOMPtr<nsIDocShell> docShell;
00287         while (count)
00288         {
00289           msgWindow = do_QueryElementAt(mWindows, count-1, &rv);
00290           NS_ENSURE_SUCCESS(rv,rv);
00291 
00292           rv = msgWindow->GetRootDocShell(getter_AddRefs(docShell));
00293           NS_ENSURE_SUCCESS(rv,rv);
00294           if (topDocShell == docShell)
00295           {
00296             NS_IF_ADDREF(*aMsgWindow = msgWindow);
00297             break;
00298           }
00299           count--;
00300         }
00301       }
00302     }
00303   }
00304 
00305   return (*aMsgWindow) ? NS_OK : NS_ERROR_FAILURE;
00306 }
00307 
00308 
00309 
00310 NS_IMETHODIMP nsMsgMailSession::AddMsgWindow(nsIMsgWindow *msgWindow)
00311 {
00312   mWindows->AppendElement(msgWindow);
00313   return NS_OK;
00314 }
00315 
00316 NS_IMETHODIMP nsMsgMailSession::RemoveMsgWindow(nsIMsgWindow *msgWindow)
00317 {
00318     mWindows->RemoveElement(msgWindow);
00319     PRUint32 count = 0;
00320     mWindows->Count(&count);
00321     if (count == 0)
00322     {
00323         nsresult rv;
00324         nsCOMPtr<nsIMsgAccountManager> accountManager = 
00325                  do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00326         if (NS_FAILED(rv)) return rv;
00327         accountManager->CleanupOnExit();
00328     }
00329        return NS_OK;
00330 }
00331 
00332 NS_IMETHODIMP nsMsgMailSession::GetMsgWindowsArray(nsISupportsArray * *aWindowsArray)
00333 {
00334   if(!aWindowsArray)
00335     return NS_ERROR_NULL_POINTER;
00336   
00337   *aWindowsArray = mWindows;
00338   NS_IF_ADDREF(*aWindowsArray);
00339   return NS_OK;
00340 }
00341 
00342 NS_IMETHODIMP nsMsgMailSession::IsFolderOpenInWindow(nsIMsgFolder *folder, PRBool *aResult)
00343 {
00344   if (!aResult)
00345     return NS_ERROR_NULL_POINTER;
00346   *aResult = PR_FALSE;
00347   
00348   PRUint32 count;
00349   nsresult rv = mWindows->Count(&count);
00350   if (NS_FAILED(rv)) return rv;
00351   
00352   if (mWindows)
00353   {
00354     for(PRUint32 i = 0; i < count; i++)
00355     {
00356       nsCOMPtr<nsIMsgWindow> openWindow = getter_AddRefs((nsIMsgWindow*)mWindows->ElementAt(i));
00357       nsCOMPtr<nsIMsgFolder> openFolder;
00358       if (openWindow)
00359         openWindow->GetOpenFolder(getter_AddRefs(openFolder));
00360       if (folder == openFolder.get())
00361       {
00362         *aResult = PR_TRUE;
00363         break;
00364       }
00365     }
00366   }
00367   
00368   return NS_OK;
00369 }
00370 
00371 NS_IMETHODIMP
00372 nsMsgMailSession::ConvertMsgURIToMsgURL(const char *aURI, nsIMsgWindow *aMsgWindow, char **aURL)
00373 {
00374   if ((!aURI) || (!aURL))
00375     return NS_ERROR_NULL_POINTER;
00376 
00377   // convert the rdf msg uri into a url that represents the message...
00378   nsCOMPtr <nsIMsgMessageService> msgService;
00379   nsresult rv = GetMessageServiceFromURI(aURI, getter_AddRefs(msgService));
00380   if (NS_FAILED(rv)) 
00381     return NS_ERROR_NULL_POINTER;
00382 
00383   nsCOMPtr<nsIURI> tURI;
00384   rv = msgService->GetUrlForUri(aURI, getter_AddRefs(tURI), aMsgWindow);
00385   if (NS_FAILED(rv)) 
00386     return NS_ERROR_NULL_POINTER;
00387 
00388   nsCAutoString urlString;
00389   if (NS_SUCCEEDED(tURI->GetSpec(urlString)))
00390   {
00391     *aURL = ToNewCString(urlString);
00392     if (!(aURL))
00393       return NS_ERROR_NULL_POINTER;
00394   }
00395   return rv;
00396 }
00397 
00398 //----------------------------------------------------------------------------------------
00399 // GetSelectedLocaleDataDir - If a locale is selected, appends the selected locale to the
00400 //                            defaults data dir and returns that new defaults data dir
00401 //----------------------------------------------------------------------------------------
00402 nsresult
00403 nsMsgMailSession::GetSelectedLocaleDataDir(nsIFile *defaultsDir)
00404 {                                                                               
00405   NS_ENSURE_ARG_POINTER(defaultsDir);                                     
00406 
00407   nsresult rv;                                                                
00408   PRBool baseDirExists = PR_FALSE;                                            
00409   rv = defaultsDir->Exists(&baseDirExists);                               
00410   NS_ENSURE_SUCCESS(rv,rv);                                                   
00411 
00412   if (baseDirExists) {                                                        
00413     nsCOMPtr<nsIXULChromeRegistry> packageRegistry =
00414       do_GetService("@mozilla.org/chrome/chrome-registry;1", &rv);
00415     if (NS_SUCCEEDED(rv)) {                                                 
00416       nsCAutoString localeName;                                           
00417       rv = packageRegistry->GetSelectedLocale(NS_LITERAL_CSTRING("global-region"), localeName);
00418 
00419       if (NS_SUCCEEDED(rv) && !localeName.IsEmpty()) {
00420         PRBool localeDirExists = PR_FALSE;                              
00421         nsCOMPtr<nsIFile> localeDataDir;                                
00422         
00423         rv = defaultsDir->Clone(getter_AddRefs(localeDataDir));     
00424         NS_ENSURE_SUCCESS(rv,rv);                                       
00425 
00426         rv = localeDataDir->AppendNative(localeName);
00427         NS_ENSURE_SUCCESS(rv,rv);                                       
00428 
00429         rv = localeDataDir->Exists(&localeDirExists);                   
00430         NS_ENSURE_SUCCESS(rv,rv);                                       
00431 
00432         if (localeDirExists) {                                          
00433           // use locale provider instead                              
00434           rv = defaultsDir->AppendNative(localeName);
00435           NS_ENSURE_SUCCESS(rv,rv);                                   
00436         }                                                               
00437       }                                                                   
00438     }                                                                       
00439   }                                                                           
00440   return NS_OK;                                                               
00441 } 
00442 
00443 //----------------------------------------------------------------------------------------
00444 // GetDataFilesDir - Gets the application's default folder and then appends the 
00445 //                   subdirectory named passed in as param dirName. If there is a seleccted
00446 //                   locale, will append that to the dir path before returning the value
00447 //----------------------------------------------------------------------------------------
00448 NS_IMETHODIMP
00449 nsMsgMailSession::GetDataFilesDir(const char* dirName, nsIFile **dataFilesDir)
00450 {                                                                                                                                                    
00451   NS_ENSURE_ARG_POINTER(dataFilesDir);
00452 
00453   nsresult rv;
00454   nsCOMPtr<nsIProperties> directoryService = 
00455     do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
00456   NS_ENSURE_SUCCESS(rv,rv);
00457 
00458   nsCOMPtr<nsIFile> defaultsDir;
00459   rv = directoryService->Get(NS_APP_DEFAULTS_50_DIR, 
00460                              NS_GET_IID(nsIFile), 
00461                              getter_AddRefs(defaultsDir));
00462   NS_ENSURE_SUCCESS(rv,rv);
00463 
00464   rv = defaultsDir->AppendNative(nsDependentCString(dirName));
00465   if (NS_SUCCEEDED(rv))
00466     rv = GetSelectedLocaleDataDir(defaultsDir);
00467 
00468   NS_IF_ADDREF(*dataFilesDir = defaultsDir);
00469 
00470   return rv;
00471 }