Bug 765074 - Fix reference count leak of Compose window on shutdown [solution by David Bienvenu]. r=mkmelin,a=Standard8
authorDavid Bienvenu
Mon, 04 Mar 2013 10:16:10 -0500
changeset 14977 663389de0c654bb33f90e316b4a4e76ee3882689
parent 14976 088bb14115ad11fd69eaaaaa1860d5678c7935b4
child 14978 1e79544624c3dd8832b882a993ff2e15ff0f0a9e
push id872
push userbugzilla@standard8.plus.com
push dateTue, 09 Apr 2013 09:16:30 +0000
treeherdercomm-beta@1e79544624c3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmkmelin, Standard8
bugs765074
Bug 765074 - Fix reference count leak of Compose window on shutdown [solution by David Bienvenu]. r=mkmelin,a=Standard8
mail/components/compose/content/MsgComposeCommands.js
--- a/mail/components/compose/content/MsgComposeCommands.js
+++ b/mail/components/compose/content/MsgComposeCommands.js
@@ -31,30 +31,31 @@ const nsIMsgCompType = Components.interf
 const nsIMsgCompFormat = Components.interfaces.nsIMsgCompFormat;
 const nsIAbPreferMailFormat = Components.interfaces.nsIAbPreferMailFormat;
 const nsIPlaintextEditorMail = Components.interfaces.nsIPlaintextEditor;
 const nsISupportsString = Components.interfaces.nsISupportsString;
 const mozISpellCheckingEngine = Components.interfaces.mozISpellCheckingEngine;
 
 var sDictCount = 0;
 
-/* Create message window object. This is use by mail-offline.js and therefore should not be renamed. We need to avoid doing
-   this kind of cross file global stuff in the future and instead pass this object as parameter when needed by function
-   in the other js file.
-*/
-var msgWindow = Components.classes["@mozilla.org/messenger/msgwindow;1"]
-                          .createInstance(Components.interfaces.nsIMsgWindow);
-
-var gMessenger = Components.classes["@mozilla.org/messenger;1"]
-                           .createInstance(Components.interfaces.nsIMessenger)
+/**
+ * Global message window object. This is used by mail-offline.js and therefore
+ * should not be renamed. We need to avoid doing this kind of cross file global
+ * stuff in the future and instead pass this object as parameter when needed by
+ * functions in the other js file.
+ */
+var msgWindow;
+
+var gMessenger;
 
 var gSpellChecker = new InlineSpellChecker();
 
 /**
- * Global variables, need to be re-initialized every time mostly because we need to release them when the window close
+ * Global variables, need to be re-initialized every time mostly because
+ * we need to release them when the window closes.
  */
 var gHideMenus;
 var gMsgCompose;
 var gAccountManager;
 var gWindowLocked;
 var gContentChanged;
 var gAutoSaving;
 var gCurrentIdentity;
@@ -94,28 +95,29 @@ function getComposeBundle() {
   return _gComposeBundle;
 }
 
 var gLastWindowToHaveFocus;
 var gReceiptOptionChanged;
 var gDSNOptionChanged;
 var gAttachVCardOptionChanged;
 
-var gMailSession;
 var gAutoSaveInterval;
 var gAutoSaveTimeout;
 var gAutoSaveKickedIn;
 var gEditingDraft;
 var gAttachmentsSize;
 var gNumUploadingAttachments;
 
 const kComposeAttachDirPrefName = "mail.compose.attach.dir";
 
 function InitializeGlobalVariables()
 {
+  gMessenger = Components.classes["@mozilla.org/messenger;1"]
+                         .createInstance(Components.interfaces.nsIMessenger);
   gAccountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);
 
   gMsgCompose = null;
   gWindowLocked = false;
   gContentChanged = false;
   gCurrentIdentity = null;
   defaultSaveOperation = "draft";
   gSendOrSaveOperationInProgress = false;
@@ -125,41 +127,46 @@ function InitializeGlobalVariables()
   gCurrentAutocompleteDirectory = null;
   gSetupLdapAutocomplete = false;
   gLDAPSession = null;
   gSavedSendNowKey = null;
   gSendFormat = nsIMsgCompSendFormat.AskUser;
   gSendDefaultCharset = null;
   gCharsetTitle = null;
   gCharsetConvertManager = Components.classes['@mozilla.org/charset-converter-manager;1'].getService(Components.interfaces.nsICharsetConverterManager);
-  gMailSession = Components.classes["@mozilla.org/messenger/services/session;1"].getService(Components.interfaces.nsIMsgMailSession);
   gHideMenus = false;
   gRemindLater = false;
 
   gLastWindowToHaveFocus = null;
   gReceiptOptionChanged = false;
   gDSNOptionChanged = false;
   gAttachVCardOptionChanged = false;
   gAttachmentsSize = 0;
   gNumUploadingAttachments = 0;
+  msgWindow = Components.classes["@mozilla.org/messenger/msgwindow;1"]
+                        .createInstance(Components.interfaces.nsIMsgWindow);
+  MailServices.mailSession.AddMsgWindow(msgWindow);
 }
 InitializeGlobalVariables();
 
 function ReleaseGlobalVariables()
 {
   gAccountManager = null;
   gCurrentIdentity = null;
   gCurrentAutocompleteDirectory = null;
   if (gLDAPSession) {
     gLDAPSession = null;
     Components.utils.forceGC();
   }
   gCharsetConvertManager = null;
   gMsgCompose = null;
-  gMailSession = null;
+  gMessenger = null;
+  _gComposeBundle = null;
+  MailServices.mailSession.RemoveMsgWindow(msgWindow);
+  msgWindow = null;
 }
 
 /**
  * Disables or enables editable elements in the window.
  * The elements to operate on are marked with the "disableonsend" attribute.
  * This includes elements like the address list, attachment list, subject
  * and message body.
  *
@@ -233,17 +240,16 @@ var gComposeRecyclingListener = {
 
     //Reset editor
     EditorResetFontAndColorAttributes();
     EditorCleanup();
 
     //Release the nsIMsgComposeParams object
     if (window.arguments && window.arguments[0])
       window.arguments[0] = null;
-
     var event = document.createEvent('Events');
     event.initEvent('compose-window-close', false, true);
     document.getElementById("msgcomposeWindow").dispatchEvent(event);
     if (gAutoSaveTimeout)
       clearTimeout(gAutoSaveTimeout);
   },
 
   onReopen: function(params) {
@@ -2400,20 +2406,16 @@ function ComposeStartup(recycled, aParam
   }
   gAutoSaveInterval = getPref("mail.compose.autosave") ?
     getPref("mail.compose.autosaveinterval") * 60000 : 0;
 
   if (gAutoSaveInterval)
     gAutoSaveTimeout = setTimeout(AutoSave, gAutoSaveInterval);
 
   gAutoSaveKickedIn = false;
-
-  Components.classes["@mozilla.org/messenger/services/session;1"]
-            .getService(Components.interfaces.nsIMsgMailSession)
-            .AddMsgWindow(msgWindow);
 }
 
 // The new, nice, simple way of getting notified when a new editor has been created
 var gMsgEditorCreationObserver =
 {
   observe: function(aSubject, aTopic, aData)
   {
     if (aTopic == "obs_documentCreated")
@@ -2538,16 +2540,20 @@ function ComposeUnload()
   if (gCurrentIdentity)
     RemoveDirectoryServerObserver("mail.identity." + gCurrentIdentity.key);
   if (gCurrentAutocompleteDirectory)
     RemoveDirectorySettingsObserver(gCurrentAutocompleteDirectory);
   if (gMsgCompose)
     gMsgCompose.UnregisterStateListener(stateListener);
   if (gAutoSaveTimeout)
     clearTimeout(gAutoSaveTimeout);
+  if (msgWindow)
+    msgWindow.closeWindow();
+
+  ReleaseGlobalVariables();
 }
 
 function SetDocumentCharacterSet(aCharset)
 {
   if (gMsgCompose) {
     gMsgCompose.SetDocumentCharset(aCharset);
     gCharsetTitle = null;
     SetComposeWindowTitle();
@@ -3499,19 +3505,16 @@ function ReleaseAutoCompleteState()
     // We're trying to force ldap sessions to get cleaned up as
     // soon as possible so they don't hang on shutdown.
     Components.utils.forceGC();
   }
 }
 
 function MsgComposeCloseWindow(recycleIt)
 {
-  Components.classes["@mozilla.org/messenger/services/session;1"]
-            .getService(Components.interfaces.nsIMsgMailSession)
-            .RemoveMsgWindow(msgWindow);
   if (gMsgCompose)
     gMsgCompose.CloseWindow(recycleIt);
   else
     window.close();
 }
 
 function GetLastAttachDirectory()
 {