diff --git a/mozilla/mailnews/base/prefs/resources/content/AccountManager.js b/mozilla/mailnews/base/prefs/resources/content/AccountManager.js index 20f52d218a8..d65c05c891b 100644 --- a/mozilla/mailnews/base/prefs/resources/content/AccountManager.js +++ b/mozilla/mailnews/base/prefs/resources/content/AccountManager.js @@ -42,6 +42,7 @@ var accountArray; +var gGenericAttributeTypes; var accounttree; var currentServerId; @@ -101,6 +102,8 @@ function onLoad() { } accountArray = new Array; + gGenericAttributeTypes = new Array; + RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager); @@ -453,16 +456,42 @@ function saveAccount(accountValues, account) } if (dest == undefined) continue; + if ((type in gGenericAttributeTypes) && (slot in gGenericAttributeTypes[type])) { + switch (gGenericAttributeTypes[type][slot]) { + case "int": + if (dest.getIntAttribute(slot) != typeArray[slot]) + dest.setIntAttribute(slot, typeArray[slot]); + break; + case "wstring": + if (dest.getUnicharAttribute(slot) != typeArray[slot]) + dest.setUnicharAttribute(slot, typeArray[slot]); + break; + case "string": + if (dest.getCharAttribute(slot) != typeArray[slot]) + dest.setCharAttribute(slot, typeArray[slot]); + break; + case "bool": + if (dest.getBoolAttribute(slot) != typeArray[slot]) + dest.setBoolAttribute(slot, typeArray[slot]); + break; + default: + dump("unexpected preftype: " + preftype + "\n"); + break; + } + } + else { if (dest[slot] != typeArray[slot]) { try { dest[slot] = typeArray[slot]; - } catch (ex) { + } + catch (ex) { // hrm... need to handle special types here } } } } } +} function updateButtons(tree,serverId) { @@ -662,7 +691,7 @@ function setAccountValue(accountValues, type, slot, value) { accountValues[type][slot] = value; } -function getAccountValue(account, accountValues, type, slot) { +function getAccountValue(account, accountValues, type, slot, preftype, isGeneric) { if (!accountValues[type]) accountValues[type] = new Array; @@ -699,9 +728,35 @@ function getAccountValue(account, accountValues, type, slot) { } if (source) { + if (isGeneric) { + if (!gGenericAttributeTypes[type]) + gGenericAttributeTypes[type] = new Array; + + // we need the preftype later, for setting when we save. + gGenericAttributeTypes[type][slot] = preftype; + switch (preftype) { + case "int": + accountValues[type][slot] = source.getIntAttribute(slot); + break; + case "wstring": + accountValues[type][slot] = source.getUnicharAttribute(slot); + break; + case "string": + accountValues[type][slot] = source.getCharAttribute(slot); + break; + case "bool": + accountValues[type][slot] = source.getBoolAttribute(slot); + break; + default: + dump("unexpected preftype: " + preftype + "\n"); + break; + } + } + else { accountValues[type][slot] = source[slot]; } } + } var value = accountValues[type][slot]; //dump("Array->Form: accountValues[" + type + "][" + slot + "] = " + value + "\n"); return value; @@ -730,7 +785,7 @@ function restorePage(pageId, serverId) { // buttons are lockable, but don't have any data so we skip that part. // elements that do have data, we get the values at poke them in. if (pageElements[i].localName != "button") { - var value = getAccountValue(account, accountValues, type, slot); + var value = getAccountValue(account, accountValues, type, slot, pageElements[i].getAttribute("preftype"), (pageElements[i].getAttribute("genericattr") == "true")); setFormElementValue(pageElements[i], value); } updateElementWithKeys(account,pageElements[i],type); diff --git a/mozilla/mailnews/base/prefs/resources/content/am-offline.js b/mozilla/mailnews/base/prefs/resources/content/am-offline.js index 5b11219b8c3..17a5866ef77 100644 --- a/mozilla/mailnews/base/prefs/resources/content/am-offline.js +++ b/mozilla/mailnews/base/prefs/resources/content/am-offline.js @@ -111,7 +111,7 @@ function initDownloadSettings() function onPreInit(account, accountValues) { - gServerType = getAccountValue(account, accountValues, "server", "type"); + gServerType = getAccountValue(account, accountValues, "server", "type", null, false); hideShowControls(gServerType); gIncomingServer= account.incomingServer; gIncomingServer.type = gServerType; diff --git a/mozilla/mailnews/base/prefs/resources/content/am-server.js b/mozilla/mailnews/base/prefs/resources/content/am-server.js index 7c1d3c0835b..5e77d798ac8 100644 --- a/mozilla/mailnews/base/prefs/resources/content/am-server.js +++ b/mozilla/mailnews/base/prefs/resources/content/am-server.js @@ -34,7 +34,7 @@ function onInit() function onPreInit(account, accountValues) { - var type = parent.getAccountValue(account, accountValues, "server", "type"); + var type = parent.getAccountValue(account, accountValues, "server", "type", null, false); hideShowControls(type); } diff --git a/mozilla/mailnews/base/public/nsIMsgAccountManager.idl b/mozilla/mailnews/base/public/nsIMsgAccountManager.idl index dc0ced28748..9c7a48ae83c 100644 --- a/mozilla/mailnews/base/public/nsIMsgAccountManager.idl +++ b/mozilla/mailnews/base/public/nsIMsgAccountManager.idl @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Seth Spitzer * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -185,3 +186,16 @@ interface nsIMsgAccountManager : nsISupports { void saveAccountInfo(); }; + +%{C++ +#define MAILNEWS_ACCOUNTMANAGER_EXTENSIONS "mailnews-accountmanager-extensions" +%} + + +[scriptable, uuid(9ce9fc76-1dd1-11b2-8da2-bf6b98b4c537)] +interface nsIMsgAccountManagerExtension : nsISupports +{ + readonly attribute string name; + boolean showPanel(in nsIMsgIncomingServer server); +}; + diff --git a/mozilla/mailnews/base/public/nsIMsgIdentity.idl b/mozilla/mailnews/base/public/nsIMsgIdentity.idl index ff35914c4db..f4293f6aa6b 100644 --- a/mozilla/mailnews/base/public/nsIMsgIdentity.idl +++ b/mozilla/mailnews/base/public/nsIMsgIdentity.idl @@ -131,5 +131,22 @@ interface nsIMsgIdentity : nsISupports { /* copy the attributes of the identity we pass in */ void copy(in nsIMsgIdentity identity); + /** + * these generic getter / setters, useful for extending mailnews + * note, these attributes persist across sessions + */ + wstring getUnicharAttribute(in string name); + void setUnicharAttribute(in string name, in wstring value); + + string getCharAttribute(in string name); + void setCharAttribute(in string name, in string value); + + boolean getBoolAttribute(in string name); + void setBoolAttribute(in string name, in boolean value); + + long getIntAttribute(in string name); + void setIntAttribute(in string name, in long value); + + /* useful for debugging */ wstring toString(); }; diff --git a/mozilla/mailnews/base/public/nsIMsgIncomingServer.idl b/mozilla/mailnews/base/public/nsIMsgIncomingServer.idl index 80eba5ca396..b70d3d035f7 100644 --- a/mozilla/mailnews/base/public/nsIMsgIncomingServer.idl +++ b/mozilla/mailnews/base/public/nsIMsgIncomingServer.idl @@ -297,6 +297,22 @@ interface nsIMsgIncomingServer : nsISupports { /* used for setting up the search UI */ readonly attribute nsMsgSearchScopeValue searchScope; + + /** + * these generic getter / setters, useful for extending mailnews + * note, these attributes persist across sessions + */ + wstring getUnicharAttribute(in string name); + void setUnicharAttribute(in string name, in wstring value); + + string getCharAttribute(in string name); + void setCharAttribute(in string name, in string value); + + boolean getBoolAttribute(in string name); + void setBoolAttribute(in string name, in boolean value); + + long getIntAttribute(in string name); + void setIntAttribute(in string name, in long value); }; %{C++ diff --git a/mozilla/mailnews/base/src/nsMsgAccountManagerDS.cpp b/mozilla/mailnews/base/src/nsMsgAccountManagerDS.cpp index 4379476bd70..1d3b74c0479 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManagerDS.cpp +++ b/mozilla/mailnews/base/src/nsMsgAccountManagerDS.cpp @@ -21,6 +21,7 @@ * * Contributor(s): * Alec Flett + * Seth Spitzer * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -56,23 +57,24 @@ #include "nsMsgBaseCID.h" #include "nsMsgIncomingServer.h" +#include "nsICategoryManager.h" +#include "nsISupportsPrimitives.h" + // turn this on to see useful output #undef DEBUG_amds -static NS_DEFINE_CID(kMsgMailSessionCID, NS_MSGMAILSESSION_CID); -static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID); -static NS_DEFINE_CID(kStringBundleServiceCID, NS_STRINGBUNDLESERVICE_CID); - -#define NC_RDF_PAGETITLE_MAIN NC_NAMESPACE_URI "PageTitleMain" -#define NC_RDF_PAGETITLE_SERVER NC_NAMESPACE_URI "PageTitleServer" -#define NC_RDF_PAGETITLE_COPIES NC_NAMESPACE_URI "PageTitleCopies" -#define NC_RDF_PAGETITLE_ADVANCED NC_NAMESPACE_URI "PageTitleAdvanced" -#define NC_RDF_PAGETITLE_OFFLINEANDDISKSPACE NC_NAMESPACE_URI "PageTitleOfflineAndDiskSpace" -#define NC_RDF_PAGETITLE_DISKSPACE NC_NAMESPACE_URI "PageTitleDiskSpace" -#define NC_RDF_PAGETITLE_ADDRESSING NC_NAMESPACE_URI "PageTitleAddressing" -#define NC_RDF_PAGETITLE_SMTP NC_NAMESPACE_URI "PageTitleSMTP" +#define NC_RDF_PAGETITLE_PREFIX NC_NAMESPACE_URI "PageTitle" +#define NC_RDF_PAGETITLE_MAIN NC_RDF_PAGETITLE_PREFIX "Main" +#define NC_RDF_PAGETITLE_SERVER NC_RDF_PAGETITLE_PREFIX "Server" +#define NC_RDF_PAGETITLE_COPIES NC_RDF_PAGETITLE_PREFIX "Copies" +#define NC_RDF_PAGETITLE_ADVANCED NC_RDF_PAGETITLE_PREFIX "Advanced" +#define NC_RDF_PAGETITLE_OFFLINEANDDISKSPACE NC_RDF_PAGETITLE_PREFIX "OfflineAndDiskSpace" +#define NC_RDF_PAGETITLE_DISKSPACE NC_RDF_PAGETITLE_PREFIX "DiskSpace" +#define NC_RDF_PAGETITLE_ADDRESSING NC_RDF_PAGETITLE_PREFIX "Addressing" +#define NC_RDF_PAGETITLE_SMTP NC_RDF_PAGETITLE_PREFIX "SMTP" #define NC_RDF_PAGETAG NC_NAMESPACE_URI "PageTag" + #define NC_RDF_ACCOUNTROOT "msgaccounts:/" typedef struct _serverCreationParams { @@ -319,15 +321,49 @@ nsMsgAccountManagerDataSource::GetTarget(nsIRDFResource *source, getter_Copies(pageTitle)); else { + // if it's a server, use the pretty name nsCOMPtr folder = do_QueryInterface(source, &rv); - if (NS_SUCCEEDED(rv)) { + if (NS_SUCCEEDED(rv) && folder) { PRBool isServer; rv = folder->GetIsServer(&isServer); if(NS_SUCCEEDED(rv) && isServer) rv = folder->GetPrettyName(getter_Copies(pageTitle)); } + else { + // allow for the accountmanager to be dynamically extended. + + nsCOMPtr strBundleService = + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + + const char *sourceValue; + rv = source->GetValueConst(&sourceValue); + NS_ENSURE_SUCCESS(rv,rv); + + // make sure the pointer math we're about to do is safe. + NS_ENSURE_TRUE(sourceValue && (nsCRT::strlen(sourceValue) > nsCRT::strlen(NC_RDF_PAGETITLE_PREFIX)), NS_ERROR_UNEXPECTED); + + nsCAutoString bundleURL; + bundleURL = "chrome://messenger/locale/"; + bundleURL += "am-"; + // turn NC#PageTitlefoobar into foobar, so we can get the am-foobar.properties bundle + bundleURL += (sourceValue + nsCRT::strlen(NC_RDF_PAGETITLE_PREFIX)); + bundleURL += ".properties"; + + nsCOMPtr bundle; + rv = strBundleService->CreateBundle(bundleURL.get(), + getter_AddRefs(bundle)); + + NS_ENSURE_SUCCESS(rv,rv); + + nsAutoString panelTitleName; + panelTitleName = NS_LITERAL_STRING("prefPanel-"); + panelTitleName.AppendWithConversion(sourceValue + nsCRT::strlen(NC_RDF_PAGETITLE_PREFIX)); + bundle->GetStringFromName(panelTitleName.get(), + getter_Copies(pageTitle)); } - str.Assign((const PRUnichar*)pageTitle); + } + str = pageTitle.get(); } else if (property == kNC_PageTag) { // do NOT localize these strings. these are the urls of the XUL files @@ -344,8 +380,8 @@ nsMsgAccountManagerDataSource::GetTarget(nsIRDFResource *source, else if (source == kNC_PageTitleSMTP) str = NS_LITERAL_STRING("am-smtp.xul"); else { - str = NS_LITERAL_STRING("am-main.xul"); - + nsCOMPtr folder = do_QueryInterface(source, &rv); + if (NS_SUCCEEDED(rv) && folder) { /* if this is a server, with no identities, then we show a special panel */ nsCOMPtr server; rv = getServerForFolderNode(source, getter_AddRefs(server)); @@ -355,6 +391,27 @@ nsMsgAccountManagerDataSource::GetTarget(nsIRDFResource *source, if (NS_SUCCEEDED(rv) && !hasIdentities) { str = NS_LITERAL_STRING("am-serverwithnoidentities.xul"); } + else { + str = NS_LITERAL_STRING("am-main.xul"); + } + } + else { + str = NS_LITERAL_STRING("am-main.xul"); + } + } + else { + // allow for the accountmanager to be dynamically extended + const char *sourceValue; + rv = source->GetValueConst(&sourceValue); + NS_ENSURE_SUCCESS(rv,rv); + + // make sure the pointer math we're about to do is safe. + NS_ENSURE_TRUE(sourceValue && (nsCRT::strlen(sourceValue) > nsCRT::strlen(NC_RDF_PAGETITLE_PREFIX)), NS_ERROR_UNEXPECTED); + + // turn NC#PageTitlefoobar into foobar, so we can get the am-foobar.xul file + str = NS_LITERAL_STRING("am-"); + str.AppendWithConversion((sourceValue + nsCRT::strlen(NC_RDF_PAGETITLE_PREFIX))); + str += NS_LITERAL_STRING(".xul"); } } } @@ -537,6 +594,77 @@ nsMsgAccountManagerDataSource::createRootResources(nsIRDFResource *property, return rv; } +nsresult +nsMsgAccountManagerDataSource::appendGenericSettingsResources(nsIMsgIncomingServer *server, nsISupportsArray *aNodeArray) +{ + nsresult rv; + + nsCOMPtr catman = do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv,rv); + + nsCOMPtr e; + rv = catman->EnumerateCategory(MAILNEWS_ACCOUNTMANAGER_EXTENSIONS, getter_AddRefs(e)); + if(NS_SUCCEEDED(rv) && e) { + while (PR_TRUE) { + nsCOMPtr catEntry; + rv = e->GetNext(getter_AddRefs(catEntry)); + if (NS_FAILED(rv) || !catEntry) + break; + + nsXPIDLCString entryString; + rv = catEntry->GetData(getter_Copies(entryString)); + if (NS_FAILED(rv)) + break; + + nsXPIDLCString contractidString; + rv = catman->GetCategoryEntry(MAILNEWS_ACCOUNTMANAGER_EXTENSIONS, entryString.get(), getter_Copies(contractidString)); + if (NS_FAILED(rv)) + break; + + nsCOMPtr extension = do_GetService(contractidString.get(), &rv); + if (NS_FAILED(rv) || !extension) + break; + + PRBool showPanel; + rv = extension->ShowPanel(server, &showPanel); + if (NS_FAILED(rv)) + break; + + if (showPanel) { + nsXPIDLCString name; + rv = extension->GetName(getter_Copies(name)); + if (NS_FAILED(rv)) + break; + + rv = appendGenericSetting(name.get(), aNodeArray); + if (NS_FAILED(rv)) + break; + } + } + } + return NS_OK; +} + +nsresult +nsMsgAccountManagerDataSource::appendGenericSetting(const char *name, nsISupportsArray *aNodeArray) +{ + NS_ENSURE_ARG_POINTER(name); + NS_ENSURE_ARG_POINTER(aNodeArray); + + nsCOMPtr resource; + + nsCAutoString resourceStr; + resourceStr = NC_RDF_PAGETITLE_PREFIX; + resourceStr += name; + + nsresult rv = getRDFService()->GetResource(resourceStr.get(), getter_AddRefs(resource)); + NS_ENSURE_SUCCESS(rv,rv); + + // AppendElement will addref. + aNodeArray->AppendElement(resource); + return NS_OK; +} + // end of all #Settings arcs nsresult nsMsgAccountManagerDataSource::createSettingsResources(nsIRDFResource *aSource, @@ -584,6 +712,10 @@ nsMsgAccountManagerDataSource::createSettingsResources(nsIRDFResource *aSource, else if (supportsDiskSpace) { aNodeArray->AppendElement(kNC_PageTitleDiskSpace); } + + // extensions come after the default panels + rv = appendGenericSettingsResources(server, aNodeArray); + NS_ASSERTION(NS_SUCCEEDED(rv), "failed to add generic panels"); } } } @@ -979,7 +1111,7 @@ nsMsgAccountManagerDataSource::getStringBundle() nsresult rv; nsCOMPtr strBundleService = - do_GetService(kStringBundleServiceCID, &rv); + do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); if (NS_FAILED(rv)) return rv; rv = strBundleService->CreateBundle("chrome://messenger/locale/prefs.properties", diff --git a/mozilla/mailnews/base/src/nsMsgAccountManagerDS.h b/mozilla/mailnews/base/src/nsMsgAccountManagerDS.h index 52ffbfef4e0..877bc362116 100644 --- a/mozilla/mailnews/base/src/nsMsgAccountManagerDS.h +++ b/mozilla/mailnews/base/src/nsMsgAccountManagerDS.h @@ -20,6 +20,7 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): + * Seth Spitzer * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -118,6 +119,8 @@ protected: nsISupportsArray* aNodeArray); nsresult createSettingsResources(nsIRDFResource *aSource, nsISupportsArray *aNodeArray); + nsresult appendGenericSettingsResources(nsIMsgIncomingServer *server, nsISupportsArray *aNodeArray); + nsresult appendGenericSetting(const char *name, nsISupportsArray *aNodeArray); static nsIRDFResource* kNC_Name; static nsIRDFResource* kNC_FolderTreeName; diff --git a/mozilla/mailnews/base/util/nsMsgIdentity.cpp b/mozilla/mailnews/base/util/nsMsgIdentity.cpp index 3cb12654271..338ea89ea79 100644 --- a/mozilla/mailnews/base/util/nsMsgIdentity.cpp +++ b/mozilla/mailnews/base/util/nsMsgIdentity.cpp @@ -19,8 +19,12 @@ * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * + * Original Author: + * Alec Flett + * * Contributor(s): * Pierre Phaneuf + * Seth Spitzer * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -520,6 +524,46 @@ nsMsgIdentity::setFolderPref(const char *prefname, const char *value) return rv; } +NS_IMETHODIMP nsMsgIdentity::SetUnicharAttribute(const char *aName, const PRUnichar *val) +{ + return setUnicharPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::GetUnicharAttribute(const char *aName, PRUnichar **val) +{ + return getUnicharPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::SetCharAttribute(const char *aName, const char *val) +{ + return setCharPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::GetCharAttribute(const char *aName, char **val) +{ + return getCharPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::SetBoolAttribute(const char *aName, PRBool val) +{ + return setBoolPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::GetBoolAttribute(const char *aName, PRBool *val) +{ + return getBoolPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::SetIntAttribute(const char *aName, PRInt32 val) +{ + return setIntPref(aName, val); +} + +NS_IMETHODIMP nsMsgIdentity::GetIntAttribute(const char *aName, PRInt32 *val) +{ + return getIntPref(aName, val); +} + #define COPY_IDENTITY_FILE_VALUE(SRC_ID,MACRO_GETTER,MACRO_SETTER) \ { \ nsresult macro_rv; \ diff --git a/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp b/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp index 40db52d9a09..8658a00e800 100644 --- a/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp +++ b/mozilla/mailnews/base/util/nsMsgIncomingServer.cpp @@ -1510,3 +1510,43 @@ NS_IMPL_SERVERPREF_BOOL(nsMsgIncomingServer, "limit_offline_message_size") NS_IMPL_SERVERPREF_INT(nsMsgIncomingServer, MaxMessageSize, "max_size") + +NS_IMETHODIMP nsMsgIncomingServer::SetUnicharAttribute(const char *aName, const PRUnichar *val) +{ + return SetUnicharValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::GetUnicharAttribute(const char *aName, PRUnichar **val) +{ + return GetUnicharValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::SetCharAttribute(const char *aName, const char *val) +{ + return SetCharValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::GetCharAttribute(const char *aName, char **val) +{ + return GetCharValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::SetBoolAttribute(const char *aName, PRBool val) +{ + return SetBoolValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::GetBoolAttribute(const char *aName, PRBool *val) +{ + return GetBoolValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::SetIntAttribute(const char *aName, PRInt32 val) +{ + return SetIntValue(aName, val); +} + +NS_IMETHODIMP nsMsgIncomingServer::GetIntAttribute(const char *aName, PRInt32 *val) +{ + return GetIntValue(aName, val); +}