Bug 797065 - Leak if I quit while Scratchpad is open. r=dcamp
authorAnton Kovalyov <anton>
Wed, 19 Dec 2012 13:39:00 +0100
changeset 116648 77d729ffd925cc76d62c2ca83ca704824b9791d7
parent 116647 c9bfb369887b9c549722e0676197335771723121
child 116649 d055a17c13246bcfbc8d646e537eccefed77918f
push idunknown
push userunknown
push dateunknown
reviewersdcamp
bugs797065
milestone20.0a1
Bug 797065 - Leak if I quit while Scratchpad is open. r=dcamp
browser/devtools/scratchpad/scratchpad-manager.jsm
--- a/browser/devtools/scratchpad/scratchpad-manager.jsm
+++ b/browser/devtools/scratchpad/scratchpad-manager.jsm
@@ -64,21 +64,39 @@ this.ScratchpadManager = {
   },
 
   /**
    * Iterate through open scratchpad windows and save their states.
    */
   saveOpenWindows: function SPM_saveOpenWindows() {
     this._scratchpads = [];
 
+    function clone(src) {
+      let dest = {};
+
+      for (let key in src) {
+        if (src.hasOwnProperty(key)) {
+          dest[key] = src[key];
+        }
+      }
+
+      return dest;
+    }
+
+    // We need to clone objects we get from Scratchpad instances
+    // because such (cross-window) objects have a property 'parent'
+    // that holds on to a ChromeWindow instance. This means that
+    // such objects are not primitive-values-only anymore so they
+    // can leak.
+
     let enumerator = Services.wm.getEnumerator("devtools:scratchpad");
     while (enumerator.hasMoreElements()) {
       let win = enumerator.getNext();
       if (!win.closed && win.Scratchpad.initialized) {
-        this._scratchpads.push(win.Scratchpad.getState());
+        this._scratchpads.push(clone(win.Scratchpad.getState()));
       }
     }
   },
 
   /**
    * Open a new scratchpad window with an optional initial state.
    *
    * @param object aState
@@ -101,16 +119,17 @@ this.ScratchpadManager = {
         return;
       }
 
       params.SetString(1, JSON.stringify(aState));
     }
 
     let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank",
                                      SCRATCHPAD_WINDOW_FEATURES, params);
+
     // Only add the shutdown observer if we've opened a scratchpad window.
     ShutdownObserver.init();
 
     return win;
   }
 };
 
 
@@ -123,24 +142,25 @@ var ShutdownObserver = {
 
   init: function SDO_init()
   {
     if (this._initialized) {
       return;
     }
 
     Services.obs.addObserver(this, "quit-application-granted", false);
+
     this._initialized = true;
   },
 
   observe: function SDO_observe(aMessage, aTopic, aData)
   {
     if (aTopic == "quit-application-granted") {
       ScratchpadManager.saveOpenWindows();
       this.uninit();
     }
   },
 
   uninit: function SDO_uninit()
   {
     Services.obs.removeObserver(this, "quit-application-granted");
   }
-};
+};
\ No newline at end of file