Backed out changeset d1cd5199bf45 (bug 867142)

This commit is contained in:
Tim Taubert 2013-05-24 15:28:29 +02:00
parent 9381ad4dcd
commit aca2d68a01
8 changed files with 117 additions and 98 deletions

View File

@ -16,6 +16,9 @@ const STATE_QUITTING = -1;
const STATE_STOPPED_STR = "stopped";
const STATE_RUNNING_STR = "running";
const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;
const PRIVACY_NONE = 0;
const PRIVACY_ENCRYPTED = 1;
const PRIVACY_FULL = 2;
@ -232,29 +235,6 @@ this.SessionStore = {
checkPrivacyLevel: function ss_checkPrivacyLevel(aIsHTTPS, aUseDefaultPref) {
return SessionStoreInternal.checkPrivacyLevel(aIsHTTPS, aUseDefaultPref);
},
/**
* Returns whether a given browser is waiting to be restored. That means its
* history and state is ready but we wait until it's higher up in the priority
* queue or until it's made visible (if restore_on_demand=true).
*
* @param aBrowser Browser reference
* @returns bool
*/
isTabStateNeedsRestore: function ss_isTabStateNeedsRestore(aBrowser) {
return TabRestoreStates.isNeedsRestore(aBrowser);
},
/**
* Returns whether a given browser is currently restoring, i.e. we wait for
* the actual page to load and will restore form data when it's finished.
*
* @param aBrowser Browser reference
* @returns bool
*/
isTabStateRestoring: function ss_isTabStateRestoring(aBrowser) {
return TabRestoreStates.isRestoring(aBrowser);
}
};
@ -1077,7 +1057,7 @@ let SessionStoreInternal = {
RestoringTabsData.remove(aTab.linkedBrowser);
delete aTab.linkedBrowser.__SS_formDataSaved;
delete aTab.linkedBrowser.__SS_hostSchemeData;
if (TabRestoreStates.has(aTab.linkedBrowser))
if (aTab.linkedBrowser.__SS_restoreState)
this._resetTabRestoringState(aTab);
});
openWindows[aWindow.__SSi] = true;
@ -1272,10 +1252,10 @@ let SessionStoreInternal = {
// If this tab was in the middle of restoring or still needs to be restored,
// we need to reset that state. If the tab was restoring, we will attempt to
// restore the next tab.
if (TabRestoreStates.has(browser)) {
let wasRestoring = TabRestoreStates.isRestoring(browser);
let previousState = browser.__SS_restoreState;
if (previousState) {
this._resetTabRestoringState(aTab);
if (wasRestoring)
if (previousState == TAB_STATE_RESTORING)
this.restoreNextTab();
}
@ -1337,7 +1317,8 @@ let SessionStoreInternal = {
// following "load" is too late for deleting the data caches)
// It's possible to get a load event after calling stop on a browser (when
// overwriting tabs). We want to return early if the tab hasn't been restored yet.
if (TabRestoreStates.isNeedsRestore(aBrowser)) {
if (aBrowser.__SS_restoreState &&
aBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
return;
}
@ -1373,8 +1354,11 @@ let SessionStoreInternal = {
this._windows[aWindow.__SSi].selected = aWindow.gBrowser.tabContainer.selectedIndex;
let tab = aWindow.gBrowser.selectedTab;
// Explicitly call restoreTab() to to restore the tab if we need to.
if (TabRestoreStates.isNeedsRestore(tab.linkedBrowser))
// If __SS_restoreState is still on the browser and it is
// TAB_STATE_NEEDS_RESTORE, then then we haven't restored
// this tab yet. Explicitly call restoreTab to kick off the restore.
if (tab.linkedBrowser.__SS_restoreState &&
tab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
this.restoreTab(tab);
// attempt to update the current URL we send in a crash report
@ -1384,7 +1368,8 @@ let SessionStoreInternal = {
onTabShow: function ssi_onTabShow(aWindow, aTab) {
// If the tab hasn't been restored yet, move it into the right bucket
if (TabRestoreStates.isNeedsRestore(aTab.linkedBrowser)) {
if (aTab.linkedBrowser.__SS_restoreState &&
aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
TabRestoreQueue.hiddenToVisible(aTab);
// let's kick off tab restoration again to ensure this tab gets restored
@ -1399,7 +1384,8 @@ let SessionStoreInternal = {
onTabHide: function ssi_onTabHide(aWindow, aTab) {
// If the tab hasn't been restored yet, move it into the right bucket
if (TabRestoreStates.isNeedsRestore(aTab.linkedBrowser)) {
if (aTab.linkedBrowser.__SS_restoreState &&
aTab.linkedBrowser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
TabRestoreQueue.visibleToHidden(aTab);
}
@ -2770,7 +2756,7 @@ let SessionStoreInternal = {
// state (in restoreHistoryPrecursor).
if (aOverwriteTabs) {
for (let i = 0; i < tabbrowser.tabs.length; i++) {
if (TabRestoreStates.has(tabbrowser.browsers[i]))
if (tabbrowser.browsers[i].__SS_restoreState)
this._resetTabRestoringState(tabbrowser.tabs[i]);
}
}
@ -3000,7 +2986,7 @@ let SessionStoreInternal = {
// keep the data around to prevent dataloss in case
// a tab gets closed before it's been properly restored
RestoringTabsData.set(browser, tabData);
TabRestoreStates.setNeedsRestore(browser);
browser.__SS_restoreState = TAB_STATE_NEEDS_RESTORE;
browser.setAttribute("pending", "true");
tab.setAttribute("pending", "true");
@ -3190,7 +3176,7 @@ let SessionStoreInternal = {
this._tabsRestoringCount++;
// Set this tab's state to restoring
TabRestoreStates.setIsRestoring(browser);
browser.__SS_restoreState = TAB_STATE_RESTORING;
browser.removeAttribute("pending");
aTab.removeAttribute("pending");
@ -4414,11 +4400,10 @@ let SessionStoreInternal = {
let browser = aTab.linkedBrowser;
// Keep the tab's previous state for later in this method
let wasRestoring = TabRestoreStates.isRestoring(browser);
let wasNeedsRestore = TabRestoreStates.isNeedsRestore(browser);
let previousState = browser.__SS_restoreState;
// The browser is no longer in any sort of restoring state.
TabRestoreStates.remove(browser);
delete browser.__SS_restoreState;
aTab.removeAttribute("pending");
browser.removeAttribute("pending");
@ -4430,11 +4415,11 @@ let SessionStoreInternal = {
// Remove the progress listener if we should.
this._removeTabsProgressListener(window);
if (wasRestoring) {
if (previousState == TAB_STATE_RESTORING) {
if (this._tabsRestoringCount)
this._tabsRestoringCount--;
}
else if (wasNeedsRestore) {
else if (previousState == TAB_STATE_NEEDS_RESTORE) {
// Make sure the session history listener is removed. This is normally
// done in restoreTab, but this tab is being removed before that gets called.
this._removeSHistoryListener(aTab);
@ -4687,41 +4672,6 @@ let TabAttributes = {
}
};
// A map keeping track of all tab restore states. A tab might be 'needs-restore'
// if it waits until the restoration process is kicked off. This might start
// when the tab reaches a higher position in the priority queue or when it's
// made visible (when restore_on_demand=true). If a tab is 'restoring' we wait
// for its actual page to load and will then restore form data etc. If has()
// returns false the tab has not been restored from previous data or it has
// already finished restoring and is thus now seen as a valid and complete tab.
let TabRestoreStates = {
_states: new WeakMap(),
has: function (browser) {
return this._states.has(browser);
},
isNeedsRestore: function ss_isNeedsRestore(browser) {
return this._states.get(browser) === "needs-restore";
},
setNeedsRestore: function (browser) {
this._states.set(browser, "needs-restore");
},
isRestoring: function ss_isRestoring(browser) {
return this._states.get(browser) === "restoring";
},
setIsRestoring: function (browser) {
this._states.set(browser, "restoring");
},
remove: function (browser) {
this._states.delete(browser);
}
};
// This is used to help meter the number of restoring tabs. This is the control
// point for telling the next tab to restore. It gets attached to each gBrowser
// via gBrowser.addTabsProgressListener
@ -4729,7 +4679,8 @@ let gRestoreTabsProgressListener = {
onStateChange: function(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
// Ignore state changes on browsers that we've already restored and state
// changes that aren't applicable.
if (TabRestoreStates.isRestoring(aBrowser) &&
if (aBrowser.__SS_restoreState &&
aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {

View File

@ -73,7 +73,7 @@ let TabsProgressListener = {
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (this.callback && SessionStore.isTabStateRestoring(aBrowser) &&
if (this.callback && aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
@ -85,9 +85,9 @@ let TabsProgressListener = {
for (let i = 0; i < this.window.gBrowser.tabs.length; i++) {
let browser = this.window.gBrowser.tabs[i].linkedBrowser;
if (SessionStore.isTabStateRestoring(browser))
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (SessionStore.isTabStateNeedsRestore(browser))
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}

View File

@ -22,6 +22,17 @@ function test() {
// any given time. This guarantees that a finishing load won't start another.
Services.prefs.setBoolPref("browser.sessionstore.restore_on_demand", true);
// We have our own progress listener for this test, which we'll attach before our state is set
let progressListener = {
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
progressCallback(aBrowser);
}
}
let state = { windows: [{ tabs: [
{ entries: [{ url: "http://example.org#1" }], extData: { "uniq": r() } },
{ entries: [{ url: "http://example.org#2" }], extData: { "uniq": r() } }, // overwriting
@ -31,10 +42,10 @@ function test() {
{ entries: [{ url: "http://example.org#6" }] } // creating
], selected: 1 }] };
gProgressListener.setCallback(function progressCallback(aBrowser) {
function progressCallback(aBrowser) {
// We'll remove the progress listener after the first one because we aren't
// loading any other tabs
gProgressListener.unsetCallback();
window.gBrowser.removeTabsProgressListener(progressListener);
let curState = JSON.parse(ss.getBrowserState());
for (let i = 0; i < curState.windows[0].tabs.length; i++) {
@ -98,8 +109,9 @@ function test() {
"(creating) new data is stored in extData where there was none");
cleanup();
});
}
window.gBrowser.addTabsProgressListener(progressListener);
ss.setBrowserState(JSON.stringify(state));
}

View File

@ -18,15 +18,19 @@ function test() {
waitForExplicitFinish();
registerCleanupFunction(function () {
TabsProgressListener.uninit();
ss.setBrowserState(stateBackup);
});
TabsProgressListener.init();
window.addEventListener("SSWindowStateReady", function onReady() {
window.removeEventListener("SSWindowStateReady", onReady, false);
let firstProgress = true;
gProgressListener.setCallback(function (browser, needsRestore, isRestoring) {
TabsProgressListener.setCallback(function (needsRestore, isRestoring) {
if (firstProgress) {
firstProgress = false;
is(isRestoring, 3, "restoring 3 tabs concurrently");
@ -35,7 +39,7 @@ function test() {
}
if (0 == needsRestore) {
gProgressListener.unsetCallback();
TabsProgressListener.unsetCallback();
waitForFocus(finish);
}
});
@ -45,3 +49,51 @@ function test() {
ss.setBrowserState(JSON.stringify(statePinned));
}
function countTabs() {
let needsRestore = 0, isRestoring = 0;
let windowsEnum = Services.wm.getEnumerator("navigator:browser");
while (windowsEnum.hasMoreElements()) {
let window = windowsEnum.getNext();
if (window.closed)
continue;
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
let browser = window.gBrowser.tabs[i].linkedBrowser;
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
}
return [needsRestore, isRestoring];
}
let TabsProgressListener = {
init: function () {
gBrowser.addTabsProgressListener(this);
},
uninit: function () {
this.unsetCallback();
gBrowser.removeTabsProgressListener(this);
},
setCallback: function (callback) {
this.callback = callback;
},
unsetCallback: function () {
delete this.callback;
},
onStateChange: function (aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) {
if (this.callback && aBrowser.__SS_restoreState == TAB_STATE_RESTORING &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW)
this.callback.apply(null, countTabs());
}
}

View File

@ -22,7 +22,7 @@ function test() {
isnot(gBrowser.selectedTab, tab, "newly created tab is not selected");
ss.setTabState(tab, JSON.stringify(tabState));
ok(SessionStore.isTabStateNeedsRestore(browser), "tab needs restoring");
is(browser.__SS_restoreState, TAB_STATE_NEEDS_RESTORE, "tab needs restoring");
let state = JSON.parse(ss.getTabState(tab));
let formdata = state.entries[0].formdata;

View File

@ -2,6 +2,9 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;
let tmp = {};
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
let SessionStore = tmp.SessionStore;
@ -238,7 +241,7 @@ let gProgressListener = {
function gProgressListener_onStateChange(aBrowser, aWebProgress, aRequest,
aStateFlags, aStatus) {
if ((!this._checkRestoreState ||
SessionStore.isTabStateRestoring(aBrowser)) &&
aBrowser.__SS_restoreState == TAB_STATE_RESTORING) &&
aStateFlags & Ci.nsIWebProgressListener.STATE_STOP &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK &&
aStateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW) {
@ -253,9 +256,9 @@ let gProgressListener = {
for (let win in BrowserWindowIterator()) {
for (let i = 0; i < win.gBrowser.tabs.length; i++) {
let browser = win.gBrowser.tabs[i].linkedBrowser;
if (SessionStore.isTabStateRestoring(browser))
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (SessionStore.isTabStateNeedsRestore(browser))
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
else
wasRestored++;

View File

@ -3,6 +3,9 @@
let ss = Cc["@mozilla.org/browser/sessionstore;1"].getService(Ci.nsISessionStore);
const TAB_STATE_NEEDS_RESTORE = 1;
const TAB_STATE_RESTORING = 2;
let stateBackup = ss.getBrowserState();
let state = {windows:[{tabs:[
@ -122,9 +125,9 @@ function countTabs() {
for (let i = 0; i < window.gBrowser.tabs.length; i++) {
let browser = window.gBrowser.tabs[i].linkedBrowser;
if (SessionStore.isTabStateRestoring(browser))
if (browser.__SS_restoreState == TAB_STATE_RESTORING)
isRestoring++;
else if (SessionStore.isTabStateNeedsRestore(browser))
else if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE)
needsRestore++;
}
}
@ -165,9 +168,8 @@ let TabsProgressListener = {
self.callback.apply(null, countTabs());
};
let isRestoring = SessionStore.isTabStateRestoring(aBrowser);
let needsRestore = SessionStore.isTabStateNeedsRestore(aBrowser);
let wasRestoring = !isRestoring && !needsRestore && aBrowser.__wasRestoring;
let isRestoring = aBrowser.__SS_restoreState == TAB_STATE_RESTORING;
let wasRestoring = !aBrowser.__SS_restoreState && aBrowser.__wasRestoring;
let hasStopped = aStateFlags & Ci.nsIWebProgressListener.STATE_STOP;
if (isRestoring && !hasStopped)

View File

@ -1,10 +1,6 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
let tmp = {};
Cu.import("resource:///modules/sessionstore/SessionStore.jsm", tmp);
let SessionStore = tmp.SessionStore;
// Some tests here assume that all restored tabs are loaded without waiting for
// the user to bring them to the foreground. We ensure this by resetting the
// related preference (see the "firefox.js" defaults file for details).
@ -121,6 +117,8 @@ function newWindowWithTabView(shownCallback, loadCallback, width, height) {
// ----------
function afterAllTabsLoaded(callback, win) {
const TAB_STATE_NEEDS_RESTORE = 1;
win = win || window;
let stillToLoad = 0;
@ -139,7 +137,8 @@ function afterAllTabsLoaded(callback, win) {
let browser = tab.linkedBrowser;
let isRestorable = !(tab.hidden && !restoreHiddenTabs &&
SessionStore.isTabStateNeedsRestore(browser));
browser.__SS_restoreState &&
browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE);
if (isRestorable && browser.contentDocument.readyState != "complete" ||
browser.webProgress.isLoadingDocument) {