Bug 670040: Make nsISessionStartup.state a jsval to save repeatedly stringifying/parsing the initial state. r=zpao
This commit is contained in:
@@ -43,11 +43,11 @@
|
|||||||
* - and allows to restore everything into one window.
|
* - and allows to restore everything into one window.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[scriptable, uuid(e7bb7828-0e32-4995-a848-4aa35df603c7)]
|
[scriptable, uuid(170c6857-7f71-46ce-bc9b-185723b1c3a8)]
|
||||||
interface nsISessionStartup: nsISupports
|
interface nsISessionStartup: nsISupports
|
||||||
{
|
{
|
||||||
// Get session state as string
|
// Get session state
|
||||||
readonly attribute AString state;
|
readonly attribute jsval state;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determine if session should be restored
|
* Determine if session should be restored
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ function SessionStartup() {
|
|||||||
SessionStartup.prototype = {
|
SessionStartup.prototype = {
|
||||||
|
|
||||||
// the state to restore at startup
|
// the state to restore at startup
|
||||||
_iniString: null,
|
_initialState: null,
|
||||||
_sessionType: Ci.nsISessionStartup.NO_SESSION,
|
_sessionType: Ci.nsISessionStartup.NO_SESSION,
|
||||||
|
|
||||||
/* ........ Global Event Handlers .............. */
|
/* ........ Global Event Handlers .............. */
|
||||||
@@ -121,31 +121,30 @@ SessionStartup.prototype = {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// get string containing session state
|
// get string containing session state
|
||||||
this._iniString = this._readStateFile(sessionFile);
|
let iniString = this._readStateFile(sessionFile);
|
||||||
if (!this._iniString)
|
if (!iniString)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// parse the session state into a JS object
|
// parse the session state into a JS object
|
||||||
let initialState;
|
|
||||||
try {
|
try {
|
||||||
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
||||||
if (this._iniString.charAt(0) == '(')
|
if (iniString.charAt(0) == '(')
|
||||||
this._iniString = this._iniString.slice(1, -1);
|
iniString = iniString.slice(1, -1);
|
||||||
try {
|
try {
|
||||||
initialState = JSON.parse(this._iniString);
|
this._initialState = JSON.parse(iniString);
|
||||||
}
|
}
|
||||||
catch (exJSON) {
|
catch (exJSON) {
|
||||||
var s = new Cu.Sandbox("about:blank");
|
var s = new Cu.Sandbox("about:blank");
|
||||||
initialState = Cu.evalInSandbox("(" + this._iniString + ")", s);
|
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
||||||
this._iniString = JSON.stringify(initialState);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ex) { debug("The session file is invalid: " + ex); }
|
catch (ex) { debug("The session file is invalid: " + ex); }
|
||||||
|
|
||||||
let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
||||||
let lastSessionCrashed =
|
let lastSessionCrashed =
|
||||||
initialState && initialState.session && initialState.session.state &&
|
this._initialState && this._initialState.session &&
|
||||||
initialState.session.state == STATE_RUNNING_STR;
|
this._initialState.session.state &&
|
||||||
|
this._initialState.session.state == STATE_RUNNING_STR;
|
||||||
|
|
||||||
// Report shutdown success via telemetry. Shortcoming here are
|
// Report shutdown success via telemetry. Shortcoming here are
|
||||||
// being-killed-by-OS-shutdown-logic, shutdown freezing after
|
// being-killed-by-OS-shutdown-logic, shutdown freezing after
|
||||||
@@ -158,17 +157,17 @@ SessionStartup.prototype = {
|
|||||||
this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
|
this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
|
||||||
else if (!lastSessionCrashed && doResumeSession)
|
else if (!lastSessionCrashed && doResumeSession)
|
||||||
this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
|
this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
|
||||||
else if (initialState)
|
else if (this._initialState)
|
||||||
this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
|
this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
|
||||||
else
|
else
|
||||||
this._iniString = null; // reset the state string
|
this._initialState = null; // reset the state
|
||||||
|
|
||||||
// wait for the first browser window to open
|
// wait for the first browser window to open
|
||||||
// Don't reset the initial window's default args (i.e. the home page(s))
|
// Don't reset the initial window's default args (i.e. the home page(s))
|
||||||
// if all stored tabs are pinned.
|
// if all stored tabs are pinned.
|
||||||
if (this.doRestore() &&
|
if (this.doRestore() &&
|
||||||
(!initialState.windows ||
|
(!this._initialState.windows ||
|
||||||
!initialState.windows.every(function (win)
|
!this._initialState.windows.every(function (win)
|
||||||
win.tabs.every(function (tab) tab.pinned))))
|
win.tabs.every(function (tab) tab.pinned))))
|
||||||
Services.obs.addObserver(this, "domwindowopened", true);
|
Services.obs.addObserver(this, "domwindowopened", true);
|
||||||
|
|
||||||
@@ -204,8 +203,8 @@ SessionStartup.prototype = {
|
|||||||
break;
|
break;
|
||||||
case "sessionstore-windows-restored":
|
case "sessionstore-windows-restored":
|
||||||
Services.obs.removeObserver(this, "sessionstore-windows-restored");
|
Services.obs.removeObserver(this, "sessionstore-windows-restored");
|
||||||
// free _iniString after nsSessionStore is done with it
|
// free _initialState after nsSessionStore is done with it
|
||||||
this._iniString = null;
|
this._initialState = null;
|
||||||
this._sessionType = Ci.nsISessionStartup.NO_SESSION;
|
this._sessionType = Ci.nsISessionStartup.NO_SESSION;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -254,7 +253,7 @@ SessionStartup.prototype = {
|
|||||||
* Get the session state as a string
|
* Get the session state as a string
|
||||||
*/
|
*/
|
||||||
get state() {
|
get state() {
|
||||||
return this._iniString;
|
return this._initialState;
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -304,33 +304,31 @@ SessionStoreService.prototype = {
|
|||||||
this._sessionFileBackup.append("sessionstore.bak");
|
this._sessionFileBackup.append("sessionstore.bak");
|
||||||
|
|
||||||
// get string containing session state
|
// get string containing session state
|
||||||
var iniString;
|
|
||||||
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
|
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
|
||||||
getService(Ci.nsISessionStartup);
|
getService(Ci.nsISessionStartup);
|
||||||
try {
|
try {
|
||||||
if (ss.doRestore() ||
|
if (ss.doRestore() ||
|
||||||
ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION)
|
ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION)
|
||||||
iniString = ss.state;
|
this._initialState = ss.state;
|
||||||
}
|
}
|
||||||
catch(ex) { dump(ex + "\n"); } // no state to restore, which is ok
|
catch(ex) { dump(ex + "\n"); } // no state to restore, which is ok
|
||||||
|
|
||||||
if (iniString) {
|
if (this._initialState) {
|
||||||
try {
|
try {
|
||||||
// If we're doing a DEFERRED session, then we want to pull pinned tabs
|
// If we're doing a DEFERRED session, then we want to pull pinned tabs
|
||||||
// out so they can be restored.
|
// out so they can be restored.
|
||||||
if (ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
|
if (ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION) {
|
||||||
let [iniState, remainingState] = this._prepDataForDeferredRestore(iniString);
|
let [iniState, remainingState] = this._prepDataForDeferredRestore(this._initialState);
|
||||||
// If we have a iniState with windows, that means that we have windows
|
// If we have a iniState with windows, that means that we have windows
|
||||||
// with app tabs to restore.
|
// with app tabs to restore.
|
||||||
if (iniState.windows.length)
|
if (iniState.windows.length)
|
||||||
this._initialState = iniState;
|
this._initialState = iniState;
|
||||||
|
else
|
||||||
|
this._initialState = null;
|
||||||
if (remainingState.windows.length)
|
if (remainingState.windows.length)
|
||||||
this._lastSessionState = remainingState;
|
this._lastSessionState = remainingState;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// parse the session state into JS objects
|
|
||||||
this._initialState = JSON.parse(iniString);
|
|
||||||
|
|
||||||
let lastSessionCrashed =
|
let lastSessionCrashed =
|
||||||
this._initialState.session && this._initialState.session.state &&
|
this._initialState.session && this._initialState.session.state &&
|
||||||
this._initialState.session.state == STATE_RUNNING_STR;
|
this._initialState.session.state == STATE_RUNNING_STR;
|
||||||
@@ -342,7 +340,7 @@ SessionStoreService.prototype = {
|
|||||||
// replace the crashed session with a restore-page-only session
|
// replace the crashed session with a restore-page-only session
|
||||||
let pageData = {
|
let pageData = {
|
||||||
url: "about:sessionrestore",
|
url: "about:sessionrestore",
|
||||||
formdata: { "#sessionData": iniString }
|
formdata: { "#sessionData": JSON.stringify(this._initialState) }
|
||||||
};
|
};
|
||||||
this._initialState = { windows: [{ tabs: [{ entries: [pageData] }] }] };
|
this._initialState = { windows: [{ tabs: [{ entries: [pageData] }] }] };
|
||||||
}
|
}
|
||||||
@@ -811,7 +809,7 @@ SessionStoreService.prototype = {
|
|||||||
// We'll cheat a little bit and reuse _prepDataForDeferredRestore
|
// We'll cheat a little bit and reuse _prepDataForDeferredRestore
|
||||||
// even though it wasn't built exactly for this.
|
// even though it wasn't built exactly for this.
|
||||||
let [appTabsState, normalTabsState] =
|
let [appTabsState, normalTabsState] =
|
||||||
this._prepDataForDeferredRestore(JSON.stringify({ windows: [closedWindowState] }));
|
this._prepDataForDeferredRestore({ windows: [closedWindowState] });
|
||||||
|
|
||||||
// These are our pinned tabs, which we should restore
|
// These are our pinned tabs, which we should restore
|
||||||
if (appTabsState.windows.length) {
|
if (appTabsState.windows.length) {
|
||||||
@@ -3794,12 +3792,11 @@ SessionStoreService.prototype = {
|
|||||||
* this._lastSessionState and will be kept in case the user explicitly wants
|
* this._lastSessionState and will be kept in case the user explicitly wants
|
||||||
* to restore the previous session (publicly exposed as restoreLastSession).
|
* to restore the previous session (publicly exposed as restoreLastSession).
|
||||||
*
|
*
|
||||||
* @param stateString
|
* @param state
|
||||||
* The state string, presumably from nsISessionStartup.state
|
* The state, presumably from nsISessionStartup.state
|
||||||
* @returns [defaultState, state]
|
* @returns [defaultState, state]
|
||||||
*/
|
*/
|
||||||
_prepDataForDeferredRestore: function sss__prepDataForDeferredRestore(stateString) {
|
_prepDataForDeferredRestore: function sss__prepDataForDeferredRestore(state) {
|
||||||
let state = JSON.parse(stateString);
|
|
||||||
let defaultState = { windows: [], selectedWindow: 1 };
|
let defaultState = { windows: [], selectedWindow: 1 };
|
||||||
|
|
||||||
state.selectedWindow = state.selectedWindow || 1;
|
state.selectedWindow = state.selectedWindow || 1;
|
||||||
|
|||||||
Reference in New Issue
Block a user