author | Ian Gilman <ian@iangilman.com> |
Wed, 05 Jan 2011 12:54:34 -0800 | |
changeset 60031 | 2d849e2d302eaca2c777bbb13f96109e6f756e03 |
parent 60030 | bddc89a2200caa8836e94704ff4084333fa28d4f |
child 60032 | b06a94065ef0726698fe6c42c706c8ddbe601f84 |
push id | 17837 |
push user | ian@iangilman.com |
push date | Wed, 05 Jan 2011 20:59:13 +0000 |
treeherder | mozilla-central@f453924d5fe1 [default view] [failures only] |
perfherder | [talos] [build metrics] [platform microbench] (compared to previous push) |
reviewers | dietrich, blocking |
bugs | 598795 |
milestone | 2.0b9pre |
first release with | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
last release without | nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
|
--- a/browser/base/content/tabview/tabitems.js +++ b/browser/base/content/tabview/tabitems.js @@ -81,16 +81,18 @@ function TabItem(tab, options) { this.tabCanvas = new TabCanvas(this.tab, this.canvasEl); this.defaultSize = new Point(TabItems.tabWidth, TabItems.tabHeight); this.locked = {}; this.isATabItem = true; this._zoomPrep = false; this.sizeExtra = new Point(); this.keepProportional = true; + this._hasBeenDrawn = false; + this._reconnected = false; var self = this; this.isDragging = false; this.sizeExtra.x = parseInt($div.css('padding-left')) + parseInt($div.css('padding-right')); @@ -99,20 +101,16 @@ function TabItem(tab, options) { this.bounds = $div.bounds(); this._lastTabUpdateTime = Date.now(); // ___ superclass setup this._init($div[0]); - // ___ reconnect to data from Storage - this._hasBeenDrawn = false; - let reconnected = TabItems.reconnect(this); - // ___ drag/drop // override dropOptions with custom tabitem methods // This is mostly to support the phantom groupItems. this.dropOptions.drop = function(e) { var $target = iQ(this.container); this.isDropTarget = false; var phantom = $target.data("phantomGroupItem"); @@ -201,29 +199,25 @@ function TabItem(tab, options) { .addClass('close') .appendTo($div); this.closeEl = (iQ(".close", $div))[0]; iQ("<div>") .addClass('expander') .appendTo($div); + this.setResizable(true, options.immediately); + this.droppable(true); this._updateDebugBounds(); TabItems.register(this); - if (!this.reconnected) - GroupItems.newTab(this, options); - - // tabs which were not reconnected at all or were not immediately added - // to a group get the same treatment. - if (!this.reconnected || (reconnected && !reconnected.addedToGroup) ) { - this.setResizable(true, options.immediately); - this.droppable(true); - } + // ___ reconnect to data from Storage + if (!TabItems.reconnectingPaused()) + this._reconnect(); }; TabItem.prototype = Utils.extend(new Item(), new Subscribable(), { // ---------- // Function: forceCanvasSize // Repaints the thumbnail with the given resolution, and forces it // to stay that resolution until unforceCanvasSize is called. forceCanvasSize: function TabItem_forceCanvasSize(w, h) { @@ -320,28 +314,70 @@ TabItem.prototype = Utils.extend(new Ite // ---------- // Function: save // Store persistent for this object. // // Parameters: // saveImageData - true to include thumbnail pixels (and page title as well); default false save: function TabItem_save(saveImageData) { try{ - if (!this.tab || this.tab.parentNode == null || !this.reconnected) // too soon/late to save + if (!this.tab || this.tab.parentNode == null || !this._reconnected) // too soon/late to save return; var data = this.getStorageData(saveImageData); if (TabItems.storageSanity(data)) Storage.saveTab(this.tab, data); } catch(e) { Utils.log("Error in saving tab value: "+e); } }, // ---------- + // Function: _reconnect + // Load the reciever's persistent data from storage. If there is none, + // treats it as a new tab. + _reconnect: function TabItem__reconnect() { + Utils.assertThrow(!this._reconnected, "shouldn't already be reconnected"); + Utils.assertThrow(this.tab, "should have a xul:tab"); + + let tabData = Storage.getTabData(this.tab); + if (tabData && TabItems.storageSanity(tabData)) { + if (this.parent) + this.parent.remove(this, {immediately: true}); + + this.setBounds(tabData.bounds, true); + + if (Utils.isPoint(tabData.userSize)) + this.userSize = new Point(tabData.userSize); + + if (tabData.groupID) { + var groupItem = GroupItems.groupItem(tabData.groupID); + if (groupItem) { + groupItem.add(this, null, {immediately: true}); + + // if it matches the selected tab or no active tab and the browser + // tab is hidden, the active group item would be set. + if (this.tab == gBrowser.selectedTab || + (!GroupItems.getActiveGroupItem() && !this.tab.hidden)) + GroupItems.setActiveGroupItem(this.parent); + } + } + + if (tabData.imageData) + this.showCachedData(tabData); + } else { + GroupItems.newTab(this, {immediately: true}); + } + + this._reconnected = true; + this.save(); + this._sendToSubscribers("reconnected"); + }, + + // ---------- // Function: setBounds // Moves this item to the specified location and size. // // Parameters: // rect - a <Rect> giving the new bounds // immediately - true if it should not animate; default false // options - an object with additional parameters, see below // @@ -747,16 +783,17 @@ let TabItems = { tabsProgressListener: null, _tabsWaitingForUpdate: [], _heartbeatOn: false, // see explanation at startHeartbeat() below _heartbeatTiming: 100, // milliseconds between _checkHeartbeat() calls _lastUpdateTime: Date.now(), _eventListeners: [], _pauseUpdateForTest: false, tempCanvas: null, + _reconnectingPaused: false, // ---------- // Function: init // Set up the necessary tracking to maintain the <TabItems>s. init: function TabItems_init() { Utils.assert(window.AllTabs, "AllTabs must be initialized first"); let self = this; @@ -897,20 +934,16 @@ let TabItems = { if (iconUrl != tabItem.favImgEl.src) tabItem.favImgEl.src = iconUrl; // ___ URL let tabUrl = tab.linkedBrowser.currentURI.spec; if (tabUrl != tabItem.url) { let oldURL = tabItem.url; tabItem.url = tabUrl; - - if (!tabItem.reconnected) - this.reconnect(tabItem); - tabItem.save(); } // ___ label let label = tab.label; let $name = iQ(tabItem.nameEl); if (!tabItem.isShowingCachedData() && $name.text() != label) $name.text(label); @@ -1055,16 +1088,45 @@ let TabItems = { // Function: isPaintingPaused // Returns a boolean indicating whether painting // is paused or not. isPaintingPaused: function TabItems_isPaintingPaused() { return this.paintingPaused > 0; }, // ---------- + // Function: pauseReconnecting + // Don't reconnect any new tabs until resume is called. + pauseReconnecting: function TabItems_pauseReconnecting() { + Utils.assertThrow(!this._reconnectingPaused, "shouldn't already be paused"); + + this._reconnectingPaused = true; + }, + + // ---------- + // Function: resumeReconnecting + // Reconnect all of the tabs that were created since we paused. + resumeReconnecting: function TabItems_resumeReconnecting() { + Utils.assertThrow(this._reconnectingPaused, "should already be paused"); + + this._reconnectingPaused = false; + this.items.forEach(function(item) { + if (!item._reconnected) + item._reconnect(); + }); + }, + + // ---------- + // Function: reconnectingPaused + // Returns true if reconnecting is paused. + reconnectingPaused: function TabItems_reconnectingPaused() { + return this._reconnectingPaused; + }, + + // ---------- // Function: register // Adds the given <TabItem> to the master list. register: function TabItems_register(item) { Utils.assert(item && item.isAnItem, 'item must be a TabItem'); Utils.assert(this.items.indexOf(item) == -1, 'only register once per item'); this.items.push(item); }, @@ -1105,77 +1167,16 @@ let TabItems = { storageSanity: function TabItems_storageSanity(data) { var sane = true; if (!Utils.isRect(data.bounds)) { Utils.log('TabItems.storageSanity: bad bounds', data.bounds); sane = false; } return sane; - }, - - // ---------- - // Function: reconnect - // Given a <TabItem>, attempts to load its persistent data from storage. - reconnect: function TabItems_reconnect(item) { - var found = false; - - try{ - Utils.assert(item, 'item'); - Utils.assert(item.tab, 'item.tab'); - - if (item.reconnected) - return true; - - if (!item.tab) - return false; - - let tabData = Storage.getTabData(item.tab); - if (tabData && this.storageSanity(tabData)) { - if (item.parent) - item.parent.remove(item, {immediately: true}); - - item.setBounds(tabData.bounds, true); - - if (Utils.isPoint(tabData.userSize)) - item.userSize = new Point(tabData.userSize); - - if (tabData.groupID) { - var groupItem = GroupItems.groupItem(tabData.groupID); - if (groupItem) { - groupItem.add(item, null, {immediately: true}); - - // if it matches the selected tab or no active tab and the browser - // tab is hidden, the active group item would be set. - if (item.tab == gBrowser.selectedTab || - (!GroupItems.getActiveGroupItem() && !item.tab.hidden)) - GroupItems.setActiveGroupItem(item.parent); - } - } - - if (tabData.imageData) - item.showCachedData(tabData); - - item.reconnected = true; - found = {addedToGroup: tabData.groupID}; - } else { - // We should never have any orphaned tabs. Therefore, item is not - // connected if it has no parent and GroupItems.newTab() would handle - // the group creation. - item.reconnected = (item.parent != null); - } - item.save(); - - if (item.reconnected) - item._sendToSubscribers("reconnected"); - } catch(e) { - Utils.log(e); - } - - return found; } }; // ########## // Class: TabCanvas // Takes care of the actual canvas for the tab thumbnail // Does not need to be accessed from outside of tabitems.js function TabCanvas(tab, canvas) {
--- a/browser/base/content/tabview/ui.js +++ b/browser/base/content/tabview/ui.js @@ -530,16 +530,17 @@ let UI = { self._privateBrowsing.transitionStage = 2; else if (self._privateBrowsing.transitionStage == 3) { if (self._privateBrowsing.transitionMode == "exit" && self._privateBrowsing.wasInTabView) self.showTabView(false); self._privateBrowsing.transitionStage = 0; self._privateBrowsing.transitionMode = ""; + TabItems.resumeReconnecting(); } } Services.obs.addObserver(srObserver, "sessionstore-browser-state-restored", false); this._cleanupFunctions.push(function() { Services.obs.removeObserver(srObserver, "sessionstore-browser-state-restored"); }); @@ -564,16 +565,17 @@ let UI = { self._privateBrowsing.wasInTabView = self.isTabViewVisible(); if (self.isTabViewVisible()) self.goToTab(gBrowser.selectedTab); } } else if (aTopic == "private-browsing-change-granted") { if (aData == "enter" || aData == "exit") { self._privateBrowsing.transitionStage = 1; self._privateBrowsing.transitionMode = aData; + TabItems.pauseReconnecting(); } } } Services.obs.addObserver(pbObserver, "private-browsing", false); Services.obs.addObserver(pbObserver, "private-browsing-change-granted", false); this._cleanupFunctions.push(function() {
--- a/browser/base/content/test/tabview/browser_tabview_bug597248.js +++ b/browser/base/content/test/tabview/browser_tabview_bug597248.js @@ -197,17 +197,17 @@ function onTabViewShown() { } } let tabItems = contentWindow.TabItems.getItems(); let count = tabItems.length; tabItems.forEach(function(tabItem) { // tabitem might not be connected so use subscriber for those which are not // connected. - if (tabItem.reconnected) { + if (tabItem._reconnected) { ok(tabItem.isShowingCachedData(), "Tab item is showing cached data and is already connected. " + tabItem.tab.linkedBrowser.currentURI.spec); if (--count == 0) nextStep(); } else { tabItem.addSubscriber(tabItem, "reconnected", function() { tabItem.removeSubscriber(tabItem, "reconnected");
--- a/browser/base/content/test/tabview/browser_tabview_orphaned_tabs.js +++ b/browser/base/content/test/tabview/browser_tabview_orphaned_tabs.js @@ -87,17 +87,17 @@ function onTabViewWindowLoaded() { newWin.gBrowser.removeTab(tabItem.tab); whenWindowObservesOnce(newWin, "domwindowclosed", function() { finish(); }); newWin.close(); }; let tabItem = groupItem.getChild(0); // the item may not be connected so subscriber would be used in that case. - if (tabItem.reconnected) { + if (tabItem._reconnected) { checkAndFinish(); } else { tabItem.addSubscriber(tabItem, "reconnected", function() { tabItem.removeSubscriber(tabItem, "reconnected"); checkAndFinish(); }); } };