Bug 437886 - nsIMsgDBService::openFolderDB unusable from JS. r/sr=bienvenu
authorJoshua Cranmer <Pidgeot18@gmail.com>
Fri, 19 Dec 2008 15:49:44 -0500
changeset 1462 e10a3baac8d7d6c7ce987e315134a9047d0de4f1
parent 1461 b145e4360b313bc96ac602e803168c45a82dce8b
child 1463 6611a5482754b877307350dcb19bdd7dc15312fd
push id1161
push userPidgeot18@gmail.com
push dateFri, 19 Dec 2008 20:53:50 +0000
treeherdercomm-central@e10a3baac8d7 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs437886
Bug 437886 - nsIMsgDBService::openFolderDB unusable from JS. r/sr=bienvenu
mailnews/base/public/nsIMsgFolder.idl
mailnews/base/search/src/nsMsgFilterService.cpp
mailnews/base/search/src/nsMsgLocalSearch.cpp
mailnews/base/src/nsMsgFolderCompactor.cpp
mailnews/db/msgdb/public/nsIMsgDatabase.idl
mailnews/db/msgdb/src/nsMsgDatabase.cpp
mailnews/db/msgdb/test/unit/test_maildb.js
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsParseMailbox.cpp
mailnews/news/src/nsNewsFolder.cpp
--- a/mailnews/base/public/nsIMsgFolder.idl
+++ b/mailnews/base/public/nsIMsgFolder.idl
@@ -413,16 +413,29 @@ interface nsIMsgFolder : nsISupports {
   void addMessageDispositionState(in nsIMsgDBHdr aMessage,
                                   in nsMsgDispositionState aDispositionFlag);
 
   void markMessagesRead(in nsIArray messages, in boolean markRead);
   void markAllMessagesRead(in nsIMsgWindow aMsgWindow);
   void markMessagesFlagged(in nsIArray messages, in boolean markFlagged);
   void markThreadRead(in nsIMsgThread thread);
   void setLabelForMessages(in nsIArray messages, in nsMsgLabelValue label);
+  /**
+   * Gets the message database for the folder.
+   *
+   * Note that if the database is out of date, the implementation MAY choose to
+   * throw an error. For a handle to the database which MAY NOT throw an error,
+   * one can use getDBFolderInfoAndDB.
+   *
+   * @exception NS_MSG_ERROR_FOLDER_SUMMARY_MISSING If the database does not
+   *                         exist.
+   * @exception NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE If the database contains
+   *                         out of date information.
+   * @see nsIMsgFolder::getDBFolderInfoAndDB.
+   */
   nsIMsgDatabase getMsgDatabase(in nsIMsgWindow msgWindow);
   void setMsgDatabase (in nsIMsgDatabase msgDatabase);
   /**
    * Get the backup message database, used in reparsing. This database must
    * be created first using closeAndBackupFolderDB()
    *
    * @return   backup message database
    */
--- a/mailnews/base/search/src/nsMsgFilterService.cpp
+++ b/mailnews/base/search/src/nsMsgFilterService.cpp
@@ -385,17 +385,17 @@ nsresult nsMsgFilterAfterTheFact::Advanc
 {
   if (m_curFolderIndex >= m_numFolders)
     return OnEndExecution(NS_OK);
 
   nsresult rv = m_folders->QueryElementAt(m_curFolderIndex++, NS_GET_IID(nsIMsgFolder), getter_AddRefs(m_curFolder));
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
   rv = m_curFolder->GetDBFolderInfoAndDB(getter_AddRefs(dbFolderInfo), getter_AddRefs(m_curFolderDB));
-  if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
+  if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
   {
     nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(m_curFolder, &rv);
     if (NS_SUCCEEDED(rv) && localFolder)
       return localFolder->ParseFolder(m_msgWindow, this);
   }
   return RunNextFilter();
 }
 
--- a/mailnews/base/search/src/nsMsgLocalSearch.cpp
+++ b/mailnews/base/search/src/nsMsgLocalSearch.cpp
@@ -301,17 +301,16 @@ nsresult nsMsgSearchOfflineMail::OpenSum
     }
     else
       return err; // not sure why m_folder wouldn't be set.
 
     switch (err)
     {
         case NS_OK:
             break;
-        case NS_MSG_ERROR_FOLDER_SUMMARY_MISSING:
         case NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE:
           {
             nsCOMPtr<nsIMsgLocalMailFolder> localFolder = do_QueryInterface(scopeFolder, &err);
             if (NS_SUCCEEDED(err) && localFolder)
             {
               nsCOMPtr<nsIMsgSearchSession> searchSession;
               m_scope->GetSearchSession(getter_AddRefs(searchSession));
               if (searchSession)
--- a/mailnews/base/src/nsMsgFolderCompactor.cpp
+++ b/mailnews/base/src/nsMsgFolderCompactor.cpp
@@ -197,17 +197,18 @@ nsFolderCompactState::Compact(nsIMsgFold
    nsCString baseMessageURI;
 
    nsCOMPtr <nsIMsgLocalMailFolder> localFolder = do_QueryInterface(folder, &rv);
    if (NS_SUCCEEDED(rv) && localFolder)
    {
      rv=localFolder->GetDatabaseWOReparse(getter_AddRefs(db));
      if (NS_FAILED(rv) || !db)
      {
-       if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
+       if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING ||
+           rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
        {
          m_folder = folder;  //will be used to compact
          m_parsingFolder = PR_TRUE;
          rv = localFolder->ParseFolder(m_window, this);
        }
        return rv;
      }
      else
--- a/mailnews/db/msgdb/public/nsIMsgDatabase.idl
+++ b/mailnews/db/msgdb/public/nsIMsgDatabase.idl
@@ -15,31 +15,49 @@
  * 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) 1999
  * the Initial Developer. All Rights Reserved.
  *
  * Contributor(s):
+ *   Joshua Cranmer <Pidgeot18@gmail.com>
  *
  * Alternatively, the contents of this file may be used under the terms of
  * either of 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 ***** */
 
+/**
+ * @defgroup msgdb Mailnews message database
+ * This module is the access point to locally-stored databases.
+ *
+ * These databases are stored in .msf files. Each file contains useful cached
+ * information, like the message id or references, as well as the cc header or
+ * tag information. This cached information is encapsulated in nsIMsgDBHdr.
+ *
+ * Also included is threading information, mostly encapsulated in nsIMsgThread.
+ * The final component is the database folder info, which contains information
+ * on the view and basic information also stored in the folder cache such as the
+ * name or most recent update.
+ *
+ * What this module does not do is access individual messages. Access is
+ * strictly controlled by the nsIMsgFolder objects and their backends.
+ * @{
+ */
 #include "nsISupports.idl"
 #include "MailNewsTypes2.idl"
 #include "nsIDBChangeAnnouncer.idl"
 #include "nsIMsgDBView.idl"
 
 %{C++
 #include "nsTArray.h"
 %}
@@ -101,58 +119,129 @@ interface nsMsgDBCommitType
   const long kLargeCommit = 1;
   const long kSessionCommit = 2;
   const long kCompressCommit = 3;
 };
 
 [ref] native nsMsgKeyArrayRef(nsTArray<nsMsgKey>);
 [ptr] native nsMsgKeyArrayPtr(nsTArray<nsMsgKey>);
 
-[scriptable, uuid(03223c50-1e88-45e8-ba1a-7ce792dc3fc3)]
+/**
+ * A service to open mail databases and manipulate listeners automatically.
+ *
+ * The contract ID for this component is
+ * <tt>\@mozilla.org/msgDatabase/msgDBService;1</tt>.
+ */
+[scriptable, uuid(26cb7242-a4ba-4811-ad7b-ff993450aae3)]
 interface nsIMsgDBService : nsISupports
 {
-    // want to remove this method from nsIMsgDatabase...
-    // if a db is opened on the folder, the listener will automatically be added
-
   /**
-   * Opens a database folder.
+   * Opens a database for a given folder.
+   *
+   * This method is preferred over nsIMsgDBService::openMailDBFromFile if the
+   * caller has an actual nsIMsgFolder around. If the database detects that it
+   * is unreadable or out of date (using nsIMsgDatabase::outOfDate) it will
+   * destroy itself and prepare to be rebuilt, unless aLeaveInvalidDB is true.
    *
-   * @param aFolderName     The name of the folder to create.
-   * @param aCreate         Whether or not the file should be created.
-   * @param aLeaveInvalidDB Set to true if you do not want the database to be
-   *                        deleted if it is invalid.
-   * @return                A new nsIMsgDatabase object representing the
-   *                        folder database that was opened.
+   * If one gets a NS_MSG_ERROR_FOLDER_SUMMARY_MISSING message, then one
+   * should call nsIMsgDBService::createNewDB to create the new database.
+   *
+   * @param aFolder         The folder whose database should be returned.
+   * @param aLeaveInvalidDB Whether or not the database should be deleted if it
+   *                        is invalid.
+   * @return                A new nsIMsgDatabase object representing the folder
+   *                        database that was opened.
    * @exception NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
-   *                        aFolderName doesn't exist and aCreate was false.
+   *                        The file could not be created.
    * @exception NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE
    *                        The database is present (and was opened), but the
    *                        summary file is out of date.
    * @exception NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
-   *                        The database is present (and was opened), but the
-   *                        summary file is missing.
+   *                        The database is present, but the summary file is
+   *                        missing.
+   * @see nsIMsgDatabase::Open
+   * @see nsIMsgDBService::createNewDB
+   */
+  nsIMsgDatabase openFolderDB(in nsIMsgFolder aFolder,
+                              in boolean aLeaveInvalidDB);
+
+  /**
+   * Creates a new database for the given folder.
+   *
+   * If the database already exists, it will return the database, emit a
+   * warning, but not fully initialize it. For this reason, it should only be
+   * used when it is known that the database does not exist, such as when
+   * nsIMsgDBService::openFolderDB throws an error.
+   *
+   * @see nsIMsgDBService::openFolderDB
    */
-  nsIMsgDatabase openFolderDB(in nsIMsgFolder aFolder, in boolean aCreate,
-                              in boolean aLeaveInvalidDB);
-    nsIMsgDatabase openMailDBFromFile(in nsILocalFile aFolderName, in boolean aCreate, in boolean aLeaveInvalidDB);
-    void registerPendingListener(in nsIMsgFolder aFolder, in nsIDBChangeListener aListener);
-    void unregisterPendingListener(in nsIDBChangeListener aListener);
+  nsIMsgDatabase createNewDB(in nsIMsgFolder aFolder);
+
+  /**
+   * Opens or creates a database for a given file.
+   *
+   * This method should only be used if the caller does not have a folder
+   * instance, because the resulting db and message headers retrieved from the
+   * database would not know their owning folder, which limits their usefulness.
+   * For this reason, one should use nsIMsgDBService::openFolderDB instead
+   * except under special circumstances.
+   *
+   * Unlike nsIMsgDBService::openFolderDB, there is no corresponding method to
+   * create a new database if opening the database failed. However, this method
+   * will never throw NS_MSG_ERROR_FOLDER_SUMMARY_MISSING, so no corresponding
+   * method is needed.
+   *
+   * @param aFile           The file for which the database should be returned.
+   * @param aCreate         Whether or not the file should be created.
+   * @param aLeaveInvalidDB Whether or not the database should be deleted if it
+   *                        is invalid.
+   * @return                A new nsIMsgDatabase object encapsulating the file
+   *                        passed in.
+   * @exception NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
+   *                        The file could not be created.
+   * @see nsIMsgDBService::openFolderDB
+   * @see nsIMsgDatabase::Open
+   */
+  nsIMsgDatabase openMailDBFromFile(in nsILocalFile aFile,
+                                    in boolean aCreate,
+                                    in boolean aLeaveInvalidDB);
+  /**
+   * Adds the given listener to the listener set for the folder.
+   *
+   * Since the message database will likely be opened and closed many times, by
+   * registering using this method, one will be guaranteed to see all subsequent
+   * modifications. This will also add the listener to the database if it is
+   * already opened.
+   *
+   * @param aFolder         The folder to add a listener to.
+   * @param aListener       The listener to add the folder to.
+   */
+  void registerPendingListener(in nsIMsgFolder aFolder,
+                               in nsIDBChangeListener aListener);
+  /**
+   * Removes the listener from all folder listener sets.
+   *
+   * @param aListener       The listener to remove.
+   * @exception NS_ERROR_FAILURE
+   *                        The listener is not registered.
+   */
+  void unregisterPendingListener(in nsIDBChangeListener aListener);
 };
 
 [scriptable, uuid(55EEECA9-FCF6-4a94-A9D4-0ECFBAAE8CAA)]
 interface nsIMsgDatabase : nsIDBChangeAnnouncer {
   /**
    * Opens a database folder.
    *
    * @param aFolderName     The name of the folder to create.
    * @param aCreate         Whether or not the file should be created.
    * @param aLeaveInvalidDB Set to true if you do not want the database to be
    *                        deleted if it is invalid.
    * @exception NS_ERROR_FILE_TARGET_DOES_NOT_EXIST
-   *                        aFolderName doesn't exist and aCreate was false.
+   *                        The file could not be created.
    * @exception NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE
    *                        The database is present (and was opened), but the
    *                        summary file is out of date.
    * @exception NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
    *                        The database is present (and was opened), but the
    *                        summary file is missing.
    */
   void Open(in nsILocalFile aFolderName, in boolean aCreate,
@@ -352,9 +441,9 @@ interface nsIMsgDatabase : nsIDBChangeAn
   // These are used for caching search hits in a db, to speed up saved search folders.
   nsISimpleEnumerator getCachedHits(in string aSearchFolderUri);
   void refreshCache(in string aSearchFolderUri, in unsigned long aNumKeys, [array, size_is (aNumKeys)] in nsMsgKey aNewHits,
      out unsigned long aNumBadHits, [array, size_is(aNumBadHits)] out nsMsgKey aStaleHits);
   void updateHdrInCache(in string aSearchFolderUri, in nsIMsgDBHdr aHdr, in boolean aAdd);
   boolean hdrIsInCache(in string aSearchFolderUri, in nsIMsgDBHdr aHdr);
 
 };
-
+/** @} */
--- a/mailnews/db/msgdb/src/nsMsgDatabase.cpp
+++ b/mailnews/db/msgdb/src/nsMsgDatabase.cpp
@@ -97,17 +97,19 @@ nsMsgDBService::nsMsgDBService()
 {
 }
 
 
 nsMsgDBService::~nsMsgDBService()
 {
 }
 
-NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder, PRBool aCreate, PRBool aLeaveInvalidDB, nsIMsgDatabase **_retval)
+NS_IMETHODIMP nsMsgDBService::OpenFolderDB(nsIMsgFolder *aFolder,
+                                           PRBool aLeaveInvalidDB,
+                                           nsIMsgDatabase **_retval)
 {
   NS_ENSURE_ARG(aFolder);
   nsMsgDatabase *cacheDB = (nsMsgDatabase *) nsMsgDatabase::FindInCache(aFolder);
   if (cacheDB)
   {
     // this db could have ended up in the folder cache w/o an m_folder pointer via
     // OpenMailDBFromFile. If so, take this chance to fix the folder.
     if (!cacheDB->m_folder)
@@ -123,20 +125,22 @@ NS_IMETHODIMP nsMsgDBService::OpenFolder
   incomingServer->GetLocalStoreType(localStoreType);
   nsCAutoString dbContractID(NS_MSGDB_CONTRACTID);
   dbContractID.Append(localStoreType.get());
   nsCOMPtr <nsIMsgDatabase> msgDB = do_CreateInstance(dbContractID.get(), &rv);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr <nsILocalFile> folderPath;
   rv = aFolder->GetFilePath(getter_AddRefs(folderPath));
   NS_ENSURE_SUCCESS(rv, rv);
-  rv = msgDB->Open(folderPath, aCreate, aLeaveInvalidDB);
-  if (NS_FAILED(rv) && (rv != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
-    && rv != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE || !aCreate))
+
+  // Don't try to create the database yet--let the createNewDB call do that.
+  rv = msgDB->Open(folderPath, PR_FALSE, aLeaveInvalidDB);
+  if (NS_FAILED(rv) && rv != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
     return rv;
+
   NS_IF_ADDREF(*_retval = msgDB);
   nsMsgDatabase *msgDatabase = static_cast<nsMsgDatabase *>(*_retval);
   msgDatabase->m_folder = aFolder;
 
   if (NS_FAILED(rv))
   {
 #ifdef DEBUG
     // Doing these checks for debug only as we don't want to report certain
@@ -202,16 +206,54 @@ NS_IMETHODIMP nsMsgDBService::OpenMailDB
   if (rv == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
     return rv;
   NS_IF_ADDREF(*pMessageDB = msgDB);
   if (aCreate && msgDB && rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
     rv = NS_OK;
   return rv;
 }
 
+NS_IMETHODIMP nsMsgDBService::CreateNewDB(nsIMsgFolder *aFolder,
+                                          nsIMsgDatabase **_retval)
+{
+  NS_ENSURE_ARG(aFolder);
+  
+  nsCOMPtr <nsIMsgIncomingServer> incomingServer;
+  nsresult rv = aFolder->GetServer(getter_AddRefs(incomingServer));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCString localStoreType;
+  incomingServer->GetLocalStoreType(localStoreType);
+  nsCAutoString dbContractID(NS_MSGDB_CONTRACTID);
+  dbContractID.Append(localStoreType.get());
+  
+  nsCOMPtr <nsIMsgDatabase> msgDB = do_CreateInstance(dbContractID.get(), &rv);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsCOMPtr <nsILocalFile> folderPath;
+  rv = aFolder->GetFilePath(getter_AddRefs(folderPath));
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  rv = msgDB->Open(folderPath, PR_TRUE, PR_TRUE);
+  NS_ENSURE_TRUE(rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING, rv);
+
+  NS_IF_ADDREF(*_retval = msgDB);
+  nsMsgDatabase *msgDatabase = static_cast<nsMsgDatabase *>(*_retval);
+  msgDatabase->m_folder = aFolder;
+
+  // Add all pending listeners to the database
+  for (PRInt32 listenerIndex = 0;
+       listenerIndex < m_foldersPendingListeners.Count(); listenerIndex++)
+  {
+    if (m_foldersPendingListeners[listenerIndex] == aFolder)
+      msgDatabase->AddListener(m_pendingListeners.ObjectAt(listenerIndex));
+  }
+  return NS_OK;
+}
+
 /* void registerPendingListener (in nsIMsgFolder aFolder, in nsIDBChangeListener aListener); */
 NS_IMETHODIMP nsMsgDBService::RegisterPendingListener(nsIMsgFolder *aFolder, nsIDBChangeListener *aListener)
 {
   // need to make sure we don't hold onto these forever. Maybe a shutdown listener?
   // if there is a db open on this folder already, we should register the listener.
   m_foldersPendingListeners.AppendObject(aFolder);
   m_pendingListeners.AppendObject(aListener);
   nsCOMPtr <nsIMsgDatabase> openDB;
--- a/mailnews/db/msgdb/test/unit/test_maildb.js
+++ b/mailnews/db/msgdb/test/unit/test_maildb.js
@@ -10,18 +10,18 @@ function run_test() {
   // Get the root folder
   var root = gLocalIncomingServer.rootFolder;
 
   root.createSubfolder("dbTest", null);
   var dbService = Components.classes["@mozilla.org/msgDatabase/msgDBService;1"]
                           .getService(Components.interfaces.nsIMsgDBService);
                         
   var folder = root.getChildNamed("dbTest");
-  var db = dbService.openFolderDB(folder, true, true);
+  var db = dbService.openFolderDB(folder, true);
   do_check_neq(db, null);
   db.dBFolderInfo.highWater = 10;
   db.Close(true);
-  db = dbService.openFolderDB(folder, true, true);
+  db = dbService.openFolderDB(folder, true);
   do_check_neq(db, null);
   do_check_eq(db.dBFolderInfo.highWater, 10);
   db.dBFolderInfo.onKeyAdded(15);
   do_check_eq(db.dBFolderInfo.highWater, 15);
 }
--- a/mailnews/imap/src/nsImapMailFolder.cpp
+++ b/mailnews/imap/src/nsImapMailFolder.cpp
@@ -649,46 +649,41 @@ NS_IMETHODIMP nsImapMailFolder::GetSubFo
 
   return aResult ? NS_NewArrayEnumerator(aResult, mSubFolders) : NS_ERROR_NULL_POINTER;
 }
 
 //Makes sure the database is open and exists.  If the database is valid then
 //returns NS_OK.  Otherwise returns a failure error value.
 nsresult nsImapMailFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
 {
-  nsresult folderOpen = NS_OK;
+  nsresult rv = NS_OK;
   if (!mDatabase)
   {
-    nsresult rv;
     nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
-    folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_FALSE, getter_AddRefs(mDatabase));
-
-    if (NS_FAILED(folderOpen) && folderOpen != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-      folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
-
-    if (NS_FAILED(folderOpen) && folderOpen != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-      return folderOpen;
-
-    if(folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-      folderOpen = NS_OK;
+    // Create the database, blowing it away if it needs to be rebuilt
+    rv = msgDBService->OpenFolderDB(this, PR_FALSE, getter_AddRefs(mDatabase));
+    if (NS_FAILED(rv))
+      rv = msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
+
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if(mDatabase)
     {
       UpdateNewMessages();
       if(mAddListener)
         mDatabase->AddListener(this);
       // UpdateSummaryTotals can null mDatabase during initialization, so we save a local copy
       nsCOMPtr<nsIMsgDatabase> database(mDatabase);
       UpdateSummaryTotals(PR_TRUE);
       mDatabase = database;
     }
   }
-  return folderOpen;
+  return rv;
 }
 
 NS_IMETHODIMP nsImapMailFolder::UpdateFolder(nsIMsgWindow * inMsgWindow)
 {
   return UpdateFolder(inMsgWindow, nsnull);
 }
 
 NS_IMETHODIMP nsImapMailFolder::UpdateFolder(nsIMsgWindow *msgWindow, nsIUrlListener *aUrlListener)
@@ -2554,22 +2549,18 @@ NS_IMETHODIMP nsImapMailFolder::UpdateIm
 
     nsCOMPtr <nsILocalFile> summaryFile;
     GetSummaryFileLocation(pathFile, getter_AddRefs(summaryFile));
     // Remove summary file.
     summaryFile->Remove(PR_FALSE);
 
     // Create a new summary file, update the folder message counts, and
     // Close the summary file db.
-    rv = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
-
-    // ********** Important *************
-    // David, help me here I don't know this is right or wrong
-    if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-      rv = NS_OK;
+    PRBool created;
+    rv = msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
 
     if (NS_FAILED(rv) && mDatabase)
     {
       mDatabase->ForceClosed();
       mDatabase = nsnull;
     }
     else if (NS_SUCCEEDED(rv) && mDatabase)
     {
--- a/mailnews/local/src/nsLocalMailFolder.cpp
+++ b/mailnews/local/src/nsLocalMailFolder.cpp
@@ -458,17 +458,19 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetD
   if (m_parsingFolder)
     return NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE;
 
   nsresult rv = NS_OK;
   if (!mDatabase)
   {
     nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
-    rv = msgDBService->OpenFolderDB(this, PR_FALSE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(mDatabase));
+    
+    rv = msgDBService->OpenFolderDB(this, PR_TRUE, getter_AddRefs(mDatabase));
+
     if (mDatabase && NS_SUCCEEDED(rv))
     {
       mDatabase->AddListener(this);
       UpdateNewMessages();
     }
   }
   NS_IF_ADDREF(*aDatabase = mDatabase);
   return rv;
@@ -496,31 +498,30 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetD
     nsCOMPtr <nsILocalFile> pathFile;
     rv = GetFilePath(getter_AddRefs(pathFile));
     if (NS_FAILED(rv)) return rv;
     PRBool exists;
     rv = pathFile->Exists(&exists);
     NS_ENSURE_SUCCESS(rv,rv);
     if (!exists)
       return NS_ERROR_NULL_POINTER;  //mDatabase will be null at this point.
-    nsresult folderOpen = NS_OK;
     nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
-    folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
-    if(NS_FAILED(folderOpen) && folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
+
+    nsresult folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE,
+                                                     getter_AddRefs(mDatabase));
+    if (folderOpen == NS_ERROR_FILE_TARGET_DOES_NOT_EXIST)
     {
       nsCOMPtr <nsIDBFolderInfo> dbFolderInfo;
       nsCOMPtr <nsIDBFolderInfo> transferInfo;
       if (mDatabase)
       {
         mDatabase->GetDBFolderInfo(getter_AddRefs(dbFolderInfo));
         if (dbFolderInfo)
         {
-          if (folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-            dbFolderInfo->SetFlags(mFlags);
           dbFolderInfo->SetNumMessages(0);
           dbFolderInfo->SetNumUnreadMessages(0);
           dbFolderInfo->GetTransferInfo(getter_AddRefs(transferInfo));
         }
         dbFolderInfo = nsnull;
 
         // A backup message database might have been created earlier, for example
         // if the user requested a reindex. We'll use the earlier one if we can,
@@ -538,34 +539,38 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetD
       }
       nsCOMPtr <nsILocalFile> summaryFile;
       rv = GetSummaryFileLocation(pathFile, getter_AddRefs(summaryFile));
       NS_ENSURE_SUCCESS(rv, rv);
       // Remove summary file.
       summaryFile->Remove(PR_FALSE);
 
       // if it's out of date then reopen with upgrade.
-      if (NS_FAILED(rv = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase)))
-        && rv != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING && rv != NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
-        return rv;
-      else if (transferInfo && mDatabase)
+      rv = msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
+      NS_ENSURE_SUCCESS(rv, rv);
+
+      if (transferInfo && mDatabase)
       {
         SetDBTransferInfo(transferInfo);
         mDatabase->SetSummaryValid(PR_FALSE);
       }
     }
+    else if (folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
+    {
+      msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
+    }
 
     if(mDatabase)
     {
       if(mAddListener)
         mDatabase->AddListener(this);
 
       // if we have to regenerate the folder, run the parser url.
-      if(folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING ||
-        folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
+      if (folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING ||
+          folderOpen == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE)
       {
         if(NS_FAILED(rv = ParseFolder(aMsgWindow, aReparseUrlListener)))
         {
           if (rv == NS_MSG_FOLDER_BUSY)
           {
             mDatabase->RemoveListener(this);  //we need to null out the db so that parsing gets kicked off again.
             mDatabase = nsnull;
             ThrowAlertMsg("parsingFolderFailed", aMsgWindow);
@@ -771,20 +776,22 @@ nsMsgLocalMailFolder::CreateSubfolder(co
     return rv;
   }
 
   // Create an empty database for this mail folder, set its name from the user
   nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
   if (msgDBService)
   {
     nsCOMPtr<nsIMsgDatabase> unusedDB;
-    rv = msgDBService->OpenFolderDB(child, PR_TRUE, PR_TRUE, getter_AddRefs(unusedDB));
-
-    if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING
-      || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) && unusedDB)
+    rv = msgDBService->OpenFolderDB(child, PR_TRUE, getter_AddRefs(unusedDB));
+    if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
+      rv = msgDBService->CreateNewDB(child, getter_AddRefs(unusedDB));
+
+    if ((NS_SUCCEEDED(rv) || rv == NS_MSG_ERROR_FOLDER_SUMMARY_OUT_OF_DATE) &&
+        unusedDB)
     {
       //need to set the folder name
       nsCOMPtr<nsIDBFolderInfo> folderInfo;
       rv = unusedDB->GetDBFolderInfo(getter_AddRefs(folderInfo));
       if(NS_SUCCEEDED(rv))
       {
         folderInfo->SetMailboxName(safeFolderName);
       }
@@ -1286,23 +1293,22 @@ NS_IMETHODIMP nsMsgLocalMailFolder::GetN
 {
   ReadDBFolderInfo(PR_FALSE);
   return nsMsgDBFolder::GetName(aName);
 }
 
 NS_IMETHODIMP
 nsMsgLocalMailFolder::GetDBFolderInfoAndDB(nsIDBFolderInfo **folderInfo, nsIMsgDatabase **db)
 {
-  nsresult openErr = NS_ERROR_UNEXPECTED;
   if(!db || !folderInfo || !mPath || mIsServer)
     return NS_ERROR_NULL_POINTER;   //ducarroz: should we use NS_ERROR_INVALID_ARG?
 
   nsresult rv;
   if (mDatabase)
-    openErr = NS_OK;
+    rv = NS_OK;
   else
   {
     nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv, rv);
 
     PRBool folderEmpty = PR_FALSE;
     nsCOMPtr <nsILocalFile> file;
     rv = GetFilePath(getter_AddRefs(file));
@@ -1310,36 +1316,36 @@ nsMsgLocalMailFolder::GetDBFolderInfoAnd
     // and in that case, tell msg db to create a new db and set it valid after opening it.
     if (NS_SUCCEEDED(rv))
     {
       PRInt64 mailboxSize;
       if (NS_SUCCEEDED(file->GetFileSize(&mailboxSize)))
         folderEmpty = !mailboxSize;
     }
 
-    openErr = msgDBService->OpenFolderDB(this, folderEmpty, PR_FALSE, getter_AddRefs(mDatabase));
+    rv = msgDBService->OpenFolderDB(this, PR_FALSE, getter_AddRefs(mDatabase));
     if (folderEmpty)
     {
-      if (openErr == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
+      if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
       {
+        rv = msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
         if (mDatabase)
           mDatabase->SetSummaryValid(PR_TRUE);
-        openErr = NS_OK;
       }
-      else if (NS_FAILED(openErr))
+      else if (NS_FAILED(rv))
         mDatabase = nsnull;
     }
     if (mAddListener && mDatabase)
       mDatabase->AddListener(this);
   }
 
   NS_IF_ADDREF(*db = mDatabase);
-  if (NS_SUCCEEDED(openErr)&& *db)
-    openErr = (*db)->GetDBFolderInfo(folderInfo);
-  return openErr;
+  if (NS_SUCCEEDED(rv) && *db)
+    rv = (*db)->GetDBFolderInfo(folderInfo);
+  return rv;
 }
 
 NS_IMETHODIMP nsMsgLocalMailFolder::ReadFromFolderCacheElem(nsIMsgFolderCacheElement *element)
 {
   NS_ENSURE_ARG_POINTER(element);
   nsresult rv = nsMsgDBFolder::ReadFromFolderCacheElem(element);
   NS_ENSURE_SUCCESS(rv, rv);
   nsCString utf8Name;
--- a/mailnews/local/src/nsParseMailbox.cpp
+++ b/mailnews/local/src/nsParseMailbox.cpp
@@ -153,18 +153,24 @@ NS_IMETHODIMP nsMsgMailboxParser::OnStar
           path->GetFileSize(&fileSize);
             // the size of the mailbox file is our total base line for measuring progress
             m_graph_progress_total = (PRUint32) fileSize;
             UpdateStatusText(LOCAL_STATUS_SELECTING_MAILBOX);
 
             nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
             if (msgDBService)
             {
-                //Use OpenFolderDB to always open the db so that db's m_folder is set correctly.
-                rv = msgDBService->OpenFolderDB(folder, PR_TRUE, PR_TRUE, (nsIMsgDatabase **) getter_AddRefs(m_mailDB));
+                // Use OpenFolderDB to always open the db so that db's m_folder
+                // is set correctly.
+                rv = msgDBService->OpenFolderDB(folder, PR_TRUE,
+                                                getter_AddRefs(m_mailDB));
+                if (rv == NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
+                  rv = msgDBService->CreateNewDB(folder,
+                                                 getter_AddRefs(m_mailDB));
+
                 if (m_mailDB)
                     m_mailDB->AddListener(this);
             }
             NS_ASSERTION(m_mailDB, "failed to open mail db parsing folder");
 
             // try to get a backup message database
             nsresult rvignore = folder->GetBackupMsgDatabase(
                 getter_AddRefs(m_backupMailDB));
@@ -1638,17 +1644,18 @@ nsParseNewMailState::Init(nsIMsgFolder *
   m_msgWindow = aMsgWindow;
   m_downloadFolder = downloadFolder;
   m_downloadingToTempFile = downloadingToTempFile;
 
   // the new mail parser isn't going to get the stream input, it seems, so we can't use
   // the OnStartRequest mechanism the mailbox parser uses. So, let's open the db right now.
   nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
   if (msgDBService)
-    rv = msgDBService->OpenFolderDB(downloadFolder, PR_TRUE, PR_FALSE, (nsIMsgDatabase **) getter_AddRefs(m_mailDB));
+    rv = msgDBService->OpenFolderDB(downloadFolder, PR_FALSE,
+                                    getter_AddRefs(m_mailDB));
   NS_ENSURE_SUCCESS(rv, rv);
   nsCOMPtr <nsIMsgFolder> rootMsgFolder = do_QueryInterface(serverFolder, &rv);
   NS_ENSURE_SUCCESS(rv, rv);
 
   nsCOMPtr<nsIMsgIncomingServer> server;
   rv = rootMsgFolder->GetServer(getter_AddRefs(server));
   if (NS_SUCCEEDED(rv))
   {
--- a/mailnews/news/src/nsNewsFolder.cpp
+++ b/mailnews/news/src/nsNewsFolder.cpp
@@ -287,23 +287,21 @@ nsMsgNewsFolder::GetSubFolders(nsISimple
 nsresult nsMsgNewsFolder::GetDatabase(nsIMsgWindow *aMsgWindow)
 {
   nsresult rv;
   if (!mDatabase)
   {
     nsCOMPtr<nsIMsgDBService> msgDBService = do_GetService(NS_MSGDB_SERVICE_CONTRACTID, &rv);
     NS_ENSURE_SUCCESS(rv,rv);
 
-    nsresult folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_FALSE, getter_AddRefs(mDatabase));
-
-    if (NS_FAILED(folderOpen) && folderOpen != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-      folderOpen = msgDBService->OpenFolderDB(this, PR_TRUE, PR_TRUE, getter_AddRefs(mDatabase));
-
-    if (NS_FAILED(folderOpen) && folderOpen != NS_MSG_ERROR_FOLDER_SUMMARY_MISSING)
-      return folderOpen;
+    // Get the database, blowing it away if it's out of date.
+    rv = msgDBService->OpenFolderDB(this, PR_FALSE, getter_AddRefs(mDatabase));
+    if (NS_FAILED(rv))
+      rv = msgDBService->CreateNewDB(this, getter_AddRefs(mDatabase));
+    NS_ENSURE_SUCCESS(rv, rv);
 
     if(mAddListener)
       rv = mDatabase->AddListener(this);
 
     nsCOMPtr<nsINewsDatabase> db = do_QueryInterface(mDatabase, &rv);
     if (NS_FAILED(rv))
       return rv;