mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 600545 - getBrowserState() (and saved session state) incorrect with app tabs and browser.sessionstore.resume_from_crash = false [r=zpao, a=blocking2.0:final]
--HG-- extra : rebase_source : 34f6380284ae51f6afb5fae7f6fd94a2990ad2ae
This commit is contained in:
parent
7ea0a76c6b
commit
d8a740cc15
@ -21,7 +21,7 @@
|
||||
* Contributor(s):
|
||||
* Dietrich Ayala <dietrich@mozilla.com>
|
||||
* Ehsan Akhgari <ehsan.akhgari@gmail.com>
|
||||
* Michael Kraft <morac99-firefox@yahoo.com>
|
||||
* Michael Kraft <morac99-firefox2@yahoo.com>
|
||||
* Paul O’Shannessy <paul@oshannessy.com>
|
||||
* Nils Maier <maierman@web.de>
|
||||
*
|
||||
@ -217,6 +217,16 @@ SessionStoreService.prototype = {
|
||||
// Whether we've been initialized
|
||||
_initialized: false,
|
||||
|
||||
// The original "sessionstore.resume_session_once" preference value before it
|
||||
// was modified by saveState. saveState will set the
|
||||
// "sessionstore.resume_session_once" to true when the
|
||||
// the "sessionstore.resume_from_crash" preference is false (crash recovery
|
||||
// is disabled) so that pinned tabs will be restored in the case of a
|
||||
// crash. This variable is used to restore the original value so the
|
||||
// previous session is not always restored when
|
||||
// "sessionstore.resume_from_crash" is true.
|
||||
_resume_session_once_on_shutdown: null,
|
||||
|
||||
/* ........ Public Getters .............. */
|
||||
|
||||
get canRestoreLastSession() {
|
||||
@ -443,6 +453,15 @@ SessionStoreService.prototype = {
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
|
||||
this._clearingOnShutdown = false;
|
||||
}
|
||||
else if (this._resume_session_once_on_shutdown != null) {
|
||||
// if the sessionstore.resume_session_once preference was changed by
|
||||
// saveState because crash recovery is disabled then restore the
|
||||
// preference back to the value it was prior to that. This will prevent
|
||||
// SessionStore from always restoring the session when crash recovery is
|
||||
// disabled.
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once",
|
||||
this._resume_session_once_on_shutdown);
|
||||
}
|
||||
this._loadState = STATE_QUITTING; // just to be sure
|
||||
this._uninit();
|
||||
break;
|
||||
@ -550,6 +569,12 @@ SessionStoreService.prototype = {
|
||||
break;
|
||||
case "sessionstore.resume_from_crash":
|
||||
this._resume_from_crash = this._prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
||||
// restore original resume_session_once preference if set in saveState
|
||||
if (this._resume_session_once_on_shutdown != null) {
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once",
|
||||
this._resume_session_once_on_shutdown);
|
||||
this._resume_session_once_on_shutdown = null;
|
||||
}
|
||||
// either create the file with crash recovery information or remove it
|
||||
// (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
|
||||
if (!this._resume_from_crash)
|
||||
@ -1336,19 +1361,14 @@ SessionStoreService.prototype = {
|
||||
* Store all session data for a window
|
||||
* @param aWindow
|
||||
* Window reference
|
||||
* @param aPinnedOnly
|
||||
* Bool collect pinned tabs only
|
||||
*/
|
||||
_saveWindowHistory: function sss_saveWindowHistory(aWindow, aPinnedOnly) {
|
||||
_saveWindowHistory: function sss_saveWindowHistory(aWindow) {
|
||||
var tabbrowser = aWindow.gBrowser;
|
||||
var tabs = tabbrowser.tabs;
|
||||
var tabsData = this._windows[aWindow.__SSi].tabs = [];
|
||||
|
||||
for (var i = 0; i < tabs.length; i++) {
|
||||
if (aPinnedOnly && !tabs[i].pinned)
|
||||
break;
|
||||
for (var i = 0; i < tabs.length; i++)
|
||||
tabsData.push(this._collectTabData(tabs[i]));
|
||||
}
|
||||
|
||||
this._windows[aWindow.__SSi].selected = tabbrowser.mTabBox.selectedIndex + 1;
|
||||
},
|
||||
@ -2011,7 +2031,7 @@ SessionStoreService.prototype = {
|
||||
if (!this._isWindowLoaded(aWindow)) // window data is still in _statesToRestore
|
||||
return;
|
||||
if (aUpdateAll || this._dirtyWindows[aWindow.__SSi] || aWindow == activeWindow) {
|
||||
this._collectWindowData(aWindow, aPinnedOnly);
|
||||
this._collectWindowData(aWindow);
|
||||
}
|
||||
else { // always update the window features (whose change alone never triggers a save operation)
|
||||
this._updateWindowFeatures(aWindow);
|
||||
@ -2063,8 +2083,15 @@ SessionStoreService.prototype = {
|
||||
#endif
|
||||
|
||||
if (aPinnedOnly) {
|
||||
// perform a deep copy so that existing session variables are not changed.
|
||||
total = JSON.parse(this._toJSONString(total));
|
||||
total = total.filter(function (win) {
|
||||
win.tabs = win.tabs.filter(function (tab) tab.pinned);
|
||||
// remove closed tabs
|
||||
win._closedTabs = [];
|
||||
// correct selected tab index if it was stripped out
|
||||
if (win.selected > win.tabs.length)
|
||||
win.selected = 1;
|
||||
return win.tabs.length > 0;
|
||||
});
|
||||
if (total.length == 0)
|
||||
@ -2077,8 +2104,9 @@ SessionStoreService.prototype = {
|
||||
this.activeWindowSSiCache = activeWindow.__SSi || "";
|
||||
}
|
||||
ix = windows.indexOf(this.activeWindowSSiCache);
|
||||
// We don't want to restore focus to a minimized window.
|
||||
if (ix != -1 && total[ix].sizemode == "minimized")
|
||||
// We don't want to restore focus to a minimized window or a window which had all its
|
||||
// tabs stripped out (doesn't exist).
|
||||
if (ix != -1 && total[ix] && total[ix].sizemode == "minimized")
|
||||
ix = -1;
|
||||
|
||||
return { windows: total, selectedWindow: ix + 1, _closedWindows: lastClosedWindowsCopy };
|
||||
@ -2104,12 +2132,12 @@ SessionStoreService.prototype = {
|
||||
return { windows: total };
|
||||
},
|
||||
|
||||
_collectWindowData: function sss_collectWindowData(aWindow, aPinnedOnly) {
|
||||
_collectWindowData: function sss_collectWindowData(aWindow) {
|
||||
if (!this._isWindowLoaded(aWindow))
|
||||
return;
|
||||
|
||||
// update the internal state data for this window
|
||||
this._saveWindowHistory(aWindow, aPinnedOnly);
|
||||
this._saveWindowHistory(aWindow);
|
||||
this._updateTextAndScrollData(aWindow);
|
||||
this._updateCookieHosts(aWindow);
|
||||
this._updateWindowFeatures(aWindow);
|
||||
@ -3016,8 +3044,18 @@ SessionStoreService.prototype = {
|
||||
if (!oState)
|
||||
return;
|
||||
|
||||
if (pinnedOnly)
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
|
||||
if (pinnedOnly) {
|
||||
// Save original resume_session_once preference for when quiting browser,
|
||||
// otherwise session will be restored next time browser starts and we
|
||||
// only want it to be restored in the case of a crash.
|
||||
if (this._resume_session_once_on_shutdown == null) {
|
||||
this._resume_session_once_on_shutdown =
|
||||
this._prefBranch.getBoolPref("sessionstore.resume_session_once");
|
||||
this._prefBranch.setBoolPref("sessionstore.resume_session_once", true);
|
||||
// flush the preference file so preference will be saved in case of a crash
|
||||
Services.prefs.savePrefFile(null);
|
||||
}
|
||||
}
|
||||
|
||||
oState.session = {
|
||||
state: this._loadState == STATE_RUNNING ? STATE_RUNNING_STR : STATE_STOPPED_STR,
|
||||
|
@ -20,7 +20,7 @@
|
||||
#
|
||||
# Contributor(s):
|
||||
# Simon Bünzli <zeniko@gmail.com>
|
||||
# Michael Kraft <morac99-firefox@yahoo.com>
|
||||
# Michael Kraft <morac99-firefox2@yahoo.com>
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either of the GNU General Public License Version 2 or later (the "GPL"),
|
||||
@ -118,6 +118,7 @@ _BROWSER_TEST_FILES = \
|
||||
browser_580512.js \
|
||||
browser_586147.js \
|
||||
browser_586068-cascaded_restore.js \
|
||||
browser_600545.js \
|
||||
$(NULL)
|
||||
|
||||
ifneq ($(OS_ARCH),Darwin)
|
||||
|
153
browser/components/sessionstore/test/browser/browser_600545.js
Normal file
153
browser/components/sessionstore/test/browser/browser_600545.js
Normal file
@ -0,0 +1,153 @@
|
||||
/* ***** BEGIN LICENSE BLOCK *****
|
||||
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
*
|
||||
* The contents of this file are subject to the Mozilla Public License Version
|
||||
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||
* the License. You may obtain a copy of the License at
|
||||
* http://www.mozilla.org/MPL/
|
||||
*
|
||||
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
* for the specific language governing rights and limitations under the
|
||||
* License.
|
||||
*
|
||||
* The Original Code is sessionstore test code.
|
||||
*
|
||||
* The Initial Developer of the Original Code is
|
||||
* Mozilla Corporation.
|
||||
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||
* the Initial Developer. All Rights Reserved.
|
||||
*
|
||||
* Contributor(s):
|
||||
* Michael Kraft <morac99-firefox2@yahoo.com>
|
||||
*
|
||||
* Alternatively, the contents of this file may be used under the terms of
|
||||
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
* of those above. If you wish to allow use of your version of this file only
|
||||
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
* use your version of this file under the terms of the MPL, indicate your
|
||||
* decision by deleting the provisions above and replace them with the notice
|
||||
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
* the provisions above, a recipient may use your version of this file under
|
||||
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
let ss = Cc["@mozilla.org/browser/sessionstore;1"].
|
||||
getService(Ci.nsISessionStore);
|
||||
|
||||
let stateBackup = ss.getBrowserState();
|
||||
|
||||
function test() {
|
||||
/** Test for Bug 600545 **/
|
||||
waitForExplicitFinish();
|
||||
testBug600545();
|
||||
}
|
||||
|
||||
function testBug600545() {
|
||||
// Set the pref to false to cause non-app tabs to be stripped out on a save
|
||||
Services.prefs.setBoolPref("browser.sessionstore.resume_from_crash", false);
|
||||
|
||||
// Need to wait for SessionStore's saveState function to be called
|
||||
// so that non-pinned tabs will be stripped from non-active window
|
||||
function waitForSaveState(aSaveStateCallback) {
|
||||
let topic = "sessionstore-state-write";
|
||||
Services.obs.addObserver(function() {
|
||||
Services.obs.removeObserver(arguments.callee, topic, false);
|
||||
executeSoon(aSaveStateCallback);
|
||||
}, topic, false);
|
||||
};
|
||||
|
||||
// Need to wait for all tabs to be restored before reading browser state
|
||||
function waitForBrowserState(aState, aSetStateCallback) {
|
||||
let locationChanges = 0;
|
||||
let tabsRestored = getStateTabCount(aState);
|
||||
|
||||
// Used to determine when tabs have been restored
|
||||
let progressListener = {
|
||||
onLocationChange: function (aBrowser) {
|
||||
if (++locationChanges == tabsRestored) {
|
||||
// Remove the progress listener from this window, it will be removed from
|
||||
// theWin when that window is closed (in setBrowserState).
|
||||
window.gBrowser.removeTabsProgressListener(this);
|
||||
executeSoon(aSetStateCallback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We also want to catch the 2nd window, so we need to observe domwindowopened
|
||||
function windowObserver(aSubject, aTopic, aData) {
|
||||
let theWin = aSubject.QueryInterface(Ci.nsIDOMWindow);
|
||||
if (aTopic == "domwindowopened") {
|
||||
theWin.addEventListener("load", function() {
|
||||
theWin.removeEventListener("load", arguments.callee, false);
|
||||
|
||||
Services.ww.unregisterNotification(windowObserver);
|
||||
theWin.gBrowser.addTabsProgressListener(progressListener);
|
||||
}, false);
|
||||
}
|
||||
}
|
||||
|
||||
Services.ww.registerNotification(windowObserver);
|
||||
window.gBrowser.addTabsProgressListener(progressListener);
|
||||
ss.setBrowserState(JSON.stringify(aState));
|
||||
}
|
||||
|
||||
// This tests the following use case:
|
||||
// When multiple windows are open and browser.sessionstore.resume_from_crash
|
||||
// preference is false, tab session data for non-active window is stripped for
|
||||
// non-pinned tabs. This occurs after "sessionstore-state-write" fires which
|
||||
// will only fire in this case if there is at least one pinned tab.
|
||||
let state = { windows: [
|
||||
{
|
||||
tabs: [
|
||||
{ entries: [{ url: "http://example.org#0" }], pinned:true },
|
||||
{ entries: [{ url: "http://example.com#1" }] },
|
||||
{ entries: [{ url: "http://example.com#2" }] },
|
||||
],
|
||||
selected: 2
|
||||
},
|
||||
{
|
||||
tabs: [
|
||||
{ entries: [{ url: "http://example.com#3" }] },
|
||||
{ entries: [{ url: "http://example.com#4" }] },
|
||||
{ entries: [{ url: "http://example.com#5" }] },
|
||||
{ entries: [{ url: "http://example.com#6" }] }
|
||||
],
|
||||
selected: 3
|
||||
}
|
||||
] };
|
||||
|
||||
waitForBrowserState(state, function() {
|
||||
waitForSaveState(function () {
|
||||
let expectedNumberOfTabs = getStateTabCount(state);
|
||||
let retrievedState = JSON.parse(ss.getBrowserState());
|
||||
let actualNumberOfTabs = getStateTabCount(retrievedState);
|
||||
|
||||
is(actualNumberOfTabs, expectedNumberOfTabs,
|
||||
"Number of tabs in retreived session data, matches number of tabs set.");
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function done() {
|
||||
// Reset the pref
|
||||
try {
|
||||
Services.prefs.clearUserPref("browser.sessionstore.resume_from_crash");
|
||||
} catch (e) {}
|
||||
|
||||
ss.setBrowserState(stateBackup);
|
||||
executeSoon(finish);
|
||||
}
|
||||
|
||||
// Count up the number of tabs in the state data
|
||||
function getStateTabCount(aState) {
|
||||
let tabCount = 0;
|
||||
for (let i in aState.windows)
|
||||
tabCount += aState.windows[i].tabs.length;
|
||||
return tabCount;
|
||||
}
|
Loading…
Reference in New Issue
Block a user