Bug 433316 Implement backend changes for MailNews transfer from wallet to login manager. r=Neil,sr=bienvenu
authorMark Banner <bugzilla@standard8.plus.com>
Thu, 15 Jan 2009 17:55:32 +0000
changeset 1645 30c7a484a3ae6529d00799d7d21ebe65c4fec2d1
parent 1644 c5c795d2335cb405e0f2c4b9490a2e7663923563
child 1646 12e714b4861c7494881fe9bafc8baaf04ce3166f
push idunknown
push userunknown
push dateunknown
reviewersNeil, bienvenu
bugs433316
Bug 433316 Implement backend changes for MailNews transfer from wallet to login manager. r=Neil,sr=bienvenu
directory/xpcom/base/src/nsLDAPProtocolHandler.js
mail/base/content/msgMail3PaneWindow.js
mail/confvars.sh
mail/installer/removed-files.in
mail/installer/windows/packages-static
mail/locales/en-US/chrome/communicator/wallet/SignonViewer.dtd
mail/locales/en-US/chrome/communicator/wallet/SignonViewer.properties
mail/locales/en-US/chrome/communicator/wallet/wallet.properties
mail/locales/en-US/chrome/messenger/news.properties
mail/locales/jar.mn
mailnews/addrbook/src/nsAbLDAPListenerBase.cpp
mailnews/addrbook/test/unit/test_ldap1.js
mailnews/base/public/nsIMsgIncomingServer.idl
mailnews/base/util/Makefile.in
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/base/util/nsMsgDBFolder.h
mailnews/base/util/nsMsgIncomingServer.cpp
mailnews/base/util/nsMsgIncomingServer.h
mailnews/base/util/nsMsgProtocol.cpp
mailnews/base/util/nsMsgUtils.cpp
mailnews/base/util/nsMsgUtils.h
mailnews/compose/src/Makefile.in
mailnews/compose/src/nsSmtpServer.cpp
mailnews/compose/test/unit/test_smtpPassword2.js
mailnews/imap/src/nsImapIncomingServer.cpp
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/imap/src/nsImapProtocol.cpp
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsPop3Sink.cpp
mailnews/local/test/unit/test_pop3Password3.js
mailnews/news/src/Makefile.in
mailnews/news/src/nsNNTPProtocol.cpp
mailnews/news/src/nsNewsFolder.cpp
mailnews/news/test/unit/test_nntpPassword3.js
mailnews/test/data/signons-mailnews1.8-multiple.txt
suite/confvars.sh
suite/installer/removed-files.in
suite/installer/unix/packages
suite/installer/windows/packages
suite/locales/en-US/chrome/mailnews/news.properties
--- a/directory/xpcom/base/src/nsLDAPProtocolHandler.js
+++ b/directory/xpcom/base/src/nsLDAPProtocolHandler.js
@@ -53,23 +53,18 @@ function makeProtocolHandler(aProtocol, 
                    nsIProtocolHandler.URI_DANGEROUS_TO_LOAD |
                    nsIProtocolHandler.ALLOWS_PROXY,
 
     newURI: function (aSpec, aOriginCharset, aBaseURI) {
       var url = Components.classes["@mozilla.org/network/ldap-url;1"]
                           .createInstance(Components.interfaces.nsIURI);
 
       if (url instanceof Components.interfaces.nsILDAPURL)
-#ifdef USE_TK_LOGIN_MANAGER
 	url.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD,
 		 aDefaultPort, aSpec, aOriginCharset, aBaseURI);
-#else
-	url.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD,
-		 -1, aSpec, aOriginCharset, aBaseURI);
-#endif
 
       return url;
     },
 
     newChannel: function (aURI) {
       if ("@mozilla.org/network/ldap-channel;1" in Components.classes) {
         var channel = Components.classes["@mozilla.org/network/ldap-channel;1"]
                                 .createInstance(Components.interfaces.nsIChannel);
--- a/mail/base/content/msgMail3PaneWindow.js
+++ b/mail/base/content/msgMail3PaneWindow.js
@@ -942,35 +942,30 @@ function loadStartFolder(initialUri)
             }
         }
 
         // it is possible we were given an initial uri and we need to subscribe or try to add
         // the folder. i.e. the user just clicked on a news folder they aren't subscribed to from a browser
         // the news url comes in here.
 
         if (isLoginAtStartUpEnabled && masterPasswordSet()) {
-          let passwordMgr = Components.classes["@mozilla.org/passwordmanager;1"]
-                              .getService(Components.interfaces.nsIPasswordManagerInternal);
-          if (passwordMgr)
+          let loginMgr = Components.classes["@mozilla.org/login-manager;1"]
+                              .getService(Components.interfaces.nsILoginManager);
+          if (loginMgr)
           {
-            let hostFound = new Object;
-            let userNameFound = new Object;
-            let passwordFound = new Object;
-
             // Get password entry corresponding to the default server.
             // This will block the UI until the use enters something.
             // This throws an exception if the user cancels. For now, I'm
             // just letting everything proceed as before, but conceivably,
             // we could loop waiting for the user to enter the right password,
             // and exit the app if they don't. But this assumes the
             // default server password is stored.
             try {
-                passwordMgr.findPasswordEntry(defaultServer.serverURI, "", "",
-                                           hostFound, userNameFound, 
-                                           passwordFound);
+                loginMgr.findLogins({}, defaultServer.serverURI, null,
+                                    defaultServer.serverURI, {});
             } catch(ex) {};
           }
         }
         // Perform biff on the server to check for new mail, except for imap
         // or a pop3 account that is deferred or deferred to,
         // or the case where initialUri is non-null (non-startup)
         if (!initialUri && isLoginAtStartUpEnabled && gLoadStartFolder
             && !defaultServer.isDeferredTo &&
--- a/mail/confvars.sh
+++ b/mail/confvars.sh
@@ -57,10 +57,9 @@ MOZ_SAFE_BROWSING=1
 # Can be dropped when we branch MOZILLA_1_9_1_BRANCH
 MOZILLA_BRANCH_VERSION=`echo ${MOZILLA_VERSION} | sed -e 's/\(^[0-9]\.[0-9]\.[0-9]\).*/\1/;'`
 if test "$MOZILLA_BRANCH_VERSION" = "1.9.1"; then
   MOZ_APP_VERSION=`cat $topsrcdir/$MOZ_BUILD_APP/config/version-191.txt`
 else
   MOZ_APP_VERSION=`cat $topsrcdir/$MOZ_BUILD_APP/config/version.txt`
 fi
 THUNDERBIRD_VERSION=$MOZ_APP_VERSION
-MOZ_EXTENSIONS_DEFAULT=" wallet"
 MOZ_NO_XPCOM_OBSOLETE=1
--- a/mail/installer/removed-files.in
+++ b/mail/installer/removed-files.in
@@ -31,17 +31,18 @@ components/pipboot.dll
 components/pipnss.dll
 components/pippki.dll
 components/profile.dll
 components/profilemigration.dll
 components/rdf.dll
 components/spellchk.dll
 components/txmgr.dll
 components/uconv.dll
-components/wallet.dll
+components/@DLL_PREFIX@wallet@DLL_SUFFIX@
+components/@DLL_PREFIX@walletviewers@DLL_SUFFIX@
 components/webbrwsr.dll
 components/wlltvwrs.dll
 components/xmlextras.dll
 components/xpc3250.dll
 components/xppref32.dll
 nsldap32v50.dll
 nsldappr32v50.dll
 #ifdef XP_WIN
@@ -135,16 +136,18 @@ components/rdf.xpt
 components/signonviewer.xpt
 components/spellchecker.xpt
 components/txmgr.xpt
 components/txtsvc.xpt
 components/uconv.xpt
 components/unicharutil.xpt
 components/uriloader.xpt
 components/wallet.xpt
+components/walleteditor.xpt
+components/walletpreview.xpt
 components/webbrowserpersist.xpt
 components/webBrowser_core.xpt
 components/webshell_idls.xpt
 components/widget.xpt
 components/windowds.xpt
 components/windowwatcher.xpt
 components/winhooks.xpt
 components/xmlextras.xpt
@@ -199,16 +202,23 @@ defaults/messenger/SpamPal.sfd
 defaults/isp/rss.rdf
 defaults/isp/movemail.rdf
 defaults/isp/dotmac.rdf
 defaults/isp/en-US/rss.rdf
 defaults/isp/en-US/movemail.rdf
 defaults/isp/en-US/dotmac.rdf
 defaults/isp/en-US/
 defaults/isp/
+defaults/wallet/VcardSchema.tbl
+defaults/wallet/FieldSchema.tbl
+defaults/wallet/SchemaConcat.tbl
+defaults/wallet/DistinguishedSchema.tbl
+defaults/wallet/SchemaStrings.tbl
+defaults/wallet/PositionalSchema.tbl
+defaults/wallet/StateSchema.tbl
 isp/gmail.rdf
 
 components/@DLL_PREFIX@xpcom_compat_c@DLL_SUFFIX@
 @DLL_PREFIX@xpcom_compat@DLL_SUFFIX@
 @DLL_PREFIX@zlib@DLL_SUFFIX@
 @DLL_PREFIX@xpistub@DLL_SUFFIX@
 #Remove Talkback files from old location (in case user updates from 1.0.x)
 components/BrandRes.dll
--- a/mail/installer/windows/packages-static
+++ b/mail/installer/windows/packages-static
@@ -143,19 +143,23 @@ bin\greprefs\*
 ; LDAP components
 bin\components\mozldap.xpt
 bin\components\nsAbLDAPAttributeMap.js
 bin\components\nsLDAPProtocolHandler.js
 bin\nsldap32v60.dll
 bin\nsldappr32v60.dll
 bin\nsldif32v60.dll
 
-; wallet
-bin\components\wallet.xpt
-bin\components\signonviewer.xpt
+; login manager
+bin\components\loginmgr.xpt
+bin\components\nsLoginInfo.js
+bin\components\nsLoginManager.js
+bin\components\nsLoginManagerPrompter.js
+bin\components\storage-Legacy.js
+bin\components\storage-mozStorage.js
 
 ; download progress
 bin\components\nsHelperAppDlg.js
 bin\components\nsDownloadManagerUI.js
 bin\components\nsProgressDialog.js
 bin\components\downloads.xpt
 
 ; Protocol/Content handling
deleted file mode 100644
--- a/mail/locales/en-US/chrome/communicator/wallet/SignonViewer.dtd
+++ /dev/null
@@ -1,17 +0,0 @@
-<!ENTITY      windowtitle.label               "Password Manager">
-<!ENTITY      windowalttitle.label            "Form Manager: Sites">
-<!ENTITY      tab.signonsstored.label         "Passwords Saved">
-<!ENTITY      tab.signonsnotstored.label      "Passwords Never Saved">
-<!ENTITY      tab.nopreview.label             "Forms Never Previewed">
-<!ENTITY      tab.nocapture.label             "Forms Never Saved">
-
-<!ENTITY      spiel.signonsstored.label       "Password Manager has saved login information for the following sites:">
-<!ENTITY      spiel.signonsnotstored.label    "Password Manager will never save login information for the following sites:">
-<!ENTITY      spiel.nopreview.label           "Form Manager will never preview forms from the following sites before pre-filling them for you:">
-<!ENTITY      spiel.nocapture.label           "Form Manager will never ask to save forms from the following sites:">
-
-<!ENTITY      treehead.site.label             "Site">
-<!ENTITY      treehead.username.label         "Username">
-<!ENTITY      treehead.password.label         "Password">
-<!ENTITY      remove.label                    "Remove">
-<!ENTITY      removeall.label                 "Remove All">
deleted file mode 100644
--- a/mail/locales/en-US/chrome/communicator/wallet/SignonViewer.properties
+++ /dev/null
@@ -1,10 +0,0 @@
-encrypted = %S (encrypted)
-close=Close
-hidePasswords=Hide Passwords
-showPasswords=Show Passwords
-noMasterPasswordPrompt=Are you sure you wish to show your passwords?
-removeAllPasswordsPrompt=Are you sure you wish to remove all passwords?
-removeAllPasswordsTitle=Remove all passwords
-
-# Default user name in the view passwords dialog
-noUserNameForPassword=<not specified>
deleted file mode 100644
--- a/mail/locales/en-US/chrome/communicator/wallet/wallet.properties
+++ /dev/null
@@ -1,83 +0,0 @@
-# ***** BEGIN LICENSE BLOCK *****
-# Version: MPL 1.1/GPL 2.0/LGPL 2.1
-#
-# The contents of this file are subject to the Mozilla Public License Version
-# 1.1 (the "License"); you may not use this file except in compliance with
-# the License. You may obtain a copy of the License at
-# http://www.mozilla.org/MPL/
-#
-# Software distributed under the License is distributed on an "AS IS" basis,
-# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
-# for the specific language governing rights and limitations under the
-# License.
-#
-# The Original Code is mozilla.org code.
-#
-# The Initial Developer of the Original Code is
-# Netscape Communications Corporation.
-# Portions created by the Initial Developer are Copyright (C) 1998
-# the Initial Developer. All Rights Reserved.
-#
-# Contributor(s):
-#
-# 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
-# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
-# in which case the provisions of the GPL or the LGPL are applicable instead
-# of those above. If you wish to allow use of your version of this file only
-# under the terms of either the GPL or the LGPL, and not to allow others to
-# use your version of this file under the terms of the MPL, indicate your
-# decision by deleting the provisions above and replace them with the notice
-# and other provisions required by the GPL or the LGPL. If you do not delete
-# the provisions above, a recipient may use your version of this file under
-# the terms of any one of the MPL, the GPL or the LGPL.
-#
-# ***** END LICENSE BLOCK *****
-IncorrectKey_TryAgain? = Master password incorrect. Do you want to try again?
-WantToCaptureForm? = Do you want to remember the values you filled in?
-WantToSavePasswordObscured? = Password Manager can remember this logon and enter it automatically the next time you return to this website.##Do you want Password Manager to remember this logon?
-WantToSavePasswordEncrypted? = Password Manager can remember this logon and enter it automatically the next time you return to this website.##Do you want Password Manager to remember this logon?
-xWantToSavePasswordObscured? = Do you want to remember your user name and password?##Stored values are not password protected.
-xWantToSavePasswordEncrypted? = Do you want to remember your user name and password?##Stored values are password protected.
-#translator's note: # in following line will be converted to linefeed by program
-firstPassword = A master password will be used to protect sensitive single-signon information stored on your hard drive.  Future releases will strongly encrypt this data for maximum protection.##Select a master password.#(Leave fields blank if you don't want to use a master password).#
-password = Enter your master password.
-#translator's note: # in following line will be converted to linefeed by program
-newPassword = Select a new master password.#(Leave fields blank if you don't want to use a master password).#
-enterPassword = Enter a master password
-confirmPassword = Retype the master password
-confirmFailed_TryAgain? = The two master passwords were not identical.  Please enter the same master password in both fields.
-SelectUser = Select a username to be entered on this form.
-SelectUserWhosePasswordIsBeingChanged = Select the user whose password is being changed.
-PasswordNotification = For your convenience, the browser can remember your user names and passwords so you won't have to re-type them in the future.  Your passwords will be obscured before being saved on your hard drive.  Do you want this feature enabled?
-WalletNotification = You can save information that you enter on forms and later automatically prefill that information on other forms.  To save such information, select Edit/Save Form Info from the menu while viewing the form.
-noPrefills = There are no fields that can be prefilled.
-Never = Never for this site
-Confirm = Confirm
-PromptForPassword = Password
-PromptForData = Prompt
-SaveTheseValuesObscured = Use Password Manager to remember these values.
-SaveTheseValuesEncrypted = Use Password Manager to remember these values.
-SaveThisValueObscured = Use Password Manager to remember this value.
-SaveThisValueEncrypted = Use Password Manager to remember this value.
-SaveThisPasswordObscured= Use Password Manager to remember this password.
-SaveThisPasswordEncrypted = Use Password Manager to remember this password.
-xSaveTheseValuesObscured = Remember these values.  Stored values are not password protected.
-xSaveTheseValuesEncrypted = Remember these values.  Stored values are password protected.
-xSaveThisValueObscured = Remember this value.  Stored values are not password protected.
-xSaveThisValueEncrypted = Remember this value.  Stored values are password protected.
-UserName = User Name
-Password = Password
-SelectUserTitleLine = Select User
-NoPasswordsEverSaved = No passwords have ever been saved.
-Captured = Data has been captured.
-NotCaptured = There is nothing to capture.
-UnableToCapture = Unable to capture data.
-Converted = Stored data has been converted.
-AllDataWillBeCleared = All stored data will be erased.
-NotConverted = Unable to convert stored data.
-PasswordNotChanged = Unable to change the password that protects your sensitive information.
-PasswordExpired = Your sensitive information is now locked.
-PasswordNotExpired = Unable to lock your sensitive information.
-Caveat = Saving Passwords and Other Sensitive Information##Password Manager and Form Manager will save passwords, user names, and other sensitive information and enter them for you automatically when they are required.#This sensitive information is stored on your computer in a file that's difficult, but not impossible, to read.#If other people have access to your computer, you may want to password protect the stored sensitive information by choosing a Master Password.#If you choose to password protect your stored information, you will be asked to provide your Master Password from time to time.  This approach provides better security but is slightly less convenient.
-CaveatTitle = Alert
--- a/mail/locales/en-US/chrome/messenger/news.properties
+++ b/mail/locales/en-US/chrome/messenger/news.properties
@@ -42,16 +42,18 @@ htmlNewsErrorTitle=Error!
 htmlNewsError=<H1>Error!</H1>newsgroup server responded: 
 # LOCALIZATION NOTE ( articleExpired ): In the following item, translate only "Perhaps the article has expired"
 articleExpired=<B><P>Perhaps the article has expired</P></B>
 removeExpiredArtLinkText=Click here to remove all expired articles
 cancelDisallowed=This message does not appear to be from you.  You may only cancel your own posts, not those made by others.
 cancelConfirm=Are you sure you want to cancel this message?
 messageCancelled=Message cancelled.
 enterUsername=Please enter a username for news server access:
+enterUsernameTitle=News Server Username Required
+saveUsername=Use Password Manager to remember this value.
 enterPassword=Please enter a password for news server access:
 enterPasswordTitle=News Server Password Required
 okButtonText=Download
 
 noNewMessages=There are no new messages on the server.
 downloadingHeaders=Downloading %S of %S headers
 downloadingFilterHeaders=Getting headers for filters: %S (%S/%S)
 downloadingArticles=Downloading articles %S-%S
--- a/mail/locales/jar.mn
+++ b/mail/locales/jar.mn
@@ -148,11 +148,8 @@
   locale/@AB_CD@/messenger-smime/certFetchingStatus.dtd                 (%chrome/messenger-smime/certFetchingStatus.dtd)
   locale/@AB_CD@/messenger-smime/msgSecurityInfo.properties             (%chrome/messenger-smime/msgSecurityInfo.properties)
 % locale messenger-region @AB_CD@ %locale/@AB_CD@/messenger-region/
   locale/@AB_CD@/messenger-region/region.properties                     (%chrome/messenger-region/region.properties)
 % locale mozldap @AB_CD@ %locale/@AB_CD@/mozldap/
   locale/@AB_CD@/mozldap/ldap.properties                                (%chrome/mozldap/ldap.properties)
 % locale communicator @AB_CD@ %locale/@AB_CD@/communicator/
   locale/@AB_CD@/communicator/utilityOverlay.dtd             (%chrome/communicator/utilityOverlay.dtd)
-  locale/@AB_CD@/communicator/wallet/wallet.properties       (%chrome/communicator/wallet/wallet.properties)
-+ locale/@AB_CD@/communicator/wallet/SignonViewer.properties (%chrome/communicator/wallet/SignonViewer.properties)
-+ locale/@AB_CD@/communicator/wallet/SignonViewer.dtd        (%chrome/communicator/wallet/SignonViewer.dtd)
--- a/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp
+++ b/mailnews/addrbook/src/nsAbLDAPListenerBase.cpp
@@ -41,23 +41,18 @@
 #include "nsAbLDAPListenerBase.h"
 #include "nsIWindowWatcher.h"
 #include "nsIDOMWindow.h"
 #include "nsIAuthPrompt.h"
 #include "nsIStringBundle.h"
 #include "nsIProxyObjectManager.h"
 #include "nsILDAPMessage.h"
 #include "nsILDAPErrors.h"
-#ifdef USE_TK_LOGIN_MANAGER
 #include "nsILoginManager.h"
 #include "nsILoginInfo.h"
-#else
-#include "nsCategoryManagerUtils.h"
-#include "nsComponentManagerUtils.h"
-#endif
 #include "nsServiceManagerUtils.h"
 #include "nsXPCOMCIDInternal.h"
 
 nsAbLDAPListenerBase::nsAbLDAPListenerBase(nsILDAPURL* url,
                                            nsILDAPConnection* connection,
                                            const nsACString &login,
                                            const PRInt32 timeOut) :
   mDirectoryUrl(url), mConnection(connection), mLogin(login),
@@ -323,17 +318,16 @@ nsresult nsAbLDAPListenerBase::OnLDAPMes
 
   if (errCode != nsILDAPErrors::SUCCESS)
   {
     // if the login failed, tell the wallet to forget this password
     //
     if (errCode == nsILDAPErrors::INAPPROPRIATE_AUTH ||
         errCode == nsILDAPErrors::INVALID_CREDENTIALS)
     {
-#ifdef USE_TK_LOGIN_MANAGER
       // Login failed, so try again - but first remove the existing login(s)
       // so that the user gets prompted. This may not be the best way of doing
       // things, we need to review that later.
 
       nsCOMPtr<nsILoginManager> loginMgr =
         do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
 
@@ -360,39 +354,16 @@ nsresult nsAbLDAPListenerBase::OnLDAPMes
         rv = loginMgr->RemoveLogin(logins[i]);
         if (NS_FAILED(rv))
         {
           NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
           return rv;
         }
       }
       NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
-#else
-      // make sure the wallet service has been created, and in doing so,
-      // pass in a login-failed message to tell it to forget this passwd.
-      //
-      // apparently getting passwords stored in the wallet
-      // doesn't require the service to be running, which is why
-      // this might not exist yet.
-      //
-      rv = NS_CreateServicesFromCategory("passwordmanager",
-                                         mDirectoryUrl,
-                                         "login-failed");
-      if (NS_FAILED(rv))
-      {
-        NS_ERROR("nsLDAPAutoCompleteSession::ForgetPassword(): error"
-                 " creating password manager service");
-        // not much to do at this point, though conceivably we could 
-        // pop up a dialog telling the user to go manually delete
-        // this password in the password manager.
-        return rv;
-      }
-
-      // Login failed, so try again
-#endif
 
       // XXX We should probably pop up an error dialog telling
       // the user that the login failed here, rather than just bringing 
       // up the password dialog again, which is what calling OnLDAPInit()
       // does.
       return OnLDAPInit(nsnull, NS_OK);
     }
 
--- a/mailnews/addrbook/test/unit/test_ldap1.js
+++ b/mailnews/addrbook/test/unit/test_ldap1.js
@@ -1,16 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /*
  * Test suite for basic LDAP address book functions
  */
 
 const kLDAPDirectory = 0; // defined in nsDirPrefs.h
 const kLDAPUriPrefix = "moz-abldapdirectory://";
-const kLDAPTestSpec = "ldap://invalidhost:389//dc=intranet??sub?(objectclass=*)";
+const kLDAPTestSpec = "ldap://invalidhost//dc=intranet??sub?(objectclass=*)";
 
 function run_test() {
   // Test - Create an LDAP directory
   var abManager = Components.classes["@mozilla.org/abmanager;1"]
                             .getService(Components.interfaces.nsIAbManager);
 
   var abUri = abManager.newAddressBook("test", kLDAPTestSpec, kLDAPDirectory);
 
--- a/mailnews/base/public/nsIMsgIncomingServer.idl
+++ b/mailnews/base/public/nsIMsgIncomingServer.idl
@@ -53,17 +53,17 @@ interface nsIMsgDBHdr;
 interface nsILocalFile;
 
 /*
  * Interface for incoming mail/news host
  * this is the base interface for all mail server types (imap, pop, nntp, etc)
  * often you will want to add extra interfaces that give you server-specific
  * attributes and methods.
  */
-[scriptable, uuid(b51b27f6-4c36-44ef-8457-52b40d2056ce)]
+[scriptable, uuid(2795ee91-7231-4c3b-a6ed-ea9a721371fa)]
 interface nsIMsgIncomingServer : nsISupports {
 
   /**
    * internal pref key - guaranteed to be unique across all servers
    */
   attribute ACString key;
 
   /**
@@ -123,21 +123,16 @@ interface nsIMsgIncomingServer : nsISupp
   attribute ACString password;
 
   /* prompt the user for a password */
   ACString getPasswordWithUI(in AString aPromptString, in AString aPromptTitle, in nsIMsgWindow aMsgWindow, out boolean okayValue);
 
   /* forget the password in memory and in single signon database */
   void forgetPassword();
 
-  /**
-   * logon succeeded - persist password, if user chooses.
-   */
-  void storePassword(); 
-
   /* forget the password in memory which is cached for the session */
   void forgetSessionPassword();
 
   /* should we download whole messages when biff goes off? */
   /* in 4.x, this was "mail.pop3_gets_new_mail" for pop */
   /* "mail.imap.new_mail_get_headers" for imap, and it was global.  in 5.x, it is per server */
   attribute boolean downloadOnBiff;
 
--- a/mailnews/base/util/Makefile.in
+++ b/mailnews/base/util/Makefile.in
@@ -79,16 +79,18 @@ REQUIRES	= xpcom \
 		  uconv \
 		  unicharutil \
 		  nkcache \
 		  mimetype \
 		  windowwatcher \
 		  htmlparser \
 		  content \
 		  layout \
+		  loginmgr \
+		  pipnss \
 		  $(NULL)
 
 CPPSRCS		= \
 		nsMsgLineBuffer.cpp \
 		nsMsgDBFolder.cpp \
 		nsMsgKeySet.cpp \
 		nsMsgIdentity.cpp \
 		nsMsgIncomingServer.cpp \
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -66,17 +66,16 @@
 #include "nsAbBaseCID.h"
 #include "nsIAbCard.h"
 #include "nsIAbDirectory.h"
 #include "nsISpamSettings.h"
 #include "nsIMsgFilterPlugin.h"
 #include "nsIMsgMailSession.h"
 #include "nsIRDFService.h"
 #include "nsTextFormatter.h"
-#include "nsCPasswordManager.h"
 #include "nsMsgDBCID.h"
 #include "nsInt64.h"
 #include "nsReadLine.h"
 #include "nsParserCIID.h"
 #include "nsIParser.h"
 #include "nsIHTMLContentSink.h"
 #include "nsIContentSerializer.h"
 #include "nsLayoutCID.h"
@@ -92,16 +91,18 @@
 #include "nsArrayUtils.h"
 #include "nsIMimeHeaders.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsIMsgTraitService.h"
 #include "nsIMessenger.h"
 #include "nsITransactionManager.h"
 #include "nsMsgReadStateTxn.h"
 #include "nsAutoPtr.h"
+#include "nsIPK11TokenDB.h"
+#include "nsIPK11Token.h"
 
 #define oneHour 3600000000U
 #include "nsMsgUtils.h"
 
 static PRTime gtimeOfLastPurgeCheck;    //variable to know when to check for purge_threshhold
 
 #define PREF_MAIL_PROMPT_PURGE_THRESHOLD "mail.prompt_purge_threshhold"
 #define PREF_MAIL_PURGE_THRESHOLD "mail.purge_threshhold"
@@ -2227,89 +2228,65 @@ nsMsgDBFolder::GetLastMessageLoaded(nsMs
 
 NS_IMETHODIMP
 nsMsgDBFolder::SetLastMessageLoaded(nsMsgKey aMsgKey)
 {
   mLastMessageLoaded = aMsgKey;
   return NS_OK;
 }
 
-nsresult nsMsgDBFolder::PromptForCachePassword(nsIMsgIncomingServer *server, nsIMsgWindow *aWindow, PRBool &passwordCorrect)
-{
-  PRBool userDidntCancel;
-  passwordCorrect = PR_FALSE;
-  nsCOMPtr <nsIStringBundle> bundle;
-  nsresult rv = GetBaseStringBundle(getter_AddRefs(bundle));
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsCString hostName;
-  nsCString userName;
-  nsString passwordTemplate;
-  nsCString password;
-  nsString passwordTitle;
-  nsString passwordPromptString;
-
-  server->GetRealHostName(hostName);
-  server->GetRealUsername(userName);
-  bundle->GetStringFromName(NS_LITERAL_STRING("passwordTitle").get(), getter_Copies(passwordTitle));
-  bundle->GetStringFromName(NS_LITERAL_STRING("passwordPrompt").get(), getter_Copies(passwordTemplate));
-  
-  NS_ConvertASCIItoUTF16 userNameStr(userName);
-  NS_ConvertASCIItoUTF16 hostNameStr(hostName);
-
-  const PRUnichar *stringParams[2] = { userNameStr.get(), hostNameStr.get() };
-
-  rv = bundle->FormatStringFromName(
-        NS_LITERAL_STRING("passwordPrompt").get(), stringParams, 2,
-        getter_Copies(passwordPromptString ));
-  NS_ENSURE_SUCCESS(rv, rv);
-
-  do
+// Returns true if: a) there is no need to prompt or b) the user is already
+// logged in or c) the user logged in successfully.
+PRBool nsMsgDBFolder::PromptForMasterPasswordIfNecessary()
+{
+  nsresult rv;
+  nsCOMPtr<nsIMsgAccountManager> accountManager =
+    do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  PRBool userNeedsToAuthenticate = PR_FALSE;
+  // if we're PasswordProtectLocalCache, then we need to find out if the server
+  // is authenticated.
+  (void) accountManager->GetUserNeedsToAuthenticate(&userNeedsToAuthenticate);
+  if (!userNeedsToAuthenticate)
+    return PR_TRUE;
+
+  // Do we have a master password?
+  nsCOMPtr<nsIPK11TokenDB> tokenDB =
+    do_GetService(NS_PK11TOKENDB_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  nsCOMPtr<nsIPK11Token> token;
+  rv = tokenDB->GetInternalKeyToken(getter_AddRefs(token));
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  PRBool result;
+  rv = token->CheckPassword(EmptyString().get(), &result);
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  if (result)
   {
-    rv = server->GetPasswordWithUI(passwordPromptString,
-                                   passwordTitle,
-                                   aWindow,
-                                   &userDidntCancel,
-                                   password);
-    if (rv != NS_MSG_PASSWORD_PROMPT_CANCELLED && !password.IsEmpty())
-    {
-      nsCOMPtr <nsIPasswordManagerInternal> passwordMgrInt = do_GetService(NS_PASSWORDMANAGER_CONTRACTID, &rv);
-      if(passwordMgrInt)
-      {
-        // Get the current server URI
-        nsCString currServerUri;
-        rv = server->GetServerURI(currServerUri);
-        NS_ENSURE_SUCCESS(rv, rv);
-
-        currServerUri.Insert('x', 0);
-        nsCAutoString hostFound;
-        nsAutoString userNameFound;
-        nsAutoString passwordFound;
-
-        // Get password entry corresponding to the host URI we are passing in.
-        rv = passwordMgrInt->FindPasswordEntry(currServerUri, EmptyString(), EmptyString(),
-                                               hostFound, userNameFound,
-                                               passwordFound);
-        if (NS_FAILED(rv))
-          break;
-        // compare the user-entered password with the saved password with
-        // the munged uri.
-        passwordCorrect = password.Equals(NS_ConvertUTF16toUTF8(passwordFound));
-        if (!passwordCorrect)
-          server->SetPassword(EmptyCString());
-        else
-        {
-          nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID);
-          if (accountManager)
-            accountManager->SetUserNeedsToAuthenticate(PR_FALSE);
-        }
-      }
-    }
+    // We don't have a master password, so this function isn't supported,
+    // therefore just tell account manager we've authenticated and return true.
+    accountManager->SetUserNeedsToAuthenticate(PR_FALSE);
+    return PR_TRUE;
   }
-  while (NS_SUCCEEDED(rv) && rv != NS_MSG_PASSWORD_PROMPT_CANCELLED && userDidntCancel && !passwordCorrect);
-  return (!passwordCorrect) ? NS_ERROR_FAILURE : rv;
+
+  // We have a master password, so try and login to the slot.
+  rv = token->Login(PR_FALSE);
+  if (NS_FAILED(rv))
+    // Login failed, so we didn't get a password (e.g. prompt cancelled).
+    return PR_FALSE;
+
+  // Double-check that we are now logged in
+  rv = token->IsLoggedIn(&result);
+  NS_ENSURE_SUCCESS(rv, PR_FALSE);
+
+  accountManager->SetUserNeedsToAuthenticate(!result);
+  return result;
 }
 
 // this gets called after the last junk mail classification has run.
 nsresult nsMsgDBFolder::PerformBiffNotifications(void)
 {
   nsCOMPtr<nsIMsgIncomingServer> server;
   nsresult rv = GetServer(getter_AddRefs(server));
   NS_ENSURE_SUCCESS(rv, rv);
--- a/mailnews/base/util/nsMsgDBFolder.h
+++ b/mailnews/base/util/nsMsgDBFolder.h
@@ -143,17 +143,20 @@ protected:
   nsresult OnHdrAddedOrDeleted(nsIMsgDBHdr *hdrChanged, PRBool added);
   nsresult CreateFileForDB(const nsACString& userLeafName, nsILocalFile *baseDir, nsILocalFile **dbFile);
 
   nsresult GetFolderCacheKey(nsILocalFile **aFile, PRBool createDBIfMissing = PR_FALSE);
   nsresult GetFolderCacheElemFromFile(nsILocalFile *file, nsIMsgFolderCacheElement **cacheElement);
   nsresult AddDirectorySeparator(nsILocalFile *path);
   nsresult CheckIfFolderExists(const nsAString& newFolderName, nsIMsgFolder *parentFolder, nsIMsgWindow *msgWindow);
 
-  nsresult PromptForCachePassword(nsIMsgIncomingServer *server, nsIMsgWindow *aWindow, PRBool &passwordCorrect);
+  // Returns true if: a) there is no need to prompt or b) the user is already
+  // logged in or c) the user logged in successfully.
+  static PRBool PromptForMasterPasswordIfNecessary();
+
   // offline support methods.
   nsresult StartNewOfflineMessage();
   nsresult WriteStartOfNewLocalMessage();
   nsresult EndNewOfflineMessage();
   nsresult CompactOfflineStore(nsIMsgWindow *inWindow, nsIUrlListener *aUrlListener);
   nsresult AutoCompact(nsIMsgWindow *aWindow);
   // this is a helper routine that ignores whether MSG_FLAG_OFFLINE is set for the folder
   nsresult MsgFitsDownloadCriteria(nsMsgKey msgKey, PRBool *result);
--- a/mailnews/base/util/nsMsgIncomingServer.cpp
+++ b/mailnews/base/util/nsMsgIncomingServer.cpp
@@ -1,9 +1,9 @@
-/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* ***** BEGIN LICENSE BLOCK *****
  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
  *
  * The contents of this file are subject to the Mozilla Public License Version
  * 1.1 (the "License"); you may not use this file except in compliance with
  * the License. You may obtain a copy of the License at
  * http://www.mozilla.org/MPL/
  *
@@ -57,28 +57,28 @@
 #include "nsIMsgWindow.h"
 #include "nsIMsgFilterService.h"
 #include "nsIMsgProtocolInfo.h"
 #include "nsIMsgMailSession.h"
 #include "nsIPrefService.h"
 #include "nsIRelativeFilePref.h"
 #include "nsIDocShell.h"
 #include "nsIAuthPrompt.h"
-#include "nsIObserverService.h"
 #include "nsNetUtil.h"
 #include "nsIWindowWatcher.h"
 #include "nsIStringBundle.h"
 #include "nsIMsgHdr.h"
 #include "nsIRDFService.h"
 #include "nsRDFCID.h"
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
+#include "nsILoginInfo.h"
+#include "nsILoginManager.h"
 
 #include "nsIMsgAccountManager.h"
-#include "nsCPasswordManager.h"
 #include "nsIMsgMdnGenerator.h"
 #include "nsMsgFolderFlags.h"
 #include "nsMsgUtils.h"
 #include "nsAppDirectoryServiceDefs.h"
 
 #define PORT_NOT_SET -1
 
 nsMsgIncomingServer::nsMsgIncomingServer():
@@ -688,52 +688,91 @@ NS_IMETHODIMP nsMsgIncomingServer::GetPa
 
 NS_IMETHODIMP nsMsgIncomingServer::GetServerRequiresPasswordForBiff(PRBool *aServerRequiresPasswordForBiff)
 {
   NS_ENSURE_ARG_POINTER(aServerRequiresPasswordForBiff);
   *aServerRequiresPasswordForBiff = PR_TRUE;
   return NS_OK;
 }
 
+void nsMsgIncomingServer::GetPasswordWithoutUI(nsACString &aPassword)
+{
+  aPassword.Truncate();
+
+  nsresult rv;
+  nsCOMPtr<nsILoginManager> loginMgr(do_GetService(NS_LOGINMANAGER_CONTRACTID,
+                                                   &rv));
+  NS_ENSURE_SUCCESS(rv, );
+
+  // Get the current server URI
+  nsCString currServerUri;
+  rv = GetLocalStoreType(currServerUri);
+  NS_ENSURE_SUCCESS(rv, );
+
+  currServerUri.AppendLiteral("://");
+
+  nsCString temp;
+  rv = GetHostName(temp);
+  NS_ENSURE_SUCCESS(rv, );
+
+  currServerUri.Append(temp);
+
+  NS_ConvertUTF8toUTF16 currServer(currServerUri);
+
+  PRUint32 numLogins = 0;
+  nsILoginInfo** logins = nsnull;
+  rv = loginMgr->FindLogins(&numLogins, currServer, EmptyString(),
+                            currServer, &logins);
+
+  // Don't abort here, if we didn't find any or failed, then we'll just have
+  // to prompt.
+  if (NS_SUCCEEDED(rv) && numLogins > 0)
+  {
+    nsCString serverCUsername;
+    rv = GetUsername(serverCUsername);
+    NS_ENSURE_SUCCESS(rv, );
+
+    NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
+
+    nsString username;
+    for (PRUint32 i = 0; i < numLogins; ++i)
+    {
+      rv = logins[i]->GetUsername(username);
+      NS_ENSURE_SUCCESS(rv, );
+
+      if (username.Equals(serverUsername))
+      {
+        nsString password;
+        rv = logins[i]->GetPassword(password);
+        NS_ENSURE_SUCCESS(rv, );
+
+        m_password = NS_LossyConvertUTF16toASCII(password);
+        break;
+      }
+    }
+    NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(numLogins, logins);
+  }
+}
+
 NS_IMETHODIMP
 nsMsgIncomingServer::GetPasswordWithUI(const nsAString& aPromptMessage, const
                                        nsAString& aPromptTitle,
                                        nsIMsgWindow* aMsgWindow,
                                        PRBool *okayValue,
                                        nsACString& aPassword)
 {
   nsresult rv = NS_OK;
   NS_ENSURE_ARG_POINTER(okayValue);
 
   if (m_password.IsEmpty())
   {
     // let's see if we have the password in the password manager and
     // can avoid this prompting thing. This makes it easier to get embedders
-    // to get up and running w/o a password prompting UI. We already depend on
-    // nsIPasswordManagerInternal so this doesn't introduce a new dependency.
-    nsCOMPtr <nsIPasswordManagerInternal> passwordMgrInt = do_GetService(NS_PASSWORDMANAGER_CONTRACTID, &rv);
-    if(passwordMgrInt)
-    {
-      // Get the current server URI
-      nsCString currServerUri;
-      rv = GetServerURI(currServerUri);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      nsCAutoString hostFound;
-      nsAutoString userNameFound;
-      nsAutoString passwordFound;
-
-      // Get password entry corresponding to the host URI we are passing in.
-      if (NS_SUCCEEDED(passwordMgrInt->FindPasswordEntry(currServerUri, EmptyString(), EmptyString(),
-                                             hostFound, userNameFound, passwordFound)))
-      {
-        LossyCopyUTF16toASCII(passwordFound, m_password);
-        *okayValue = PR_TRUE;
-      }
-    }
+    // to get up and running w/o a password prompting UI.
+    GetPasswordWithoutUI(aPassword);
   }
   if (m_password.IsEmpty())
   {
     nsCOMPtr<nsIAuthPrompt> dialog;
     // aMsgWindow is required if we need to prompt
     if (aMsgWindow)
     {
       // prompt the user for the password
@@ -741,30 +780,44 @@ nsMsgIncomingServer::GetPasswordWithUI(c
       rv = aMsgWindow->GetRootDocShell(getter_AddRefs(docShell));
       NS_ENSURE_SUCCESS(rv, rv);
       dialog = do_GetInterface(docShell, &rv);
       NS_ENSURE_SUCCESS(rv, rv);
     }
     if (dialog)
     {
       nsCString serverUri;
-      rv = GetServerURI(serverUri);
+      rv = GetLocalStoreType(serverUri);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      serverUri.AppendLiteral("://");
+      nsCString temp;
+      rv = GetRealUsername(temp);
       NS_ENSURE_SUCCESS(rv, rv);
 
+      serverUri.Append(temp);
+      serverUri.AppendLiteral("@");
+
+      rv = GetRealHostName(temp);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      serverUri.Append(temp);
+
       // we pass in the previously used password, if any, into PromptPassword
       // so that it will appear as ******. This means we can't use an nsString
       // and getter_Copies.
       PRUnichar *uniPassword = nsnull;
       if (!aPassword.IsEmpty())
         uniPassword = ToNewUnicode(NS_ConvertASCIItoUTF16(aPassword));
 
-      PRUint32 savePasswordType = PasswordProtectLocalCache() ? nsIAuthPrompt::SAVE_PASSWORD_FOR_SESSION : nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY;
-      rv = dialog->PromptPassword(nsString(aPromptTitle).get(), nsString(aPromptMessage).get(),
-        NS_ConvertASCIItoUTF16(serverUri).get(), savePasswordType,
-        &uniPassword, okayValue);
+      rv = dialog->PromptPassword(PromiseFlatString(aPromptTitle).get(),
+                                  PromiseFlatString(aPromptMessage).get(),
+                                  NS_ConvertASCIItoUTF16(serverUri).get(),
+                                  nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
+                                  &uniPassword, okayValue);
       nsAutoString uniPasswordAdopted;
       uniPasswordAdopted.Adopt(uniPassword);
       NS_ENSURE_SUCCESS(rv, rv);
 
       if (!*okayValue) // if the user pressed cancel, just return an empty string;
       {
         aPassword.Truncate();
         return NS_MSG_PASSWORD_PROMPT_CANCELLED;
@@ -774,70 +827,66 @@ nsMsgIncomingServer::GetPasswordWithUI(c
       rv = SetPassword(NS_LossyConvertUTF16toASCII(uniPasswordAdopted));
       NS_ENSURE_SUCCESS(rv, rv);
     } // if we got a prompt dialog
   } // if the password is empty
   return GetPassword(aPassword);
 }
 
 NS_IMETHODIMP
-nsMsgIncomingServer::StorePassword()
+nsMsgIncomingServer::ForgetPassword()
 {
   nsresult rv;
+  nsCOMPtr<nsILoginManager> loginMgr =
+    do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  // we only need to store this if we're password protecting the local cache.
-  // Otherwise, the password manager handles storing the password if the user
-  // checks the "remember password" box.
-  if (!PasswordProtectLocalCache())
-    return NS_OK;
+  // Get the current server URI
+  nsCString currServerUri;
+  rv = GetLocalStoreType(currServerUri);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString pwd;
-  rv = GetPassword(pwd);
+  currServerUri.AppendLiteral("://");
+
+  nsCString temp;
+  rv = GetHostName(temp);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCString serverSpec;
-  rv = GetServerURI(serverSpec);
-  NS_ENSURE_SUCCESS(rv,rv);
+  currServerUri.Append(temp);
+
+  PRUint32 count;
+  nsILoginInfo** logins;
+
+  NS_ConvertUTF8toUTF16 currServer(currServerUri);
 
-  // We're password protecting the local cache, we're going to munge the uri in the password mgr to
-  // start with 'x', so that we can remember the password in order to challenge the user, w/o having the
-  // password mgr automatically use the password.
-  serverSpec.Insert('x', 0);
-  nsCOMPtr<nsIURI> uri;
-  NS_NewURI(getter_AddRefs(uri), serverSpec);
+  nsCString serverCUsername;
+  rv = GetUsername(serverCUsername);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  //this is need to make sure wallet service has been created
-  rv = CreateServicesForPasswordManager();
+  NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
+
+  rv = loginMgr->FindLogins(&count, currServer, EmptyString(),
+                            currServer, &logins);
   NS_ENSURE_SUCCESS(rv, rv);
-  
-  nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
-  NS_ENSURE_SUCCESS(rv,rv);
-  rv = observerService->NotifyObservers(uri, "login-succeeded", NS_ConvertUTF8toUTF16(pwd).get());
-  NS_ENSURE_SUCCESS(rv,rv);
-  nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID);
-  if (accountManager)
-    accountManager->SetUserNeedsToAuthenticate(PR_FALSE);
-  return rv;
-}
 
-NS_IMETHODIMP
-nsMsgIncomingServer::ForgetPassword()
-{
-  //this is needed to make sure the wallet service has been created
-  nsresult rv = CreateServicesForPasswordManager();
-  NS_ENSURE_SUCCESS(rv, rv);
-  nsCOMPtr <nsIPasswordManager> passwordMgr = do_GetService(NS_PASSWORDMANAGER_CONTRACTID, &rv);
-  if (NS_SUCCEEDED(rv) && passwordMgr)
+  // There should only be one-login stored for this url, however just in case
+  // there isn't.
+  nsString username;
+  for (PRUint32 i = 0; i < count; ++i)
   {
-    // Get the current server URI
-    nsCString currServerUri;
-    rv = GetServerURI(currServerUri);
-    NS_ENSURE_SUCCESS(rv, rv);
-    passwordMgr->RemoveUser(currServerUri, EmptyString());
+    if (NS_SUCCEEDED(logins[i]->GetUsername(username)) &&
+        username.Equals(serverUsername))
+    {
+      // If this fails, just continue, we'll still want to remove the password
+      // from our local cache.
+      loginMgr->RemoveLogin(logins[i]);
+    }
   }
+  NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
+
   return SetPassword(EmptyCString());
 }
 
 NS_IMETHODIMP
 nsMsgIncomingServer::ForgetSessionPassword()
 {
   m_password.Truncate();
   return NS_OK;
@@ -896,27 +945,16 @@ nsMsgIncomingServer::GetLocalPath(nsILoc
 NS_IMETHODIMP
 nsMsgIncomingServer::SetLocalPath(nsILocalFile *aLocalPath)
 {
   NS_ENSURE_ARG_POINTER(aLocalPath);
   aLocalPath->Create(nsIFile::DIRECTORY_TYPE, 0755);
   return SetFileValue("directory-rel", "directory", aLocalPath);
 }
 
-PRBool nsMsgIncomingServer::PasswordProtectLocalCache()
-{
-  nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
-  NS_ENSURE_TRUE(prefs, PR_FALSE);
-
-  PRBool passwordProtectLocalCache;
-  nsresult rv = prefs->GetBoolPref( "mail.password_protect_local_cache", &passwordProtectLocalCache);
-  NS_ENSURE_SUCCESS(rv, PR_FALSE);
-  return passwordProtectLocalCache;
-}
-
 NS_IMETHODIMP
 nsMsgIncomingServer::GetLocalStoreType(nsACString& aResult)
 {
   NS_NOTYETIMPLEMENTED("nsMsgIncomingServer superclass not implementing GetLocalStoreType!");
   return NS_ERROR_UNEXPECTED;
 }
 
 NS_IMETHODIMP
@@ -1630,45 +1668,24 @@ nsMsgIncomingServer::GetPasswordPromptRe
   // If the password is not even required for biff we don't need to check any further
   nsresult rv = GetServerRequiresPasswordForBiff(aPasswordIsRequired);
   NS_ENSURE_SUCCESS(rv, rv);
   if (!*aPasswordIsRequired)
     return NS_OK;
 
   // If the password is empty, check to see if it is stored and to be retrieved
   if (m_password.IsEmpty()) {
-    nsCOMPtr <nsIPasswordManagerInternal> passwordMgrInt = do_GetService(NS_PASSWORDMANAGER_CONTRACTID, &rv);
-    if(NS_SUCCEEDED(rv) && passwordMgrInt) {
-
-      // Get the current server URI
-      nsCString currServerUri;
-      rv = GetServerURI(currServerUri);
-      NS_ENSURE_SUCCESS(rv, rv);
-
-      // Obtain the server URI which is in the format <protocol>://<userid>@<hostname>.
-      // Password manager uses the same format when it stores the password on user's request.
-      nsCAutoString hostFound;
-      nsAutoString userNameFound;
-      nsAutoString passwordFound;
+    nsCString password;
+    GetPasswordWithoutUI(password);
 
-      // Get password entry corresponding to the host URI we are passing in.
-      rv = passwordMgrInt->FindPasswordEntry(currServerUri, EmptyString(), EmptyString(),
-                                             hostFound, userNameFound, passwordFound);
-      if (NS_FAILED(rv))
-        return NS_OK;
-
-      // If a match is found, password element is filled in. Convert the
-      // obtained password and store it for the session.
-      if (!passwordFound.IsEmpty())
-      {
-        if (PasswordProtectLocalCache()) // hmm, shouldn't be in here, so remove it.
-          ForgetPassword();
-        else
-          rv = SetPassword(NS_LossyConvertUTF16toASCII(passwordFound));
-      }
+    // If a match is found, password element is filled in. Convert the
+    // obtained password and store it for the session.
+    if (!password.IsEmpty())
+    {
+      rv = SetPassword(password);
     }
   }
   *aPasswordIsRequired = m_password.IsEmpty();
   return rv;
 }
 
 NS_IMETHODIMP nsMsgIncomingServer::ConfigureTemporaryFilters(nsIMsgFilterList *aFilterList)
 {
--- a/mailnews/base/util/nsMsgIncomingServer.h
+++ b/mailnews/base/util/nsMsgIncomingServer.h
@@ -73,19 +73,20 @@ class NS_MSG_BASE nsMsgIncomingServer : 
   virtual ~nsMsgIncomingServer();
 
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMSGINCOMINGSERVER
 
 protected:
   nsCString m_serverKey;
 
+  void GetPasswordWithoutUI(nsACString &aPassword);
+
   nsresult ConfigureTemporaryReturnReceiptsFilter(nsIMsgFilterList *filterList);
   nsresult ConfigureTemporaryServerSpamFilters(nsIMsgFilterList *filterList);
-  PRBool PasswordProtectLocalCache();
 
   nsCOMPtr <nsIMsgFolder> m_rootFolder;
   nsCOMPtr <nsIMsgRetentionSettings> m_retentionSettings;
   nsCOMPtr <nsIMsgDownloadSettings> m_downloadSettings;
 
   nsresult CreateLocalFolder(nsIFile *path, const nsACString& folderName);
   nsresult GetDeferredServers(nsIMsgIncomingServer *server, nsISupportsArray **_retval);
 
--- a/mailnews/base/util/nsMsgProtocol.cpp
+++ b/mailnews/base/util/nsMsgProtocol.cpp
@@ -641,19 +641,22 @@ NS_IMETHODIMP nsMsgProtocol::GetContentL
 }
 
 NS_IMETHODIMP nsMsgProtocol::GetSecurityInfo(nsISupports * *aSecurityInfo)
 {
   *aSecurityInfo = nsnull;
   return NS_ERROR_NOT_IMPLEMENTED;
 }
 
-NS_IMETHODIMP nsMsgProtocol::GetName(nsACString &aName)
+NS_IMETHODIMP nsMsgProtocol::GetName(nsACString &result)
 {
-  return NS_ERROR_NOT_IMPLEMENTED;
+  if (m_url)
+    return m_url->GetSpec(result);
+  result.Truncate();
+  return NS_OK;
 }
 
 
 NS_IMETHODIMP
 nsMsgProtocol::SetContentLength(PRInt32 aContentLength)
 {
   return NS_ERROR_NOT_IMPLEMENTED;
 }
--- a/mailnews/base/util/nsMsgUtils.cpp
+++ b/mailnews/base/util/nsMsgUtils.cpp
@@ -61,18 +61,16 @@
 #include "nsIMimeConverter.h"
 #include "nsMsgMimeCID.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsISupportsPrimitives.h"
 #include "nsIPrefLocalizedString.h"
 #include "nsIRelativeFilePref.h"
 #include "nsAppDirectoryServiceDefs.h"
-#include "nsICategoryManager.h"
-#include "nsCategoryManagerUtils.h"
 #include "nsISpamSettings.h"
 #include "nsISignatureVerifier.h"
 #include "nsICryptoHash.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsDirectoryServiceUtils.h"
 #include "nsIRssIncomingServer.h"
 #include "nsIMsgFolder.h"
 #include "nsIMsgMessageService.h"
@@ -88,19 +86,16 @@
 static NS_DEFINE_CID(kImapUrlCID, NS_IMAPURL_CID);
 static NS_DEFINE_CID(kCMailboxUrl, NS_MAILBOXURL_CID);
 static NS_DEFINE_CID(kCNntpUrlCID, NS_NNTPURL_CID);
 
 #define ILLEGAL_FOLDER_CHARS ";#"
 #define ILLEGAL_FOLDER_CHARS_AS_FIRST_LETTER "."
 #define ILLEGAL_FOLDER_CHARS_AS_LAST_LETTER  ".~ "
 
-#define NS_PASSWORDMANAGER_CATEGORY "passwordmanager"
-static PRBool gInitPasswordManager = PR_FALSE;
-
 nsresult GetMessageServiceContractIDForURI(const char *uri, nsCString &contractID)
 {
   nsresult rv = NS_OK;
   //Find protocol
   nsCAutoString uriStr(uri);
   PRInt32 pos = uriStr.FindChar(':');
   if (pos == -1)
     return NS_ERROR_FAILURE;
@@ -825,29 +820,16 @@ nsresult EscapeFromSpaceLine(nsIOutputSt
       rv = outputStream->Write(start, end-start, &written);
       NS_ENSURE_SUCCESS(rv,rv);
       break;
     }
   }
   return NS_OK;
 }
 
-nsresult CreateServicesForPasswordManager()
-{
-  if (!gInitPasswordManager)
-  {
-     // Initialize the password manager category
-    gInitPasswordManager = PR_TRUE;
-    return NS_CreateServicesFromCategory(NS_PASSWORDMANAGER_CATEGORY,
-                                  nsnull,
-                                  NS_PASSWORDMANAGER_CATEGORY);
-  }
-  return NS_OK;
-}
-
 nsresult IsRFC822HeaderFieldName(const char *aHdr, PRBool *aResult)
 {
   NS_ENSURE_ARG_POINTER(aHdr);
   NS_ENSURE_ARG_POINTER(aResult);
   PRUint32 length = strlen(aHdr);
   for(PRUint32 i=0; i<length; i++)
   {
     char c = aHdr[i];
--- a/mailnews/base/util/nsMsgUtils.h
+++ b/mailnews/base/util/nsMsgUtils.h
@@ -113,18 +113,16 @@ NS_MSG_BASE nsresult NS_GetPersistentFil
                                           nsILocalFile **aFile,
                                           nsIPrefBranch *prefBranch = nsnull);
 
 NS_MSG_BASE nsresult NS_SetPersistentFile(const char *relPrefName,
                                           const char *absPrefName,
                                           nsILocalFile *aFile,
                                           nsIPrefBranch *prefBranch = nsnull);
 
-NS_MSG_BASE nsresult CreateServicesForPasswordManager();
-
 NS_MSG_BASE nsresult IsRFC822HeaderFieldName(const char *aHdr, PRBool *aResult);
 
 NS_MSG_BASE nsresult NS_GetUnicharPreferenceWithDefault(nsIPrefBranch *prefBranch,   //can be null, if so uses the root branch
                                                         const char *prefName,
                                                         const nsAString& defValue,
                                                         nsAString& prefValue);
  
 NS_MSG_BASE nsresult NS_GetLocalizedUnicharPreferenceWithDefault(nsIPrefBranch *prefBranch,   //can be null, if so uses the root branch
--- a/mailnews/compose/src/Makefile.in
+++ b/mailnews/compose/src/Makefile.in
@@ -78,16 +78,17 @@ REQUIRES	= xpcom \
 		  txmgr \
 		  caps \
 		  exthandler \
 		  nkcache \
 		  mimetype \
 		  windowwatcher \
 		  gfx \
 		  zipwriter \
+		  loginmgr \
 		  $(NULL)
 
 ifdef MOZ_THUNDERBIRD
 REQUIRES	+= xulapp
 endif
 
 DEFINES += -DMOZ_APP_VERSION="$(MOZ_APP_VERSION)"
 
--- a/mailnews/compose/src/nsSmtpServer.cpp
+++ b/mailnews/compose/src/nsSmtpServer.cpp
@@ -31,31 +31,29 @@
  * use your version of this file under the terms of the MPL, indicate your
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
-#include "msgCore.h"
 #include "nsIPrefService.h"
 #include "nsIPrefBranch.h"
 #include "nsEscape.h"
 #include "nsSmtpServer.h"
-#include "nsIObserverService.h"
 #include "nsNetUtil.h"
 #include "nsIAuthPrompt.h"
-#include "nsReadableUtils.h"
-#include "nsISmtpUrl.h"
 #include "nsMsgUtils.h"
 #include "nsIMsgAccountManager.h"
 #include "nsMsgBaseCID.h"
 #include "nsISmtpService.h"
 #include "nsMsgCompCID.h"
+#include "nsILoginInfo.h"
+#include "nsILoginManager.h"
 
 NS_IMPL_ADDREF(nsSmtpServer)
 NS_IMPL_RELEASE(nsSmtpServer)
 NS_INTERFACE_MAP_BEGIN(nsSmtpServer)
     NS_INTERFACE_MAP_ENTRY(nsISmtpServer)
     NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsISmtpServer)
 NS_INTERFACE_MAP_END
@@ -448,25 +446,30 @@ nsSmtpServer::GetPasswordWithUI(const PR
         if (NS_SUCCEEDED(rv))
         {
             nsString uniPassword;
             PRBool okayValue = PR_TRUE;
             nsCString serverUri;
             rv = GetServerURI(serverUri);
             if (NS_FAILED(rv))
                 return rv;
+
             nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+            NS_ENSURE_SUCCESS(rv, rv);
+
             PRBool passwordProtectLocalCache = PR_FALSE;
 
-            (void) prefBranch->GetBoolPref( "mail.password_protect_local_cache", &passwordProtectLocalCache);
+            (void) prefBranch->GetBoolPref("mail.password_protect_local_cache",
+                                           &passwordProtectLocalCache);
 
-            PRUint32 savePasswordType = (passwordProtectLocalCache) ? nsIAuthPrompt::SAVE_PASSWORD_FOR_SESSION : nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY;
             rv = aDialog->PromptPassword(aPromptTitle, aPromptMessage,
-                    NS_ConvertASCIItoUTF16(serverUri).get(), savePasswordType,
-                    getter_Copies(uniPassword), &okayValue);
+              NS_ConvertASCIItoUTF16(serverUri).get(),
+              passwordProtectLocalCache ? nsIAuthPrompt::SAVE_PASSWORD_NEVER
+                                        : nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
+              getter_Copies(uniPassword), &okayValue);
             if (NS_FAILED(rv))
                 return rv;
 
             if (!okayValue) // if the user pressed cancel, just return NULL;
             {
                 aPassword.Truncate();
                 return rv;
             }
@@ -500,19 +503,30 @@ nsSmtpServer::GetUsernamePasswordWithUI(
         {
             nsString uniUsername;
             nsString uniPassword;
             PRBool okayValue = PR_TRUE;
             nsCString serverUri;
             rv = GetServerURI(serverUri);
             if (NS_FAILED(rv))
                 return rv;
+
+            nsCOMPtr<nsIPrefBranch> prefBranch(do_GetService(NS_PREFSERVICE_CONTRACTID, &rv));
+            NS_ENSURE_SUCCESS(rv, rv);
+
+            PRBool passwordProtectLocalCache = PR_FALSE;
+
+            (void) prefBranch->GetBoolPref("mail.password_protect_local_cache",
+                                           &passwordProtectLocalCache);
+
             rv = aDialog->PromptUsernameAndPassword(aPromptTitle, aPromptMessage,
-                                         NS_ConvertASCIItoUTF16(serverUri).get(), nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
-                                         getter_Copies(uniUsername), getter_Copies(uniPassword), &okayValue);
+              NS_ConvertASCIItoUTF16(serverUri).get(),
+              passwordProtectLocalCache ? nsIAuthPrompt::SAVE_PASSWORD_NEVER
+                                        : nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY,
+              getter_Copies(uniUsername), getter_Copies(uniPassword), &okayValue);
             if (NS_FAILED(rv))
                 return rv;
 
             if (!okayValue) // if the user pressed cancel, just return NULL;
             {
               aUsername.Truncate();
               aPassword.Truncate();
               return rv;
@@ -537,47 +551,74 @@ nsSmtpServer::GetUsernamePasswordWithUI(
     if (NS_FAILED(rv))
         return rv;
     return GetPassword(aPassword);
 }
 
 NS_IMETHODIMP
 nsSmtpServer::ForgetPassword()
 {
-    nsresult rv;
-    nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
-    NS_ENSURE_SUCCESS(rv,rv);
+  nsresult rv;
+  nsCOMPtr<nsILoginManager> loginMgr =
+    do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // Get the current server URI without the username
+  nsCAutoString serverUri(NS_LITERAL_CSTRING("smtp://"));
+
+  nsCString hostname;
+  rv = GetHostname(hostname);
 
-    nsCString serverUri;
-    rv = GetServerURI(serverUri);
-    if (NS_FAILED(rv))
-        return rv;
+  if (NS_SUCCEEDED(rv) && !hostname.IsEmpty()) {
+    nsCString escapedHostname;
+    *((char **)getter_Copies(escapedHostname)) =
+      nsEscape(hostname.get(), url_Path);
+    // not all servers have a hostname
+    serverUri.Append(escapedHostname);
+  }
+
+  PRUint32 count;
+  nsILoginInfo** logins;
+
+  NS_ConvertUTF8toUTF16 currServer(serverUri);
 
-    nsCOMPtr<nsIURI> uri;
-    NS_NewURI(getter_AddRefs(uri), serverUri);
+  nsCString serverCUsername;
+  rv = GetUsername(serverCUsername);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-    //this is need to make sure wallet service has been created
-    rv = CreateServicesForPasswordManager();
-    NS_ENSURE_SUCCESS(rv, rv);
+  NS_ConvertUTF8toUTF16 serverUsername(serverCUsername);
+
+  rv = loginMgr->FindLogins(&count, currServer, EmptyString(),
+                            currServer, &logins);
+  NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = observerService->NotifyObservers(uri, "login-failed", nsnull);
-    NS_ENSURE_SUCCESS(rv,rv);
+  // There should only be one-login stored for this url, however just in case
+  // there isn't.
+  nsString username;
+  for (PRUint32 i = 0; i < count; ++i)
+  {
+    if (NS_SUCCEEDED(logins[i]->GetUsername(username)) &&
+        username.Equals(serverUsername))
+    {
+      // If this fails, just continue, we'll still want to remove the password
+      // from our local cache.
+      loginMgr->RemoveLogin(logins[i]);
+    }
+  }
+  NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
 
-    rv = SetPassword(EmptyCString());
-    m_logonFailed = PR_TRUE;
-    return rv;
+  rv = SetPassword(EmptyCString());
+  m_logonFailed = PR_TRUE;
+  return rv;
 }
 
 NS_IMETHODIMP
 nsSmtpServer::GetServerURI(nsACString &aResult)
 {
-    nsCAutoString uri;
-
-    uri.AssignLiteral("smtp");
-    uri.AppendLiteral("://");
+    nsCAutoString uri(NS_LITERAL_CSTRING("smtp://"));
 
     nsCString username;
     nsresult rv = GetUsername(username);
 
     if (NS_SUCCEEDED(rv) && !username.IsEmpty()) {
         nsCString escapedUsername;
         MsgEscapeString(username, nsINetUtil::ESCAPE_XALPHAS, escapedUsername);
         // not all servers have a username
new file mode 100644
--- /dev/null
+++ b/mailnews/compose/test/unit/test_smtpPassword2.js
@@ -0,0 +1,67 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Extra tests for SMTP passwords (forgetPassword)
+ */
+
+const kUser1 = "testsmtp";
+const kUser2 = "testsmtpa";
+const kProtocol = "smtp";
+const kHostname = "localhost";
+const kServerUrl = kProtocol + "://" + kHostname;
+
+function run_test()
+{
+  // Login Manager
+  var loginMgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
+
+  // Passwords File (generated from Mozilla 1.8 branch).
+  var signons = do_get_file("../mailnews/test/data/signons-mailnews1.8-multiple.txt");
+
+  // Copy the file to the profile directory for a PAB
+  signons.copyTo(gProfileDir, "signons.txt");
+
+  // Set up the basic accounts and folders.
+  loadLocalMailAccount();
+
+  var smtpServer1 = getBasicSmtpServer();
+  var smtpServer2 = getBasicSmtpServer();
+
+  smtpServer1.authMethod = 1;
+  smtpServer1.username = kUser1;
+  smtpServer2.authMethod = 1;
+  smtpServer2.username = kUser2;
+
+  var i;
+  var count = {};
+
+  // Test - Check there are two logins to begin with.
+  var logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
+
+  do_check_eq(count.value, 2);
+
+  // These will either be one way around or the other.
+  if (logins[0].username == kUser1) {
+    do_check_eq(logins[1].username, kUser2);
+  } else {
+    do_check_eq(logins[0].username, kUser2);
+    do_check_eq(logins[1].username, kUser1);
+  }
+
+  // Test - Remove a login via the incoming server
+  smtpServer1.forgetPassword();
+
+  logins = logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
+
+  // should be one login left for kUser2
+  do_check_eq(count.value, 1);
+  do_check_eq(logins[0].username, kUser2);
+
+  // Test - Remove the other login via the incoming server
+  smtpServer2.forgetPassword();
+
+  logins = logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
+
+  // should be one login left for kUser2
+  do_check_eq(count.value, 0);
+  do_check_eq(logins.length, 0);
+}
--- a/mailnews/imap/src/nsImapIncomingServer.cpp
+++ b/mailnews/imap/src/nsImapIncomingServer.cpp
@@ -2045,17 +2045,24 @@ NS_IMETHODIMP nsImapIncomingServer::Rese
   }
   return rv;
 }
 
 NS_IMETHODIMP nsImapIncomingServer::SetUserAuthenticated(PRBool aUserAuthenticated)
 {
   m_userAuthenticated = aUserAuthenticated;
   if (aUserAuthenticated)
-    StorePassword();
+  {
+    nsresult rv;
+    nsCOMPtr<nsIMsgAccountManager> accountManager =
+      do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    accountManager->SetUserNeedsToAuthenticate(PR_FALSE);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP nsImapIncomingServer::GetUserAuthenticated(PRBool *aUserAuthenticated)
 {
   NS_ENSURE_ARG_POINTER(aUserAuthenticated);
   *aUserAuthenticated = m_userAuthenticated;
   return NS_OK;
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -764,36 +764,21 @@ NS_IMETHODIMP nsImapMailFolder::UpdateFo
   {
     if (hasOfflineEvents)
     {
       nsImapOfflineSync *goOnline = new nsImapOfflineSync(msgWindow, this, this);
       if (goOnline)
         return goOnline->ProcessNextOperation();
     }
   }
-  else // we're offline - check if we're password protecting the offline store
-  {
-    nsCOMPtr<nsIMsgAccountManager> accountManager = do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
-    NS_ENSURE_SUCCESS(rv, rv);
-    PRBool userNeedsToAuthenticate = PR_FALSE;
-    // if we're PasswordProtectLocalCache, then we need to find out if the server is authenticated.
-    (void) accountManager->GetUserNeedsToAuthenticate(&userNeedsToAuthenticate);
-    if (userNeedsToAuthenticate)
-    {
-      nsCOMPtr<nsIMsgIncomingServer> server;
-      rv = GetServer(getter_AddRefs(server));
-      if (NS_SUCCEEDED(rv))
-      {
-        PRBool passwordMatches = PR_FALSE;
-        rv = PromptForCachePassword(server, msgWindow, passwordMatches);
-        if (!passwordMatches)
-          return NS_ERROR_FAILURE;
-      }
-    }
-  }
+
+  // Check it we're password protecting the local store.
+  if (!PromptForMasterPasswordIfNecessary())
+    return NS_ERROR_FAILURE;
+
   if (!canOpenThisFolder)
     selectFolder = PR_FALSE;
   // don't run select if we can't select the folder...
   if (NS_SUCCEEDED(rv) && !m_urlRunning && selectFolder)
   {
     nsCOMPtr<nsIImapService> imapService = do_GetService(NS_IMAPSERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
--- a/mailnews/imap/src/nsImapProtocol.cpp
+++ b/mailnews/imap/src/nsImapProtocol.cpp
@@ -8759,17 +8759,20 @@ NS_IMETHODIMP nsImapMockChannel::SetSecu
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // From nsIRequest
 ////////////////////////////////////////////////////////////////////////////////
 
 NS_IMETHODIMP nsImapMockChannel::GetName(nsACString &result)
 {
-    return NS_ERROR_NOT_IMPLEMENTED;
+  if (m_url)
+    return m_url->GetSpec(result);
+  result.Truncate();
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsImapMockChannel::IsPending(PRBool *result)
 {
     *result = m_channelListener != nsnull;
     return NS_OK;
 }
 
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -592,48 +592,19 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetD
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::UpdateFolder(nsIMsgWindow *aWindow)
 {
   (void) RefreshSizeOnDisk();
   nsresult rv;
 
-  nsCOMPtr<nsIMsgAccountManager> accountManager =
-           do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
-  NS_ENSURE_SUCCESS(rv, rv);
-  PRBool userNeedsToAuthenticate = PR_FALSE;
-  // if we're PasswordProtectLocalCache, then we need to find out if the server is authenticated.
-  (void) accountManager->GetUserNeedsToAuthenticate(&userNeedsToAuthenticate);
-  if (userNeedsToAuthenticate)
-  {
-    nsCOMPtr<nsIMsgIncomingServer> server;
-    rv = GetServer(getter_AddRefs(server));
-    NS_ENSURE_SUCCESS(rv, NS_MSG_INVALID_OR_MISSING_SERVER);
-    // need to check if this is a pop3 or no mail server to determine which password
-    // we should challenge the user with.
-    nsCOMPtr<nsIMsgIncomingServer> serverToAuthenticateAgainst;
-    nsCOMPtr<nsINoIncomingServer> noIncomingServer = do_QueryInterface(server);
-    if (noIncomingServer)
-    {
-      nsCOMPtr<nsIMsgAccount> defaultAccount;
-      accountManager->GetDefaultAccount(getter_AddRefs(defaultAccount));
-      if (defaultAccount)
-        defaultAccount->GetIncomingServer(getter_AddRefs(serverToAuthenticateAgainst));
-    }
-    else
-      GetServer(getter_AddRefs(serverToAuthenticateAgainst));
-    if (serverToAuthenticateAgainst)
-    {
-      PRBool passwordMatches = PR_FALSE;
-      rv = PromptForCachePassword(serverToAuthenticateAgainst, aWindow, passwordMatches);
-      if (!passwordMatches)
-        return NS_ERROR_FAILURE;
-    }
-  }
+  if (!PromptForMasterPasswordIfNecessary())
+    return NS_ERROR_FAILURE;
+
   //If we don't currently have a database, get it.  Otherwise, the folder has been updated (presumably this
   //changes when we download headers when opening inbox).  If it's updated, send NotifyFolderLoaded.
   if(!mDatabase)
     // return of NS_ERROR_NOT_INITIALIZED means running parsing URL
     rv = GetDatabaseWithReparse(this, aWindow, getter_AddRefs(mDatabase));
   else
   {
     PRBool valid;
--- a/mailnews/local/src/nsPop3Sink.cpp
+++ b/mailnews/local/src/nsPop3Sink.cpp
@@ -103,23 +103,16 @@ nsPop3Sink::~nsPop3Sink()
     NS_IF_RELEASE(m_newMailParser);
 }
 
 nsresult
 nsPop3Sink::SetUserAuthenticated(PRBool authed)
 {
   m_authed = authed;
   m_popServer->SetAuthenticated(authed);
-  if (authed)
-  {
-    nsCOMPtr<nsIMsgIncomingServer> server = do_QueryInterface(m_popServer);
-    if (!server)
-      return NS_ERROR_UNEXPECTED;
-    return server->StorePassword();
-  }
   return NS_OK;
 }
 
 nsresult
 nsPop3Sink::GetUserAuthenticated(PRBool* authed)
 {
   return m_popServer->GetAuthenticated(authed);
 }
new file mode 100644
--- /dev/null
+++ b/mailnews/local/test/unit/test_pop3Password3.js
@@ -0,0 +1,71 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Extra tests for POP3 passwords (forgetPassword)
+ */
+
+const kUser1 = "testpop3";
+const kUser2 = "testpop3a";
+const kProtocol = "pop3";
+const kHostname = "localhost";
+const kServerUrl = "mailbox://" + kHostname;
+
+function run_test()
+{
+  // Login Manager
+  var loginMgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
+
+  // Passwords File (generated from Mozilla 1.8 branch).
+  var signons = do_get_file("../mailnews/test/data/signons-mailnews1.8-multiple.txt");
+
+  // Copy the file to the profile directory for a PAB
+  signons.copyTo(gProfileDir, "signons.txt");
+
+  // Set up the basic accounts and folders.
+  // We would use createPop3ServerAndLocalFolders() however we want to have
+  // a different username and NO password for this test (as we expect to load
+  // it from signons.txt).
+  loadLocalMailAccount();
+
+  var acctMgr = Cc["@mozilla.org/messenger/account-manager;1"]
+                  .getService(Ci.nsIMsgAccountManager);
+
+  var incomingServer1 = acctMgr.createIncomingServer(kUser1, kHostname,
+                                                     kProtocol);
+
+  var incomingServer2 = acctMgr.createIncomingServer(kUser2, kHostname,
+                                                     kProtocol);
+
+  var i;
+  var count = {};
+
+  // Test - Check there are two logins to begin with.
+  var logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
+
+  do_check_eq(count.value, 2);
+
+  // These will either be one way around or the other.
+  if (logins[0].username == kUser1) {
+    do_check_eq(logins[1].username, kUser2);
+  } else {
+    do_check_eq(logins[0].username, kUser2);
+    do_check_eq(logins[1].username, kUser1);
+  }
+
+  // Test - Remove a login via the incoming server
+  incomingServer1.forgetPassword();
+
+ logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
+
+  // should be one login left for kUser2
+  do_check_eq(count.value, 1);
+  do_check_eq(logins[0].username, kUser2);
+
+  // Test - Remove the other login via the incoming server
+  incomingServer2.forgetPassword();
+
+  logins = loginMgr.findLogins(count, kServerUrl, null, kServerUrl);
+
+  // should be one login left for kUser2
+  do_check_eq(count.value, 0);
+  do_check_eq(logins.length, 0);
+}
--- a/mailnews/news/src/Makefile.in
+++ b/mailnews/news/src/Makefile.in
@@ -64,16 +64,18 @@ REQUIRES	= xpcom \
 		  appshell \
 		  toolkitcomps \
 		  mime \
 		  intl \
 		  rdfutil \
 		  nkcache \
 		  windowwatcher \
 		  unicharutil \
+		  embed_base \
+		  loginmgr \
 		  $(NULL)
 
 CPPSRCS		= \
 		nsNNTPArticleList.cpp \
 		nsNNTPNewsgroupList.cpp \
 		nsNNTPNewsgroupPost.cpp \
 		nsNNTPProtocol.cpp \
 		nsNntpUrl.cpp \
--- a/mailnews/news/src/nsNNTPProtocol.cpp
+++ b/mailnews/news/src/nsNNTPProtocol.cpp
@@ -2655,24 +2655,29 @@ PRInt32 nsNNTPProtocol::BeginAuthorizati
     rv = m_newsFolder->GetGroupUsername(cachedUsername);
 
   if (NS_FAILED(rv) || cachedUsername.IsEmpty()) {
     rv = NS_OK;
     NNTP_LOG_NOTE("ask for the news username");
 
     nsString usernamePromptText;
     GetNewsStringByName("enterUsername", getter_Copies(usernamePromptText));
+    nsString usernamePromptTitleText;
+    GetNewsStringByName("enterUsernameTitle",
+                        getter_Copies(usernamePromptTitleText));
     if (m_newsFolder) {
       if (!m_msgWindow) {
         nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(m_runningURL);
         if (mailnewsurl)
           rv = mailnewsurl->GetMsgWindow(getter_AddRefs(m_msgWindow));
       }
 
-      rv = m_newsFolder->GetGroupUsernameWithUI(usernamePromptText, EmptyString(), m_msgWindow, username);
+      rv = m_newsFolder->GetGroupUsernameWithUI(usernamePromptText,
+                                                usernamePromptTitleText,
+                                                m_msgWindow, username);
     }
     else
       return(MK_NNTP_AUTH_FAILED);
 
     if (NS_FAILED(rv)) {
       AlertError(MK_NNTP_AUTH_FAILED, "Aborted by user");
       return(MK_NNTP_AUTH_FAILED);
     }
--- a/mailnews/news/src/nsNewsFolder.cpp
+++ b/mailnews/news/src/nsNewsFolder.cpp
@@ -71,17 +71,16 @@
 #include "nsMsgBaseCID.h"
 #include "nsILineInputStream.h"
 
 #include "nsIMsgWindow.h"
 #include "nsIDocShell.h"
 #include "nsIPrompt.h"
 #include "nsIWindowWatcher.h"
 
-#include "nsIObserverService.h"
 #include "nsNetUtil.h"
 #include "nsIAuthPrompt.h"
 #include "nsIURL.h"
 #include "nsNetCID.h"
 #include "nsINntpUrl.h"
 
 #include "nsIInterfaceRequestor.h"
 #include "nsIInterfaceRequestorUtils.h"
@@ -91,16 +90,21 @@
 #include "nsIStringBundle.h"
 #include "nsEscape.h"
 #include "nsMsgI18N.h"
 #include "nsNativeCharsetUtils.h"
 #include "nsIMsgAccountManager.h"
 #include "nsArrayUtils.h"
 #include "nsIMsgFolderNotificationService.h"
 #include "nsIMutableArray.h"
+#include "nsILoginInfo.h"
+#include "nsILoginManager.h"
+#include "nsIPromptService.h"
+#include "nsEmbedCID.h"
+#include "nsIDOMWindow.h"
 
 static NS_DEFINE_CID(kRDFServiceCID, NS_RDFSERVICE_CID);
 
 // ###tw  This really ought to be the most
 // efficient file reading size for the current
 // operating system.
 #define NEWSRC_FILE_BUFFER_SIZE 1024
 
@@ -1063,18 +1067,16 @@ nsresult nsMsgNewsFolder::CreateNewsgrou
 nsresult nsMsgNewsFolder::CreateNewsgroupPasswordUrlForSignon(const nsACString& inUriStr, nsACString& result)
 {
   return CreateNewsgroupUrlForSignon(inUriStr, "password", result);
 }
 
 nsresult nsMsgNewsFolder::CreateNewsgroupUrlForSignon(const nsACString& inUriStr, const char *ref, nsACString& result)
 {
   nsresult rv;
-  PRInt32 port = 0;
-
   nsCOMPtr<nsIURL> url = do_CreateInstance(NS_STANDARDURL_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv,rv);
 
   nsCOMPtr<nsIMsgIncomingServer> server;
   rv = GetServer(getter_AddRefs(server));
   if (NS_FAILED(rv)) return rv;
 
   nsCOMPtr<nsINntpIncomingServer> nntpServer;
@@ -1094,84 +1096,134 @@ nsresult nsMsgNewsFolder::CreateNewsgrou
     NS_ENSURE_SUCCESS(rv, rv);
   }
   else
   {
     rv = url->SetSpec(inUriStr);
     NS_ENSURE_SUCCESS(rv, rv);
   }
 
+  PRInt32 port = 0;
   rv = url->GetPort(&port);
-  if (NS_FAILED(rv)) return rv;
+  NS_ENSURE_SUCCESS(rv, rv);
 
   if (port <= 0)
   {
     nsCOMPtr<nsIMsgIncomingServer> server;
     rv = GetServer(getter_AddRefs(server));
     NS_ENSURE_SUCCESS(rv, rv);
 
     PRInt32 socketType;
     nsresult rv = server->GetSocketType(&socketType);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = url->SetPort((socketType == nsIMsgIncomingServer::useSSL) ?
-                      nsINntpUrl::DEFAULT_NNTPS_PORT : nsINntpUrl::DEFAULT_NNTP_PORT);
-    NS_ENSURE_SUCCESS(rv, rv);
+    // Only set this for ssl newsgroups as for non-ssl connections, we don't
+    // need to specify the port as it is the default for the protocol and
+    // password manager "blanks" those out.
+    if (socketType == nsIMsgIncomingServer::useSSL)
+    {
+      rv = url->SetPort(nsINntpUrl::DEFAULT_NNTPS_PORT);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
   }
 
-  rv = url->SetRef(nsDependentCString(ref));
+  if (ref)
+  {
+    rv = url->SetRef(nsDependentCString(ref));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    return url->GetSpec(result);
+  }
+
+  // If the url doesn't have a path, make sure we don't get a '/' on the end
+  // as that will confuse searching in password manager.
+  nsCString spec;
+  rv = url->GetSpec(spec);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return url->GetSpec(result);
+  if (!spec.IsEmpty() && spec[spec.Length() - 1] == '/')
+    result = StringHead(spec, spec.Length() - 1);
+  else
+    result = spec;
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgNewsFolder::ForgetGroupUsername()
 {
-  nsresult rv;
-  nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  rv = SetGroupUsername(EmptyCString());
-  if (NS_FAILED(rv)) return rv;
+  nsCString hostname;
+  nsresult rv = CreateNewsgroupUrlForSignon(mURI, nsnull, hostname);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   nsCString signonURL;
   rv = CreateNewsgroupUsernameUrlForSignon(mURI, signonURL);
-  if (NS_FAILED(rv)) return rv;
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIURI> uri;
-  NS_NewURI(getter_AddRefs(uri), signonURL);
-
-  //this is need to make sure wallet service has been created
-  rv = CreateServicesForPasswordManager();
+  nsCOMPtr<nsILoginManager> loginMgr =
+    do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return observerService->NotifyObservers(uri, "login-failed", nsnull);
+  PRUint32 count;
+  nsILoginInfo** logins;
+
+  // XXX we don't support multiple logins per news server, so just delete any
+  // we find.
+  rv = loginMgr->FindLogins(&count, NS_ConvertASCIItoUTF16(hostname),
+                            EmptyString(),
+                            NS_ConvertASCIItoUTF16(signonURL), &logins);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // There should only be one-login stored for this url, however just in case
+  // there isn't.
+  for (PRUint32 i = 0; i < count; ++i)
+  {
+    // If this fails, just continue, we'll still want to remove the password
+    // from our local cache.
+    loginMgr->RemoveLogin(logins[i]);
+  }
+  NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
+
+  return NS_OK;
 }
 
 NS_IMETHODIMP nsMsgNewsFolder::ForgetGroupPassword()
 {
-  nsresult rv = NS_OK;
-  nsCOMPtr<nsIObserverService> observerService = do_GetService("@mozilla.org/observer-service;1", &rv);
-  NS_ENSURE_SUCCESS(rv,rv);
-
-  rv = SetGroupPassword(EmptyCString());
-  if (NS_FAILED(rv)) return rv;
+  nsCString hostname;
+  nsresult rv = CreateNewsgroupUrlForSignon(mURI, nsnull, hostname);
+  NS_ENSURE_SUCCESS(rv, rv);
 
   nsCString signonURL;
   rv = CreateNewsgroupPasswordUrlForSignon(mURI, signonURL);
-  if (NS_FAILED(rv)) return rv;
+  NS_ENSURE_SUCCESS(rv, rv);
 
-  nsCOMPtr<nsIURI> uri;
-  NS_NewURI(getter_AddRefs(uri), signonURL);
-
-  //this is need to make sure wallet service has been created
-  rv = CreateServicesForPasswordManager();
+  nsCOMPtr<nsILoginManager> loginMgr =
+    do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
-  return observerService->NotifyObservers(uri, "login-failed", nsnull);
+  PRUint32 count;
+  nsILoginInfo** logins;
+
+  // XXX we don't support multiple logins per news server, so just delete any
+  // we find.
+  rv = loginMgr->FindLogins(&count, NS_ConvertASCIItoUTF16(hostname),
+                            EmptyString(),
+                            NS_ConvertASCIItoUTF16(signonURL), &logins);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  // There should only be one-login stored for this url, however just in case
+  // there isn't.
+  for (PRUint32 i = 0; i < count; ++i)
+  {
+    // If this fails, just continue, we'll still want to remove the password
+    // from our local cache.
+    loginMgr->RemoveLogin(logins[i]);
+  }
+  NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
+
+  return SetGroupPassword(EmptyCString());
 }
 
 // change order of subfolders (newsgroups)
 // aOrientation = -1 ... aNewsgroupToMove aRefNewsgroup ...
 // aOrientation =  1 ... aRefNewsgroup aNewsgroupToMove ...
 NS_IMETHODIMP nsMsgNewsFolder::MoveFolder(nsIMsgFolder *aNewsgroupToMove, nsIMsgFolder *aRefNewsgroup, PRInt32 aOrientation)
 {
   // if folders are identical do nothing
@@ -1335,30 +1387,126 @@ nsMsgNewsFolder::GetGroupUsernameWithUI(
     
     NS_ENSURE_TRUE(dialog, NS_ERROR_FAILURE);
 
     nsString uniGroupUsername;
     PRBool okayValue = PR_TRUE;
 
     nsCString signonURL;
     rv = CreateNewsgroupUsernameUrlForSignon(mURI, signonURL);
-    if (NS_FAILED(rv)) return rv;
+    if (NS_FAILED(rv))
+      return rv;
+
+    // This is the hostname without the #username or #password on the end.
+    nsCString hostnameURL;
+    rv = CreateNewsgroupUrlForSignon(mURI, nsnull, hostnameURL);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    // Due to the way the new login manager doesn't want to let us save
+    // usernames in the password field, unfortunately the way mailnews has
+    // worked historically, means we need to do this.
+    // So we have to first check manully, then prompt, the save separately if
+    // we want to get a value.
+    nsCOMPtr<nsILoginManager> loginMgr =
+      do_GetService(NS_LOGINMANAGER_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    PRUint32 count = 0;
+    nsILoginInfo **logins = nsnull;
+    rv = loginMgr->FindLogins(&count, NS_ConvertASCIItoUTF16(hostnameURL),
+                              EmptyString(), NS_ConvertASCIItoUTF16(signonURL), &logins);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    if (count > 0)
+    {
+      nsString username;
+      rv = logins[0]->GetPassword(username);
+
+      NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
+
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      NS_LossyConvertUTF16toASCII result(username);
 
-    rv = dialog->Prompt(nsString(aPromptTitle).get(), nsString(aPromptMessage).get(),
-                        NS_ConvertASCIItoUTF16(signonURL).get(),
-                        nsIAuthPrompt::SAVE_PASSWORD_PERMANENTLY, NS_ConvertASCIItoUTF16(mPrevUsername).get(),
-                        getter_Copies(uniGroupUsername), &okayValue);
-    if (NS_FAILED(rv)) return rv;
+      // Just use the first as that is all we should have
+      rv = SetGroupUsername(result);
+      if (NS_FAILED(rv))
+        return rv;
+
+      mPrevUsername = aGroupUsername = result;
+      return NS_OK;
+    }
+    NS_FREE_XPCOM_ISUPPORTS_POINTER_ARRAY(count, logins);
+
+
+    // No logins, so time to prompt. Toolkit password manager doesn't let us
+    // use nsIAuthPrompt.prompt in the way we'd like currently, and it doesn't
+    // let us store username-only passwords. So go direct to the dialog and
+    // cut out the middle-man.
+    nsCOMPtr<nsIPromptService> promptSvc =
+      do_GetService(NS_PROMPTSERVICE_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    PRBool saveUsername = PR_FALSE;
+
+    nsCOMPtr<nsIStringBundleService> bundleService = do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv);
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsCOMPtr<nsIStringBundle> bundle;
+    rv = bundleService->CreateBundle(NEWS_MSGS_URL, getter_AddRefs(bundle));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    nsString saveUsernameText;
+    rv = bundle->GetStringFromName(NS_LITERAL_STRING("saveUsername").get(),
+                                   getter_Copies(saveUsernameText));
+    NS_ENSURE_SUCCESS(rv, rv);
+
+    rv = promptSvc->Prompt(nsnull, nsString(aPromptTitle).get(),
+                           nsString(aPromptMessage).get(),
+                           getter_Copies(uniGroupUsername),
+                           saveUsernameText.get(), &saveUsername,
+                           &okayValue);
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if (!okayValue) // if the user pressed cancel, just return NULL;
     {
       aGroupUsername.Truncate();
       return rv;
     }
 
+    if (saveUsername)
+    {
+      nsCOMPtr<nsILoginInfo> login =
+        do_CreateInstance("@mozilla.org/login-manager/loginInfo;1", &rv);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = login->SetHostname(NS_ConvertASCIItoUTF16(hostnameURL));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = login->SetHttpRealm(NS_ConvertASCIItoUTF16(signonURL));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = login->SetPassword(uniGroupUsername);
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      // Apparently there is a small difference between empty strings and null
+      // strings, but setting these to empty works for us.
+      rv = login->SetUsername(EmptyString());
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = login->SetUsernameField(EmptyString());
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = login->SetPasswordField(EmptyString());
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      rv = loginMgr->AddLogin(login);
+      NS_ENSURE_SUCCESS(rv, rv);
+    }
+
     // we got a username back, remember it
     rv = SetGroupUsername(NS_LossyConvertUTF16toASCII(uniGroupUsername));
     if (NS_FAILED(rv)) return rv;
 
   } // if the password is empty
 
   rv = GetGroupUsername(aGroupUsername);
   mPrevUsername = aGroupUsername;
new file mode 100644
--- /dev/null
+++ b/mailnews/news/test/unit/test_nntpPassword3.js
@@ -0,0 +1,65 @@
+/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/**
+ * Extra tests for forgetting newsgroup usernames and passwords.
+ */
+
+do_import_script("../mailnews/test/resources/mailTestUtils.js");
+
+const kUsername = "testnews";
+const kPassword = "newstest";
+const kProtocol = "nntp";
+const kHostname = "localhost";
+const kServerUrl = "news://" + kHostname;
+
+function run_test()
+{
+  // Login Manager
+  var loginMgr = Cc["@mozilla.org/login-manager;1"].getService(Ci.nsILoginManager);
+
+  // Passwords File (generated from Mozilla 1.8 branch).
+  var signons = do_get_file("../mailnews/test/data/signons-mailnews1.8.txt");
+
+  // Copy the file to the profile directory for a PAB
+  signons.copyTo(gProfileDir, "signons.txt");
+
+  // Set up the basic accounts and folders.
+  loadLocalMailAccount();
+
+  var acctMgr = Cc["@mozilla.org/messenger/account-manager;1"]
+                  .getService(Ci.nsIMsgAccountManager);
+
+  var incomingServer = acctMgr.createIncomingServer(null, kHostname,
+                                                    kProtocol);
+
+  var i;
+  var count = {};
+
+  // Test - Check there is a password to begin with...
+  var logins = loginMgr.findLogins(count, kServerUrl, null,
+                                   kServerUrl + "/#password");
+
+  do_check_eq(count.value, 1);
+  do_check_eq(logins[0].password, kPassword);
+
+  // ...and a username.
+  var logins = loginMgr.findLogins(count, kServerUrl, null,
+                                   kServerUrl + "/#username");
+
+  do_check_eq(count.value, 1);
+  do_check_eq(logins[0].password, kUsername);
+
+  // Test - Remove the news password login via the incoming server
+  incomingServer.forgetPassword();
+
+  logins = logins = loginMgr.findLogins(count, kServerUrl, null,
+                                        kServerUrl + "/#password");
+
+  // should be no passwords left...
+  do_check_eq(count.value, 0);
+
+  logins = logins = loginMgr.findLogins(count, kServerUrl, null,
+                                        kServerUrl + "/#username");
+
+  // ...and no usernames left either.
+  do_check_eq(count.value, 0);
+}
new file mode 100644
--- /dev/null
+++ b/mailnews/test/data/signons-mailnews1.8-multiple.txt
@@ -0,0 +1,26 @@
+#2c
+.
+mailbox://testpop3@localhost
+\=username=\
+~
+*\=password=\
+~cG9wM3Rlc3Q=
+.
+mailbox://testpop3a@localhost
+\=username=\
+~
+*\=password=\
+~c210cHRlc3Q=
+.
+smtp://testsmtp@localhost
+\=username=\
+~
+*\=password=\
+~c210cHRlc3Q=
+.
+smtp://testsmtpa@localhost
+\=username=\
+~
+*\=password=\
+~cG9wM3Rlc3Q=
+.
--- a/suite/confvars.sh
+++ b/suite/confvars.sh
@@ -43,12 +43,12 @@ if [ "$COMM_BUILD" ]; then
   MOZ_LDAP_XPCOM=1
 fi
 MOZ_STATIC_MAIL_BUILD=1
 MOZ_COMPOSER=1
 MOZ_SUITE=1
 MOZ_APP_VERSION=`cat $topsrcdir/$MOZ_BUILD_APP/config/version.txt`
 SEAMONKEY_VERSION=$MOZ_APP_VERSION
 MOZ_NO_XPCOM_OBSOLETE=1
-MOZ_EXTENSIONS_DEFAULT=" wallet venkman inspector irc gnomevfs reporter"
+MOZ_EXTENSIONS_DEFAULT=" venkman inspector irc gnomevfs reporter"
 MOZ_PLACES=1
 MOZ_UPDATER=1
 MOZ_HELP_VIEWER=1
--- a/suite/installer/removed-files.in
+++ b/suite/installer/removed-files.in
@@ -72,26 +72,39 @@ components/nsKillAll.js
 components/nsResetPref.js
 components/nsScriptableIO.js
 components/nsSetDefaultBrowser.js
 components/nsSetDefaultMail.js
 components/nsUnsetDefaultMail.js
 components/nsXmlRpcClient.js
 components/progressDlg.xpt
 components/search.xpt
+components/sigonviewer.xpt
 components/sidebar.xpt
 components/@DLL_PREFIX@srchsvc@DLL_SUFFIX@
 components/suitetypeaheadfind.xpt
 components/@DLL_PREFIX@suitetypeaheadfind@DLL_SUFFIX@
 components/urlwidgt.xpt
 components/util.xpt
 components/venkman-service.js
+components/@DLL_PREFIX@wallet@DLL_SUFFIX@
+components/@DLL_PREFIX@walletviewers@DLL_SUFFIX@
+components/wallet.xpt
+components/walleteditor.xpt
+components/walletpreview.xpt
 components/@DLL_PREFIX@xmlextras@DLL_SUFFIX@
 components/winhooks.xpt
 components/xml-rpc.xpt
+defaults/wallet/VcardSchema.tbl
+defaults/wallet/FieldSchema.tbl
+defaults/wallet/SchemaConcat.tbl
+defaults/wallet/DistinguishedSchema.tbl
+defaults/wallet/SchemaStrings.tbl
+defaults/wallet/PositionalSchema.tbl
+defaults/wallet/StateSchema.tbl
 @DLL_PREFIX@xpistub@DLL_SUFFIX@
 res/cmessage.txt
 LICENSE
 #ifdef XP_WIN
 #ifdef MOZ_MEMORY
 Microsoft.VC80.CRT.manifest
 msvcm80.dll
 msvcp80.dll
--- a/suite/installer/unix/packages
+++ b/suite/installer/unix/packages
@@ -185,17 +185,16 @@ bin/components/libremoteservice.so
 bin/components/librdf.so
 bin/components/rdf.xpt
 bin/components/libsatchel.so
 bin/components/libspellchecker.so
 bin/components/satchel.xpt
 bin/components/saxparser.xpt
 bin/components/shistory.xpt
 bin/components/shellservice.xpt
-bin/components/signonviewer.xpt
 bin/components/spellchecker.xpt
 bin/components/storage.xpt
 bin/components/libstoragecomps.so
 bin/components/libsuite.so
 bin/components/suitebrowser.xpt
 bin/components/suitecommon.xpt
 bin/components/suitemigration.xpt
 bin/components/libsystem-pref.so
@@ -209,21 +208,16 @@ bin/components/txtsvc.xpt
 bin/components/libuconv.so
 bin/components/uconv.xpt
 bin/components/unicharutil.xpt
 bin/components/libucvmath.so
 bin/components/libuniversalchardet.so
 bin/components/update.xpt
 bin/components/uriloader.xpt
 bin/components/urlformatter.xpt
-bin/components/libwallet.so
-bin/components/libwalletviewers.so
-bin/components/wallet.xpt
-bin/components/walleteditor.xpt
-bin/components/walletpreview.xpt
 bin/components/webBrowser_core.xpt
 bin/components/webbrowserpersist.xpt
 bin/components/libwebbrwsr.so
 bin/components/webshell_idls.xpt
 bin/components/widget.xpt
 bin/components/libwidget_gtk2.so
 bin/components/libwindowds.so
 bin/components/windowds.xpt
@@ -276,16 +270,17 @@ bin/components/nsSuiteGlue.js
 bin/components/nsTaggingService.js
 bin/components/nsTypeAheadFind.js
 bin/components/nsTryToClose.js
 bin/components/nsUpdateService.js
 bin/components/nsURLFormatter.js
 bin/components/nsWebHandlerApp.js
 bin/components/pluginGlue.js
 bin/components/storage-Legacy.js
+bin/components/storage-mozStorage.js
 bin/components/txEXSLTRegExFunctions.js
 
 ; Modules
 bin/modules/*
 bin/modules/gloda/*
 
 ; Safe Browsing
 
@@ -351,25 +346,16 @@ bin/extensions/modern@themes.mozilla.org
 bin/extensions/modern@themes.mozilla.org/preview.png
 
 ; Default Preferences
 ; All the pref files must be part of base to prevent migration bugs
 bin/defaults/autoconfig/*
 bin/defaults/pref/*
 bin/greprefs/*
 
-; Wallet schemas
-bin/defaults/wallet/VcardSchema.tbl
-bin/defaults/wallet/FieldSchema.tbl
-bin/defaults/wallet/SchemaConcat.tbl
-bin/defaults/wallet/DistinguishedSchema.tbl
-bin/defaults/wallet/SchemaStrings.tbl
-bin/defaults/wallet/PositionalSchema.tbl
-bin/defaults/wallet/StateSchema.tbl
-
 ; LDAP components need to be in the browser for AutoConfig
 bin/libldap60.so
 bin/libldif60.so
 bin/libprldap60.so
 bin/components/libmozldap.so
 bin/components/mozldap.xpt
 bin/components/nsLDAPProtocolHandler.js
 
--- a/suite/installer/windows/packages
+++ b/suite/installer/windows/packages
@@ -187,17 +187,16 @@ bin\components\profile.xpt
 bin\components\proxyObject.xpt
 bin\components\rdf.dll
 bin\components\rdf.xpt
 bin\components\satchel.dll
 bin\components\satchel.xpt
 bin\components\saxparser.xpt
 bin\components\shellservice.xpt
 bin\components\shistory.xpt
-bin\components\signonviewer.xpt
 bin\components\storage.xpt
 bin\components\strgcmps.dll
 bin\components\suite.dll
 bin\components\suitebrowser.xpt
 bin\components\suitecommon.xpt
 bin\components\suitemigration.xpt
 bin\components\tkautoc.dll
 bin\components\tkitcmps.dll
@@ -207,20 +206,16 @@ bin\components\txmgr.xpt
 bin\components\txtsvc.xpt
 bin\components\uconv.dll
 bin\components\uconv.xpt
 bin\components\unicharutil.xpt
 bin\components\universalchardet.dll
 bin\components\update.xpt
 bin\components\uriloader.xpt
 bin\components\urlformatter.xpt
-bin\components\wallet.dll
-bin\components\wallet.xpt
-bin\components\walleteditor.xpt
-bin\components\walletpreview.xpt
 bin\components\webBrowser_core.xpt
 bin\components\webbrowserpersist.xpt
 bin\components\webbrwsr.dll
 bin\components\webshell_idls.xpt
 bin\components\widget.xpt
 bin\components\windowds.dll
 bin\components\windowds.xpt
 bin\components\windowwatcher.xpt
@@ -276,16 +271,17 @@ bin\components\nsSetDefault.js
 bin\components\nsSidebar.js
 bin\components\nsSuiteGlue.js
 bin\components\nsTaggingService.js
 bin\components\nsTypeAheadFind.js
 bin\components\nsUpdateService.js
 bin\components\nsURLFormatter.js
 bin\components\pluginGlue.js
 bin\components\storage-Legacy.js
+bin\components\storage-mozStorage.js
 bin\components\txEXSLTRegExFunctions.js
 bin\components\nsAboutAbout.js
 bin\components\nsDefaultCLH.js
 bin\components\nsHandlerService.js
 bin\components\nsWebHandlerApp.js
 
 ; Modules
 bin\modules\*
@@ -398,23 +394,16 @@ bin\res\charsetalias.properties
 bin\res\charsetData.properties
 bin\res\langGroups.properties
 bin\res\language.properties
 bin\res\wincharset.properties
 bin\res\entityTables\*
 bin\res\dtd\*
 bin\res\fonts\*
 bin\res\html\*
-bin\defaults\wallet\VcardSchema.tbl
-bin\defaults\wallet\FieldSchema.tbl
-bin\defaults\wallet\SchemaConcat.tbl
-bin\defaults\wallet\DistinguishedSchema.tbl
-bin\defaults\wallet\SchemaStrings.tbl
-bin\defaults\wallet\PositionalSchema.tbl
-bin\defaults\wallet\StateSchema.tbl
 
 ; MathML, optional for MathML charset conversion
 bin\components\ucvmath.dll
 bin\res\mathml.css
 bin\res\entityTables\mathml20.properties
 bin\res\fonts\mathfont.properties
 bin\res\fonts\mathfontCMEX10.properties
 bin\res\fonts\mathfontCMSY10.properties
--- a/suite/locales/en-US/chrome/mailnews/news.properties
+++ b/suite/locales/en-US/chrome/mailnews/news.properties
@@ -42,16 +42,18 @@ htmlNewsErrorTitle=Error!
 htmlNewsError=<H1>Error!</H1>newsgroup server responded: 
 # LOCALIZATION NOTE ( articleExpired ): In the following item, translate only "Perhaps the article has expired"
 articleExpired=<B><P>Perhaps the article has expired</P></B>
 removeExpiredArtLinkText=Click here to remove all expired articles
 cancelDisallowed=This message does not appear to be from you.  You may only cancel your own posts, not those made by others.
 cancelConfirm=Are you sure you want to cancel this message?
 messageCancelled=Message cancelled.
 enterUsername=Please enter a username for news server access:
+enterUsernameTitle=News Server Username Required
+saveUsername=Use Password Manager to remember this value.
 enterPassword=Please enter a password for news server access:
 enterPasswordTitle=News Server Password Required
 okButtonText=Download
 
 noNewMessages=There are no new messages on the server.
 downloadingHeaders=Downloading %S of %S headers
 downloadingFilterHeaders=Getting headers for filters: %S (%S/%S)
 downloadingArticles=Downloading articles %S-%S