Backed out changeset 10c21d116e5d from bug 407110 to investigate Ts

regression.
This commit is contained in:
Dave Townsend 2008-11-07 10:14:51 +00:00
parent bfe3d608ee
commit 89151a360c

View File

@ -100,6 +100,8 @@ const CAPABILITIES = [
"Subframes", "Plugins", "Javascript", "MetaRedirects", "Images"
];
// module for JSON conversion (needed for the nsISessionStore API)
Cu.import("resource://gre/modules/JSON.jsm");
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
function debug(aMsg) {
@ -580,6 +582,13 @@ SessionStoreService.prototype = {
// cache the window state until the window is completely gone
aWindow.__SS_dyingCache = winData;
// reset the _tab property to avoid keeping the tab's XUL element alive
// longer than we need it
var tabCount = aWindow.__SS_dyingCache.tabs.length;
for (var t = 0; t < tabCount; t++) {
delete aWindow.__SS_dyingCache.tabs[t]._tab;
}
delete aWindow.__SSi;
},
@ -653,6 +662,10 @@ SessionStoreService.prototype = {
var tabState = this._collectTabData(aTab);
this._updateTextAndScrollDataForTab(aWindow, aTab.linkedBrowser, tabState);
// reset the _tab property to avoid keeping the tab's XUL element alive
// longer than we need it
delete tabState._tab;
// store closed-tab data for undo
if (tabState.entries.length > 0) {
let tabTitle = aTab.label;
@ -802,8 +815,10 @@ SessionStoreService.prototype = {
if (!tabState.entries || !aTab.ownerDocument || !aTab.ownerDocument.defaultView.__SSi)
throw (Components.returnCode = Cr.NS_ERROR_INVALID_ARG);
tabState._tab = aTab;
var window = aTab.ownerDocument.defaultView;
this.restoreHistoryPrecursor(window, [aTab], [tabState], 0, 0, 0);
this.restoreHistoryPrecursor(window, [tabState], 0, 0, 0);
},
duplicateTab: function sss_duplicateTab(aWindow, aTab) {
@ -816,7 +831,8 @@ SessionStoreService.prototype = {
this._updateTextAndScrollDataForTab(sourceWindow, aTab.linkedBrowser, tabState, true);
var newTab = aWindow.getBrowser().addTab();
this.restoreHistoryPrecursor(aWindow, [newTab], [tabState], 0, 0, 0);
tabState._tab = newTab;
this.restoreHistoryPrecursor(aWindow, [tabState], 0, 0, 0);
return newTab;
},
@ -857,13 +873,13 @@ SessionStoreService.prototype = {
// create a new tab
let browser = aWindow.gBrowser;
let tab = browser.addTab();
let tab = closedTabState._tab = browser.addTab();
// restore the tab's position
browser.moveTabTo(tab, closedTab.pos);
// restore tab content
this.restoreHistoryPrecursor(aWindow, [tab], [closedTabState], 1, 0, 0);
this.restoreHistoryPrecursor(aWindow, [closedTabState], 1, 0, 0);
// focus the tab's content area
let content = browser.getBrowserForTab(tab).contentWindow;
@ -966,7 +982,7 @@ SessionStoreService.prototype = {
if (!browser || !browser.currentURI)
// can happen when calling this function right after .addTab()
return tabData;
else if (browser.parentNode.__SS_data && browser.parentNode.__SS_data._tabStillLoading)
else if (browser.parentNode.__SS_data && browser.parentNode.__SS_data._tab)
// use the data to be restored when the tab hasn't been completely loaded
return browser.parentNode.__SS_data;
@ -1204,8 +1220,7 @@ SessionStoreService.prototype = {
for (var i = 0; i < browsers.length; i++) {
try {
var tabData = this._windows[aWindow.__SSi].tabs[i];
if (browsers[i].parentNode.__SS_data &&
browsers[i].parentNode.__SS_data._tabStillLoading)
if (browsers[i].parentNode.__SS_data && browsers[i].parentNode.__SS_data._tab)
continue; // ignore incompletely initialized tabs
this._updateTextAndScrollDataForTab(aWindow, browsers[i], tabData);
}
@ -1606,13 +1621,12 @@ SessionStoreService.prototype = {
var tabbrowser = aWindow.getBrowser();
var openTabCount = aOverwriteTabs ? tabbrowser.browsers.length : -1;
var newTabCount = winData.tabs.length;
let tabs = [];
for (var t = 0; t < newTabCount; t++) {
tabs.push(t < openTabCount ? tabbrowser.mTabs[t] : tabbrowser.addTab());
winData.tabs[t]._tab = t < openTabCount ? tabbrowser.mTabs[t] : tabbrowser.addTab();
// when resuming at startup: add additionally requested pages to the end
if (!aOverwriteTabs && root._firstTabs) {
tabbrowser.moveTabTo(tabs[t], t);
tabbrowser.moveTabTo(winData.tabs[t]._tab, t);
}
}
@ -1639,20 +1653,18 @@ SessionStoreService.prototype = {
this._windows[aWindow.__SSi]._closedTabs = winData._closedTabs;
}
this.restoreHistoryPrecursor(aWindow, tabs, winData.tabs,
(aOverwriteTabs ? (parseInt(winData.selected) || 1) : 0), 0, 0);
this.restoreHistoryPrecursor(aWindow, winData.tabs, (aOverwriteTabs ?
(parseInt(winData.selected) || 1) : 0), 0, 0);
this._notifyIfAllWindowsRestored();
},
/**
* Manage history restoration for a window
* @param aWindow
* Window to restore the tabs into
* @param aTabs
* Array of tab references
* @param aTabData
* Array of tab data
* @param aCurrentTabs
* Array of tab references
* @param aSelectTab
* Index of selected tab
* @param aIx
@ -1660,22 +1672,21 @@ SessionStoreService.prototype = {
* @param aCount
* Counter for number of times delaying b/c browser or history aren't ready
*/
restoreHistoryPrecursor:
function sss_restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab, aIx, aCount) {
restoreHistoryPrecursor: function sss_restoreHistoryPrecursor(aWindow, aTabs, aSelectTab, aIx, aCount) {
var tabbrowser = aWindow.getBrowser();
// make sure that all browsers and their histories are available
// - if one's not, resume this check in 100ms (repeat at most 10 times)
for (var t = aIx; t < aTabs.length; t++) {
try {
if (!tabbrowser.getBrowserForTab(aTabs[t]).webNavigation.sessionHistory) {
if (!tabbrowser.getBrowserForTab(aTabs[t]._tab).webNavigation.sessionHistory) {
throw new Error();
}
}
catch (ex) { // in case browser or history aren't ready yet
if (aCount < 10) {
var restoreHistoryFunc = function(self) {
self.restoreHistoryPrecursor(aWindow, aTabs, aTabData, aSelectTab, aIx, aCount + 1);
self.restoreHistoryPrecursor(aWindow, aTabs, aSelectTab, aIx, aCount + 1);
}
aWindow.setTimeout(restoreHistoryFunc, 100, this);
return;
@ -1685,11 +1696,10 @@ SessionStoreService.prototype = {
// mark the tabs as loading
for (t = 0; t < aTabs.length; t++) {
var tab = aTabs[t];
var tab = aTabs[t]._tab;
var browser = tabbrowser.getBrowserForTab(tab);
aTabData[t]._tabStillLoading = true;
if (!aTabData[t].entries || aTabData[t].entries.length == 0) {
if (!aTabs[t].entries || aTabs[t].entries.length == 0) {
// make sure to blank out this tab's content
// (just purging the tab's history won't be enough)
browser.contentDocument.location = "about:blank";
@ -1704,20 +1714,19 @@ SessionStoreService.prototype = {
// wall-paper fix for bug 439675: make sure that the URL to be loaded
// is always visible in the address bar
let activeIndex = (aTabData[t].index || aTabData[t].entries.length) - 1;
let activePageData = aTabData[t].entries[activeIndex] || null;
let activeIndex = (aTabs[t].index || aTabs[t].entries.length) - 1;
let activePageData = aTabs[t].entries[activeIndex] || null;
browser.userTypedValue = activePageData ? activePageData.url || null : null;
// keep the data around to prevent dataloss in case
// a tab gets closed before it's been properly restored
browser.parentNode.__SS_data = aTabData[t];
browser.parentNode.__SS_data = aTabs[t];
}
// make sure to restore the selected tab first (if any)
if (aSelectTab-- && aTabs[aSelectTab]) {
aTabs.unshift(aTabs.splice(aSelectTab, 1)[0]);
aTabData.unshift(aTabData.splice(aSelectTab, 1)[0]);
tabbrowser.selectedTab = aTabs[0];
tabbrowser.selectedTab = aTabs[0]._tab;
}
if (!this._isWindowLoaded(aWindow)) {
@ -1728,7 +1737,7 @@ SessionStoreService.prototype = {
// helper hash for ensuring unique frame IDs
var idMap = { used: {} };
this.restoreHistory(aWindow, aTabs, aTabData, idMap);
this.restoreHistory(aWindow, aTabs, idMap);
},
/**
@ -1736,25 +1745,22 @@ SessionStoreService.prototype = {
* @param aWindow
* Window reference
* @param aTabs
* Array of tab references
* @param aTabData
* Array of tab data
* @param aIdMap
* Hash for ensuring unique frame IDs
*/
restoreHistory: function sss_restoreHistory(aWindow, aTabs, aTabData, aIdMap) {
restoreHistory: function sss_restoreHistory(aWindow, aTabs, aIdMap) {
var _this = this;
while (aTabs.length > 0 && (!aTabData[0]._tabStillLoading || !aTabs[0].parentNode)) {
while (aTabs.length > 0 && (!aTabs[0]._tab || !aTabs[0]._tab.parentNode)) {
aTabs.shift(); // this tab got removed before being completely restored
aTabData.shift();
}
if (aTabs.length == 0) {
return; // no more tabs to restore
}
var tab = aTabs.shift();
var tabData = aTabData.shift();
var tabData = aTabs.shift();
var tab = tabData._tab;
var browser = aWindow.getBrowser().getBrowserForTab(tab);
var history = browser.webNavigation.sessionHistory;
@ -1825,7 +1831,7 @@ SessionStoreService.prototype = {
browser.addEventListener("load", browser.__SS_restore, true);
}
aWindow.setTimeout(function(){ _this.restoreHistory(aWindow, aTabs, aTabData, aIdMap); }, 0);
aWindow.setTimeout(function(){ _this.restoreHistory(aWindow, aTabs, aIdMap); }, 0);
},
/**
@ -2218,8 +2224,7 @@ SessionStoreService.prototype = {
_saveStateObject: function sss_saveStateObject(aStateObj) {
var stateString = Cc["@mozilla.org/supports-string;1"].
createInstance(Ci.nsISupportsString);
// parentheses are for backwards compatibility with Firefox 2.0 and 3.0
stateString.data = "(" + this._toJSONString(aStateObj) + ")";
stateString.data = aStateObj.toSource();
var observerService = Cc["@mozilla.org/observer-service;1"].
getService(Ci.nsIObserverService);
@ -2464,15 +2469,20 @@ SessionStoreService.prototype = {
* Converts a JavaScript object into a JSON string
* (see http://www.json.org/ for more information).
*
* The inverse operation consists of JSON.parse(JSON_string).
* The inverse operation consists of eval("(" + JSON_string + ")");
* and should be provably safe.
*
* @param aJSObject is the object to be converted
* @returns the object's JSON representation
* @return the object's JSON representation
*/
_toJSONString: function sss_toJSONString(aJSObject) {
// XXXzeniko drop the following keys used only for internal bookkeeping:
// _tabStillLoading, _hosts, _formDataSaved
return JSON.stringify(aJSObject);
let str = JSONModule.toString(aJSObject, ["_tab", "_hosts", "_formDataSaved"] /* keys to drop */);
// sanity check - so that API consumers can just eval this string
if (!JSONModule.isMostlyHarmless(str))
throw new Error("JSON conversion failed unexpectedly!");
return str;
},
_notifyIfAllWindowsRestored: function sss_notifyIfAllWindowsRestored() {