diff options
author | Matt A. Tobin <email@mattatobin.com> | 2019-11-03 00:17:46 -0400 |
---|---|---|
committer | Matt A. Tobin <email@mattatobin.com> | 2019-11-03 00:17:46 -0400 |
commit | 302bf1b523012e11b60425d6eee1221ebc2724eb (patch) | |
tree | b191a895f8716efcbe42f454f37597a545a6f421 /mailnews/base/src/nsMsgAccount.cpp | |
parent | 21b3f6247403c06f85e1f45d219f87549862198f (diff) | |
download | uxp-302bf1b523012e11b60425d6eee1221ebc2724eb.tar.gz |
Issue #1258 - Part 1: Import mailnews, ldap, and mork from comm-esr52.9.1
Diffstat (limited to 'mailnews/base/src/nsMsgAccount.cpp')
-rw-r--r-- | mailnews/base/src/nsMsgAccount.cpp | 435 |
1 files changed, 435 insertions, 0 deletions
diff --git a/mailnews/base/src/nsMsgAccount.cpp b/mailnews/base/src/nsMsgAccount.cpp new file mode 100644 index 0000000000..9022176bf3 --- /dev/null +++ b/mailnews/base/src/nsMsgAccount.cpp @@ -0,0 +1,435 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + + +#include "prprf.h" +#include "plstr.h" +#include "prmem.h" +#include "nsIComponentManager.h" +#include "nsIServiceManager.h" +#include "nsCRTGlue.h" +#include "nsCOMPtr.h" +#include "nsIMsgFolderNotificationService.h" + +#include "nsIPrefService.h" +#include "nsIPrefBranch.h" +#include "nsMsgBaseCID.h" +#include "nsMsgAccount.h" +#include "nsIMsgAccount.h" +#include "nsIMsgAccountManager.h" +#include "nsServiceManagerUtils.h" +#include "nsMemory.h" +#include "nsComponentManagerUtils.h" +#include "nsMsgUtils.h" +#include "nsArrayUtils.h" + +NS_IMPL_ISUPPORTS(nsMsgAccount, nsIMsgAccount) + +nsMsgAccount::nsMsgAccount() + : mTriedToGetServer(false) +{ +} + +nsMsgAccount::~nsMsgAccount() +{ +} + +nsresult +nsMsgAccount::getPrefService() +{ + if (m_prefs) + return NS_OK; + + nsresult rv; + NS_ENSURE_FALSE(m_accountKey.IsEmpty(), NS_ERROR_NOT_INITIALIZED); + nsCOMPtr<nsIPrefService> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + + nsAutoCString accountRoot("mail.account."); + accountRoot.Append(m_accountKey); + accountRoot.Append('.'); + return prefs->GetBranch(accountRoot.get(), getter_AddRefs(m_prefs)); +} + +NS_IMETHODIMP +nsMsgAccount::GetIncomingServer(nsIMsgIncomingServer **aIncomingServer) +{ + NS_ENSURE_ARG_POINTER(aIncomingServer); + + // create the incoming server lazily + if (!mTriedToGetServer && !m_incomingServer) { + mTriedToGetServer = true; + // ignore the error (and return null), but it's still bad so warn + mozilla::DebugOnly<nsresult> rv = createIncomingServer(); + NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "couldn't lazily create the server\n"); + } + + NS_IF_ADDREF(*aIncomingServer = m_incomingServer); + + return NS_OK; +} + +NS_IMETHODIMP +nsMsgAccount::CreateServer() +{ + if (m_incomingServer) + return NS_ERROR_ALREADY_INITIALIZED; + return createIncomingServer(); +} + +nsresult +nsMsgAccount::createIncomingServer() +{ + // from here, load mail.account.myaccount.server + // Load the incoming server + // + // ex) mail.account.myaccount.server = "myserver" + + nsresult rv = getPrefService(); + NS_ENSURE_SUCCESS(rv, rv); + + // get the "server" pref + nsCString serverKey; + rv = m_prefs->GetCharPref("server", getter_Copies(serverKey)); + NS_ENSURE_SUCCESS(rv, rv); + + // get the server from the account manager + nsCOMPtr<nsIMsgAccountManager> accountManager = + do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCOMPtr<nsIMsgIncomingServer> server; + rv = accountManager->GetIncomingServer(serverKey, getter_AddRefs(server)); + NS_ENSURE_SUCCESS(rv, rv); + + // store the server in this structure + m_incomingServer = server; + accountManager->NotifyServerLoaded(server); + + return NS_OK; +} + + +NS_IMETHODIMP +nsMsgAccount::SetIncomingServer(nsIMsgIncomingServer *aIncomingServer) +{ + NS_ENSURE_ARG_POINTER(aIncomingServer); + + nsCString key; + nsresult rv = aIncomingServer->GetKey(key); + + if (NS_SUCCEEDED(rv)) { + rv = getPrefService(); + NS_ENSURE_SUCCESS(rv, rv); + m_prefs->SetCharPref("server", key.get()); + } + + m_incomingServer = aIncomingServer; + + bool serverValid; + (void) aIncomingServer->GetValid(&serverValid); + // only notify server loaded if server is valid so + // account manager only gets told about finished accounts. + if (serverValid) + { + // this is the point at which we can notify listeners about the + // creation of the root folder, which implies creation of the new server. + nsCOMPtr<nsIMsgFolder> rootFolder; + rv = aIncomingServer->GetRootFolder(getter_AddRefs(rootFolder)); + NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr<nsIFolderListener> mailSession = + do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + mailSession->OnItemAdded(nullptr, rootFolder); + nsCOMPtr<nsIMsgFolderNotificationService> notifier(do_GetService(NS_MSGNOTIFICATIONSERVICE_CONTRACTID, &rv)); + NS_ENSURE_SUCCESS(rv, rv); + notifier->NotifyFolderAdded(rootFolder); + + nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); + if (NS_SUCCEEDED(rv)) + accountManager->NotifyServerLoaded(aIncomingServer); + + // Force built-in folders to be created and discovered. Then, notify listeners + // about them. + nsCOMPtr<nsISimpleEnumerator> enumerator; + rv = rootFolder->GetSubFolders(getter_AddRefs(enumerator)); + NS_ENSURE_SUCCESS(rv, rv); + + bool hasMore; + while (NS_SUCCEEDED(enumerator->HasMoreElements(&hasMore)) && hasMore) + { + nsCOMPtr<nsISupports> item; + enumerator->GetNext(getter_AddRefs(item)); + + nsCOMPtr<nsIMsgFolder> msgFolder(do_QueryInterface(item)); + if (!msgFolder) + continue; + mailSession->OnItemAdded(rootFolder, msgFolder); + notifier->NotifyFolderAdded(msgFolder); + } + } + return NS_OK; +} + +NS_IMETHODIMP +nsMsgAccount::GetIdentities(nsIArray **_retval) +{ + NS_ENSURE_ARG_POINTER(_retval); + NS_ENSURE_TRUE(m_identities, NS_ERROR_FAILURE); + + NS_IF_ADDREF(*_retval = m_identities); + return NS_OK; +} + +/* + * set up the m_identities array + * do not call this more than once or we'll leak. + */ +nsresult +nsMsgAccount::createIdentities() +{ + NS_ENSURE_FALSE(m_identities, NS_ERROR_FAILURE); + + nsresult rv; + m_identities = do_CreateInstance(NS_ARRAY_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString identityKey; + rv = getPrefService(); + NS_ENSURE_SUCCESS(rv, rv); + + m_prefs->GetCharPref("identities", getter_Copies(identityKey)); + if (identityKey.IsEmpty()) // not an error if no identities, but + return NS_OK; // strtok will be unhappy + // get the server from the account manager + nsCOMPtr<nsIMsgAccountManager> accountManager = + do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv); + NS_ENSURE_SUCCESS(rv, rv); + + char* newStr = identityKey.BeginWriting(); + char* token = NS_strtok(",", &newStr); + + // temporaries used inside the loop + nsCOMPtr<nsIMsgIdentity> identity; + nsAutoCString key; + + // iterate through id1,id2, etc + while (token) { + key = token; + key.StripWhitespace(); + + // create the account + rv = accountManager->GetIdentity(key, getter_AddRefs(identity)); + if (NS_SUCCEEDED(rv)) { + // ignore error from addIdentityInternal() - if it fails, it fails. + rv = addIdentityInternal(identity); + NS_ASSERTION(NS_SUCCEEDED(rv), "Couldn't create identity"); + } + + // advance to next key, if any + token = NS_strtok(",", &newStr); + } + + return rv; +} + + +/* attribute nsIMsgIdentity defaultIdentity; */ +NS_IMETHODIMP +nsMsgAccount::GetDefaultIdentity(nsIMsgIdentity **aDefaultIdentity) +{ + NS_ENSURE_ARG_POINTER(aDefaultIdentity); + NS_ENSURE_TRUE(m_identities, NS_ERROR_NOT_INITIALIZED); + + *aDefaultIdentity = nullptr; + uint32_t count; + nsresult rv = m_identities->GetLength(&count); + NS_ENSURE_SUCCESS(rv, rv); + if (count == 0) + return NS_OK; + + nsCOMPtr<nsIMsgIdentity> identity = do_QueryElementAt(m_identities, 0, &rv); + identity.swap(*aDefaultIdentity); + return rv; +} + +NS_IMETHODIMP +nsMsgAccount::SetDefaultIdentity(nsIMsgIdentity *aDefaultIdentity) +{ + NS_ENSURE_TRUE(m_identities, NS_ERROR_FAILURE); + + uint32_t position = 0; + nsresult rv = m_identities->IndexOf(0, aDefaultIdentity, &position); + NS_ENSURE_SUCCESS(rv, rv); + + rv = m_identities->RemoveElementAt(position); + NS_ENSURE_SUCCESS(rv, rv); + + // The passed in identity is in the list, so we have at least one element. + rv = m_identities->InsertElementAt(aDefaultIdentity, 0, false); + NS_ENSURE_SUCCESS(rv, rv); + + return saveIdentitiesPref(); +} + +// add the identity to m_identities, but don't fiddle with the +// prefs. The assumption here is that the pref for this identity is +// already set. +nsresult +nsMsgAccount::addIdentityInternal(nsIMsgIdentity *identity) +{ + NS_ENSURE_TRUE(m_identities, NS_ERROR_FAILURE); + + return m_identities->AppendElement(identity, false); +} + +/* void addIdentity (in nsIMsgIdentity identity); */ +NS_IMETHODIMP +nsMsgAccount::AddIdentity(nsIMsgIdentity *identity) +{ + NS_ENSURE_ARG_POINTER(identity); + + // hack hack - need to add this to the list of identities. + // for now just treat this as a Setxxx accessor + // when this is actually implemented, don't refcount the default identity + nsCString key; + nsresult rv = identity->GetKey(key); + + if (NS_SUCCEEDED(rv)) { + nsCString identityList; + m_prefs->GetCharPref("identities", getter_Copies(identityList)); + + nsAutoCString newIdentityList(identityList); + + nsAutoCString testKey; // temporary to strip whitespace + bool foundIdentity = false; // if the input identity is found + + if (!identityList.IsEmpty()) { + char *newStr = identityList.BeginWriting(); + char *token = NS_strtok(",", &newStr); + + // look for the identity key that we're adding + while (token) { + testKey = token; + testKey.StripWhitespace(); + + if (testKey.Equals(key)) + foundIdentity = true; + + token = NS_strtok(",", &newStr); + } + } + + // if it didn't already exist, append it + if (!foundIdentity) { + if (newIdentityList.IsEmpty()) + newIdentityList = key; + else { + newIdentityList.Append(','); + newIdentityList.Append(key); + } + } + + m_prefs->SetCharPref("identities", newIdentityList.get()); + } + + // now add it to the in-memory list + return addIdentityInternal(identity); +} + +/* void removeIdentity (in nsIMsgIdentity identity); */ +NS_IMETHODIMP +nsMsgAccount::RemoveIdentity(nsIMsgIdentity *aIdentity) +{ + NS_ENSURE_ARG_POINTER(aIdentity); + NS_ENSURE_TRUE(m_identities, NS_ERROR_FAILURE); + + uint32_t count = 0; + m_identities->GetLength(&count); + // At least one identity must stay after the delete. + NS_ENSURE_TRUE(count > 1, NS_ERROR_FAILURE); + + uint32_t pos = 0; + nsresult rv = m_identities->IndexOf(0, aIdentity, &pos); + NS_ENSURE_SUCCESS(rv, rv); + + // remove our identity + m_identities->RemoveElementAt(pos); + + // clear out the actual pref values associated with the identity + aIdentity->ClearAllValues(); + + return saveIdentitiesPref(); +} + +nsresult +nsMsgAccount::saveIdentitiesPref() +{ + nsAutoCString newIdentityList; + + // Iterate over the existing identities and build the pref value, + // a string of identity keys: id1, id2, idX... + uint32_t count; + nsresult rv = m_identities->GetLength(&count); + NS_ENSURE_SUCCESS(rv, rv); + + nsCString key; + for (uint32_t index = 0; index < count; index++) + { + nsCOMPtr<nsIMsgIdentity> identity = do_QueryElementAt(m_identities, index, &rv); + if (identity) + { + identity->GetKey(key); + + if (!index) { + newIdentityList = key; + } + else + { + newIdentityList.Append(','); + newIdentityList.Append(key); + } + } + } + + // Save the pref. + m_prefs->SetCharPref("identities", newIdentityList.get()); + + return NS_OK; +} + +NS_IMETHODIMP nsMsgAccount::GetKey(nsACString& accountKey) +{ + accountKey = m_accountKey; + return NS_OK; +} + +NS_IMETHODIMP +nsMsgAccount::SetKey(const nsACString& accountKey) +{ + m_accountKey = accountKey; + m_prefs = nullptr; + m_identities = nullptr; + return createIdentities(); +} + +NS_IMETHODIMP +nsMsgAccount::ToString(nsAString& aResult) +{ + nsAutoString val; + aResult.AssignLiteral("[nsIMsgAccount: "); + aResult.Append(NS_ConvertASCIItoUTF16(m_accountKey)); + aResult.AppendLiteral("]"); + return NS_OK; +} + +NS_IMETHODIMP +nsMsgAccount::ClearAllValues() +{ + nsresult rv = getPrefService(); + NS_ENSURE_SUCCESS(rv, rv); + + return m_prefs->DeleteBranch(""); +} |