Bug 534579 - Tab thumbnail takes 1/2 a second longer to disappear after tab close [r=stuart]
authorMark Finkle <mfinkle@mozilla.com>
Tue, 15 Dec 2009 15:37:02 -0500
changeset 65917 f84568d171f10b3666412da2f029b7b77f98a11b
parent 65916 9a583eafbd2e5e8b55cd4324292c2040f8518ab2
child 65918 ad3b0f83d90aefaceb453721ac9f22f2a24d716c
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersstuart
bugs534579
Bug 534579 - Tab thumbnail takes 1/2 a second longer to disappear after tab close [r=stuart]
mobile/chrome/content/browser.js
--- a/mobile/chrome/content/browser.js
+++ b/mobile/chrome/content/browser.js
@@ -1602,17 +1602,17 @@ nsBrowserAccess.prototype = {
     return Browser.browsers.some(function (browser) browser.contentWindow == aWindow);
   }
 };
 
 const BrowserSearch = {
   engines: null,
   _allEngines: [],
 
-  observe: function (aSubject, aTopic, aData) {
+  observe: function bs_observe(aSubject, aTopic, aData) {
     if (aTopic != "browser-search-engine-modified")
       return;
 
     switch (aData) {
       case "engine-added":
       case "engine-removed":
         // force a rebuild of the prefs list, if needed
         // XXX this is inefficient, shouldn't have to rebuild the entire list
@@ -1745,17 +1745,17 @@ ContentCustomClicker.prototype = {
         let cwu = BrowserView.Util.getBrowserDOMWindowUtils(browser);
         let scrollX = {}, scrollY = {};
         cwu.getScrollXY(false, scrollX, scrollY);
         cwu.sendMouseEvent(name, x - scrollX.value, y - scrollY.value, 0, 1, 0, true);
       }
     },
 
     /** Returns a node if selecting this node causes a focus. */
-    _getFocusable: function(node) {
+    _getFocusable: function _getFocusable(node) {
       if (node && node.mozMatchesSelector("*:link,*:visited,*:link *,*:visited *,button,input,option,select,textarea"))
         return node;
       return null;
     },
  
     /** Stop highlighting current element. */
     _hideCanvas: function _hideCanvas() {
       let overlay = this._overlay;
@@ -2345,17 +2345,17 @@ const gSessionHistoryObserver = {
     if (urlbar) {
       // Clear undo history of the URL bar
       urlbar.editor.transactionManager.clear();
     }
   }
 };
 
 var MemoryObserver = {
-  observe: function() {
+  observe: function mo_observe() {
     let memory = Cc["@mozilla.org/xpcom/memory-service;1"].getService(Ci.nsIMemory);
     do {
       Browser.windowUtils.garbageCollect();      
     } while (memory.isLowMemory() && Browser.sacrificeTab());
   }
 };
 
 #ifdef WINCE
@@ -2542,21 +2542,21 @@ ProgressController.prototype = {
         this._networkStop();
     } else if (aStateFlags & Ci.nsIWebProgressListener.STATE_IS_DOCUMENT) {
       if (aStateFlags & Ci.nsIWebProgressListener.STATE_STOP)
         this._documentStop();
     }
   },
 
   /** This method is called to indicate progress changes for the currently loading page. */
-  onProgressChange: function(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
+  onProgressChange: function onProgressChange(aWebProgress, aRequest, aCurSelf, aMaxSelf, aCurTotal, aMaxTotal) {
   },
 
   /** This method is called to indicate a change to the current location. */
-  onLocationChange: function(aWebProgress, aRequest, aLocationURI) {
+  onLocationChange: function onLocationChange(aWebProgress, aRequest, aLocationURI) {
     let location = aLocationURI ? aLocationURI.spec : "";
 
     this._hostChanged = true;
     
     if (location != this.browser.lastSpec) {
       this.browser.lastSpec = this.browser.currentURI.spec;
       Browser.removeTransientNotificationsForTab(this._tab);
 
@@ -2565,21 +2565,21 @@ ProgressController.prototype = {
       }
     }
   },
 
   /**
    * This method is called to indicate a status changes for the currently
    * loading page.  The message is already formatted for display.
    */
-  onStatusChange: function(aWebProgress, aRequest, aStatus, aMessage) {
+  onStatusChange: function onStatusChange(aWebProgress, aRequest, aStatus, aMessage) {
   },
 
   /** This method is called when the security state of the browser changes. */
-  onSecurityChange: function(aWebProgress, aRequest, aState) {
+  onSecurityChange: function onSecurityChange(aWebProgress, aRequest, aState) {
     // Don't need to do anything if the data we use to update the UI hasn't changed
     if (this.state == aState && !this._hostChanged)
       return;
 
     this._hostChanged = false;
     this.state = aState;
 
     if (this._tab == Browser.selectedTab) {
@@ -2615,17 +2615,17 @@ ProgressController.prototype = {
       BrowserUI.update(TOOLBARSTATE_LOADED);
       this.browser.docShell.isOffScreenBrowser = true;
     }
 
     if (this.browser.currentURI.spec != "about:blank")
       this._tab.updateThumbnail();
   },
 
-  _documentStop: function() {
+  _documentStop: function _documentStop() {
   }
 };
 
 var OfflineApps = {
   get _pm() {
     delete this._pm;
     return this._pm = Cc["@mozilla.org/permissionmanager;1"].getService(Ci.nsIPermissionManager);
   },
@@ -2747,52 +2747,52 @@ Tab.prototype = {
   get chromeTab() {
     return this._chromeTab;
   },
 
   /**
    * Throttles redraws to once every 2 seconds while loading the page, zooming to fit page if
    * user hasn't started zooming.
    */
-  _resizeAndPaint: function() {
+  _resizeAndPaint: function _resizeAndPaint() {
     let bv = Browser._browserView;
     bv.commitBatchOperation();
 
     if (this._loadingPaintCount == 0)
       Browser.scrollContentToTop();
 
     if (this._loading) {
       // kick ourselves off 2s later while we're still loading
       bv.beginBatchOperation();
       this._loadingTimeout = setTimeout(this._resizeAndPaint, 2000);
     } else {
       delete this._loadingTimeout;
     }
     this._loadingPaintCount++;
   },
 
-  _startResizeAndPaint: function() {
+  _startResizeAndPaint: function _startResizeAndPaint() {
     this._loadingTimeout = setTimeout(this._resizeAndPaint, 2000);
     this._loadingPaintCount = 0;
   },
 
-  _stopResizeAndPaint: function() {
+  _stopResizeAndPaint: function _stopResizeAndPaint() {
     if (this._loadingTimeout) {
       Browser._browserView.commitBatchOperation();
       clearTimeout(this._loadingTimeout);
       delete this._loadingTimeout;
     }
   },
 
   /** Returns tab's identity state for updating security UI. */
-  getIdentityState: function() {
+  getIdentityState: function getIdentityState() {
     return this._listener.state;
   },
 
-  startLoading: function() {
+  startLoading: function startLoading() {
     this._loading = true;
     let bvs = this._browserViewportState;
     bvs.defaultZoomLevel = bvs.zoomLevel; // ensures zoom level is reset on new pages
 
     if (!this._loadingTimeout) {
       let bv = Browser._browserView;
       bv.beginBatchOperation();
       bv.invalidateEntireView();
@@ -2800,17 +2800,17 @@ Tab.prototype = {
         bv.setAggressive(false);
       // Sync up browser so previous and forward scroll positions are set. This is a good time to do
       // this because the resulting invalidation is irrelevant.
       Browser.scrollBrowserToContent();
       this._startResizeAndPaint();
     }
   },
 
-  endLoading: function() {
+  endLoading: function endLoading() {
     // Determine at what resolution the browser is rendered based on meta tag
     let browser = this._browser;
     let metaData = Util.contentIsHandheld(browser);
     let bv = Browser._browserView;
 
     if (metaData.reason == "handheld" || metaData.reason == "doctype") {
       browser.className = "browser-handheld";
     } else if (metaData.reason == "viewport") {
@@ -2850,59 +2850,60 @@ Tab.prototype = {
     this._loading = false;
 
     if (this == Browser.selectedTab)
       bv.setAggressive(true);
 
     // Don't render until pane has been scrolled to the correct position.
     bv.pauseRendering();
     this._stopResizeAndPaint();
+
     // XXX Sometimes MozScrollSizeChange has not occurred, so the scroll pane will not
     // be resized yet. We are assuming this event is on the queue, so scroll the pane
     // "soon."
     Util.executeSoon(function() {
       Browser.scrollContentToBrowser();
       bv.resumeRendering();
     });
 
     // if this tab was sacrificed previously, restore its state
     this.restoreState();
   },
 
-  isLoading: function() {
+  isLoading: function isLoading() {
     return this._loading;
   },
 
-  load: function(uri) {
+  load: function load(uri) {
     this._browser.setAttribute("src", uri);
   },
 
-  create: function() {
+  create: function create() {
     // Initialize a viewport state for BrowserView
     this._browserViewportState = BrowserView.Util.createBrowserViewportState();
 
     this._chromeTab = document.getElementById("tabs").addTab();
     this._createBrowser();
   },
 
-  destroy: function() {
-    this._destroyBrowser();
+  destroy: function destroy() {
     document.getElementById("tabs").removeTab(this._chromeTab);
     this._chromeTab = null;
+    this._destroyBrowser();
   },
 
   /** Create browser if it doesn't already exist. */
-  ensureBrowserExists: function() {
+  ensureBrowserExists: function ensureBrowserExists() {
     if (!this._browser) {
       this._createBrowser();
       this.browser.contentDocument.location = this._state._url;
     }
   },
 
-  _createBrowser: function() {
+  _createBrowser: function _createBrowser() {
     if (this._browser)
       throw "Browser already exists";
 
     // Create the browser using the current width the dynamically size the height
     let browser = this._browser = document.createElement("browser");
 
     browser.className = "browser";
     browser.setAttribute("style", "overflow: -moz-hidden-unscrollable; visibility: hidden;");
@@ -2914,27 +2915,34 @@ Tab.prototype = {
     // stop about:blank from loading
     browser.stop();
 
     // Attach a separate progress listener to the browser
     this._listener = new ProgressController(this);
     browser.addProgressListener(this._listener);
   },
 
-  _destroyBrowser: function() {
+  _destroyBrowser: function _destroyBrowser() {
     if (this._browser) {
-      document.getElementById("browsers").removeChild(this._browser);
+      var browser = this._browser;
+      browser.removeProgressListener(this._listener);
+
       this._browser = null;
+      this._listener = null;
       this._loading = false;
       this._stopResizeAndPaint();
+
+      Util.executeSoon(function() {
+        document.getElementById("browsers").removeChild(browser);
+      });      
     }
   },
 
   /** Serializes as much state as possible of the current content.  */
-  saveState: function() {
+  saveState: function saveState() {
     let state = { };
 
     var browser = this._browser;
     var doc = browser.contentDocument;
     state._url = doc.location.href;
     state._scroll = BrowserView.Util.getContentScrollOffset(this.browser);
     if (doc instanceof HTMLDocument) {
       var tags = ["input", "textarea", "select"];
@@ -2954,17 +2962,17 @@ Tab.prototype = {
         }
       }
     }
 
     this._state = state;
   },
 
   /** Restores serialized content from saveState.  */
-  restoreState: function() {
+  restoreState: function restoreState() {
     let state = this._state;
     if (!state)
       return;
 
     let doc = this._browser.contentDocument;
 
     for (var item in state) {
       var elem = null;
@@ -2981,25 +2989,25 @@ Tab.prototype = {
     }
 
     this.browser.contentWindow.scrollX = state._scroll.x;
     this.browser.contentWindow.scrollY = state._scroll.y;
 
     this._state = null;
   },
 
-  updateThumbnail: function() {
+  updateThumbnail: function updateThumbnail() {
     if (!this._browser)
       return;
 
     let browserView = (Browser.selectedBrowser == this._browser) ? Browser._browserView : null;
     this._chromeTab.updateThumbnail(this._browser, browserView);
   },
 
-  setIcon: function(aURI) {
+  setIcon: function setIcon(aURI) {
     let faviconURI = null;
     if (aURI) {
       try {
         faviconURI = gIOService.newURI(aURI, null, null);
       }
       catch (e) {
         faviconURI = null;
       }