Back to index

lightning-sunbird  0.9+nobinonly
nsMsgAccountManagerDS.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
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  *   Alec Flett <alecf@netscape.com>
00024  *   Seth Spitzer <sspitzer@netscape.com>
00025  *
00026  * Alternatively, the contents of this file may be used under the terms of
00027  * either of the GNU General Public License Version 2 or later (the "GPL"),
00028  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00029  * in which case the provisions of the GPL or the LGPL are applicable instead
00030  * of those above. If you wish to allow use of your version of this file only
00031  * under the terms of either the GPL or the LGPL, and not to allow others to
00032  * use your version of this file under the terms of the MPL, indicate your
00033  * decision by deleting the provisions above and replace them with the notice
00034  * and other provisions required by the GPL or the LGPL. If you do not delete
00035  * the provisions above, a recipient may use your version of this file under
00036  * the terms of any one of the MPL, the GPL or the LGPL.
00037  *
00038  * ***** END LICENSE BLOCK ***** */
00039 
00040 /*
00041  * RDF datasource for the account manager
00042  */
00043 
00044 #include "nsMsgAccountManagerDS.h"
00045 
00046 
00047 #include "rdf.h"
00048 #include "nsRDFCID.h"
00049 #include "nsIRDFDataSource.h"
00050 #include "nsEnumeratorUtils.h"
00051 #include "nsIServiceManager.h"
00052 #include "nsIMsgMailSession.h"
00053 #include "nsXPIDLString.h"
00054 
00055 #include "nsMsgRDFUtils.h"
00056 #include "nsIMsgFolder.h"
00057 #include "nsMsgBaseCID.h"
00058 #include "nsMsgIncomingServer.h"
00059 
00060 #include "nsICategoryManager.h"
00061 #include "nsXPCOM.h"
00062 #include "nsISupportsPrimitives.h"
00063 #include "nsIPrefService.h"
00064 #include "nsIPrefBranch2.h"
00065 
00066 // turn this on to see useful output
00067 #undef DEBUG_amds
00068 
00069 #define NC_RDF_PAGETITLE_PREFIX               NC_NAMESPACE_URI "PageTitle"
00070 #define NC_RDF_PAGETITLE_MAIN                 NC_RDF_PAGETITLE_PREFIX "Main"
00071 #define NC_RDF_PAGETITLE_SERVER               NC_RDF_PAGETITLE_PREFIX "Server"
00072 #define NC_RDF_PAGETITLE_COPIES               NC_RDF_PAGETITLE_PREFIX "Copies"
00073 #define NC_RDF_PAGETITLE_OFFLINEANDDISKSPACE  NC_RDF_PAGETITLE_PREFIX "OfflineAndDiskSpace"
00074 #define NC_RDF_PAGETITLE_DISKSPACE            NC_RDF_PAGETITLE_PREFIX "DiskSpace"
00075 #define NC_RDF_PAGETITLE_ADDRESSING           NC_RDF_PAGETITLE_PREFIX "Addressing"
00076 #define NC_RDF_PAGETITLE_SMTP                 NC_RDF_PAGETITLE_PREFIX "SMTP"
00077 #define NC_RDF_PAGETITLE_JUNK                 NC_RDF_PAGETITLE_PREFIX "Junk"
00078 #define NC_RDF_PAGETITLE_FAKEACCOUNT          NC_RDF_PAGETITLE_PREFIX "FakeAccount"
00079 #define NC_RDF_PAGETAG NC_NAMESPACE_URI "PageTag"
00080 
00081 
00082 #define NC_RDF_ACCOUNTROOT "msgaccounts:/"
00083 
00084 #define PREF_SHOW_FAKE_ACCOUNT "mailnews.fakeaccount.show"
00085 
00086 typedef struct _serverCreationParams {
00087   nsISupportsArray *serverArray;
00088   nsIRDFService *rdfService;
00089 } serverCreationParams;
00090 
00091 typedef struct {
00092   const char* serverKey;
00093   PRBool found;
00094 } findServerByKeyEntry;
00095 
00096 // the root resource (msgaccounts:/)
00097 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_AccountRoot=nsnull;
00098 
00099 // attributes of accounts
00100 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Name=nsnull;
00101 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_FolderTreeName=nsnull;
00102 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_FolderTreeSimpleName=nsnull;
00103 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_NameSort=nsnull;
00104 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_FolderTreeNameSort=nsnull;
00105 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTag=nsnull;
00106 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_IsDefaultServer=nsnull;
00107 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_SupportsFilters=nsnull;
00108 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_CanGetMessages=nsnull;
00109 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_CanGetIncomingMessages=nsnull;
00110 
00111 // containment
00112 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Child=nsnull;
00113 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Settings=nsnull;
00114 
00115 
00116 // properties corresponding to interfaces
00117 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Account=nsnull;
00118 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Server=nsnull;
00119 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Identity=nsnull;
00120 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_Junk=nsnull;
00121 
00122 // individual pages
00123 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleMain=nsnull;
00124 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleServer=nsnull;
00125 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleCopies=nsnull;
00126 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleOfflineAndDiskSpace=nsnull;
00127 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleDiskSpace=nsnull;
00128 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleAddressing=nsnull;
00129 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleSMTP=nsnull;
00130 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleJunk=nsnull;
00131 nsIRDFResource* nsMsgAccountManagerDataSource::kNC_PageTitleFakeAccount=nsnull;
00132 
00133 // common literals
00134 nsIRDFLiteral* nsMsgAccountManagerDataSource::kTrueLiteral = nsnull;
00135 
00136 nsIAtom* nsMsgAccountManagerDataSource::kDefaultServerAtom = nsnull;
00137 
00138 nsrefcnt nsMsgAccountManagerDataSource::gAccountManagerResourceRefCnt = 0;
00139 
00140 // shared arc lists
00141 nsCOMPtr<nsISupportsArray> nsMsgAccountManagerDataSource::mAccountArcsOut;
00142 nsCOMPtr<nsISupportsArray> nsMsgAccountManagerDataSource::mAccountRootArcsOut;
00143 
00144 
00145 // RDF to match
00146 #define NC_RDF_ACCOUNT NC_NAMESPACE_URI "Account"
00147 #define NC_RDF_SERVER  NC_NAMESPACE_URI "Server"
00148 #define NC_RDF_IDENTITY NC_NAMESPACE_URI "Identity"
00149 #define NC_RDF_SETTINGS NC_NAMESPACE_URI "Settings"
00150 #define NC_RDF_JUNK NC_NAMESPACE_URI "Junk"
00151 #define NC_RDF_ISDEFAULTSERVER NC_NAMESPACE_URI "IsDefaultServer"
00152 #define NC_RDF_SUPPORTSFILTERS NC_NAMESPACE_URI "SupportsFilters"
00153 #define NC_RDF_CANGETMESSAGES NC_NAMESPACE_URI "CanGetMessages"
00154 #define NC_RDF_CANGETINCOMINGMESSAGES NC_NAMESPACE_URI "CanGetIncomingMessages"
00155 
00156 nsMsgAccountManagerDataSource::nsMsgAccountManagerDataSource()
00157 {
00158 #ifdef DEBUG_amds
00159   printf("nsMsgAccountManagerDataSource() being created\n");
00160 #endif
00161 
00162   // do per-class initialization here
00163   if (gAccountManagerResourceRefCnt++ == 0) {
00164     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_CHILD), &kNC_Child);
00165     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_NAME), &kNC_Name);
00166     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERTREENAME),
00167                                  &kNC_FolderTreeName);
00168     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERTREESIMPLENAME),
00169                                  &kNC_FolderTreeSimpleName);
00170     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_NAME_SORT), &kNC_NameSort);
00171     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_FOLDERTREENAME_SORT),
00172                                  &kNC_FolderTreeNameSort);
00173     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETAG), &kNC_PageTag);
00174     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_ISDEFAULTSERVER),
00175                                  &kNC_IsDefaultServer);
00176     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_SUPPORTSFILTERS),
00177                                  &kNC_SupportsFilters);
00178     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANGETMESSAGES),
00179                                  &kNC_CanGetMessages);
00180     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_CANGETINCOMINGMESSAGES),
00181                                  &kNC_CanGetIncomingMessages);
00182 
00183     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_ACCOUNT), &kNC_Account);
00184     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_SERVER), &kNC_Server);
00185     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_IDENTITY), &kNC_Identity);
00186     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_JUNK), &kNC_Junk);
00187     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_MAIN),
00188                                  &kNC_PageTitleMain);
00189     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_SERVER),
00190                                  &kNC_PageTitleServer);
00191     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_COPIES),
00192                                  &kNC_PageTitleCopies);
00193     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_OFFLINEANDDISKSPACE),
00194                                  &kNC_PageTitleOfflineAndDiskSpace);
00195     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_DISKSPACE),
00196                                  &kNC_PageTitleDiskSpace);
00197     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_ADDRESSING),
00198                                  &kNC_PageTitleAddressing);
00199     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_SMTP),
00200                                  &kNC_PageTitleSMTP);
00201     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_JUNK),
00202                                  &kNC_PageTitleJunk);
00203     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_PAGETITLE_FAKEACCOUNT),
00204                                  &kNC_PageTitleFakeAccount);
00205 
00206     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_ACCOUNTROOT),
00207                                  &kNC_AccountRoot);
00208 
00209     getRDFService()->GetLiteral(NS_LITERAL_STRING("true").get(),
00210                                 &kTrueLiteral);
00211 
00212     // eventually these need to exist in some kind of array
00213     // that's easily extensible
00214     getRDFService()->GetResource(NS_LITERAL_CSTRING(NC_RDF_SETTINGS), &kNC_Settings);
00215 
00216     kDefaultServerAtom = NS_NewAtom("DefaultServer");
00217   }
00218 
00219   nsCOMPtr<nsIPrefBranch2> prefBranchInternal(do_GetService(NS_PREFSERVICE_CONTRACTID));
00220   if (prefBranchInternal)
00221     prefBranchInternal->AddObserver(PREF_SHOW_FAKE_ACCOUNT, this, PR_FALSE);
00222 }
00223 
00224 nsMsgAccountManagerDataSource::~nsMsgAccountManagerDataSource()
00225 {
00226   nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager);
00227   if (am)
00228     am->RemoveIncomingServerListener(this);
00229 
00230   if (--gAccountManagerResourceRefCnt == 0) {
00231     NS_IF_RELEASE(kNC_Child);
00232     NS_IF_RELEASE(kNC_Name);
00233     NS_IF_RELEASE(kNC_FolderTreeName);
00234     NS_IF_RELEASE(kNC_FolderTreeSimpleName);
00235     NS_IF_RELEASE(kNC_NameSort);
00236     NS_IF_RELEASE(kNC_FolderTreeNameSort);
00237     NS_IF_RELEASE(kNC_PageTag);
00238     NS_IF_RELEASE(kNC_IsDefaultServer);
00239     NS_IF_RELEASE(kNC_SupportsFilters);
00240     NS_IF_RELEASE(kNC_CanGetMessages);
00241     NS_IF_RELEASE(kNC_CanGetIncomingMessages);
00242     NS_IF_RELEASE(kNC_Account);
00243     NS_IF_RELEASE(kNC_Server);
00244     NS_IF_RELEASE(kNC_Identity);
00245     NS_IF_RELEASE(kNC_Junk);
00246     NS_IF_RELEASE(kNC_PageTitleMain);
00247     NS_IF_RELEASE(kNC_PageTitleServer);
00248     NS_IF_RELEASE(kNC_PageTitleCopies);
00249     NS_IF_RELEASE(kNC_PageTitleOfflineAndDiskSpace);
00250     NS_IF_RELEASE(kNC_PageTitleDiskSpace);
00251     NS_IF_RELEASE(kNC_PageTitleAddressing);
00252     NS_IF_RELEASE(kNC_PageTitleSMTP);
00253     NS_IF_RELEASE(kNC_PageTitleJunk);
00254     NS_IF_RELEASE(kNC_PageTitleFakeAccount);
00255     NS_IF_RELEASE(kTrueLiteral);
00256 
00257     NS_IF_RELEASE(kNC_AccountRoot);
00258 
00259     // eventually these need to exist in some kind of array
00260     // that's easily extensible
00261     NS_IF_RELEASE(kNC_Settings);
00262 
00263 
00264     NS_IF_RELEASE(kDefaultServerAtom);
00265     mAccountArcsOut = nsnull;
00266     mAccountRootArcsOut = nsnull;
00267   }
00268 
00269 }
00270 
00271 NS_IMPL_ADDREF_INHERITED(nsMsgAccountManagerDataSource, nsMsgRDFDataSource)
00272 NS_IMPL_RELEASE_INHERITED(nsMsgAccountManagerDataSource, nsMsgRDFDataSource)
00273 NS_INTERFACE_MAP_BEGIN(nsMsgAccountManagerDataSource)
00274   NS_INTERFACE_MAP_ENTRY(nsIIncomingServerListener)
00275   NS_INTERFACE_MAP_ENTRY(nsIFolderListener)
00276 NS_INTERFACE_MAP_END_INHERITING(nsMsgRDFDataSource)
00277 
00278 nsresult
00279 nsMsgAccountManagerDataSource::Init()
00280 {
00281   nsresult rv;
00282 
00283   rv = nsMsgRDFDataSource::Init();
00284   if (NS_FAILED(rv)) return rv;
00285 
00286   nsCOMPtr<nsIMsgAccountManager> am;
00287 
00288   // get a weak ref to the account manager
00289   if (!mAccountManager) 
00290   {
00291     am = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
00292     mAccountManager = do_GetWeakReference(am);
00293   }
00294   else
00295     am = do_QueryReferent(mAccountManager);
00296 
00297   if (am) 
00298   {
00299     am->AddIncomingServerListener(this);
00300     am->AddRootFolderListener(this);
00301   }
00302 
00303 
00304   return NS_OK;
00305 }
00306 
00307 void nsMsgAccountManagerDataSource::Cleanup()
00308 {
00309   nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager);
00310 
00311   if (am)
00312   {
00313     am->RemoveIncomingServerListener(this);
00314     am->RemoveRootFolderListener(this);
00315   }
00316 
00317   nsMsgRDFDataSource::Cleanup();
00318 }
00319 
00320 /* nsIRDFNode GetTarget (in nsIRDFResource aSource, in nsIRDFResource property, in boolean aTruthValue); */
00321 NS_IMETHODIMP
00322 nsMsgAccountManagerDataSource::GetTarget(nsIRDFResource *source,
00323                                          nsIRDFResource *property,
00324                                          PRBool aTruthValue,
00325                                          nsIRDFNode **target)
00326 {
00327   nsresult rv;
00328 
00329 
00330   rv = NS_RDF_NO_VALUE;
00331 
00332   nsAutoString str;
00333   if (property == kNC_Name || property == kNC_FolderTreeName ||
00334       property == kNC_FolderTreeSimpleName) 
00335   {
00336     rv = getStringBundle();
00337     NS_ENSURE_SUCCESS(rv, rv);
00338 
00339     nsXPIDLString pageTitle;
00340     if (source == kNC_PageTitleServer)
00341       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-server").get(),
00342                                        getter_Copies(pageTitle));
00343 
00344     else if (source == kNC_PageTitleCopies)
00345       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-copies").get(),
00346                                        getter_Copies(pageTitle));
00347     else if (source == kNC_PageTitleOfflineAndDiskSpace)
00348       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-offline-and-diskspace").get(),
00349                                        getter_Copies(pageTitle));
00350     else if (source == kNC_PageTitleDiskSpace)
00351       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-diskspace").get(),
00352                                        getter_Copies(pageTitle));
00353     else if (source == kNC_PageTitleAddressing)
00354       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-addressing").get(),
00355                                        getter_Copies(pageTitle));
00356     else if (source == kNC_PageTitleSMTP)
00357       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-smtp").get(),
00358                                        getter_Copies(pageTitle));
00359     else if (source == kNC_PageTitleJunk)
00360       mStringBundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-junk").get(),
00361                                        getter_Copies(pageTitle));
00362 
00363     else if (source == kNC_PageTitleFakeAccount) {
00364       PRBool showFakeAccount;
00365       nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
00366       if (NS_SUCCEEDED(rv))
00367         rv = prefBranch->GetBoolPref(PREF_SHOW_FAKE_ACCOUNT, &showFakeAccount);
00368 
00369       if (showFakeAccount) {
00370         nsCOMPtr<nsIStringBundleService> strBundleService =
00371           do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
00372         if (NS_FAILED(rv)) return rv;
00373         nsCOMPtr<nsIStringBundle> bundle;
00374         rv = strBundleService->CreateBundle("chrome://messenger/locale/fakeAccount.properties",
00375                                              getter_AddRefs(bundle));
00376         if (NS_SUCCEEDED(rv))
00377           bundle->GetStringFromName(NS_LITERAL_STRING("prefPanel-fake-account").get(),
00378                                     getter_Copies(pageTitle));
00379       }
00380     }
00381 
00382     else {
00383       // if it's a server, use the pretty name
00384       nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(source, &rv);
00385       if (NS_SUCCEEDED(rv) && folder) {
00386         PRBool isServer;
00387         rv = folder->GetIsServer(&isServer);
00388         if (NS_SUCCEEDED(rv) && isServer)
00389           rv = folder->GetPrettyName(getter_Copies(pageTitle));
00390       }
00391       else {
00392         // allow for the accountmanager to be dynamically extended.
00393 
00394         nsCOMPtr<nsIStringBundleService> strBundleService =
00395           do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
00396         NS_ENSURE_SUCCESS(rv,rv);
00397 
00398         const char *sourceValue;
00399         rv = source->GetValueConst(&sourceValue);
00400         NS_ENSURE_SUCCESS(rv,rv);
00401 
00402         // make sure the pointer math we're about to do is safe.
00403         NS_ENSURE_TRUE(sourceValue && (strlen(sourceValue) > strlen(NC_RDF_PAGETITLE_PREFIX)), NS_ERROR_UNEXPECTED);
00404 
00405         nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager, &rv);
00406         NS_ENSURE_SUCCESS(rv, PR_FALSE);
00407 
00408         // turn NC#PageTitlefoobar into foobar, so we can get the am-foobar.properties bundle
00409         nsXPIDLCString chromePackageName;
00410         rv = am->GetChromePackageName((sourceValue + strlen(NC_RDF_PAGETITLE_PREFIX)), getter_Copies(chromePackageName));
00411         NS_ENSURE_SUCCESS(rv,rv);
00412 
00413         nsCAutoString bundleURL;
00414         bundleURL = "chrome://";
00415         bundleURL += chromePackageName;
00416         bundleURL += "/locale/am-";
00417         bundleURL += (sourceValue + strlen(NC_RDF_PAGETITLE_PREFIX));
00418         bundleURL += ".properties";
00419 
00420         nsCOMPtr <nsIStringBundle> bundle;
00421         rv = strBundleService->CreateBundle(bundleURL.get(), getter_AddRefs(bundle));
00422 
00423         NS_ENSURE_SUCCESS(rv,rv);
00424 
00425         nsAutoString panelTitleName;
00426         panelTitleName.AssignLiteral("prefPanel-");
00427         panelTitleName.AppendWithConversion(sourceValue + strlen(NC_RDF_PAGETITLE_PREFIX));
00428         bundle->GetStringFromName(panelTitleName.get(), getter_Copies(pageTitle));
00429       }
00430     }
00431     str = pageTitle.get();
00432   }
00433   else if (property == kNC_PageTag) {
00434     // do NOT localize these strings. these are the urls of the XUL files
00435     if (source == kNC_PageTitleServer)
00436       str.AssignLiteral("am-server.xul");
00437     else if (source == kNC_PageTitleCopies)
00438       str.AssignLiteral("am-copies.xul");
00439     else if ((source == kNC_PageTitleOfflineAndDiskSpace) ||
00440              (source == kNC_PageTitleDiskSpace))
00441       str.AssignLiteral("am-offline.xul");
00442     else if (source == kNC_PageTitleAddressing)
00443       str.AssignLiteral("am-addressing.xul");
00444     else if (source == kNC_PageTitleSMTP)
00445       str.AssignLiteral("am-smtp.xul");
00446     else if (source == kNC_PageTitleJunk)
00447       str.AssignLiteral("am-junk.xul");
00448     else if (source == kNC_PageTitleFakeAccount)
00449       str.AssignLiteral("am-fakeaccount.xul");
00450     else {
00451       nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(source, &rv);
00452       if (NS_SUCCEEDED(rv) && folder) {
00453         /* if this is a server, with no identities, then we show a special panel */
00454         nsCOMPtr<nsIMsgIncomingServer> server;
00455         rv = getServerForFolderNode(source, getter_AddRefs(server));
00456         if (server)
00457           server->GetAccountManagerChrome(str);
00458         else 
00459           str.AssignLiteral("am-main.xul");
00460       }
00461       else {
00462         // allow for the accountmanager to be dynamically extended
00463         const char *sourceValue;
00464         rv = source->GetValueConst(&sourceValue);
00465         NS_ENSURE_SUCCESS(rv,rv);
00466 
00467         // make sure the pointer math we're about to do is safe.
00468         NS_ENSURE_TRUE(sourceValue && (strlen(sourceValue) > strlen(NC_RDF_PAGETITLE_PREFIX)), NS_ERROR_UNEXPECTED);
00469 
00470         // turn NC#PageTitlefoobar into foobar, so we can get the am-foobar.xul file
00471         str.AssignLiteral("am-");
00472         str.AppendWithConversion((sourceValue + strlen(NC_RDF_PAGETITLE_PREFIX)));
00473         str.AppendLiteral(".xul");
00474       }
00475     }
00476   }
00477 
00478   // handle sorting of servers
00479   else if ((property == kNC_NameSort) ||
00480            (property == kNC_FolderTreeNameSort)) {
00481 
00482     // order for the folder pane
00483     // and for the account manager tree is:
00484     //
00485     // - default mail account
00486     // - <other mail accounts>
00487     // - "Local Folders" account
00488     // - news accounts
00489     // - smtp settings (note, this is only in account manager tree)
00490     // - fake account
00491 
00492     // make sure we're handling a root folder that is a server
00493     nsCOMPtr<nsIMsgIncomingServer> server;
00494     rv = getServerForFolderNode(source, getter_AddRefs(server));
00495 
00496     if (NS_SUCCEEDED(rv) && server) {
00497       PRInt32 accountNum;
00498       nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager);
00499 
00500       if (isDefaultServer(server))
00501         str.AssignLiteral("0000");
00502       else {
00503         rv = am->FindServerIndex(server, &accountNum);
00504         if (NS_FAILED(rv)) return rv;
00505 
00506         // this is a hack for now - hardcode server order by type
00507         nsXPIDLCString serverType;
00508         server->GetType(getter_Copies(serverType));
00509 
00510         if (nsCRT::strcasecmp(serverType, "none")==0)
00511           accountNum += 2000;
00512         else if (nsCRT::strcasecmp(serverType, "nntp")==0)
00513           accountNum += 3000;
00514         else
00515           accountNum += 1000;     // default is to appear at the top
00516 
00517         str.AppendInt(accountNum);
00518       }
00519     }
00520     else {
00521       const char *sourceValue;
00522       rv = source->GetValueConst(&sourceValue);
00523       NS_ENSURE_SUCCESS(rv, NS_RDF_NO_VALUE);
00524 
00525       // if this is a page (which we determine by the prefix of the URI)
00526       // we want to generate a sort value
00527       // so that we can sort the categories in the account manager tree
00528       // (or the folder pane)
00529       //
00530       // otherwise, return NS_RDF_NO_VALUE
00531       // so that the folder data source will take care of it.
00532       if (sourceValue && (strncmp(sourceValue, NC_RDF_PAGETITLE_PREFIX, strlen(NC_RDF_PAGETITLE_PREFIX)) == 0)) {
00533         if (source == kNC_PageTitleSMTP)
00534           str.AssignLiteral("4000");
00535         else if (source == kNC_PageTitleFakeAccount)
00536           str.AssignLiteral("5000");
00537         else if (source == kNC_PageTitleServer)
00538           str.AssignLiteral("1");
00539         else if (source == kNC_PageTitleCopies)
00540           str.AssignLiteral("2");
00541         else if (source == kNC_PageTitleAddressing)
00542           str.AssignLiteral("3");
00543         else if (source == kNC_PageTitleOfflineAndDiskSpace)
00544           str.AssignLiteral("4");
00545         else if (source == kNC_PageTitleDiskSpace)
00546           str.AssignLiteral("4");
00547         else if (source == kNC_PageTitleJunk)
00548           str.AssignLiteral("5");
00549         else {
00550           // allow for the accountmanager to be dynamically extended
00551           // all the other pages come after the standard ones
00552           // server, copies, addressing, disk space (or offline & disk space)
00553           str.AssignWithConversion(sourceValue);
00554         }
00555       }
00556       else {
00557         return NS_RDF_NO_VALUE;
00558       }
00559     }
00560   }
00561 
00562   // GetTargets() stuff - need to return a valid answer so that
00563   // twisties will appear
00564   else if (property == kNC_Settings) {
00565     nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(source,&rv);
00566     if (NS_FAILED(rv))
00567       return NS_RDF_NO_VALUE;
00568 
00569     PRBool isServer=PR_FALSE;
00570     folder->GetIsServer(&isServer);
00571     // no need to localize this!
00572     if (isServer)
00573       str.AssignLiteral("ServerSettings");
00574   }
00575 
00576   else if (property == kNC_IsDefaultServer) {
00577     nsCOMPtr<nsIMsgIncomingServer> thisServer;
00578     rv = getServerForFolderNode(source, getter_AddRefs(thisServer));
00579     if (NS_FAILED(rv) || !thisServer) return NS_RDF_NO_VALUE;
00580 
00581     if (isDefaultServer(thisServer))
00582       str.AssignLiteral("true");
00583   }
00584 
00585   else if (property == kNC_SupportsFilters) {
00586     nsCOMPtr<nsIMsgIncomingServer> server;
00587     rv = getServerForFolderNode(source, getter_AddRefs(server));
00588     if (NS_FAILED(rv) || !server) return NS_RDF_NO_VALUE;
00589 
00590     if (supportsFilters(server))
00591       str.AssignLiteral("true");
00592   }
00593   else if (property == kNC_CanGetMessages) {
00594     nsCOMPtr<nsIMsgIncomingServer> server;
00595     rv = getServerForFolderNode(source, getter_AddRefs(server));
00596     if (NS_FAILED(rv) || !server) return NS_RDF_NO_VALUE;
00597 
00598     if (canGetMessages(server))
00599       str.AssignLiteral("true");
00600   }
00601   else if (property == kNC_CanGetIncomingMessages) {
00602     nsCOMPtr<nsIMsgIncomingServer> server;
00603     rv = getServerForFolderNode(source, getter_AddRefs(server));
00604     if (NS_FAILED(rv) || !server) return NS_RDF_NO_VALUE;
00605 
00606     if (canGetIncomingMessages(server))
00607       str.AssignLiteral("true");
00608   }
00609   else if (property == kNC_PageTitleFakeAccount) {
00610     if (source == kNC_PageTitleFakeAccount)
00611       str.AssignLiteral("true");
00612   }
00613   if (!str.IsEmpty())
00614     rv = createNode(str.get(), target, getRDFService());
00615 
00616   //if we have an empty string and we don't have an error value, then
00617   //we don't have a value for RDF.
00618   else if(NS_SUCCEEDED(rv))
00619     rv = NS_RDF_NO_VALUE;
00620 
00621   return rv;
00622 }
00623 
00624 
00625 
00626 /* nsISimpleEnumerator GetTargets (in nsIRDFResource aSource, in nsIRDFResource property, in boolean aTruthValue); */
00627 NS_IMETHODIMP
00628 nsMsgAccountManagerDataSource::GetTargets(nsIRDFResource *source,
00629                                           nsIRDFResource *property,
00630                                           PRBool aTruthValue,
00631                                           nsISimpleEnumerator **_retval)
00632 {
00633   nsresult rv = NS_RDF_NO_VALUE;
00634 
00635   // create array and enumerator
00636   // even if we're not handling this we need to return something empty?
00637   nsCOMPtr<nsISupportsArray> nodes;
00638   rv = NS_NewISupportsArray(getter_AddRefs(nodes));
00639   if (NS_FAILED(rv)) return rv;
00640 
00641   rv = NS_NewArrayEnumerator(_retval, nodes);
00642   if (NS_FAILED(rv)) return rv;
00643 
00644 #ifdef DEBUG_amds
00645   nsXPIDLCString source_value;
00646   rv = source->GetValue(getter_Copies(source_value));
00647 
00648   nsXPIDLCString property_arc;
00649   rv = property->GetValue(getter_Copies(property_arc));
00650   if (NS_FAILED(rv)) return rv;
00651 
00652   printf("GetTargets(%s with arc %s...)\n",
00653          (const char*)source_value,
00654          (const char*)property_arc);
00655 #endif
00656 
00657   if (source == kNC_AccountRoot)
00658     rv = createRootResources(property, nodes);
00659   else if (property == kNC_Settings)
00660     rv = createSettingsResources(source, nodes);
00661 
00662   if (NS_FAILED(rv))
00663     return NS_RDF_NO_VALUE;
00664 
00665   return NS_OK;
00666 }
00667 
00668 // end of all arcs coming out of msgaccounts:/
00669 nsresult
00670 nsMsgAccountManagerDataSource::createRootResources(nsIRDFResource *property,
00671                                                    nsISupportsArray* aNodeArray)
00672 {
00673   nsresult rv = NS_OK;
00674   if (isContainment(property)) {
00675 
00676     nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager);
00677     if (!am) return NS_ERROR_FAILURE;
00678 
00679     nsCOMPtr<nsISupportsArray> servers;
00680     rv = am->GetAllServers(getter_AddRefs(servers));
00681     if (NS_FAILED(rv)) return rv;
00682 
00683     // fill up the nodes array with the RDF Resources for the servers
00684     serverCreationParams params = { aNodeArray, getRDFService() };
00685     servers->EnumerateForwards(createServerResources, (void*)&params);
00686 #ifdef DEBUG_amds
00687     PRUint32 nodecount;
00688     aNodeArray->Count(&nodecount);
00689     printf("GetTargets(): added %d servers on %s\n", nodecount,
00690            (const char*)property_arc);
00691 #endif
00692     // for the "settings" arc, we also want to add SMTP setting and the fake account (if required)
00693     if (property == kNC_Settings) {
00694       aNodeArray->AppendElement(kNC_PageTitleSMTP);
00695       if (IsFakeAccountRequired())
00696         aNodeArray->AppendElement(kNC_PageTitleFakeAccount);
00697     }
00698     else if (property == kNC_Child && IsFakeAccountRequired()) {
00699       aNodeArray->AppendElement(kNC_PageTitleFakeAccount);
00700     }
00701   }
00702 
00703 #ifdef DEBUG_amds
00704   else {
00705     printf("unknown arc %s on msgaccounts:/\n", (const char*)property_arc);
00706   }
00707 #endif
00708 
00709   return rv;
00710 }
00711 
00712 nsresult
00713 nsMsgAccountManagerDataSource::appendGenericSettingsResources(nsIMsgIncomingServer *server, nsISupportsArray *aNodeArray)
00714 {
00715   nsresult rv;
00716 
00717   nsCOMPtr<nsICategoryManager> catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv);
00718   NS_ENSURE_SUCCESS(rv,rv);
00719 
00720   nsCOMPtr<nsISimpleEnumerator> e;
00721   rv = catman->EnumerateCategory(MAILNEWS_ACCOUNTMANAGER_EXTENSIONS, getter_AddRefs(e));
00722   if(NS_SUCCEEDED(rv) && e) {
00723     while (PR_TRUE) {
00724       nsCOMPtr<nsISupportsCString> catEntry;
00725       rv = e->GetNext(getter_AddRefs(catEntry));
00726       if (NS_FAILED(rv) || !catEntry)
00727         break;
00728 
00729       nsCAutoString entryString;
00730       rv = catEntry->GetData(entryString);
00731       if (NS_FAILED(rv))
00732         break;
00733 
00734       nsXPIDLCString contractidString;
00735       rv = catman->GetCategoryEntry(MAILNEWS_ACCOUNTMANAGER_EXTENSIONS, entryString.get(), getter_Copies(contractidString));
00736       if (NS_FAILED(rv))
00737         break;
00738 
00739       nsCOMPtr <nsIMsgAccountManagerExtension> extension =
00740         do_GetService(contractidString.get(), &rv);
00741       if (NS_FAILED(rv) || !extension)
00742         break;
00743 
00744       PRBool showPanel;
00745       rv = extension->ShowPanel(server, &showPanel);
00746       if (NS_FAILED(rv))
00747         break;
00748 
00749       if (showPanel) {
00750         nsXPIDLCString name;
00751         rv = extension->GetName(getter_Copies(name));
00752         if (NS_FAILED(rv))
00753           break;
00754 
00755         rv = appendGenericSetting(name.get(), aNodeArray);
00756         if (NS_FAILED(rv))
00757           break;
00758       }
00759     }
00760   }
00761   return NS_OK;
00762 }
00763 
00764 nsresult
00765 nsMsgAccountManagerDataSource::appendGenericSetting(const char *name,
00766                                                     nsISupportsArray *aNodeArray)
00767 {
00768   NS_ENSURE_ARG_POINTER(name);
00769   NS_ENSURE_ARG_POINTER(aNodeArray);
00770 
00771   nsCOMPtr <nsIRDFResource> resource;
00772 
00773   nsCAutoString resourceStr;
00774   resourceStr = NC_RDF_PAGETITLE_PREFIX;
00775   resourceStr += name;
00776 
00777   nsresult rv = getRDFService()->GetResource(resourceStr, getter_AddRefs(resource));
00778   NS_ENSURE_SUCCESS(rv,rv);
00779 
00780   // AppendElement will addref.
00781   aNodeArray->AppendElement(resource);
00782   return NS_OK;
00783 }
00784 
00785 // end of all #Settings arcs
00786 nsresult
00787 nsMsgAccountManagerDataSource::createSettingsResources(nsIRDFResource *aSource,
00788                                                        nsISupportsArray *aNodeArray)
00789 {
00790   // If this isn't a server, just return.
00791   if (aSource == kNC_PageTitleSMTP)
00792     return NS_OK;
00793 
00794   nsCOMPtr<nsIMsgIncomingServer> server;
00795   nsresult rv = getServerForFolderNode(aSource, getter_AddRefs(server));
00796   NS_ENSURE_SUCCESS(rv, rv);
00797   if (server) {
00798     PRBool hasIdentities;
00799     rv = serverHasIdentities(server, &hasIdentities);
00800 
00801     if (hasIdentities) {
00802       aNodeArray->AppendElement(kNC_PageTitleServer);
00803       aNodeArray->AppendElement(kNC_PageTitleCopies);
00804       aNodeArray->AppendElement(kNC_PageTitleAddressing);
00805     }
00806 
00807     // junk settings apply for all server types except for news
00808     nsXPIDLCString serverType;
00809     server->GetType(getter_Copies(serverType));
00810     if (!serverType.LowerCaseEqualsLiteral("nntp"))
00811       aNodeArray->AppendElement(kNC_PageTitleJunk);
00812 
00813     // Check the offline capability before adding
00814     // offline item
00815     PRInt32 offlineSupportLevel = 0;
00816     rv = server->GetOfflineSupportLevel(&offlineSupportLevel);
00817     NS_ENSURE_SUCCESS(rv,rv);
00818 
00819     PRBool supportsDiskSpace;
00820     rv = server->GetSupportsDiskSpace(&supportsDiskSpace);
00821     NS_ENSURE_SUCCESS(rv,rv);
00822 
00823     // currently there is no offline without diskspace
00824     if (offlineSupportLevel >= OFFLINE_SUPPORT_LEVEL_REGULAR) 
00825       aNodeArray->AppendElement(kNC_PageTitleOfflineAndDiskSpace);
00826     else if (supportsDiskSpace)
00827       aNodeArray->AppendElement(kNC_PageTitleDiskSpace);
00828 
00829     if (hasIdentities) {
00830       // extensions come after the default panels
00831       rv = appendGenericSettingsResources(server, aNodeArray);
00832       NS_ASSERTION(NS_SUCCEEDED(rv), "failed to add generic panels");
00833     }
00834   }
00835 
00836   return NS_OK;
00837 }
00838 
00839 nsresult
00840 nsMsgAccountManagerDataSource::serverHasIdentities(nsIMsgIncomingServer* aServer,
00841                                                    PRBool *aResult)
00842 {
00843   nsresult rv;
00844   *aResult = PR_FALSE;
00845 
00846   nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager, &rv);
00847 
00848   if (NS_FAILED(rv)) return rv;
00849 
00850   nsCOMPtr<nsISupportsArray> identities;
00851   rv = am->GetIdentitiesForServer(aServer, getter_AddRefs(identities));
00852 
00853   // no identities just means no arcs
00854   if (NS_FAILED(rv)) return NS_OK;
00855 
00856   PRUint32 count;
00857   rv = identities->Count(&count);
00858   if (NS_FAILED(rv)) return NS_OK;
00859 
00860   if (count >0)
00861     *aResult = PR_TRUE;
00862   return NS_OK;
00863 }
00864 
00865 // enumeration function to convert each server (element)
00866 // to an nsIRDFResource and append it to the array (in data)
00867 // always return PR_TRUE to try on every element instead of aborting early
00868 PRBool
00869 nsMsgAccountManagerDataSource::createServerResources(nsISupports *element,
00870                                                      void *data)
00871 {
00872   nsresult rv;
00873   // get parameters out of the data argument
00874   serverCreationParams *params = (serverCreationParams*)data;
00875   nsCOMPtr<nsISupportsArray> servers = params->serverArray;
00876   nsCOMPtr<nsIRDFService> rdf = params->rdfService;
00877 
00878   // the server itself is in the element argument
00879   nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(element, &rv);
00880   if (NS_FAILED(rv)) return PR_TRUE;
00881 
00882   nsCOMPtr <nsIMsgFolder> serverFolder;
00883   rv = server->GetRootFolder(getter_AddRefs(serverFolder));
00884   if(NS_FAILED(rv)) return PR_TRUE;
00885 
00886   // add the resource to the array
00887   nsCOMPtr<nsIRDFResource> serverResource = do_QueryInterface(serverFolder);
00888   if(serverResource)
00889     (void) servers->AppendElement(serverResource);
00890   return PR_TRUE;
00891 }
00892 
00893 nsresult
00894 nsMsgAccountManagerDataSource::getAccountArcs(nsISupportsArray **aResult)
00895 {
00896   nsresult rv;
00897   if (!mAccountArcsOut) {
00898 
00899     rv = NS_NewISupportsArray(getter_AddRefs(mAccountArcsOut));
00900     NS_ENSURE_SUCCESS(rv, rv);
00901 
00902     mAccountArcsOut->AppendElement(kNC_Settings);
00903     mAccountArcsOut->AppendElement(kNC_Name);
00904     mAccountArcsOut->AppendElement(kNC_FolderTreeName);
00905     mAccountArcsOut->AppendElement(kNC_FolderTreeSimpleName);
00906     mAccountArcsOut->AppendElement(kNC_NameSort);
00907     mAccountArcsOut->AppendElement(kNC_FolderTreeNameSort);
00908     mAccountArcsOut->AppendElement(kNC_PageTag);
00909   }
00910 
00911   *aResult = mAccountArcsOut;
00912   NS_IF_ADDREF(*aResult);
00913   return NS_OK;
00914 }
00915 
00916 nsresult
00917 nsMsgAccountManagerDataSource::getAccountRootArcs(nsISupportsArray **aResult)
00918 {
00919   nsresult rv;
00920   if (!mAccountRootArcsOut) {
00921 
00922     rv = NS_NewISupportsArray(getter_AddRefs(mAccountRootArcsOut));
00923     NS_ENSURE_SUCCESS(rv, rv);
00924 
00925     mAccountRootArcsOut->AppendElement(kNC_Server);
00926     mAccountRootArcsOut->AppendElement(kNC_Child);
00927 
00928     mAccountRootArcsOut->AppendElement(kNC_Settings);
00929     mAccountRootArcsOut->AppendElement(kNC_Name);
00930     mAccountRootArcsOut->AppendElement(kNC_FolderTreeName);
00931     mAccountRootArcsOut->AppendElement(kNC_FolderTreeSimpleName);
00932     mAccountRootArcsOut->AppendElement(kNC_NameSort);
00933     mAccountRootArcsOut->AppendElement(kNC_FolderTreeNameSort);
00934     mAccountRootArcsOut->AppendElement(kNC_PageTag);
00935   }
00936 
00937   *aResult = mAccountRootArcsOut;
00938   NS_IF_ADDREF(*aResult);
00939   return NS_OK;
00940 }
00941 
00942 NS_IMETHODIMP
00943 nsMsgAccountManagerDataSource::HasArcOut(nsIRDFResource *source, nsIRDFResource *aArc, PRBool *result)
00944 {
00945   nsresult rv = NS_OK;
00946   if (aArc == kNC_Settings) {
00947     // based on createSettingsResources()
00948     // we only have settings for local folders and servers with identities
00949     nsCOMPtr<nsIMsgIncomingServer> server;
00950     rv = getServerForFolderNode(source, getter_AddRefs(server));
00951     if (server) {
00952       // Check the offline capability before adding arc
00953       PRInt32 offlineSupportLevel = 0;
00954       (void) server->GetOfflineSupportLevel(&offlineSupportLevel);
00955       if (offlineSupportLevel >= OFFLINE_SUPPORT_LEVEL_REGULAR) {
00956         *result = PR_TRUE;
00957         return NS_OK;
00958       }
00959 
00960       PRBool supportsDiskSpace;
00961       (void) server->GetSupportsDiskSpace(&supportsDiskSpace);
00962       if (supportsDiskSpace) {
00963         *result = PR_TRUE;
00964         return NS_OK;
00965       }
00966       return serverHasIdentities(server, result);
00967     }
00968   }
00969 
00970   *result = PR_FALSE;
00971   return NS_OK;
00972 }
00973 
00974 /* nsISimpleEnumerator ArcLabelsOut (in nsIRDFResource aSource); */
00975 NS_IMETHODIMP
00976 nsMsgAccountManagerDataSource::ArcLabelsOut(nsIRDFResource *source,
00977                                             nsISimpleEnumerator **_retval)
00978 {
00979   nsresult rv;
00980 
00981   // we have to return something, so always create the array/enumerators
00982   nsCOMPtr<nsISupportsArray> arcs;
00983   if (source == kNC_AccountRoot)
00984     rv = getAccountRootArcs(getter_AddRefs(arcs));
00985   else
00986     rv = getAccountArcs(getter_AddRefs(arcs));
00987   NS_ENSURE_SUCCESS(rv, rv);
00988 
00989   rv = NS_NewArrayEnumerator(_retval, arcs);
00990   if (NS_FAILED(rv)) return rv;
00991 
00992 #ifdef DEBUG_amds_
00993   printf("GetArcLabelsOut(%s): Adding child, settings, and name arclabels\n", value);
00994 #endif
00995 
00996   return NS_OK;
00997 }
00998 
00999 NS_IMETHODIMP
01000 nsMsgAccountManagerDataSource::HasAssertion(nsIRDFResource *aSource,
01001                                             nsIRDFResource *aProperty,
01002                                             nsIRDFNode *aTarget,
01003                                             PRBool aTruthValue,
01004                                             PRBool *_retval)
01005 {
01006   nsresult rv=NS_ERROR_FAILURE;
01007 
01008   //
01009   // msgaccounts:/ properties
01010   //
01011   if (aSource == kNC_AccountRoot) {
01012     rv = HasAssertionAccountRoot(aProperty, aTarget, aTruthValue, _retval);
01013   }
01014   //
01015   // server properties
01016   //   try to convert the resource to a folder, and then only
01017   //   answer if it's a server.. any failure falls through to the default case
01018   //
01019   // short-circuit on property, so objects like filters, etc, don't get queried
01020   else if (aProperty == kNC_IsDefaultServer || aProperty == kNC_CanGetMessages ||
01021            aProperty == kNC_CanGetIncomingMessages || aProperty == kNC_SupportsFilters) {
01022     nsCOMPtr<nsIMsgIncomingServer> server;
01023     rv = getServerForFolderNode(aSource, getter_AddRefs(server));
01024     if (NS_SUCCEEDED(rv) && server)
01025       rv = HasAssertionServer(server, aProperty, aTarget,
01026                               aTruthValue, _retval);
01027   }
01028 
01029   // any failures above fallthrough to the parent class
01030   if (NS_FAILED(rv))
01031     return nsMsgRDFDataSource::HasAssertion(aSource, aProperty,
01032                                             aTarget, aTruthValue, _retval);
01033   return NS_OK;
01034 }
01035 
01036 
01037 
01038 nsresult
01039 nsMsgAccountManagerDataSource::HasAssertionServer(nsIMsgIncomingServer *aServer,
01040                                                   nsIRDFResource *aProperty,
01041                                                   nsIRDFNode *aTarget,
01042                                                   PRBool aTruthValue,
01043                                                   PRBool *_retval)
01044 {
01045   if (aProperty == kNC_IsDefaultServer)
01046     *_retval = (aTarget == kTrueLiteral) ? isDefaultServer(aServer) : !isDefaultServer(aServer);
01047   else if (aProperty == kNC_SupportsFilters)
01048     *_retval = (aTarget == kTrueLiteral) ? supportsFilters(aServer) : !supportsFilters(aServer);
01049   else if (aProperty == kNC_CanGetMessages)
01050    *_retval = (aTarget == kTrueLiteral) ? canGetMessages(aServer) : !canGetMessages(aServer);
01051   else if (aProperty == kNC_CanGetIncomingMessages)
01052     *_retval = (aTarget == kTrueLiteral) ? canGetIncomingMessages(aServer) : !canGetIncomingMessages(aServer);
01053   else
01054     *_retval = PR_FALSE;
01055   return NS_OK;
01056 }
01057 
01058 PRBool
01059 nsMsgAccountManagerDataSource::isDefaultServer(nsIMsgIncomingServer *aServer)
01060 {
01061   nsresult rv;
01062   if (!aServer) return PR_FALSE;
01063 
01064   nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager, &rv);
01065   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01066 
01067   nsCOMPtr<nsIMsgAccount> defaultAccount;
01068   rv = am->GetDefaultAccount(getter_AddRefs(defaultAccount));
01069   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01070   if (!defaultAccount) return PR_FALSE;
01071 
01072   // in some weird case that there is no default and they asked
01073   // for the default
01074   nsCOMPtr<nsIMsgIncomingServer> defaultServer;
01075   rv = defaultAccount->GetIncomingServer(getter_AddRefs(defaultServer));
01076   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01077   if (!defaultServer) return PR_FALSE;
01078 
01079   PRBool isEqual;
01080   rv = defaultServer->Equals(aServer, &isEqual);
01081   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01082 
01083   return isEqual;
01084 }
01085 
01086 
01087 PRBool
01088 nsMsgAccountManagerDataSource::supportsFilters(nsIMsgIncomingServer *aServer)
01089 {
01090   PRBool supportsFilters;
01091   nsresult rv = aServer->GetCanHaveFilters(&supportsFilters);
01092   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01093 
01094   return supportsFilters;
01095 }
01096 
01097 PRBool
01098 nsMsgAccountManagerDataSource::canGetMessages(nsIMsgIncomingServer *aServer)
01099 {
01100   nsXPIDLCString type;
01101   nsresult rv = aServer->GetType(getter_Copies(type));
01102   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01103 
01104   nsCAutoString contractid(NS_MSGPROTOCOLINFO_CONTRACTID_PREFIX);
01105   contractid.Append(type);
01106 
01107   nsCOMPtr<nsIMsgProtocolInfo> protocolInfo = do_GetService(contractid.get(), &rv);
01108   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01109 
01110   PRBool canGetMessages = PR_FALSE;
01111   protocolInfo->GetCanGetMessages(&canGetMessages);
01112 
01113   return canGetMessages;
01114 }
01115 
01116 PRBool
01117 nsMsgAccountManagerDataSource::canGetIncomingMessages(nsIMsgIncomingServer *aServer)
01118 {
01119   nsXPIDLCString type;
01120   nsresult rv = aServer->GetType(getter_Copies(type));
01121   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01122 
01123   nsCAutoString contractid(NS_MSGPROTOCOLINFO_CONTRACTID_PREFIX);
01124   contractid.Append(type);
01125 
01126   nsCOMPtr<nsIMsgProtocolInfo> protocolInfo = do_GetService(contractid.get(), &rv);
01127   NS_ENSURE_SUCCESS(rv, PR_FALSE);
01128 
01129   PRBool canGetIncomingMessages = PR_FALSE;
01130   protocolInfo->GetCanGetIncomingMessages(&canGetIncomingMessages);
01131 
01132   return canGetIncomingMessages;
01133 }
01134 
01135 nsresult
01136 nsMsgAccountManagerDataSource::HasAssertionAccountRoot(nsIRDFResource *aProperty,
01137                                                        nsIRDFNode *aTarget,
01138                                                        PRBool aTruthValue,
01139                                                        PRBool *_retval)
01140 {
01141 
01142   nsresult rv;
01143 
01144   // set up default
01145   *_retval = PR_FALSE;
01146 
01147   // for child and settings arcs, just make sure it's a valid server:
01148   if (isContainment(aProperty)) {
01149 
01150     nsCOMPtr<nsIMsgIncomingServer> server;
01151     rv = getServerForFolderNode(aTarget, getter_AddRefs(server));
01152     if (NS_FAILED(rv) || !server) return rv;
01153 
01154     nsXPIDLCString serverKey;
01155     server->GetKey(getter_Copies(serverKey));
01156 
01157     nsCOMPtr<nsIMsgAccountManager> am = do_QueryReferent(mAccountManager, &rv);
01158     if (NS_FAILED(rv)) return rv;
01159 
01160     nsCOMPtr<nsISupportsArray> serverArray;
01161     rv = am->GetAllServers(getter_AddRefs(serverArray));
01162     if (NS_FAILED(rv)) return rv;
01163 
01164     findServerByKeyEntry entry;
01165     entry.serverKey = serverKey;
01166     entry.found = PR_FALSE;
01167 
01168     serverArray->EnumerateForwards(findServerByKey, &entry);
01169     (*_retval) = entry.found;
01170 
01171   }
01172 
01173   return NS_OK;
01174 }
01175 
01176 PRBool
01177 nsMsgAccountManagerDataSource::isContainment(nsIRDFResource *aProperty)
01178 {
01179 
01180   if (aProperty == kNC_Child ||
01181       aProperty == kNC_Settings)
01182     return PR_TRUE;
01183   return PR_FALSE;
01184 }
01185 
01186 // returns failure if the object is not a root server
01187 nsresult
01188 nsMsgAccountManagerDataSource::getServerForFolderNode(nsIRDFNode *aResource,
01189                                                       nsIMsgIncomingServer **aResult)
01190 {
01191   nsresult rv;
01192   nsCOMPtr<nsIMsgFolder> folder = do_QueryInterface(aResource, &rv);
01193   if (NS_SUCCEEDED(rv)) 
01194   {
01195     PRBool isServer;
01196     rv = folder->GetIsServer(&isServer);
01197     if (NS_SUCCEEDED(rv) && isServer) 
01198       return folder->GetServer(aResult);
01199   }
01200   return NS_ERROR_FAILURE;
01201 }
01202 
01203 PRBool
01204 nsMsgAccountManagerDataSource::findServerByKey(nsISupports *aElement,
01205                                                void *aData)
01206 {
01207   nsresult rv;
01208   findServerByKeyEntry *entry = (findServerByKeyEntry*)aData;
01209 
01210   nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(aElement, &rv);
01211   if (NS_FAILED(rv)) return PR_TRUE;
01212 
01213   nsXPIDLCString key;
01214   server->GetKey(getter_Copies(key));
01215   if (nsCRT::strcmp(key, entry->serverKey)==0) 
01216   {
01217     entry->found = PR_TRUE;
01218     return PR_FALSE;        // stop when found
01219   }
01220 
01221   return PR_TRUE;
01222 }
01223 
01224 nsresult
01225 nsMsgAccountManagerDataSource::getStringBundle()
01226 {
01227   if (mStringBundle) return NS_OK;
01228 
01229   nsresult rv;
01230 
01231   nsCOMPtr<nsIStringBundleService> strBundleService =
01232       do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
01233   if (NS_FAILED(rv)) return rv;
01234 
01235   return strBundleService->CreateBundle("chrome://messenger/locale/prefs.properties",
01236                                       getter_AddRefs(mStringBundle));
01237 }
01238 
01239 NS_IMETHODIMP
01240 nsMsgAccountManagerDataSource::OnServerLoaded(nsIMsgIncomingServer* aServer)
01241 {
01242   nsCOMPtr<nsIMsgFolder> serverFolder;
01243   nsresult rv = aServer->GetRootFolder(getter_AddRefs(serverFolder));
01244   if (NS_FAILED(rv)) return rv;
01245 
01246   nsCOMPtr<nsIRDFResource> serverResource = do_QueryInterface(serverFolder,&rv);
01247   if (NS_FAILED(rv)) return rv;
01248 
01249 #ifdef DEBUG_alecf_
01250   nsXPIDLCString serverUri;
01251   serverResource->GetValue(getter_Copies(serverUri));
01252   printf("nsMsgAccountmanagerDataSource::OnServerLoaded(%s)\n", (const char*)serverUri);
01253 #endif
01254 
01255   NotifyObservers(kNC_AccountRoot, kNC_Child, serverResource, nsnull, PR_TRUE, PR_FALSE);
01256   NotifyObservers(kNC_AccountRoot, kNC_Settings, serverResource, nsnull, PR_TRUE, PR_FALSE);
01257 
01258   PRBool fakeAccountServer;
01259   IsIncomingServerForFakeAccount(aServer, &fakeAccountServer);
01260 
01261   if (fakeAccountServer) {
01262     NotifyObservers(kNC_AccountRoot, kNC_Child, kNC_PageTitleFakeAccount, nsnull, PR_FALSE, PR_FALSE);
01263     NotifyObservers(kNC_AccountRoot, kNC_Settings, kNC_PageTitleFakeAccount, nsnull, PR_FALSE, PR_FALSE);
01264   }
01265 
01266   return NS_OK;
01267 }
01268 
01269 NS_IMETHODIMP
01270 nsMsgAccountManagerDataSource::OnServerUnloaded(nsIMsgIncomingServer* aServer)
01271 {
01272   nsCOMPtr<nsIMsgFolder> serverFolder;
01273   nsresult rv = aServer->GetRootFolder(getter_AddRefs(serverFolder));
01274   if (NS_FAILED(rv)) return rv;
01275 
01276   nsCOMPtr<nsIRDFResource> serverResource = do_QueryInterface(serverFolder,&rv);
01277   if (NS_FAILED(rv)) return rv;
01278 
01279 
01280   NotifyObservers(kNC_AccountRoot, kNC_Child, serverResource, nsnull, PR_FALSE, PR_FALSE);
01281   NotifyObservers(kNC_AccountRoot, kNC_Settings, serverResource, nsnull, PR_FALSE, PR_FALSE);
01282 
01283   return NS_OK;
01284 }
01285 
01286 NS_IMETHODIMP
01287 nsMsgAccountManagerDataSource::OnServerChanged(nsIMsgIncomingServer *server)
01288 {
01289   return NS_OK;
01290 }
01291 
01292 nsresult
01293 nsMsgAccountManagerDataSource::OnItemPropertyChanged(nsIRDFResource *, nsIAtom *, char const *, char const *)
01294 {
01295   return NS_OK;
01296 }
01297 
01298 nsresult
01299 nsMsgAccountManagerDataSource::OnItemUnicharPropertyChanged(nsIRDFResource *, nsIAtom *, const PRUnichar *, const PRUnichar *)
01300 {
01301   return NS_OK;
01302 }
01303 
01304 nsresult
01305 nsMsgAccountManagerDataSource::OnItemRemoved(nsIRDFResource *, nsISupports *)
01306 {
01307   return NS_OK;
01308 }
01309 
01310 nsresult
01311 nsMsgAccountManagerDataSource::OnItemPropertyFlagChanged(nsIMsgDBHdr *, nsIAtom *, PRUint32, PRUint32)
01312 {
01313   return NS_OK;
01314 }
01315 
01316 nsresult
01317 nsMsgAccountManagerDataSource::OnItemAdded(nsIRDFResource *, nsISupports *)
01318 {
01319   return NS_OK;
01320 }
01321 
01322 
01323 nsresult
01324 nsMsgAccountManagerDataSource::OnItemBoolPropertyChanged(nsIRDFResource *aItem,
01325                                                          nsIAtom *aProperty,
01326                                                          PRBool aOldValue,
01327                                                          PRBool aNewValue)
01328 {
01329   if (aProperty == kDefaultServerAtom)
01330     NotifyObservers(aItem, kNC_IsDefaultServer, kTrueLiteral, nsnull, aNewValue, PR_FALSE);
01331   return NS_OK;
01332 }
01333 
01334 nsresult
01335 nsMsgAccountManagerDataSource::OnItemEvent(nsIMsgFolder *, nsIAtom *)
01336 {
01337   return NS_OK;
01338 }
01339 
01340 nsresult
01341 nsMsgAccountManagerDataSource::OnItemIntPropertyChanged(nsIRDFResource *, nsIAtom *, PRInt32, PRInt32)
01342 {
01343   return NS_OK;
01344 }
01345 
01346 PRBool
01347 nsMsgAccountManagerDataSource::IsFakeAccountRequired()
01348 {
01349   nsresult rv;
01350   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
01351 
01352   PRBool showFakeAccount = PR_FALSE;
01353   if (NS_SUCCEEDED(rv))
01354     rv = prefBranch->GetBoolPref(PREF_SHOW_FAKE_ACCOUNT, &showFakeAccount);
01355 
01356   if (!showFakeAccount)
01357     return PR_FALSE;
01358 
01359   nsXPIDLCString fakeHostName;
01360   rv = GetFakeAccountHostName(getter_Copies(fakeHostName));
01361   NS_ENSURE_SUCCESS(rv,rv);
01362 
01363   nsCOMPtr<nsIMsgAccountManager> accountManager = do_QueryReferent(mAccountManager);
01364   if (!accountManager)
01365     return NS_ERROR_FAILURE;
01366 
01367   nsCOMPtr<nsIMsgIncomingServer> server;
01368 
01369   if (!fakeHostName.IsEmpty()) {
01370     rv = accountManager->FindServer("",fakeHostName.get(),"", getter_AddRefs(server));
01371     if (NS_SUCCEEDED(rv) && server)
01372       return PR_FALSE;
01373   }
01374 
01375   return PR_TRUE;
01376 }
01377 
01378 nsresult
01379 nsMsgAccountManagerDataSource::IsIncomingServerForFakeAccount(nsIMsgIncomingServer* aServer, PRBool *aResult)
01380 {
01381   NS_ENSURE_ARG_POINTER(aServer);
01382   NS_ENSURE_ARG_POINTER(aResult);
01383 
01384   nsresult rv;
01385   nsXPIDLCString fakeAccountHostName;
01386   rv = GetFakeAccountHostName(getter_Copies(fakeAccountHostName));
01387   NS_ENSURE_SUCCESS(rv,rv);
01388 
01389   if (fakeAccountHostName.IsEmpty()) 
01390   {
01391     *aResult = PR_FALSE;
01392     return NS_OK;
01393   }
01394 
01395   nsXPIDLCString hostname;
01396   rv = aServer->GetHostName(getter_Copies(hostname));
01397   NS_ENSURE_SUCCESS(rv,rv);
01398 
01399   *aResult = (strcmp(hostname.get(), fakeAccountHostName.get()) == 0);
01400   return NS_OK;
01401 }
01402 
01403 
01404 nsresult
01405 nsMsgAccountManagerDataSource::GetFakeAccountHostName(char **aHostName)
01406 {
01407   NS_ENSURE_ARG_POINTER(aHostName);
01408   nsresult rv;
01409   nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
01410   if (NS_SUCCEEDED(rv))
01411     rv = prefBranch->GetCharPref("mailnews.fakeaccount.server", aHostName);
01412 
01413   return rv;
01414 }
01415 
01416 NS_IMETHODIMP
01417 nsMsgAccountManagerDataSource::Observe(nsISupports *aSubject, const char *aTopic, const PRUnichar *aData)
01418 {
01419   nsMsgRDFDataSource::Observe(aSubject, aTopic, aData);
01420 
01421   if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID)) {
01422     nsDependentString prefName(aData);
01423     if (prefName.EqualsLiteral(PREF_SHOW_FAKE_ACCOUNT)) {
01424       NotifyObservers(kNC_AccountRoot, kNC_Child, kNC_PageTitleFakeAccount, nsnull, PR_FALSE, PR_FALSE);
01425       NotifyObservers(kNC_AccountRoot, kNC_Settings, kNC_PageTitleFakeAccount, nsnull, PR_FALSE, PR_FALSE);
01426     }
01427   }
01428   else if (!strcmp(aTopic, NS_XPCOM_SHUTDOWN_OBSERVER_ID)) {
01429     nsCOMPtr<nsIPrefBranch2> prefBranchInternal = do_GetService(NS_PREFSERVICE_CONTRACTID);
01430     if (prefBranchInternal)
01431       prefBranchInternal->RemoveObserver(PREF_SHOW_FAKE_ACCOUNT, this);
01432   }
01433   return NS_OK;
01434 }
01435