Bug 1575512 - Avoid IMAP folder operations until final-ui-startup is done. r=aceman DONTBUILD
authorJorg K <jorgk@jorgk.com>
Sun, 20 Oct 2019 10:47:39 +0200
changeset 37185 8c7735bd0dc3e7ace3f860df8749e4948227a8b4
parent 37184 920a9004b78ce116e96c05da498bea3f226bd17b
child 37186 2abc5e2495fc83ffa438def667bac604c4b8be22
push id395
push userclokep@gmail.com
push dateMon, 02 Dec 2019 19:38:57 +0000
reviewersaceman
bugs1575512
Bug 1575512 - Avoid IMAP folder operations until final-ui-startup is done. r=aceman DONTBUILD
mail/components/mailGlue.js
mailnews/base/public/nsIMsgFolder.idl
mailnews/base/public/nsMsgBaseCID.h
mailnews/base/util/ServiceList.h
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/base/util/nsMsgDBFolder.h
mailnews/build/nsMailModule.cpp
mailnews/imap/src/nsImapService.cpp
--- a/mail/components/mailGlue.js
+++ b/mail/components/mailGlue.js
@@ -136,16 +136,20 @@ MailGlue.prototype = {
 
   // nsIObserver implementation
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "xpcom-shutdown":
         this._dispose();
         break;
       case "final-ui-startup":
+        let fs = Cc["@mozilla.org/msgFolder/msgFolderService;1"].getService(
+          Ci.nsIMsgFolderService
+        );
+        fs.initializeFolderStrings();
         this._onProfileStartup();
         break;
       case "mail-startup-done":
         this._onMailStartupDone();
         break;
       case "handle-xul-text-link":
         this._handleLink(aSubject, aData);
         break;
--- a/mailnews/base/public/nsIMsgFolder.idl
+++ b/mailnews/base/public/nsIMsgFolder.idl
@@ -25,16 +25,25 @@ interface nsIArray;
 interface nsIMutableArray;
 interface nsIMsgPluggableStore;
 
 typedef long nsMsgBiffState;
 
 // enumerated type for determining if a message has been replied to, forwarded, etc.
 typedef long nsMsgDispositionState;
 
+/*
+ * The contract ID for this component is @mozilla.org/msgFolder/msgFolderService;1.
+ */
+[scriptable, uuid(5639c204-48ac-4115-897f-3b16821fe118)]
+interface nsIMsgFolderService : nsISupports
+{
+  void initializeFolderStrings();
+};
+
 [scriptable, uuid(5d253ba2-42aa-43a7-b584-0059855ababf)]
 interface nsIMsgFolder : nsISupports {
 
   const nsMsgBiffState nsMsgBiffState_NewMail = 0; // User has new mail waiting.
   const nsMsgBiffState nsMsgBiffState_NoMail =  1; // No new mail is waiting.
   const nsMsgBiffState nsMsgBiffState_Unknown = 2; // We dunno whether there is new mail.
 
   /* folder name properties */
@@ -53,16 +62,18 @@ interface nsIMsgFolder : nsISupports {
    * a folder to initialize its URI. You would not normally
    * call this method directly.
    */
   void Init(in string uri);
 
   void startFolderLoading();
   void endFolderLoading();
 
+  void folderNamesReady(out boolean aReady);
+
   /* get new headers for db */
   void updateFolder(in nsIMsgWindow aWindow);
 
   /**
    * URL for this folder
    */
   readonly attribute ACString folderURL;
 
--- a/mailnews/base/public/nsMsgBaseCID.h
+++ b/mailnews/base/public/nsMsgBaseCID.h
@@ -425,16 +425,28 @@
 #define NS_MSGTAGSERVICE_CID                         \
   {                                                  \
     0xb897da55, 0x8256, 0x4cf5, {                    \
       0x89, 0x2b, 0x32, 0xe7, 0x7b, 0xc7, 0xc5, 0x0b \
     }                                                \
   }
 
 //
+// nsMsgFolderService
+//
+#define NS_MSGFOLDERSERVICE_CONTRACTID \
+  "@mozilla.org/msgFolder/msgFolderService;1"
+#define NS_MSGFOLDERSERVICE_CID                      \
+  {                                                  \
+    0x0c8ec907, 0x49c7, 0x49bc, {                    \
+      0x8b, 0xdf, 0xb1, 0x6e, 0x29, 0xbd, 0x6c, 0x47 \
+    }                                                \
+  }
+
+//
 // nsMsgNotificationService
 //
 #define NS_MSGNOTIFICATIONSERVICE_CONTRACTID \
   "@mozilla.org/messenger/msgnotificationservice;1"
 
 #define NS_MSGNOTIFICATIONSERVICE_CID                \
   {                                                  \
     0xf1f7cbcd, 0xd5e3, 0x45a0, {                    \
--- a/mailnews/base/util/ServiceList.h
+++ b/mailnews/base/util/ServiceList.h
@@ -8,16 +8,18 @@ MOZ_SERVICE(AbManager, nsIAbManager, "@m
 MOZ_SERVICE(AccountManager, nsIMsgAccountManager,
             "@mozilla.org/messenger/account-manager;1")
 MOZ_SERVICE(ComposeService, nsIMsgComposeService,
             "@mozilla.org/messengercompose;1")
 MOZ_SERVICE(CopyService, nsIMsgCopyService,
             "@mozilla.org/messenger/messagecopyservice;1")
 MOZ_SERVICE(DBService, nsIMsgDBService,
             "@mozilla.org/msgDatabase/msgDBService;1")
+MOZ_SERVICE(FolderService, nsIMsgFolderService,
+            "@mozilla.org/msgFolder/msgFolderService;1")
 MOZ_SERVICE(FilterService, nsIMsgFilterService,
             "@mozilla.org/messenger/services/filters;1")
 MOZ_SERVICE(HeaderParser, nsIMsgHeaderParser,
             "@mozilla.org/messenger/headerparser;1")
 MOZ_SERVICE(ImapService, nsIImapService, "@mozilla.org/messenger/imapservice;1")
 MOZ_SERVICE(ImportService, nsIImportService,
             "@mozilla.org/import/import-service;1")
 MOZ_SERVICE(MailNotifyService, mozINewMailNotificationService,
--- a/mailnews/base/util/nsMsgDBFolder.cpp
+++ b/mailnews/base/util/nsMsgDBFolder.cpp
@@ -65,16 +65,17 @@
 #include "nsDirectoryServiceUtils.h"
 #include "mozilla/Services.h"
 #include "nsMimeTypes.h"
 #include "nsIMsgFilter.h"
 #include "nsIScriptError.h"
 #include "nsIURIMutator.h"
 #include "mozilla/intl/LocaleService.h"
 #include "mozilla/Logging.h"
+#include "nsIXULAppInfo.h"
 
 using namespace mozilla;
 
 extern LazyLogModule FILTERLOGMODULE;
 
 static PRTime gtimeOfLastPurgeCheck;  // variable to know when to check for
                                       // purge threshold
 
@@ -82,30 +83,46 @@ static PRTime gtimeOfLastPurgeCheck;  //
 #define PREF_MAIL_PURGE_THRESHOLD "mail.purge_threshhold"
 #define PREF_MAIL_PURGE_THRESHOLD_MB "mail.purge_threshhold_mb"
 #define PREF_MAIL_PURGE_MIGRATED "mail.purge_threshold_migrated"
 #define PREF_MAIL_PURGE_ASK "mail.purge.ask"
 #define PREF_MAIL_WARN_FILTER_CHANGED "mail.warn_filter_changed"
 
 const char *kUseServerRetentionProp = "useServerRetention";
 
+NS_IMPL_ISUPPORTS(nsMsgFolderService, nsIMsgFolderService)
+
+// This method serves the only purpose to re-initialize the
+// folder name strings when UI intialization is done.
+// XXX TODO: This can be removed when the localization system gets
+// initialized in M-C code before, for example, the permission manager
+// triggers folder creation during imap: URI creation.
+// In fact, the entire class together with nsMsgDBFolder::FolderNamesReady()
+// can be removed.
+NS_IMETHODIMP nsMsgFolderService::InitializeFolderStrings() {
+  nsMsgDBFolder::initializeStrings();
+  nsMsgDBFolder::gInitializeStringsDone = true;
+  return NS_OK;
+}
+
 nsICollation *nsMsgDBFolder::gCollationKeyGenerator = nullptr;
 
 nsString nsMsgDBFolder::kLocalizedInboxName;
 nsString nsMsgDBFolder::kLocalizedTrashName;
 nsString nsMsgDBFolder::kLocalizedSentName;
 nsString nsMsgDBFolder::kLocalizedDraftsName;
 nsString nsMsgDBFolder::kLocalizedTemplatesName;
 nsString nsMsgDBFolder::kLocalizedUnsentName;
 nsString nsMsgDBFolder::kLocalizedJunkName;
 nsString nsMsgDBFolder::kLocalizedArchivesName;
 
 nsString nsMsgDBFolder::kLocalizedBrandShortName;
 
 nsrefcnt nsMsgDBFolder::mInstanceCount = 0;
+bool nsMsgDBFolder::gInitializeStringsDone = false;
 
 // We define strings for folder properties and events.
 // Properties:
 NS_NAMED_LITERAL_CSTRING(kBiffState, "BiffState");
 NS_NAMED_LITERAL_CSTRING(kCanFileMessages, "CanFileMessages");
 NS_NAMED_LITERAL_CSTRING(kDefaultServer, "DefaultServer");
 NS_NAMED_LITERAL_CSTRING(kFlagged, "Flagged");
 NS_NAMED_LITERAL_CSTRING(kFolderFlag, "FolderFlag");
@@ -159,16 +176,33 @@ nsMsgDBFolder::nsMsgDBFolder(void)
       mNumPendingTotalMessages(0),
       mFolderSize(kSizeUnknown),
       mNumNewBiffMessages(0),
       mHaveParsedURI(false),
       mIsServerIsValid(false),
       mIsServer(false) {
   if (mInstanceCount++ <= 0) {
     initializeStrings();
+
+    do {
+      nsresult rv;
+      // We need to check whether we're running under xpcshell,
+      // in that case, we always assume that the strings are good.
+      // XXX TODO: This hack can be removed when the localization system gets
+      // initialized in M-C code before, for example, the permission manager
+      // triggers folder creation during imap: URI creation.
+      nsCOMPtr<nsIXULAppInfo> appinfo =
+          do_GetService("@mozilla.org/xre/app-info;1", &rv);
+      if (NS_FAILED(rv)) break;
+      nsAutoCString appName;
+      rv = appinfo->GetName(appName);
+      if (NS_FAILED(rv)) break;
+      if (appName.Equals("xpcshell")) gInitializeStringsDone = true;
+    } while (false);
+
     createCollationKeyGenerator();
     gtimeOfLastPurgeCheck = 0;
   }
 
   mProcessingFlag[0].bit = nsMsgProcessingFlags::ClassifyJunk;
   mProcessingFlag[1].bit = nsMsgProcessingFlags::ClassifyTraits;
   mProcessingFlag[2].bit = nsMsgProcessingFlags::TraitsDone;
   mProcessingFlag[3].bit = nsMsgProcessingFlags::FiltersDone;
@@ -184,16 +218,21 @@ nsMsgDBFolder::~nsMsgDBFolder(void) {
 
   if (--mInstanceCount == 0) {
     NS_IF_RELEASE(gCollationKeyGenerator);
   }
   // shutdown but don't shutdown children.
   Shutdown(false);
 }
 
+NS_IMETHODIMP nsMsgDBFolder::FolderNamesReady(bool *aReady) {
+  *aReady = gInitializeStringsDone;
+  return NS_OK;
+}
+
 NS_IMETHODIMP nsMsgDBFolder::Shutdown(bool shutdownChildren) {
   if (mDatabase) {
     mDatabase->RemoveListener(this);
     mDatabase->ForceClosed();
     mDatabase = nullptr;
     if (mBackupDatabase) {
       mBackupDatabase->ForceClosed();
       mBackupDatabase = nullptr;
--- a/mailnews/base/util/nsMsgDBFolder.h
+++ b/mailnews/base/util/nsMsgDBFolder.h
@@ -66,28 +66,40 @@ extern const nsLiteralCString kFolderCre
 extern const nsLiteralCString kFolderLoaded;
 extern const nsLiteralCString kNumNewBiffMessages;
 extern const nsLiteralCString kRenameCompleted;
 
 class nsIMsgFolderCacheElement;
 class nsICollation;
 class nsMsgKeySetU;
 
+class nsMsgFolderService final : public nsIMsgFolderService {
+ public:
+  NS_DECL_ISUPPORTS
+  NS_DECL_NSIMSGFOLDERSERVICE
+
+  nsMsgFolderService(){};
+
+ protected:
+  ~nsMsgFolderService(){};
+};
+
 /*
  * nsMsgDBFolder
  * class derived from nsMsgFolder for those folders that use an nsIMsgDatabase
  */
-
 class NS_MSG_BASE nsMsgDBFolder : public nsSupportsWeakReference,
                                   public nsIMsgFolder,
                                   public nsIDBChangeListener,
                                   public nsIUrlListener,
                                   public nsIJunkMailClassificationListener,
                                   public nsIMsgTraitClassificationListener {
  public:
+  friend class nsMsgFolderService;
+
   nsMsgDBFolder(void);
   NS_DECL_THREADSAFE_ISUPPORTS
   NS_DECL_NSIMSGFOLDER
   NS_DECL_NSIDBCHANGELISTENER
   NS_DECL_NSIURLLISTENER
   NS_DECL_NSIJUNKMAILCLASSIFICATIONLISTENER
   NS_DECL_NSIMSGTRAITCLASSIFICATIONLISTENER
 
@@ -281,16 +293,17 @@ class NS_MSG_BASE nsMsgDBFolder : public
   static NS_MSG_BASE_STATIC_MEMBER_(nsString) kLocalizedTemplatesName;
   static NS_MSG_BASE_STATIC_MEMBER_(nsString) kLocalizedUnsentName;
   static NS_MSG_BASE_STATIC_MEMBER_(nsString) kLocalizedJunkName;
   static NS_MSG_BASE_STATIC_MEMBER_(nsString) kLocalizedArchivesName;
 
   static NS_MSG_BASE_STATIC_MEMBER_(nsString) kLocalizedBrandShortName;
 
   static NS_MSG_BASE_STATIC_MEMBER_(nsICollation *) gCollationKeyGenerator;
+  static NS_MSG_BASE_STATIC_MEMBER_(bool) gInitializeStringsDone;
 
   // store of keys that have a processing flag set
   struct {
     uint32_t bit;
     nsMsgKeySetU *keys;
   } mProcessingFlag[nsMsgProcessingFlags::NumberOfFlags];
 
   // list of nsIMsgDBHdrs for messages to process post-bayes
--- a/mailnews/build/nsMailModule.cpp
+++ b/mailnews/build/nsMailModule.cpp
@@ -354,16 +354,17 @@ NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgWatc
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgSearchDBView)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgXFVirtualFolderDBView)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgQuickSearchDBView)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgGroupView)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgOfflineManager)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgProgress)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsSpamSettings)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgTagService)
+NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgFolderService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgFolderNotificationService)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsCidProtocolHandler)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMailDirProvider)
 NS_GENERIC_FACTORY_CONSTRUCTOR(nsMsgShutdownService)
 #ifdef XP_WIN
 NS_GENERIC_FACTORY_CONSTRUCTOR_INIT(nsMessengerWinIntegration, Init)
 #endif
 #ifdef XP_MACOSX
@@ -410,16 +411,17 @@ NS_DEFINE_NAMED_CID(NS_MSGSEARCHDBVIEW_C
 NS_DEFINE_NAMED_CID(NS_MSGQUICKSEARCHDBVIEW_CID);
 NS_DEFINE_NAMED_CID(NS_MSG_XFVFDBVIEW_CID);
 NS_DEFINE_NAMED_CID(NS_MSG_GROUPDBVIEW_CID);
 NS_DEFINE_NAMED_CID(NS_MSGOFFLINEMANAGER_CID);
 NS_DEFINE_NAMED_CID(NS_MSGPROGRESS_CID);
 NS_DEFINE_NAMED_CID(NS_SPAMSETTINGS_CID);
 NS_DEFINE_NAMED_CID(NS_CIDPROTOCOL_CID);
 NS_DEFINE_NAMED_CID(NS_MSGTAGSERVICE_CID);
+NS_DEFINE_NAMED_CID(NS_MSGFOLDERSERVICE_CID);
 NS_DEFINE_NAMED_CID(NS_MSGNOTIFICATIONSERVICE_CID);
 #ifdef XP_WIN
 NS_DEFINE_NAMED_CID(NS_MESSENGERWININTEGRATION_CID);
 #endif
 #ifdef XP_MACOSX
 NS_DEFINE_NAMED_CID(NS_MESSENGEROSXINTEGRATION_CID);
 #endif
 #if defined(MOZ_WIDGET_GTK)
@@ -876,16 +878,17 @@ const mozilla::Module::CIDEntry kMailNew
     {&kNS_MSG_XFVFDBVIEW_CID, false, NULL,
      nsMsgXFVirtualFolderDBViewConstructor},
     {&kNS_MSG_GROUPDBVIEW_CID, false, NULL, nsMsgGroupViewConstructor},
     {&kNS_MSGOFFLINEMANAGER_CID, false, NULL, nsMsgOfflineManagerConstructor},
     {&kNS_MSGPROGRESS_CID, false, NULL, nsMsgProgressConstructor},
     {&kNS_SPAMSETTINGS_CID, false, NULL, nsSpamSettingsConstructor},
     {&kNS_CIDPROTOCOL_CID, false, NULL, nsCidProtocolHandlerConstructor},
     {&kNS_MSGTAGSERVICE_CID, false, NULL, nsMsgTagServiceConstructor},
+    {&kNS_MSGFOLDERSERVICE_CID, false, NULL, nsMsgFolderServiceConstructor},
     {&kNS_MSGNOTIFICATIONSERVICE_CID, false, NULL,
      nsMsgFolderNotificationServiceConstructor},
 #ifdef XP_WIN
     {&kNS_MESSENGERWININTEGRATION_CID, false, NULL,
      nsMessengerWinIntegrationConstructor},
 #endif
 #ifdef XP_MACOSX
     {&kNS_MESSENGEROSXINTEGRATION_CID, false, NULL,
@@ -1124,16 +1127,17 @@ const mozilla::Module::ContractIDEntry k
     {NS_MSGQUICKSEARCHDBVIEW_CONTRACTID, &kNS_MSGQUICKSEARCHDBVIEW_CID},
     {NS_MSGXFVFDBVIEW_CONTRACTID, &kNS_MSG_XFVFDBVIEW_CID},
     {NS_MSGGROUPDBVIEW_CONTRACTID, &kNS_MSG_GROUPDBVIEW_CID},
     {NS_MSGOFFLINEMANAGER_CONTRACTID, &kNS_MSGOFFLINEMANAGER_CID},
     {NS_MSGPROGRESS_CONTRACTID, &kNS_MSGPROGRESS_CID},
     {NS_SPAMSETTINGS_CONTRACTID, &kNS_SPAMSETTINGS_CID},
     {NS_CIDPROTOCOLHANDLER_CONTRACTID, &kNS_CIDPROTOCOL_CID},
     {NS_MSGTAGSERVICE_CONTRACTID, &kNS_MSGTAGSERVICE_CID},
+    {NS_MSGFOLDERSERVICE_CONTRACTID, &kNS_MSGFOLDERSERVICE_CID},
     {NS_MSGNOTIFICATIONSERVICE_CONTRACTID, &kNS_MSGNOTIFICATIONSERVICE_CID},
 #ifdef XP_WIN
     {NS_MESSENGEROSINTEGRATION_CONTRACTID, &kNS_MESSENGERWININTEGRATION_CID},
 #endif
 #ifdef XP_MACOSX
     {NS_MESSENGEROSINTEGRATION_CONTRACTID, &kNS_MESSENGEROSXINTEGRATION_CID},
 #endif
 #if defined(MOZ_WIDGET_GTK)
--- a/mailnews/imap/src/nsImapService.cpp
+++ b/mailnews/imap/src/nsImapService.cpp
@@ -2409,17 +2409,24 @@ nsresult nsImapService::NewURI(const nsA
   rv = GetServerFromUrl(aImapUrl, getter_AddRefs(server));
   // if we can't extract the imap server from this url then give up!!!
   NS_ENSURE_SUCCESS(rv, rv);
   NS_ENSURE_TRUE(server, NS_ERROR_FAILURE);
 
   // now try to get the folder in question...
   nsCOMPtr<nsIMsgFolder> rootFolder;
   server->GetRootFolder(getter_AddRefs(rootFolder));
-  if (rootFolder && !folderName.IsEmpty()) {
+  bool ready;
+  if (rootFolder && !folderName.IsEmpty() &&
+      // Skip folder processing if folder names aren't ready yet.
+      // They may not be available during early initialization.
+      // XXX TODO: This hack can be removed when the localization system gets
+      // initialized in M-C code before, for example, the permission manager
+      // which creates all sorts of URIs incl. imap: URIs.
+      NS_SUCCEEDED(rootFolder->FolderNamesReady(&ready)) && ready) {
     nsCOMPtr<nsIMsgFolder> folder;
     nsCOMPtr<nsIMsgImapMailFolder> imapRoot = do_QueryInterface(rootFolder);
     nsCOMPtr<nsIMsgImapMailFolder> subFolder;
     if (imapRoot) {
       imapRoot->FindOnlineSubFolder(folderName, getter_AddRefs(subFolder));
       folder = do_QueryInterface(subFolder);
     }