mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Backed out 2 changesets (bug 532150) for test failure
Backed out changeset 57bbbda0dedd (bug 532150) Backed out changeset 5cab33f5bfbd (bug 532150)
This commit is contained in:
parent
61642fa545
commit
e46027a5e7
@ -10,15 +10,9 @@
|
|||||||
* - and allows to restore everything into one window.
|
* - and allows to restore everything into one window.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
[scriptable, uuid(35235b39-7098-4b3b-8e28-cd004a88b06f)]
|
[scriptable, uuid(170c6857-7f71-46ce-bc9b-185723b1c3a8)]
|
||||||
interface nsISessionStartup: nsISupports
|
interface nsISessionStartup: nsISupports
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Return a promise that is resolved once initialization
|
|
||||||
* is complete.
|
|
||||||
*/
|
|
||||||
readonly attribute jsval onceInitialized;
|
|
||||||
|
|
||||||
// Get session state
|
// Get session state
|
||||||
readonly attribute jsval state;
|
readonly attribute jsval state;
|
||||||
|
|
||||||
|
@ -12,8 +12,8 @@ include $(topsrcdir)/config/config.mk
|
|||||||
|
|
||||||
EXTRA_COMPONENTS = \
|
EXTRA_COMPONENTS = \
|
||||||
nsSessionStore.manifest \
|
nsSessionStore.manifest \
|
||||||
nsSessionStore.js \
|
nsSessionStore.js \
|
||||||
nsSessionStartup.js \
|
nsSessionStartup.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
JS_MODULES_PATH := $(FINAL_TARGET)/modules/sessionstore
|
JS_MODULES_PATH := $(FINAL_TARGET)/modules/sessionstore
|
||||||
@ -22,7 +22,6 @@ EXTRA_JS_MODULES := \
|
|||||||
DocumentUtils.jsm \
|
DocumentUtils.jsm \
|
||||||
SessionStorage.jsm \
|
SessionStorage.jsm \
|
||||||
XPathGenerator.jsm \
|
XPathGenerator.jsm \
|
||||||
_SessionFile.jsm \
|
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
EXTRA_PP_JS_MODULES := \
|
EXTRA_PP_JS_MODULES := \
|
||||||
|
@ -75,18 +75,14 @@ const TAB_EVENTS = [
|
|||||||
#define BROKEN_WM_Z_ORDER
|
#define BROKEN_WM_Z_ORDER
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm", this);
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
|
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||||
// debug.js adds NS_ASSERT. cf. bug 669196
|
// debug.js adds NS_ASSERT. cf. bug 669196
|
||||||
Cu.import("resource://gre/modules/debug.js", this);
|
Cu.import("resource://gre/modules/debug.js");
|
||||||
Cu.import("resource:///modules/TelemetryTimestamps.jsm", this);
|
Cu.import("resource:///modules/TelemetryTimestamps.jsm");
|
||||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm", this);
|
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||||
Cu.import("resource://gre/modules/osfile.jsm", this);
|
Cu.import("resource://gre/modules/osfile.jsm");
|
||||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm", this);
|
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/commonjs/promise/core.js", this);
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "gSessionStartup",
|
|
||||||
"@mozilla.org/browser/sessionstartup;1", "nsISessionStartup");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
||||||
"resource://gre/modules/NetUtil.jsm");
|
"resource://gre/modules/NetUtil.jsm");
|
||||||
@ -96,8 +92,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "DocumentUtils",
|
|||||||
"resource:///modules/sessionstore/DocumentUtils.jsm");
|
"resource:///modules/sessionstore/DocumentUtils.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
|
XPCOMUtils.defineLazyModuleGetter(this, "SessionStorage",
|
||||||
"resource:///modules/sessionstore/SessionStorage.jsm");
|
"resource:///modules/sessionstore/SessionStorage.jsm");
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "_SessionFile",
|
|
||||||
"resource:///modules/sessionstore/_SessionFile.jsm");
|
|
||||||
|
|
||||||
#ifdef MOZ_CRASHREPORTER
|
#ifdef MOZ_CRASHREPORTER
|
||||||
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
|
XPCOMUtils.defineLazyServiceGetter(this, "CrashReporter",
|
||||||
@ -296,11 +290,8 @@ let SessionStoreInternal = {
|
|||||||
// session
|
// session
|
||||||
_lastSessionState: null,
|
_lastSessionState: null,
|
||||||
|
|
||||||
// A promise resolved once initialization is complete
|
// Whether we've been initialized
|
||||||
_promiseInitialization: Promise.defer(),
|
_initialized: false,
|
||||||
|
|
||||||
// Whether session has been initialized
|
|
||||||
_sessionInitialized: false,
|
|
||||||
|
|
||||||
// The original "sessionstore.resume_session_once" preference value before it
|
// The original "sessionstore.resume_session_once" preference value before it
|
||||||
// was modified by saveState. saveState will set the
|
// was modified by saveState. saveState will set the
|
||||||
@ -335,9 +326,6 @@ let SessionStoreInternal = {
|
|||||||
* Initialize the component
|
* Initialize the component
|
||||||
*/
|
*/
|
||||||
initService: function ssi_initService() {
|
initService: function ssi_initService() {
|
||||||
if (this._sessionInitialized) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
TelemetryTimestamps.add("sessionRestoreInitialized");
|
TelemetryTimestamps.add("sessionRestoreInitialized");
|
||||||
OBSERVING.forEach(function(aTopic) {
|
OBSERVING.forEach(function(aTopic) {
|
||||||
Services.obs.addObserver(this, aTopic, true);
|
Services.obs.addObserver(this, aTopic, true);
|
||||||
@ -370,13 +358,15 @@ let SessionStoreInternal = {
|
|||||||
this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand");
|
this._prefBranch.getBoolPref("sessionstore.restore_pinned_tabs_on_demand");
|
||||||
this._prefBranch.addObserver("sessionstore.restore_pinned_tabs_on_demand", this, true);
|
this._prefBranch.addObserver("sessionstore.restore_pinned_tabs_on_demand", this, true);
|
||||||
|
|
||||||
gSessionStartup.onceInitialized.then(
|
// get file references
|
||||||
this.initSession.bind(this)
|
this._sessionFile = Services.dirsvc.get("ProfD", Ci.nsILocalFile);
|
||||||
);
|
this._sessionFileBackup = this._sessionFile.clone();
|
||||||
},
|
this._sessionFile.append("sessionstore.js");
|
||||||
|
this._sessionFileBackup.append("sessionstore.bak");
|
||||||
|
|
||||||
initSession: function ssi_initSession() {
|
// get string containing session state
|
||||||
let ss = gSessionStartup;
|
var ss = Cc["@mozilla.org/browser/sessionstartup;1"].
|
||||||
|
getService(Ci.nsISessionStartup);
|
||||||
try {
|
try {
|
||||||
if (ss.doRestore() ||
|
if (ss.doRestore() ||
|
||||||
ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION)
|
ss.sessionType == Ci.nsISessionStartup.DEFER_SESSION)
|
||||||
@ -447,11 +437,14 @@ let SessionStoreInternal = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (this._resume_from_crash) {
|
if (this._resume_from_crash) {
|
||||||
// Launch background copy of the session file. Note that we do
|
// create a backup if the session data file exists
|
||||||
// not have race conditions here as _SessionFile guarantees
|
try {
|
||||||
// that any I/O operation is completed before proceeding to
|
if (this._sessionFileBackup.exists())
|
||||||
// the next I/O operation.
|
this._sessionFileBackup.remove(false);
|
||||||
_SessionFile.createBackupCopy();
|
if (this._sessionFile.exists())
|
||||||
|
this._sessionFile.copyTo(null, this._sessionFileBackup.leafName);
|
||||||
|
}
|
||||||
|
catch (ex) { Cu.reportError(ex); } // file was write-locked?
|
||||||
}
|
}
|
||||||
|
|
||||||
// at this point, we've as good as resumed the session, so we can
|
// at this point, we've as good as resumed the session, so we can
|
||||||
@ -462,9 +455,7 @@ let SessionStoreInternal = {
|
|||||||
|
|
||||||
this._initEncoding();
|
this._initEncoding();
|
||||||
|
|
||||||
// Session is ready.
|
this._initialized = true;
|
||||||
this._sessionInitialized = true;
|
|
||||||
this._promiseInitialization.resolve();
|
|
||||||
},
|
},
|
||||||
|
|
||||||
_initEncoding : function ssi_initEncoding() {
|
_initEncoding : function ssi_initEncoding() {
|
||||||
@ -504,7 +495,16 @@ let SessionStoreInternal = {
|
|||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
_initWindow: function ssi_initWindow(aWindow) {
|
/**
|
||||||
|
* Start tracking a window.
|
||||||
|
* This function also initializes the component if it's not already
|
||||||
|
* initialized.
|
||||||
|
*/
|
||||||
|
init: function ssi_init(aWindow) {
|
||||||
|
// Initialize the service if needed.
|
||||||
|
if (!this._initialized)
|
||||||
|
this.initService();
|
||||||
|
|
||||||
if (!aWindow || this._loadState == STATE_RUNNING) {
|
if (!aWindow || this._loadState == STATE_RUNNING) {
|
||||||
// make sure that all browser windows which try to initialize
|
// make sure that all browser windows which try to initialize
|
||||||
// SessionStore are really tracked by it
|
// SessionStore are really tracked by it
|
||||||
@ -524,30 +524,13 @@ let SessionStoreInternal = {
|
|||||||
this.onLoad(aWindow);
|
this.onLoad(aWindow);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
|
||||||
* Start tracking a window.
|
|
||||||
*
|
|
||||||
* This function also initializes the component if it is not
|
|
||||||
* initialized yet.
|
|
||||||
*/
|
|
||||||
init: function ssi_init(aWindow) {
|
|
||||||
let self = this;
|
|
||||||
this.initService();
|
|
||||||
this._promiseInitialization.promise.then(
|
|
||||||
function onSuccess() {
|
|
||||||
self._initWindow(aWindow);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called on application shutdown, after notifications:
|
* Called on application shutdown, after notifications:
|
||||||
* quit-application-granted, quit-application
|
* quit-application-granted, quit-application
|
||||||
*/
|
*/
|
||||||
_uninit: function ssi_uninit() {
|
_uninit: function ssi_uninit() {
|
||||||
// save all data for session resuming
|
// save all data for session resuming
|
||||||
if (this._sessionInitialized)
|
this.saveState(true);
|
||||||
this.saveState(true);
|
|
||||||
|
|
||||||
// clear out _tabsToRestore in case it's still holding refs
|
// clear out _tabsToRestore in case it's still holding refs
|
||||||
this._tabsToRestore.priority = null;
|
this._tabsToRestore.priority = null;
|
||||||
@ -1015,7 +998,7 @@ let SessionStoreInternal = {
|
|||||||
*/
|
*/
|
||||||
onPurgeSessionHistory: function ssi_onPurgeSessionHistory() {
|
onPurgeSessionHistory: function ssi_onPurgeSessionHistory() {
|
||||||
var _this = this;
|
var _this = this;
|
||||||
_SessionFile.wipe();
|
this._clearDisk();
|
||||||
// If the browser is shutting down, simply return after clearing the
|
// If the browser is shutting down, simply return after clearing the
|
||||||
// session data on disk as this notification fires after the
|
// session data on disk as this notification fires after the
|
||||||
// quit-application notification so the browser is about to exit.
|
// quit-application notification so the browser is about to exit.
|
||||||
@ -1156,7 +1139,7 @@ let SessionStoreInternal = {
|
|||||||
// either create the file with crash recovery information or remove it
|
// 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)
|
// (when _loadState is not STATE_RUNNING, that file is used for session resuming instead)
|
||||||
if (!this._resume_from_crash)
|
if (!this._resume_from_crash)
|
||||||
_SessionFile.wipe();
|
this._clearDisk();
|
||||||
this.saveState(true);
|
this.saveState(true);
|
||||||
break;
|
break;
|
||||||
case "sessionstore.restore_on_demand":
|
case "sessionstore.restore_on_demand":
|
||||||
@ -3784,37 +3767,40 @@ let SessionStoreInternal = {
|
|||||||
*/
|
*/
|
||||||
_saveStateObject: function ssi_saveStateObject(aStateObj) {
|
_saveStateObject: function ssi_saveStateObject(aStateObj) {
|
||||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
|
||||||
let data = this._toJSONString(aStateObj);
|
var stateString = Cc["@mozilla.org/supports-string;1"].
|
||||||
|
createInstance(Ci.nsISupportsString);
|
||||||
|
stateString.data = this._toJSONString(aStateObj);
|
||||||
TelemetryStopwatch.finish("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_SERIALIZE_DATA_MS");
|
||||||
|
|
||||||
let stateString = this._createSupportsString(data);
|
|
||||||
Services.obs.notifyObservers(stateString, "sessionstore-state-write", "");
|
Services.obs.notifyObservers(stateString, "sessionstore-state-write", "");
|
||||||
data = stateString.data;
|
|
||||||
|
|
||||||
// Don't touch the file if an observer has deleted all state data.
|
// don't touch the file if an observer has deleted all state data
|
||||||
if (!data) {
|
if (stateString.data)
|
||||||
return;
|
this._writeFile(this._sessionFile, stateString.data);
|
||||||
}
|
|
||||||
|
|
||||||
let self = this;
|
this._lastSaveTime = Date.now();
|
||||||
_SessionFile.write(data).then(
|
},
|
||||||
function onSuccess() {
|
|
||||||
self._lastSaveTime = Date.now();
|
/**
|
||||||
Services.obs.notifyObservers(null, "sessionstore-state-write-complete", "");
|
* delete session datafile and backup
|
||||||
|
*/
|
||||||
|
_clearDisk: function ssi_clearDisk() {
|
||||||
|
if (this._sessionFile.exists()) {
|
||||||
|
try {
|
||||||
|
this._sessionFile.remove(false);
|
||||||
}
|
}
|
||||||
);
|
catch (ex) { dump(ex + '\n'); } // couldn't remove the file - what now?
|
||||||
|
}
|
||||||
|
if (this._sessionFileBackup.exists()) {
|
||||||
|
try {
|
||||||
|
this._sessionFileBackup.remove(false);
|
||||||
|
}
|
||||||
|
catch (ex) { dump(ex + '\n'); } // couldn't remove the file - what now?
|
||||||
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* ........ Auxiliary Functions .............. */
|
/* ........ Auxiliary Functions .............. */
|
||||||
|
|
||||||
// Wrap a string as a nsISupports
|
|
||||||
_createSupportsString: function ssi_createSupportsString(aData) {
|
|
||||||
let string = Cc["@mozilla.org/supports-string;1"]
|
|
||||||
.createInstance(Ci.nsISupportsString);
|
|
||||||
string.data = aData;
|
|
||||||
return string;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* call a callback for all currently opened browser windows
|
* call a callback for all currently opened browser windows
|
||||||
* (might miss the most recent one)
|
* (might miss the most recent one)
|
||||||
@ -4508,6 +4494,33 @@ let SessionStoreInternal = {
|
|||||||
removeSHistoryListener(browser.__SS_shistoryListener);
|
removeSHistoryListener(browser.__SS_shistoryListener);
|
||||||
delete browser.__SS_shistoryListener;
|
delete browser.__SS_shistoryListener;
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write file to disk
|
||||||
|
* @param aFile
|
||||||
|
* nsIFile
|
||||||
|
* @param aData
|
||||||
|
* String data
|
||||||
|
*/
|
||||||
|
_writeFile: function ssi_writeFile(aFile, aData) {
|
||||||
|
let refObj = {};
|
||||||
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
||||||
|
let path = aFile.path;
|
||||||
|
let encoded = this._writeFileEncoder.encode(aData);
|
||||||
|
let promise = OS.File.writeAtomic(path, encoded, {tmpPath: path + ".tmp"});
|
||||||
|
|
||||||
|
promise.then(
|
||||||
|
function onSuccess() {
|
||||||
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
||||||
|
Services.obs.notifyObservers(null,
|
||||||
|
"sessionstore-state-write-complete",
|
||||||
|
"");
|
||||||
|
},
|
||||||
|
function onFailure(reason) {
|
||||||
|
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
||||||
|
Components.reportError("ssi_writeFile failure " + reason);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1,255 +0,0 @@
|
|||||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
||||||
* 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/. */
|
|
||||||
|
|
||||||
"use strict";
|
|
||||||
|
|
||||||
this.EXPORTED_SYMBOLS = ["_SessionFile"];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Implementation of all the disk I/O required by the session store.
|
|
||||||
* This is a private API, meant to be used only by the session store.
|
|
||||||
* It will change. Do not use it for any other purpose.
|
|
||||||
*
|
|
||||||
* Note that this module implicitly depends on one of two things:
|
|
||||||
* 1. either the asynchronous file I/O system enqueues its requests
|
|
||||||
* and never attempts to simultaneously execute two I/O requests on
|
|
||||||
* the files used by this module from two distinct threads; or
|
|
||||||
* 2. the clients of this API are well-behaved and do not place
|
|
||||||
* concurrent requests to the files used by this module.
|
|
||||||
*
|
|
||||||
* Otherwise, we could encounter bugs, especially under Windows,
|
|
||||||
* e.g. if a request attempts to write sessionstore.js while
|
|
||||||
* another attempts to copy that file.
|
|
||||||
*
|
|
||||||
* This implementation uses OS.File, which guarantees property 1.
|
|
||||||
*/
|
|
||||||
|
|
||||||
const Cu = Components.utils;
|
|
||||||
const Cc = Components.classes;
|
|
||||||
const Ci = Components.interfaces;
|
|
||||||
|
|
||||||
Cu.import("resource://gre/modules/Services.jsm");
|
|
||||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|
||||||
Cu.import("resource://gre/modules/osfile.jsm");
|
|
||||||
Cu.import("resource://gre/modules/commonjs/promise/core.js");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "TelemetryStopwatch",
|
|
||||||
"resource://gre/modules/TelemetryStopwatch.jsm");
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
|
|
||||||
"resource://gre/modules/NetUtil.jsm");
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
|
|
||||||
"resource://gre/modules/FileUtils.jsm");
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "Task",
|
|
||||||
"resource://gre/modules/Task.jsm");
|
|
||||||
|
|
||||||
// An encoder to UTF-8.
|
|
||||||
XPCOMUtils.defineLazyGetter(this, "gEncoder", function () {
|
|
||||||
return new TextEncoder();
|
|
||||||
});
|
|
||||||
|
|
||||||
this._SessionFile = {
|
|
||||||
/**
|
|
||||||
* A promise fulfilled once initialization (either synchronous or
|
|
||||||
* asynchronous) is complete.
|
|
||||||
*/
|
|
||||||
promiseInitialized: function SessionFile_initialized() {
|
|
||||||
return SessionFileInternal.promiseInitialized;
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Read the contents of the session file, asynchronously.
|
|
||||||
*/
|
|
||||||
read: function SessionFile_read() {
|
|
||||||
return SessionFileInternal.read();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Read the contents of the session file, synchronously.
|
|
||||||
*/
|
|
||||||
syncRead: function SessionFile_syncRead() {
|
|
||||||
return SessionFileInternal.syncRead();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Write the contents of the session file, asynchronously.
|
|
||||||
*/
|
|
||||||
write: function SessionFile_write(aData) {
|
|
||||||
return SessionFileInternal.write(aData);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Create a backup copy, asynchronously.
|
|
||||||
*/
|
|
||||||
createBackupCopy: function SessionFile_createBackupCopy() {
|
|
||||||
return SessionFileInternal.createBackupCopy();
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Wipe the contents of the session file, asynchronously.
|
|
||||||
*/
|
|
||||||
wipe: function SessionFile_wipe() {
|
|
||||||
return SessionFileInternal.wipe();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Object.freeze(_SessionFile);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Utilities for dealing with promises and Task.jsm
|
|
||||||
*/
|
|
||||||
const TaskUtils = {
|
|
||||||
/**
|
|
||||||
* Add logging to a promise.
|
|
||||||
*
|
|
||||||
* @param {Promise} promise
|
|
||||||
* @return {Promise} A promise behaving as |promise|, but with additional
|
|
||||||
* logging in case of uncaught error.
|
|
||||||
*/
|
|
||||||
captureErrors: function captureErrors(promise) {
|
|
||||||
return promise.then(
|
|
||||||
null,
|
|
||||||
function onError(reason) {
|
|
||||||
Cu.reportError("Uncaught asynchronous error: " + reason + " at\n" + reason.stack);
|
|
||||||
throw reason;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
},
|
|
||||||
/**
|
|
||||||
* Spawn a new Task from a generator.
|
|
||||||
*
|
|
||||||
* This function behaves as |Task.spawn|, with the exception that it
|
|
||||||
* adds logging in case of uncaught error. For more information, see
|
|
||||||
* the documentation of |Task.jsm|.
|
|
||||||
*
|
|
||||||
* @param {generator} gen Some generator.
|
|
||||||
* @return {Promise} A promise built from |gen|, with the same semantics
|
|
||||||
* as |Task.spawn(gen)|.
|
|
||||||
*/
|
|
||||||
spawn: function spawn(gen) {
|
|
||||||
return this.captureErrors(Task.spawn(gen));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let SessionFileInternal = {
|
|
||||||
/**
|
|
||||||
* A promise fulfilled once initialization is complete
|
|
||||||
*/
|
|
||||||
promiseInitialized: Promise.defer(),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path to sessionstore.js
|
|
||||||
*/
|
|
||||||
path: OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.js"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The path to sessionstore.bak
|
|
||||||
*/
|
|
||||||
backupPath: OS.Path.join(OS.Constants.Path.profileDir, "sessionstore.bak"),
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Read the sessionstore file synchronously.
|
|
||||||
*
|
|
||||||
* This function is meant to serve as a fallback in case of race
|
|
||||||
* between a synchronous usage of the API and asynchronous
|
|
||||||
* initialization.
|
|
||||||
*/
|
|
||||||
syncRead: function ssfi_syncRead() {
|
|
||||||
let text;
|
|
||||||
let exn;
|
|
||||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_SYNC_READ_FILE_MS");
|
|
||||||
try {
|
|
||||||
let file = new FileUtils.File(this.path);
|
|
||||||
if (!file.exists()) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
let chan = NetUtil.newChannel(file);
|
|
||||||
let stream = chan.open();
|
|
||||||
text = NetUtil.readInputStreamToString(stream, stream.available(), {charset: "utf-8"});
|
|
||||||
} catch(ex) {
|
|
||||||
exn = ex;
|
|
||||||
} finally {
|
|
||||||
TelemetryStopwatch.finish("FX_SESSION_RESTORE_SYNC_READ_FILE_MS");
|
|
||||||
}
|
|
||||||
if (exn) {
|
|
||||||
Cu.reportError(exn);
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return text;
|
|
||||||
},
|
|
||||||
|
|
||||||
read: function ssfi_read() {
|
|
||||||
let refObj = {};
|
|
||||||
let self = this;
|
|
||||||
return TaskUtils.spawn(function task() {
|
|
||||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_READ_FILE_MS", refObj);
|
|
||||||
let text;
|
|
||||||
try {
|
|
||||||
let bytes = yield OS.File.read(self.path);
|
|
||||||
text = new TextDecoder().decode(bytes);
|
|
||||||
TelemetryStopwatch.finish("FX_SESSION_RESTORE_READ_FILE_MS", refObj);
|
|
||||||
} catch (ex) {
|
|
||||||
if (self._isNoSuchFile(ex)) {
|
|
||||||
// The file does not exist, this is perfectly valid
|
|
||||||
TelemetryStopwatch.finish("FX_SESSION_RESTORE_READ_FILE_MS", refObj);
|
|
||||||
} else {
|
|
||||||
// Any other error: let's not measure with telemetry
|
|
||||||
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_READ_FILE_MS", refObj);
|
|
||||||
Cu.reportError(ex);
|
|
||||||
}
|
|
||||||
text = "";
|
|
||||||
}
|
|
||||||
throw new Task.Result(text);
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
write: function ssfi_write(aData) {
|
|
||||||
let refObj = {};
|
|
||||||
let self = this;
|
|
||||||
return TaskUtils.spawn(function task() {
|
|
||||||
TelemetryStopwatch.start("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
|
||||||
|
|
||||||
let bytes = gEncoder.encode(aData);
|
|
||||||
|
|
||||||
try {
|
|
||||||
yield OS.File.writeAtomic(self.path, bytes, {tmpPath: self.path + ".tmp"});
|
|
||||||
TelemetryStopwatch.finish("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
|
||||||
} catch (ex) {
|
|
||||||
TelemetryStopwatch.cancel("FX_SESSION_RESTORE_WRITE_FILE_MS", refObj);
|
|
||||||
Cu.reportError("Could not write session state file " + self.path
|
|
||||||
+ ": " + aReason);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
createBackupCopy: function ssfi_createBackupCopy() {
|
|
||||||
let self = this;
|
|
||||||
return TaskUtils.spawn(function task() {
|
|
||||||
try {
|
|
||||||
yield OS.File.copy(self.path, self.backupPath);
|
|
||||||
} catch (ex) {
|
|
||||||
if (!self._isNoSuchFile(ex)) {
|
|
||||||
Cu.reportError("Could not backup session state file: " + ex);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
wipe: function ssfi_wipe() {
|
|
||||||
let self = this;
|
|
||||||
return TaskUtils.spawn(function task() {
|
|
||||||
try {
|
|
||||||
yield OS.File.remove(self.path);
|
|
||||||
} catch (ex) {
|
|
||||||
Cu.reportError("Could not remove session state file: " + ex);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
try {
|
|
||||||
yield OS.File.remove(self.backupPath);
|
|
||||||
} catch (ex) {
|
|
||||||
Cu.reportError("Could not remove session state backup file: " + ex);
|
|
||||||
throw ex;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
_isNoSuchFile: function ssfi_isNoSuchFile(aReason) {
|
|
||||||
return aReason instanceof OS.File.Error && aReason.becauseNoSuchFile;
|
|
||||||
}
|
|
||||||
};
|
|
@ -39,20 +39,15 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
|||||||
Cu.import("resource://gre/modules/Services.jsm");
|
Cu.import("resource://gre/modules/Services.jsm");
|
||||||
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
Cu.import("resource://gre/modules/TelemetryStopwatch.jsm");
|
||||||
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
Cu.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
|
||||||
Cu.import("resource://gre/modules/commonjs/promise/core.js");
|
|
||||||
|
|
||||||
XPCOMUtils.defineLazyModuleGetter(this, "_SessionFile",
|
|
||||||
"resource:///modules/sessionstore/_SessionFile.jsm");
|
|
||||||
|
|
||||||
const STATE_RUNNING_STR = "running";
|
const STATE_RUNNING_STR = "running";
|
||||||
|
const MAX_FILE_SIZE = 100 * 1024 * 1024; // 100 megabytes
|
||||||
|
|
||||||
function debug(aMsg) {
|
function debug(aMsg) {
|
||||||
aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
|
aMsg = ("SessionStartup: " + aMsg).replace(/\S{80}/g, "$&\n");
|
||||||
Services.console.logStringMessage(aMsg);
|
Services.console.logStringMessage(aMsg);
|
||||||
}
|
}
|
||||||
|
|
||||||
let gOnceInitializedDeferred = Promise.defer();
|
|
||||||
|
|
||||||
/* :::::::: The Service ::::::::::::::: */
|
/* :::::::: The Service ::::::::::::::: */
|
||||||
|
|
||||||
function SessionStartup() {
|
function SessionStartup() {
|
||||||
@ -63,7 +58,6 @@ SessionStartup.prototype = {
|
|||||||
// the state to restore at startup
|
// the state to restore at startup
|
||||||
_initialState: null,
|
_initialState: null,
|
||||||
_sessionType: Ci.nsISessionStartup.NO_SESSION,
|
_sessionType: Ci.nsISessionStartup.NO_SESSION,
|
||||||
_initialized: false,
|
|
||||||
|
|
||||||
/* ........ Global Event Handlers .............. */
|
/* ........ Global Event Handlers .............. */
|
||||||
|
|
||||||
@ -71,121 +65,95 @@ SessionStartup.prototype = {
|
|||||||
* Initialize the component
|
* Initialize the component
|
||||||
*/
|
*/
|
||||||
init: function sss_init() {
|
init: function sss_init() {
|
||||||
debug("init starting");
|
|
||||||
// do not need to initialize anything in auto-started private browsing sessions
|
// do not need to initialize anything in auto-started private browsing sessions
|
||||||
let pbs = Cc["@mozilla.org/privatebrowsing;1"].
|
let pbs = Cc["@mozilla.org/privatebrowsing;1"].
|
||||||
getService(Ci.nsIPrivateBrowsingService);
|
getService(Ci.nsIPrivateBrowsingService);
|
||||||
if (PrivateBrowsingUtils.permanentPrivateBrowsing ||
|
if (PrivateBrowsingUtils.permanentPrivateBrowsing ||
|
||||||
pbs.lastChangedByCommandLine)
|
pbs.lastChangedByCommandLine)
|
||||||
return;
|
return;
|
||||||
// Session state is unknown until we read the file.
|
|
||||||
this._sessionType = null;
|
|
||||||
_SessionFile.read().then(
|
|
||||||
this._onSessionFileRead.bind(this)
|
|
||||||
);
|
|
||||||
debug("init launched");
|
|
||||||
},
|
|
||||||
|
|
||||||
// Wrap a string as a nsISupports
|
let prefBranch = Cc["@mozilla.org/preferences-service;1"].
|
||||||
_createSupportsString: function ssfi_createSupportsString(aData) {
|
getService(Ci.nsIPrefService).getBranch("browser.");
|
||||||
let string = Cc["@mozilla.org/supports-string;1"]
|
|
||||||
.createInstance(Ci.nsISupportsString);
|
|
||||||
string.data = aData;
|
|
||||||
return string;
|
|
||||||
},
|
|
||||||
|
|
||||||
_onSessionFileRead: function sss_onSessionFileRead(aStateString) {
|
// get file references
|
||||||
debug("onSessionFileRead ");
|
var dirService = Cc["@mozilla.org/file/directory_service;1"].
|
||||||
if (this._initialized) {
|
getService(Ci.nsIProperties);
|
||||||
debug("onSessionFileRead: Initialization is already complete");
|
let sessionFile = dirService.get("ProfD", Ci.nsILocalFile);
|
||||||
// Initialization is complete, nothing else to do
|
sessionFile.append("sessionstore.js");
|
||||||
|
|
||||||
|
let doResumeSessionOnce = prefBranch.getBoolPref("sessionstore.resume_session_once");
|
||||||
|
let doResumeSession = doResumeSessionOnce ||
|
||||||
|
prefBranch.getIntPref("startup.page") == 3;
|
||||||
|
|
||||||
|
// only continue if the session file exists
|
||||||
|
if (!sessionFile.exists())
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
// get string containing session state
|
||||||
|
let iniString = this._readStateFile(sessionFile);
|
||||||
|
if (!iniString)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// parse the session state into a JS object
|
||||||
|
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
||||||
|
if (iniString.charAt(0) == '(')
|
||||||
|
iniString = iniString.slice(1, -1);
|
||||||
|
let corruptFile = false;
|
||||||
try {
|
try {
|
||||||
this._initialized = true;
|
this._initialState = JSON.parse(iniString);
|
||||||
|
|
||||||
// Let observers modify the state before it is used
|
|
||||||
let supportsStateString = this._createSupportsString(aStateString);
|
|
||||||
Services.obs.notifyObservers(supportsStateString, "sessionstore-state-read", "");
|
|
||||||
aStateString = supportsStateString.data;
|
|
||||||
|
|
||||||
// No valid session found.
|
|
||||||
if (!aStateString) {
|
|
||||||
this._sessionType = Ci.nsISessionStartup.NO_SESSION;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// parse the session state into a JS object
|
|
||||||
// remove unneeded braces (added for compatibility with Firefox 2.0 and 3.0)
|
|
||||||
if (aStateString.charAt(0) == '(')
|
|
||||||
aStateString = aStateString.slice(1, -1);
|
|
||||||
let corruptFile = false;
|
|
||||||
try {
|
|
||||||
this._initialState = JSON.parse(aStateString);
|
|
||||||
}
|
|
||||||
catch (ex) {
|
|
||||||
debug("The session file contained un-parse-able JSON: " + ex);
|
|
||||||
// This is not valid JSON, but this might still be valid JavaScript,
|
|
||||||
// as used in FF2/FF3, so we need to eval.
|
|
||||||
// evalInSandbox will throw if aStateString is not parse-able.
|
|
||||||
try {
|
|
||||||
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
|
|
||||||
this._initialState = Cu.evalInSandbox("(" + aStateString + ")", s);
|
|
||||||
} catch(ex) {
|
|
||||||
debug("The session file contained un-eval-able JSON: " + ex);
|
|
||||||
corruptFile = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Services.telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").add(corruptFile);
|
|
||||||
|
|
||||||
let doResumeSessionOnce = Services.prefs.getBoolPref("browser.sessionstore.resume_session_once");
|
|
||||||
let doResumeSession = doResumeSessionOnce ||
|
|
||||||
Services.prefs.getIntPref("browser.startup.page") == 3;
|
|
||||||
|
|
||||||
// If this is a normal restore then throw away any previous session
|
|
||||||
if (!doResumeSessionOnce)
|
|
||||||
delete this._initialState.lastSessionState;
|
|
||||||
|
|
||||||
let resumeFromCrash = Services.prefs.getBoolPref("browser.sessionstore.resume_from_crash");
|
|
||||||
let lastSessionCrashed =
|
|
||||||
this._initialState && this._initialState.session &&
|
|
||||||
this._initialState.session.state &&
|
|
||||||
this._initialState.session.state == STATE_RUNNING_STR;
|
|
||||||
|
|
||||||
// Report shutdown success via telemetry. Shortcoming here are
|
|
||||||
// being-killed-by-OS-shutdown-logic, shutdown freezing after
|
|
||||||
// session restore was written, etc.
|
|
||||||
Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
|
|
||||||
|
|
||||||
// set the startup type
|
|
||||||
if (lastSessionCrashed && resumeFromCrash)
|
|
||||||
this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
|
|
||||||
else if (!lastSessionCrashed && doResumeSession)
|
|
||||||
this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
|
|
||||||
else if (this._initialState)
|
|
||||||
this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
|
|
||||||
else
|
|
||||||
this._initialState = null; // reset the state
|
|
||||||
|
|
||||||
// wait for the first browser window to open
|
|
||||||
// Don't reset the initial window's default args (i.e. the home page(s))
|
|
||||||
// if all stored tabs are pinned.
|
|
||||||
if (this.doRestore() &&
|
|
||||||
(!this._initialState.windows ||
|
|
||||||
!this._initialState.windows.every(function (win)
|
|
||||||
win.tabs.every(function (tab) tab.pinned))))
|
|
||||||
Services.obs.addObserver(this, "domwindowopened", true);
|
|
||||||
|
|
||||||
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
|
||||||
|
|
||||||
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
|
|
||||||
Services.obs.addObserver(this, "browser:purge-session-history", true);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
// We're ready. Notify everyone else.
|
|
||||||
Services.obs.notifyObservers(null, "sessionstore-state-finalized", "");
|
|
||||||
gOnceInitializedDeferred.resolve();
|
|
||||||
}
|
}
|
||||||
|
catch (ex) {
|
||||||
|
debug("The session file contained un-parse-able JSON: " + ex);
|
||||||
|
// Try to eval.
|
||||||
|
// evalInSandbox will throw if iniString is not parse-able.
|
||||||
|
try {
|
||||||
|
var s = new Cu.Sandbox("about:blank", {sandboxName: 'nsSessionStartup'});
|
||||||
|
this._initialState = Cu.evalInSandbox("(" + iniString + ")", s);
|
||||||
|
} catch(ex) {
|
||||||
|
debug("The session file contained un-eval-able JSON: " + ex);
|
||||||
|
corruptFile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Services.telemetry.getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE").add(corruptFile);
|
||||||
|
|
||||||
|
// If this is a normal restore then throw away any previous session
|
||||||
|
if (!doResumeSessionOnce)
|
||||||
|
delete this._initialState.lastSessionState;
|
||||||
|
|
||||||
|
let resumeFromCrash = prefBranch.getBoolPref("sessionstore.resume_from_crash");
|
||||||
|
let lastSessionCrashed =
|
||||||
|
this._initialState && this._initialState.session &&
|
||||||
|
this._initialState.session.state &&
|
||||||
|
this._initialState.session.state == STATE_RUNNING_STR;
|
||||||
|
|
||||||
|
// Report shutdown success via telemetry. Shortcoming here are
|
||||||
|
// being-killed-by-OS-shutdown-logic, shutdown freezing after
|
||||||
|
// session restore was written, etc.
|
||||||
|
Services.telemetry.getHistogramById("SHUTDOWN_OK").add(!lastSessionCrashed);
|
||||||
|
|
||||||
|
// set the startup type
|
||||||
|
if (lastSessionCrashed && resumeFromCrash)
|
||||||
|
this._sessionType = Ci.nsISessionStartup.RECOVER_SESSION;
|
||||||
|
else if (!lastSessionCrashed && doResumeSession)
|
||||||
|
this._sessionType = Ci.nsISessionStartup.RESUME_SESSION;
|
||||||
|
else if (this._initialState)
|
||||||
|
this._sessionType = Ci.nsISessionStartup.DEFER_SESSION;
|
||||||
|
else
|
||||||
|
this._initialState = null; // reset the state
|
||||||
|
|
||||||
|
// wait for the first browser window to open
|
||||||
|
// Don't reset the initial window's default args (i.e. the home page(s))
|
||||||
|
// if all stored tabs are pinned.
|
||||||
|
if (this.doRestore() &&
|
||||||
|
(!this._initialState.windows ||
|
||||||
|
!this._initialState.windows.every(function (win)
|
||||||
|
win.tabs.every(function (tab) tab.pinned))))
|
||||||
|
Services.obs.addObserver(this, "domwindowopened", true);
|
||||||
|
|
||||||
|
Services.obs.addObserver(this, "sessionstore-windows-restored", true);
|
||||||
|
|
||||||
|
if (this._sessionType != Ci.nsISessionStartup.NO_SESSION)
|
||||||
|
Services.obs.addObserver(this, "browser:purge-session-history", true);
|
||||||
},
|
},
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -269,15 +237,10 @@ SessionStartup.prototype = {
|
|||||||
|
|
||||||
/* ........ Public API ................*/
|
/* ........ Public API ................*/
|
||||||
|
|
||||||
get onceInitialized() {
|
|
||||||
return gOnceInitializedDeferred.promise;
|
|
||||||
},
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the session state as a jsval
|
* Get the session state as a jsval
|
||||||
*/
|
*/
|
||||||
get state() {
|
get state() {
|
||||||
this._ensureInitialized();
|
|
||||||
return this._initialState;
|
return this._initialState;
|
||||||
},
|
},
|
||||||
|
|
||||||
@ -286,7 +249,6 @@ SessionStartup.prototype = {
|
|||||||
* @returns bool
|
* @returns bool
|
||||||
*/
|
*/
|
||||||
doRestore: function sss_doRestore() {
|
doRestore: function sss_doRestore() {
|
||||||
this._ensureInitialized();
|
|
||||||
return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
|
return this._sessionType == Ci.nsISessionStartup.RECOVER_SESSION ||
|
||||||
this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
|
this._sessionType == Ci.nsISessionStartup.RESUME_SESSION;
|
||||||
},
|
},
|
||||||
@ -295,26 +257,59 @@ SessionStartup.prototype = {
|
|||||||
* Get the type of pending session store, if any.
|
* Get the type of pending session store, if any.
|
||||||
*/
|
*/
|
||||||
get sessionType() {
|
get sessionType() {
|
||||||
this._ensureInitialized();
|
|
||||||
return this._sessionType;
|
return this._sessionType;
|
||||||
},
|
},
|
||||||
|
|
||||||
// Ensure that initialization is complete.
|
/* ........ Storage API .............. */
|
||||||
// If initialization is not complete yet, fall back to a synchronous
|
|
||||||
// initialization and kill ongoing asynchronous initialization
|
/**
|
||||||
_ensureInitialized: function sss__ensureInitialized() {
|
* Reads a session state file into a string and lets
|
||||||
|
* observers modify the state before it's being used
|
||||||
|
*
|
||||||
|
* @param aFile is any nsIFile
|
||||||
|
* @returns a session state string
|
||||||
|
*/
|
||||||
|
_readStateFile: function sss_readStateFile(aFile) {
|
||||||
|
TelemetryStopwatch.start("FX_SESSION_RESTORE_READ_FILE_MS");
|
||||||
|
var stateString = Cc["@mozilla.org/supports-string;1"].
|
||||||
|
createInstance(Ci.nsISupportsString);
|
||||||
|
stateString.data = this._readFile(aFile) || "";
|
||||||
|
TelemetryStopwatch.finish("FX_SESSION_RESTORE_READ_FILE_MS");
|
||||||
|
|
||||||
|
Services.obs.notifyObservers(stateString, "sessionstore-state-read", "");
|
||||||
|
|
||||||
|
return stateString.data;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* reads a file into a string
|
||||||
|
* @param aFile
|
||||||
|
* nsIFile
|
||||||
|
* @returns string
|
||||||
|
*/
|
||||||
|
_readFile: function sss_readFile(aFile) {
|
||||||
try {
|
try {
|
||||||
debug("_ensureInitialized: " + this._initialState);
|
var stream = Cc["@mozilla.org/network/file-input-stream;1"].
|
||||||
if (this._initialized) {
|
createInstance(Ci.nsIFileInputStream);
|
||||||
// Initialization is complete, nothing else to do
|
stream.init(aFile, 0x01, 0, 0);
|
||||||
return;
|
var cvstream = Cc["@mozilla.org/intl/converter-input-stream;1"].
|
||||||
}
|
createInstance(Ci.nsIConverterInputStream);
|
||||||
let contents = _SessionFile.syncRead();
|
|
||||||
this._onSessionFileRead(contents);
|
var fileSize = stream.available();
|
||||||
} catch(ex) {
|
if (fileSize > MAX_FILE_SIZE)
|
||||||
debug("ensureInitialized: could not read session " + ex + ", " + ex.stack);
|
throw "SessionStartup: sessionstore.js was not processed because it was too large.";
|
||||||
throw ex;
|
|
||||||
|
cvstream.init(stream, "UTF-8", fileSize, Ci.nsIConverterInputStream.DEFAULT_REPLACEMENT_CHARACTER);
|
||||||
|
var data = {};
|
||||||
|
cvstream.readString(fileSize, data);
|
||||||
|
var content = data.value;
|
||||||
|
cvstream.close();
|
||||||
|
|
||||||
|
return content.replace(/\r\n?/g, "\n");
|
||||||
}
|
}
|
||||||
|
catch (ex) { Cu.reportError(ex); }
|
||||||
|
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
|
|
||||||
/* ........ QueryInterface .............. */
|
/* ........ QueryInterface .............. */
|
||||||
|
@ -16,10 +16,6 @@ include $(DEPTH)/config/autoconf.mk
|
|||||||
# browser_580512.js is disabled for leaking browser windows (bug 752467)
|
# browser_580512.js is disabled for leaking browser windows (bug 752467)
|
||||||
# browser_586068-reload.js is disabled due to generally being broken (bug 809123, 797263)
|
# browser_586068-reload.js is disabled due to generally being broken (bug 809123, 797263)
|
||||||
|
|
||||||
XPCSHELL_TESTS = \
|
|
||||||
unit \
|
|
||||||
$(NULL)
|
|
||||||
|
|
||||||
MOCHITEST_BROWSER_FILES = \
|
MOCHITEST_BROWSER_FILES = \
|
||||||
head.js \
|
head.js \
|
||||||
browser_form_restore_events.js \
|
browser_form_restore_events.js \
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
{
|
|
||||||
"windows": []
|
|
||||||
}
|
|
@ -1,26 +0,0 @@
|
|||||||
let Cu = Components.utils;
|
|
||||||
let Cc = Components.classes;
|
|
||||||
let Ci = Components.interfaces;
|
|
||||||
|
|
||||||
Components.utils.import("resource://gre/modules/Services.jsm");
|
|
||||||
|
|
||||||
// Call a function once initialization of SessionStartup is complete
|
|
||||||
let afterSessionStartupInitialization =
|
|
||||||
function afterSessionStartupInitialization(cb) {
|
|
||||||
do_print("Waiting for session startup initialization");
|
|
||||||
let observer = function() {
|
|
||||||
try {
|
|
||||||
do_print("Session startup initialization observed");
|
|
||||||
Services.obs.removeObserver(observer, "sessionstore-state-finalized");
|
|
||||||
cb();
|
|
||||||
} catch (ex) {
|
|
||||||
do_throw(ex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
|
|
||||||
getService(Ci.nsIObserver);
|
|
||||||
Services.obs.addObserver(startup, "final-ui-startup", false);
|
|
||||||
Services.obs.addObserver(startup, "quit-application", false);
|
|
||||||
Services.obs.notifyObservers(null, "final-ui-startup", "");
|
|
||||||
Services.obs.addObserver(observer, "sessionstore-state-finalized", false);
|
|
||||||
};
|
|
@ -1,19 +0,0 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
|
|
||||||
// Test nsISessionStartup.sessionType in the following scenario:
|
|
||||||
// - no sessionstore.js;
|
|
||||||
// - the session store has been loaded, so no need to go
|
|
||||||
// through the synchronous fallback
|
|
||||||
|
|
||||||
function run_test() {
|
|
||||||
do_test_pending();
|
|
||||||
let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
|
|
||||||
getService(Ci.nsISessionStartup);
|
|
||||||
|
|
||||||
afterSessionStartupInitialization(function cb() {
|
|
||||||
do_check_eq(startup.sessionType, Ci.nsISessionStartup.NO_SESSION);
|
|
||||||
do_test_finished();
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,15 +0,0 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
|
|
||||||
// Test nsISessionStartup.sessionType in the following scenario:
|
|
||||||
// - no sessionstore.js;
|
|
||||||
// - the session store has not been loaded yet, so we have to trigger
|
|
||||||
// synchronous fallback
|
|
||||||
|
|
||||||
function run_test() {
|
|
||||||
do_get_profile();
|
|
||||||
let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
|
|
||||||
getService(Ci.nsISessionStartup);
|
|
||||||
do_check_eq(startup.sessionType, Ci.nsISessionStartup.NO_SESSION);
|
|
||||||
}
|
|
@ -1,23 +0,0 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
|
|
||||||
// Test nsISessionStartup.sessionType in the following scenario:
|
|
||||||
// - valid sessionstore.js;
|
|
||||||
// - the session store has been loaded, so no need to go
|
|
||||||
// through the synchronous fallback
|
|
||||||
|
|
||||||
function run_test() {
|
|
||||||
let profd = do_get_profile();
|
|
||||||
let source = do_get_file("data/sessionstore_valid.js");
|
|
||||||
source.copyTo(profd, "sessionstore.js");
|
|
||||||
|
|
||||||
do_test_pending();
|
|
||||||
let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
|
|
||||||
getService(Ci.nsISessionStartup);
|
|
||||||
|
|
||||||
afterSessionStartupInitialization(function cb() {
|
|
||||||
do_check_eq(startup.sessionType, Ci.nsISessionStartup.DEFER_SESSION);
|
|
||||||
do_test_finished();
|
|
||||||
});
|
|
||||||
}
|
|
@ -1,17 +0,0 @@
|
|||||||
/* Any copyright is dedicated to the Public Domain.
|
|
||||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
|
||||||
|
|
||||||
|
|
||||||
// Test nsISessionStartup.sessionType in the following scenario:
|
|
||||||
// - valid sessionstore.js;
|
|
||||||
// - the session store has not been loaded yet, so we have to trigger
|
|
||||||
// synchronous fallback
|
|
||||||
|
|
||||||
function run_test() {
|
|
||||||
let profd = do_get_profile();
|
|
||||||
let source = do_get_file("data/sessionstore_valid.js");
|
|
||||||
source.copyTo(profd, "sessionstore.js");
|
|
||||||
let startup = Cc["@mozilla.org/browser/sessionstartup;1"].
|
|
||||||
getService(Ci.nsISessionStartup);
|
|
||||||
do_check_eq(startup.sessionType, Ci.nsISessionStartup.DEFER_SESSION);
|
|
||||||
}
|
|
@ -1,8 +0,0 @@
|
|||||||
[DEFAULT]
|
|
||||||
head = head.js
|
|
||||||
tail =
|
|
||||||
|
|
||||||
[test_startup_nosession_sync.js]
|
|
||||||
[test_startup_nosession_async.js]
|
|
||||||
[test_startup_session_sync.js]
|
|
||||||
[test_startup_session_async.js]
|
|
@ -97,7 +97,6 @@ skip-if = os == "android"
|
|||||||
[include:browser/components/migration/tests/unit/xpcshell.ini]
|
[include:browser/components/migration/tests/unit/xpcshell.ini]
|
||||||
[include:browser/components/places/tests/unit/xpcshell.ini]
|
[include:browser/components/places/tests/unit/xpcshell.ini]
|
||||||
[include:browser/components/privatebrowsing/test/unit/xpcshell.ini]
|
[include:browser/components/privatebrowsing/test/unit/xpcshell.ini]
|
||||||
[include:browser/components/sessionstore/test/unit/xpcshell.ini]
|
|
||||||
[include:browser/components/shell/test/unit/xpcshell.ini]
|
[include:browser/components/shell/test/unit/xpcshell.ini]
|
||||||
[include:browser/devtools/shared/test/unit/xpcshell.ini]
|
[include:browser/devtools/shared/test/unit/xpcshell.ini]
|
||||||
[include:browser/modules/test/unit/xpcshell.ini]
|
[include:browser/modules/test/unit/xpcshell.ini]
|
||||||
|
@ -2113,12 +2113,6 @@
|
|||||||
"n_buckets": 10,
|
"n_buckets": 10,
|
||||||
"description": "Session restore: Time to read the session data from the file on disk (ms)"
|
"description": "Session restore: Time to read the session data from the file on disk (ms)"
|
||||||
},
|
},
|
||||||
"FX_SESSION_RESTORE_SYNC_READ_FILE_MS": {
|
|
||||||
"kind": "exponential",
|
|
||||||
"high": "3000",
|
|
||||||
"n_buckets": 10,
|
|
||||||
"description": "Session restore: Time to read the session data from the file on disk, using the synchronous fallback (ms)"
|
|
||||||
},
|
|
||||||
"FX_SESSION_RESTORE_WRITE_FILE_MS": {
|
"FX_SESSION_RESTORE_WRITE_FILE_MS": {
|
||||||
"kind": "exponential",
|
"kind": "exponential",
|
||||||
"high": "3000",
|
"high": "3000",
|
||||||
|
Loading…
Reference in New Issue
Block a user