diff options
Diffstat (limited to 'browser/components/sessionstore')
69 files changed, 694 insertions, 2493 deletions
diff --git a/browser/components/sessionstore/ContentRestore.sys.mjs b/browser/components/sessionstore/ContentRestore.sys.mjs deleted file mode 100644 index e55772cab3..0000000000 --- a/browser/components/sessionstore/ContentRestore.sys.mjs +++ /dev/null @@ -1,435 +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/. */ - -const lazy = {}; - -ChromeUtils.defineESModuleGetters(lazy, { - SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.sys.mjs", - Utils: "resource://gre/modules/sessionstore/Utils.sys.mjs", -}); - -/** - * This module implements the content side of session restoration. The chrome - * side is handled by SessionStore.sys.mjs. The functions in this module are called - * by content-sessionStore.js based on messages received from SessionStore.sys.mjs - * (or, in one case, based on a "load" event). Each tab has its own - * ContentRestore instance, constructed by content-sessionStore.js. - * - * In a typical restore, content-sessionStore.js will call the following based - * on messages and events it receives: - * - * restoreHistory(tabData, loadArguments, callbacks) - * Restores the tab's history and session cookies. - * restoreTabContent(loadArguments, finishCallback) - * Starts loading the data for the current page to restore. - * restoreDocument() - * Restore form and scroll data. - * - * When the page has been loaded from the network, we call finishCallback. It - * should send a message to SessionStore.sys.mjs, which may cause other tabs to be - * restored. - * - * When the page has finished loading, a "load" event will trigger in - * content-sessionStore.js, which will call restoreDocument. At that point, - * form data is restored and the restore is complete. - * - * At any time, SessionStore.sys.mjs can cancel the ongoing restore by sending a - * reset message, which causes resetRestore to be called. At that point it's - * legal to begin another restore. - */ -export function ContentRestore(chromeGlobal) { - let internal = new ContentRestoreInternal(chromeGlobal); - let external = {}; - - let EXPORTED_METHODS = [ - "restoreHistory", - "restoreTabContent", - "restoreDocument", - "resetRestore", - ]; - - for (let method of EXPORTED_METHODS) { - external[method] = internal[method].bind(internal); - } - - return Object.freeze(external); -} - -function ContentRestoreInternal(chromeGlobal) { - this.chromeGlobal = chromeGlobal; - - // The following fields are only valid during certain phases of the restore - // process. - - // The tabData for the restore. Set in restoreHistory and removed in - // restoreTabContent. - this._tabData = null; - - // Contains {entry, scrollPositions, formdata}, where entry is a - // single entry from the tabData.entries array. Set in - // restoreTabContent and removed in restoreDocument. - this._restoringDocument = null; - - // This listener is used to detect reloads on restoring tabs. Set in - // restoreHistory and removed in restoreTabContent. - this._historyListener = null; - - // This listener detects when a pending tab starts loading (when not - // initiated by sessionstore) and when a restoring tab has finished loading - // data from the network. Set in restoreHistory() and restoreTabContent(), - // removed in resetRestore(). - this._progressListener = null; -} - -/** - * The API for the ContentRestore module. Methods listed in EXPORTED_METHODS are - * public. - */ -ContentRestoreInternal.prototype = { - get docShell() { - return this.chromeGlobal.docShell; - }, - - /** - * Starts the process of restoring a tab. The tabData to be restored is passed - * in here and used throughout the restoration. The epoch (which must be - * non-zero) is passed through to all the callbacks. If a load in the tab - * is started while it is pending, the appropriate callbacks are called. - */ - restoreHistory(tabData, loadArguments, callbacks) { - this._tabData = tabData; - - // In case about:blank isn't done yet. - let webNavigation = this.docShell.QueryInterface(Ci.nsIWebNavigation); - webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL); - - // Make sure currentURI is set so that switch-to-tab works before the tab is - // restored. We'll reset this to about:blank when we try to restore the tab - // to ensure that docshell doeesn't get confused. Don't bother doing this if - // we're restoring immediately due to a process switch. It just causes the - // URL bar to be temporarily blank. - let activeIndex = tabData.index - 1; - let activePageData = tabData.entries[activeIndex] || {}; - let uri = activePageData.url || null; - if (uri && !loadArguments) { - webNavigation.setCurrentURIForSessionStore(Services.io.newURI(uri)); - } - - lazy.SessionHistory.restore(this.docShell, tabData); - - // Add a listener to watch for reloads. - let listener = new HistoryListener(this.docShell, () => { - // On reload, restore tab contents. - this.restoreTabContent(null, false, callbacks.onLoadFinished); - }); - - webNavigation.sessionHistory.legacySHistory.addSHistoryListener(listener); - this._historyListener = listener; - - // Make sure to reset the capabilities and attributes in case this tab gets - // reused. - SessionStoreUtils.restoreDocShellCapabilities( - this.docShell, - tabData.disallow - ); - - // Add a progress listener to correctly handle browser.loadURI() - // calls from foreign code. - this._progressListener = new ProgressListener(this.docShell, { - onStartRequest: () => { - // Some code called browser.loadURI() on a pending tab. It's safe to - // assume we don't care about restoring scroll or form data. - this._tabData = null; - - // Listen for the tab to finish loading. - this.restoreTabContentStarted(callbacks.onLoadFinished); - - // Notify the parent. - callbacks.onLoadStarted(); - }, - }); - }, - - /** - * Start loading the current page. When the data has finished loading from the - * network, finishCallback is called. Returns true if the load was successful. - */ - restoreTabContent(loadArguments, isRemotenessUpdate, finishCallback) { - let tabData = this._tabData; - this._tabData = null; - - let webNavigation = this.docShell.QueryInterface(Ci.nsIWebNavigation); - - // Listen for the tab to finish loading. - this.restoreTabContentStarted(finishCallback); - - // Reset the current URI to about:blank. We changed it above for - // switch-to-tab, but now it must go back to the correct value before the - // load happens. Don't bother doing this if we're restoring immediately - // due to a process switch. - if (!isRemotenessUpdate) { - webNavigation.setCurrentURIForSessionStore( - Services.io.newURI("about:blank") - ); - } - - try { - if (loadArguments) { - // If the load was started in another process, and the in-flight channel - // was redirected into this process, resume that load within our process. - // - // NOTE: In this case `isRemotenessUpdate` must be true. - webNavigation.resumeRedirectedLoad( - loadArguments.redirectLoadSwitchId, - loadArguments.redirectHistoryIndex - ); - } else if (tabData.userTypedValue && tabData.userTypedClear) { - // If the user typed a URL into the URL bar and hit enter right before - // we crashed, we want to start loading that page again. A non-zero - // userTypedClear value means that the load had started. - // Load userTypedValue and fix up the URL if it's partial/broken. - let loadURIOptions = { - triggeringPrincipal: - Services.scriptSecurityManager.getSystemPrincipal(), - loadFlags: Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP, - }; - webNavigation.fixupAndLoadURIString( - tabData.userTypedValue, - loadURIOptions - ); - } else if (tabData.entries.length) { - // Stash away the data we need for restoreDocument. - this._restoringDocument = { - formdata: tabData.formdata || {}, - scrollPositions: tabData.scroll || {}, - }; - - // In order to work around certain issues in session history, we need to - // force session history to update its internal index and call reload - // instead of gotoIndex. See bug 597315. - let history = webNavigation.sessionHistory.legacySHistory; - history.reloadCurrentEntry(); - } else { - // If there's nothing to restore, we should still blank the page. - let loadURIOptions = { - triggeringPrincipal: - Services.scriptSecurityManager.getSystemPrincipal(), - loadFlags: Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY, - // Specify an override to force the load to finish in the current - // process, as tests rely on this behaviour for non-fission session - // restore. - remoteTypeOverride: Services.appinfo.remoteType, - }; - webNavigation.loadURI( - Services.io.newURI("about:blank"), - loadURIOptions - ); - } - - return true; - } catch (ex) { - if (ex instanceof Ci.nsIException) { - // Ignore page load errors, but return false to signal that the load never - // happened. - return false; - } - } - return null; - }, - - /** - * To be called after restoreHistory(). Removes all listeners needed for - * pending tabs and makes sure to notify when the tab finished loading. - */ - restoreTabContentStarted(finishCallback) { - // The reload listener is no longer needed. - this._historyListener.uninstall(); - this._historyListener = null; - - // Remove the old progress listener. - this._progressListener.uninstall(); - - // We're about to start a load. This listener will be called when the load - // has finished getting everything from the network. - this._progressListener = new ProgressListener(this.docShell, { - onStopRequest: () => { - // Call resetRestore() to reset the state back to normal. The data - // needed for restoreDocument() (which hasn't happened yet) will - // remain in _restoringDocument. - this.resetRestore(); - - finishCallback(); - }, - }); - }, - - /** - * Finish restoring the tab by filling in form data and setting the scroll - * position. The restore is complete when this function exits. It should be - * called when the "load" event fires for the restoring tab. Returns true - * if we're restoring a document. - */ - restoreDocument() { - if (!this._restoringDocument) { - return; - } - - let { formdata, scrollPositions } = this._restoringDocument; - this._restoringDocument = null; - - let window = this.docShell.domWindow; - - // Restore form data. - lazy.Utils.restoreFrameTreeData(window, formdata, (frame, data) => { - // restore() will return false, and thus abort restoration for the - // current |frame| and its descendants, if |data.url| is given but - // doesn't match the loaded document's URL. - return SessionStoreUtils.restoreFormData(frame.document, data); - }); - - // Restore scroll data. - lazy.Utils.restoreFrameTreeData(window, scrollPositions, (frame, data) => { - if (data.scroll) { - SessionStoreUtils.restoreScrollPosition(frame, data); - } - }); - }, - - /** - * Cancel an ongoing restore. This function can be called any time between - * restoreHistory and restoreDocument. - * - * This function is called externally (if a restore is canceled) and - * internally (when the loads for a restore have finished). In the latter - * case, it's called before restoreDocument, so it cannot clear - * _restoringDocument. - */ - resetRestore() { - this._tabData = null; - - if (this._historyListener) { - this._historyListener.uninstall(); - } - this._historyListener = null; - - if (this._progressListener) { - this._progressListener.uninstall(); - } - this._progressListener = null; - }, -}; - -/* - * This listener detects when a page being restored is reloaded. It triggers a - * callback and cancels the reload. The callback will send a message to - * SessionStore.sys.mjs so that it can restore the content immediately. - */ -function HistoryListener(docShell, callback) { - let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation); - webNavigation.sessionHistory.legacySHistory.addSHistoryListener(this); - - this.webNavigation = webNavigation; - this.callback = callback; -} -HistoryListener.prototype = { - QueryInterface: ChromeUtils.generateQI([ - "nsISHistoryListener", - "nsISupportsWeakReference", - ]), - - uninstall() { - let shistory = this.webNavigation.sessionHistory.legacySHistory; - if (shistory) { - shistory.removeSHistoryListener(this); - } - }, - - OnHistoryGotoIndex() {}, - OnHistoryPurge() {}, - OnHistoryReplaceEntry() {}, - - // This will be called for a pending tab when loadURI(uri) is called where - // the given |uri| only differs in the fragment. - OnHistoryNewEntry(newURI) { - let currentURI = this.webNavigation.currentURI; - - // Ignore new SHistory entries with the same URI as those do not indicate - // a navigation inside a document by changing the #hash part of the URL. - // We usually hit this when purging session history for browsers. - if (currentURI && currentURI.spec == newURI.spec) { - return; - } - - // Reset the tab's URL to what it's actually showing. Without this loadURI() - // would use the current document and change the displayed URL only. - this.webNavigation.setCurrentURIForSessionStore( - Services.io.newURI("about:blank") - ); - - // Kick off a new load so that we navigate away from about:blank to the - // new URL that was passed to loadURI(). The new load will cause a - // STATE_START notification to be sent and the ProgressListener will then - // notify the parent and do the rest. - let loadFlags = Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; - let loadURIOptions = { - triggeringPrincipal: Services.scriptSecurityManager.getSystemPrincipal(), - loadFlags, - }; - this.webNavigation.loadURI(newURI, loadURIOptions); - }, - - OnHistoryReload() { - this.callback(); - - // Cancel the load. - return false; - }, -}; - -/** - * This class informs SessionStore.sys.mjs whenever the network requests for a - * restoring page have completely finished. We only restore three tabs - * simultaneously, so this is the signal for SessionStore.sys.mjs to kick off - * another restore (if there are more to do). - * - * The progress listener is also used to be notified when a load not initiated - * by sessionstore starts. Pending tabs will then need to be marked as no - * longer pending. - */ -function ProgressListener(docShell, callbacks) { - let webProgress = docShell - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebProgress); - webProgress.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_WINDOW); - - this.webProgress = webProgress; - this.callbacks = callbacks; -} - -ProgressListener.prototype = { - QueryInterface: ChromeUtils.generateQI([ - "nsIWebProgressListener", - "nsISupportsWeakReference", - ]), - - uninstall() { - this.webProgress.removeProgressListener(this); - }, - - onStateChange(webProgress, request, stateFlags, status) { - let { STATE_IS_WINDOW, STATE_STOP, STATE_START } = - Ci.nsIWebProgressListener; - if (!webProgress.isTopLevel || !(stateFlags & STATE_IS_WINDOW)) { - return; - } - - if (stateFlags & STATE_START && this.callbacks.onStartRequest) { - this.callbacks.onStartRequest(); - } - - if (stateFlags & STATE_STOP && this.callbacks.onStopRequest) { - this.callbacks.onStopRequest(); - } - }, -}; diff --git a/browser/components/sessionstore/ContentSessionStore.sys.mjs b/browser/components/sessionstore/ContentSessionStore.sys.mjs deleted file mode 100644 index 44f59cd39d..0000000000 --- a/browser/components/sessionstore/ContentSessionStore.sys.mjs +++ /dev/null @@ -1,685 +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/. */ - -import { - clearTimeout, - setTimeoutWithTarget, -} from "resource://gre/modules/Timer.sys.mjs"; - -const lazy = {}; - -ChromeUtils.defineESModuleGetters(lazy, { - ContentRestore: "resource:///modules/sessionstore/ContentRestore.sys.mjs", - SessionHistory: "resource://gre/modules/sessionstore/SessionHistory.sys.mjs", -}); - -// This pref controls whether or not we send updates to the parent on a timeout -// or not, and should only be used for tests or debugging. -const TIMEOUT_DISABLED_PREF = "browser.sessionstore.debug.no_auto_updates"; - -const PREF_INTERVAL = "browser.sessionstore.interval"; - -const kNoIndex = Number.MAX_SAFE_INTEGER; -const kLastIndex = Number.MAX_SAFE_INTEGER - 1; - -class Handler { - constructor(store) { - this.store = store; - } - - get contentRestore() { - return this.store.contentRestore; - } - - get contentRestoreInitialized() { - return this.store.contentRestoreInitialized; - } - - get mm() { - return this.store.mm; - } - - get messageQueue() { - return this.store.messageQueue; - } -} - -/** - * Listens for and handles content events that we need for the - * session store service to be notified of state changes in content. - */ -class EventListener extends Handler { - constructor(store) { - super(store); - - SessionStoreUtils.addDynamicFrameFilteredListener( - this.mm, - "load", - this, - true - ); - } - - handleEvent(event) { - let { content } = this.mm; - - // Ignore load events from subframes. - if (event.target != content.document) { - return; - } - - if (content.document.documentURI.startsWith("about:reader")) { - if ( - event.type == "load" && - !content.document.body.classList.contains("loaded") - ) { - // Don't restore the scroll position of an about:reader page at this - // point; listen for the custom event dispatched from AboutReader.sys.mjs. - content.addEventListener("AboutReaderContentReady", this); - return; - } - - content.removeEventListener("AboutReaderContentReady", this); - } - - if (this.contentRestoreInitialized) { - // Restore the form data and scroll position. - this.contentRestore.restoreDocument(); - } - } -} - -/** - * Listens for changes to the session history. Whenever the user navigates - * we will collect URLs and everything belonging to session history. - * - * Causes a SessionStore:update message to be sent that contains the current - * session history. - * - * Example: - * {entries: [{url: "about:mozilla", ...}, ...], index: 1} - */ -class SessionHistoryListener extends Handler { - constructor(store) { - super(store); - - this._fromIdx = kNoIndex; - - // By adding the SHistoryListener immediately, we will unfortunately be - // notified of every history entry as the tab is restored. We don't bother - // waiting to add the listener later because these notifications are cheap. - // We will likely only collect once since we are batching collection on - // a delay. - this.mm.docShell - .QueryInterface(Ci.nsIWebNavigation) - .sessionHistory.legacySHistory.addSHistoryListener(this); // OK in non-geckoview - - let webProgress = this.mm.docShell - .QueryInterface(Ci.nsIInterfaceRequestor) - .getInterface(Ci.nsIWebProgress); - - webProgress.addProgressListener( - this, - Ci.nsIWebProgress.NOTIFY_STATE_DOCUMENT - ); - - // Collect data if we start with a non-empty shistory. - if (!lazy.SessionHistory.isEmpty(this.mm.docShell)) { - this.collect(); - // When a tab is detached from the window, for the new window there is a - // new SessionHistoryListener created. Normally it is empty at this point - // but in a test env. the initial about:blank might have a children in which - // case we fire off a history message here with about:blank in it. If we - // don't do it ASAP then there is going to be a browser swap and the parent - // will be all confused by that message. - this.store.messageQueue.send(); - } - - // Listen for page title changes. - this.mm.addEventListener("DOMTitleChanged", this); - } - - get mm() { - return this.store.mm; - } - - uninit() { - let sessionHistory = this.mm.docShell.QueryInterface( - Ci.nsIWebNavigation - ).sessionHistory; - if (sessionHistory) { - sessionHistory.legacySHistory.removeSHistoryListener(this); // OK in non-geckoview - } - } - - collect() { - // We want to send down a historychange even for full collects in case our - // session history is a partial session history, in which case we don't have - // enough information for a full update. collectFrom(-1) tells the collect - // function to collect all data avaliable in this process. - if (this.mm.docShell) { - this.collectFrom(-1); - } - } - - // History can grow relatively big with the nested elements, so if we don't have to, we - // don't want to send the entire history all the time. For a simple optimization - // we keep track of the smallest index from after any change has occured and we just send - // the elements from that index. If something more complicated happens we just clear it - // and send the entire history. We always send the additional info like the current selected - // index (so for going back and forth between history entries we set the index to kLastIndex - // if nothing else changed send an empty array and the additonal info like the selected index) - collectFrom(idx) { - if (this._fromIdx <= idx) { - // If we already know that we need to update history fromn index N we can ignore any changes - // tha happened with an element with index larger than N. - // Note: initially we use kNoIndex which is MAX_SAFE_INTEGER which means we don't ignore anything - // here, and in case of navigation in the history back and forth we use kLastIndex which ignores - // only the subsequent navigations, but not any new elements added. - return; - } - - this._fromIdx = idx; - this.store.messageQueue.push("historychange", () => { - if (this._fromIdx === kNoIndex) { - return null; - } - - let history = lazy.SessionHistory.collect( - this.mm.docShell, - this._fromIdx - ); - this._fromIdx = kNoIndex; - return history; - }); - } - - handleEvent(event) { - this.collect(); - } - - OnHistoryNewEntry(newURI, oldIndex) { - // Collect the current entry as well, to make sure to collect any changes - // that were made to the entry while the document was active. - this.collectFrom(oldIndex == -1 ? oldIndex : oldIndex - 1); - } - - OnHistoryGotoIndex() { - // We ought to collect the previously current entry as well, see bug 1350567. - this.collectFrom(kLastIndex); - } - - OnHistoryPurge() { - this.collect(); - } - - OnHistoryReload() { - this.collect(); - return true; - } - - OnHistoryReplaceEntry() { - this.collect(); - } - - /** - * @see nsIWebProgressListener.onStateChange - */ - onStateChange(webProgress, request, stateFlags, status) { - // Ignore state changes for subframes because we're only interested in the - // top-document starting or stopping its load. - if (!webProgress.isTopLevel || webProgress.DOMWindow != this.mm.content) { - return; - } - - // onStateChange will be fired when loading the initial about:blank URI for - // a browser, which we don't actually care about. This is particularly for - // the case of unrestored background tabs, where the content has not yet - // been restored: we don't want to accidentally send any updates to the - // parent when the about:blank placeholder page has loaded. - if (!this.mm.docShell.hasLoadedNonBlankURI) { - return; - } - - if (stateFlags & Ci.nsIWebProgressListener.STATE_START) { - this.collect(); - } else if (stateFlags & Ci.nsIWebProgressListener.STATE_STOP) { - this.collect(); - } - } -} -SessionHistoryListener.prototype.QueryInterface = ChromeUtils.generateQI([ - "nsIWebProgressListener", - "nsISHistoryListener", - "nsISupportsWeakReference", -]); - -/** - * A message queue that takes collected data and will take care of sending it - * to the chrome process. It allows flushing using synchronous messages and - * takes care of any race conditions that might occur because of that. Changes - * will be batched if they're pushed in quick succession to avoid a message - * flood. - */ -class MessageQueue extends Handler { - constructor(store) { - super(store); - - /** - * A map (string -> lazy fn) holding lazy closures of all queued data - * collection routines. These functions will return data collected from the - * docShell. - */ - this._data = new Map(); - - /** - * The delay (in ms) used to delay sending changes after data has been - * invalidated. - */ - this.BATCH_DELAY_MS = 1000; - - /** - * The minimum idle period (in ms) we need for sending data to chrome process. - */ - this.NEEDED_IDLE_PERIOD_MS = 5; - - /** - * Timeout for waiting an idle period to send data. We will set this from - * the pref "browser.sessionstore.interval". - */ - this._timeoutWaitIdlePeriodMs = null; - - /** - * The current timeout ID, null if there is no queue data. We use timeouts - * to damp a flood of data changes and send lots of changes as one batch. - */ - this._timeout = null; - - /** - * Whether or not sending batched messages on a timer is disabled. This should - * only be used for debugging or testing. If you need to access this value, - * you should probably use the timeoutDisabled getter. - */ - this._timeoutDisabled = false; - - /** - * True if there is already a send pending idle dispatch, set to prevent - * scheduling more than one. If false there may or may not be one scheduled. - */ - this._idleScheduled = false; - - this.timeoutDisabled = Services.prefs.getBoolPref(TIMEOUT_DISABLED_PREF); - this._timeoutWaitIdlePeriodMs = Services.prefs.getIntPref(PREF_INTERVAL); - - Services.prefs.addObserver(TIMEOUT_DISABLED_PREF, this); - Services.prefs.addObserver(PREF_INTERVAL, this); - } - - /** - * True if batched messages are not being fired on a timer. This should only - * ever be true when debugging or during tests. - */ - get timeoutDisabled() { - return this._timeoutDisabled; - } - - /** - * Disables sending batched messages on a timer. Also cancels any pending - * timers. - */ - set timeoutDisabled(val) { - this._timeoutDisabled = val; - - if (val && this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - } - - uninit() { - Services.prefs.removeObserver(TIMEOUT_DISABLED_PREF, this); - Services.prefs.removeObserver(PREF_INTERVAL, this); - this.cleanupTimers(); - } - - /** - * Cleanup pending idle callback and timer. - */ - cleanupTimers() { - this._idleScheduled = false; - if (this._timeout) { - clearTimeout(this._timeout); - this._timeout = null; - } - } - - observe(subject, topic, data) { - if (topic == "nsPref:changed") { - switch (data) { - case TIMEOUT_DISABLED_PREF: - this.timeoutDisabled = Services.prefs.getBoolPref( - TIMEOUT_DISABLED_PREF - ); - break; - case PREF_INTERVAL: - this._timeoutWaitIdlePeriodMs = - Services.prefs.getIntPref(PREF_INTERVAL); - break; - default: - console.error("received unknown message '" + data + "'"); - break; - } - } - } - - /** - * Pushes a given |value| onto the queue. The given |key| represents the type - * of data that is stored and can override data that has been queued before - * but has not been sent to the parent process, yet. - * - * @param key (string) - * A unique identifier specific to the type of data this is passed. - * @param fn (function) - * A function that returns the value that will be sent to the parent - * process. - */ - push(key, fn) { - this._data.set(key, fn); - - if (!this._timeout && !this._timeoutDisabled) { - // Wait a little before sending the message to batch multiple changes. - this._timeout = setTimeoutWithTarget( - () => this.sendWhenIdle(), - this.BATCH_DELAY_MS, - this.mm.tabEventTarget - ); - } - } - - /** - * Sends queued data when the remaining idle time is enough or waiting too - * long; otherwise, request an idle time again. If the |deadline| is not - * given, this function is going to schedule the first request. - * - * @param deadline (object) - * An IdleDeadline object passed by idleDispatch(). - */ - sendWhenIdle(deadline) { - if (!this.mm.content) { - // The frameloader is being torn down. Nothing more to do. - return; - } - - if (deadline) { - if ( - deadline.didTimeout || - deadline.timeRemaining() > this.NEEDED_IDLE_PERIOD_MS - ) { - this.send(); - return; - } - } else if (this._idleScheduled) { - // Bail out if there's a pending run. - return; - } - ChromeUtils.idleDispatch(deadline_ => this.sendWhenIdle(deadline_), { - timeout: this._timeoutWaitIdlePeriodMs, - }); - this._idleScheduled = true; - } - - /** - * Sends queued data to the chrome process. - * - * @param options (object) - * {flushID: 123} to specify that this is a flush - * {isFinal: true} to signal this is the final message sent on unload - */ - send(options = {}) { - // Looks like we have been called off a timeout after the tab has been - // closed. The docShell is gone now and we can just return here as there - // is nothing to do. - if (!this.mm.docShell) { - return; - } - - this.cleanupTimers(); - - let flushID = (options && options.flushID) || 0; - let histID = "FX_SESSION_RESTORE_CONTENT_COLLECT_DATA_MS"; - - let data = {}; - for (let [key, func] of this._data) { - if (key != "isPrivate") { - TelemetryStopwatch.startKeyed(histID, key); - } - - let value = func(); - - if (key != "isPrivate") { - TelemetryStopwatch.finishKeyed(histID, key); - } - - if (value || (key != "storagechange" && key != "historychange")) { - data[key] = value; - } - } - - this._data.clear(); - - try { - // Send all data to the parent process. - this.mm.sendAsyncMessage("SessionStore:update", { - data, - flushID, - isFinal: options.isFinal || false, - epoch: this.store.epoch, - }); - } catch (ex) { - if (ex && ex.result == Cr.NS_ERROR_OUT_OF_MEMORY) { - Services.telemetry - .getHistogramById("FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM") - .add(1); - this.mm.sendAsyncMessage("SessionStore:error"); - } - } - } -} - -/** - * Listens for and handles messages sent by the session store service. - */ -const MESSAGES = [ - "SessionStore:restoreHistory", - "SessionStore:restoreTabContent", - "SessionStore:resetRestore", - "SessionStore:flush", - "SessionStore:prepareForProcessChange", -]; - -export class ContentSessionStore { - constructor(mm) { - if (Services.appinfo.sessionHistoryInParent) { - throw new Error("This frame script should not be loaded for SHIP"); - } - - this.mm = mm; - this.messageQueue = new MessageQueue(this); - - this.epoch = 0; - - this.contentRestoreInitialized = false; - - this.handlers = [ - this.messageQueue, - new EventListener(this), - new SessionHistoryListener(this), - ]; - - ChromeUtils.defineLazyGetter(this, "contentRestore", () => { - this.contentRestoreInitialized = true; - return new lazy.ContentRestore(mm); - }); - - MESSAGES.forEach(m => mm.addMessageListener(m, this)); - - mm.addEventListener("unload", this); - } - - receiveMessage({ name, data }) { - // The docShell might be gone. Don't process messages, - // that will just lead to errors anyway. - if (!this.mm.docShell) { - return; - } - - // A fresh tab always starts with epoch=0. The parent has the ability to - // override that to signal a new era in this tab's life. This enables it - // to ignore async messages that were already sent but not yet received - // and would otherwise confuse the internal tab state. - if (data && data.epoch && data.epoch != this.epoch) { - this.epoch = data.epoch; - } - - switch (name) { - case "SessionStore:restoreHistory": - this.restoreHistory(data); - break; - case "SessionStore:restoreTabContent": - this.restoreTabContent(data); - break; - case "SessionStore:resetRestore": - this.contentRestore.resetRestore(); - break; - case "SessionStore:flush": - this.flush(data); - break; - case "SessionStore:prepareForProcessChange": - // During normal in-process navigations, the DocShell would take - // care of automatically persisting layout history state to record - // scroll positions on the nsSHEntry. Unfortunately, process switching - // is not a normal navigation, so for now we do this ourselves. This - // is a workaround until session history state finally lives in the - // parent process. - this.mm.docShell.persistLayoutHistoryState(); - break; - default: - console.error("received unknown message '" + name + "'"); - break; - } - } - - // non-SHIP only - restoreHistory(data) { - let { epoch, tabData, loadArguments, isRemotenessUpdate } = data; - - this.contentRestore.restoreHistory(tabData, loadArguments, { - // Note: The callbacks passed here will only be used when a load starts - // that was not initiated by sessionstore itself. This can happen when - // some code calls browser.loadURI() or browser.reload() on a pending - // browser/tab. - - onLoadStarted: () => { - // Notify the parent that the tab is no longer pending. - this.mm.sendAsyncMessage("SessionStore:restoreTabContentStarted", { - epoch, - }); - }, - - onLoadFinished: () => { - // Tell SessionStore.sys.mjs that it may want to restore some more tabs, - // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time. - this.mm.sendAsyncMessage("SessionStore:restoreTabContentComplete", { - epoch, - }); - }, - }); - - if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_DEFAULT) { - // For non-remote tabs, when restoreHistory finishes, we send a synchronous - // message to SessionStore.sys.mjs so that it can run SSTabRestoring. Users of - // SSTabRestoring seem to get confused if chrome and content are out of - // sync about the state of the restore (particularly regarding - // docShell.currentURI). Using a synchronous message is the easiest way - // to temporarily synchronize them. - // - // For remote tabs, because all nsIWebProgress notifications are sent - // asynchronously using messages, we get the same-order guarantees of the - // message manager, and can use an async message. - this.mm.sendSyncMessage("SessionStore:restoreHistoryComplete", { - epoch, - isRemotenessUpdate, - }); - } else { - this.mm.sendAsyncMessage("SessionStore:restoreHistoryComplete", { - epoch, - isRemotenessUpdate, - }); - } - } - - restoreTabContent({ loadArguments, isRemotenessUpdate, reason }) { - let epoch = this.epoch; - - // We need to pass the value of didStartLoad back to SessionStore.sys.mjs. - let didStartLoad = this.contentRestore.restoreTabContent( - loadArguments, - isRemotenessUpdate, - () => { - // Tell SessionStore.sys.mjs that it may want to restore some more tabs, - // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time. - this.mm.sendAsyncMessage("SessionStore:restoreTabContentComplete", { - epoch, - isRemotenessUpdate, - }); - } - ); - - this.mm.sendAsyncMessage("SessionStore:restoreTabContentStarted", { - epoch, - isRemotenessUpdate, - reason, - }); - - if (!didStartLoad) { - // Pretend that the load succeeded so that event handlers fire correctly. - this.mm.sendAsyncMessage("SessionStore:restoreTabContentComplete", { - epoch, - isRemotenessUpdate, - }); - } - } - - flush({ id }) { - // Flush the message queue, send the latest updates. - this.messageQueue.send({ flushID: id }); - } - - handleEvent(event) { - if (event.type == "unload") { - this.onUnload(); - } - } - - onUnload() { - // Upon frameLoader destruction, send a final update message to - // the parent and flush all data currently held in the child. - this.messageQueue.send({ isFinal: true }); - - for (let handler of this.handlers) { - if (handler.uninit) { - handler.uninit(); - } - } - - if (this.contentRestoreInitialized) { - // Remove progress listeners. - this.contentRestore.resetRestore(); - } - - // We don't need to take care of any StateChangeNotifier observers as they - // will die with the content script. The same goes for the privacy transition - // observer that will die with the docShell when the tab is closed. - } -} diff --git a/browser/components/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.sys.mjs b/browser/components/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.sys.mjs index 4d53b166c0..d0627180f0 100644 --- a/browser/components/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.sys.mjs +++ b/browser/components/sessionstore/RecentlyClosedTabsAndWindowsMenuUtils.sys.mjs @@ -182,7 +182,7 @@ export var RecentlyClosedTabsAndWindowsMenuUtils = { * @param aEvent * The command event when the user clicks the restore all menu item */ - onRestoreAllWindowsCommand(aEvent) { + onRestoreAllWindowsCommand() { const count = lazy.SessionStore.getClosedWindowCount(); for (let index = 0; index < count; index++) { lazy.SessionStore.undoCloseWindow(index); @@ -265,7 +265,7 @@ function createEntry( element.removeAttribute("oncommand"); element.addEventListener( "command", - event => { + () => { lazy.SessionStore.undoClosedTabFromClosedWindow( { sourceClosedId }, aClosedTab.closedId diff --git a/browser/components/sessionstore/SessionFile.sys.mjs b/browser/components/sessionstore/SessionFile.sys.mjs index 1e5a3bf718..077529d739 100644 --- a/browser/components/sessionstore/SessionFile.sys.mjs +++ b/browser/components/sessionstore/SessionFile.sys.mjs @@ -194,6 +194,7 @@ var SessionFileInternal = { }, async _readInternal(useOldExtension) { + Services.telemetry.setEventRecordingEnabled("session_restore", true); let result; let noFilesFound = true; this._usingOldExtension = useOldExtension; @@ -251,6 +252,18 @@ var SessionFileInternal = { path, ". Wrong format/version: " + JSON.stringify(parsed.version) + "." ); + Services.telemetry.recordEvent( + "session_restore", + "backup_can_be_loaded", + "session_file", + null, + { + can_load: "false", + path_key: key, + loadfail_reason: + "Wrong format/version: " + JSON.stringify(parsed.version) + ".", + } + ); continue; } result = { @@ -259,6 +272,17 @@ var SessionFileInternal = { parsed, useOldExtension, }; + Services.telemetry.recordEvent( + "session_restore", + "backup_can_be_loaded", + "session_file", + null, + { + can_load: "true", + path_key: key, + loadfail_reason: "N/A", + } + ); Services.telemetry .getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE") .add(false); @@ -269,6 +293,17 @@ var SessionFileInternal = { } catch (ex) { if (DOMException.isInstance(ex) && ex.name == "NotFoundError") { exists = false; + Services.telemetry.recordEvent( + "session_restore", + "backup_can_be_loaded", + "session_file", + null, + { + can_load: "false", + path_key: key, + loadfail_reason: "File doesn't exist.", + } + ); } else if ( DOMException.isInstance(ex) && ex.name == "NotAllowedError" @@ -277,6 +312,17 @@ var SessionFileInternal = { // or similar failures. We'll just count it as "corrupted". console.error("Could not read session file ", ex); corrupted = true; + Services.telemetry.recordEvent( + "session_restore", + "backup_can_be_loaded", + "session_file", + null, + { + can_load: "false", + path_key: key, + loadfail_reason: ` ${ex.name}: Could not read session file`, + } + ); } else if (ex instanceof SyntaxError) { console.error( "Corrupt session file (invalid JSON found) ", @@ -285,6 +331,17 @@ var SessionFileInternal = { ); // File is corrupted, try next file corrupted = true; + Services.telemetry.recordEvent( + "session_restore", + "backup_can_be_loaded", + "session_file", + null, + { + can_load: "false", + path_key: key, + loadfail_reason: ` ${ex.name}: Corrupt session file (invalid JSON found)`, + } + ); } } finally { if (exists) { @@ -292,6 +349,17 @@ var SessionFileInternal = { Services.telemetry .getHistogramById("FX_SESSION_RESTORE_CORRUPT_FILE") .add(corrupted); + Services.telemetry.recordEvent( + "session_restore", + "backup_can_be_loaded", + "session_file", + null, + { + can_load: (!corrupted).toString(), + path_key: key, + loadfail_reason: "N/A", + } + ); } } } diff --git a/browser/components/sessionstore/SessionSaver.sys.mjs b/browser/components/sessionstore/SessionSaver.sys.mjs index 2f08bb2243..1237e3f970 100644 --- a/browser/components/sessionstore/SessionSaver.sys.mjs +++ b/browser/components/sessionstore/SessionSaver.sys.mjs @@ -210,7 +210,7 @@ var SessionSaverInternal = { /** * Observe idle/ active notifications. */ - observe(subject, topic, data) { + observe(subject, topic) { switch (topic) { case "idle": this._isIdle = true; diff --git a/browser/components/sessionstore/SessionStartup.sys.mjs b/browser/components/sessionstore/SessionStartup.sys.mjs index ff3ba55176..0d017ac035 100644 --- a/browser/components/sessionstore/SessionStartup.sys.mjs +++ b/browser/components/sessionstore/SessionStartup.sys.mjs @@ -158,6 +158,11 @@ export var SessionStartup = { */ _onSessionFileRead({ source, parsed, noFilesFound }) { this._initialized = true; + const crashReasons = { + FINAL_STATE_WRITING_INCOMPLETE: "final-state-write-incomplete", + SESSION_STATE_FLAG_MISSING: + "session-state-missing-or-running-at-last-write", + }; // Let observers modify the state before it is used let supportsStateString = this._createSupportsString(source); @@ -210,12 +215,17 @@ export var SessionStartup = { delete this._initialState.lastSessionState; } + let previousSessionCrashedReason = "N/A"; lazy.CrashMonitor.previousCheckpoints.then(checkpoints => { if (checkpoints) { // If the previous session finished writing the final state, we'll // assume there was no crash. this._previousSessionCrashed = !checkpoints["sessionstore-final-state-write-complete"]; + if (!checkpoints["sessionstore-final-state-write-complete"]) { + previousSessionCrashedReason = + crashReasons.FINAL_STATE_WRITING_INCOMPLETE; + } } else if (noFilesFound) { // If the Crash Monitor could not load a checkpoints file it will // provide null. This could occur on the first run after updating to @@ -241,6 +251,13 @@ export var SessionStartup = { this._previousSessionCrashed = !stateFlagPresent || this._initialState.session.state == STATE_RUNNING_STR; + if ( + !stateFlagPresent || + this._initialState.session.state == STATE_RUNNING_STR + ) { + previousSessionCrashedReason = + crashReasons.SESSION_STATE_FLAG_MISSING; + } } // Report shutdown success via telemetry. Shortcoming here are @@ -249,6 +266,16 @@ export var SessionStartup = { Services.telemetry .getHistogramById("SHUTDOWN_OK") .add(!this._previousSessionCrashed); + Services.telemetry.recordEvent( + "session_restore", + "shutdown_success", + "session_startup", + null, + { + shutdown_ok: this._previousSessionCrashed.toString(), + shutdown_reason: previousSessionCrashedReason, + } + ); Services.obs.addObserver(this, "sessionstore-windows-restored", true); @@ -268,7 +295,7 @@ export var SessionStartup = { /** * Handle notifications */ - observe(subject, topic, data) { + observe(subject, topic) { switch (topic) { case "sessionstore-windows-restored": Services.obs.removeObserver(this, "sessionstore-windows-restored"); diff --git a/browser/components/sessionstore/SessionStore.sys.mjs b/browser/components/sessionstore/SessionStore.sys.mjs index f269251f54..16137b8388 100644 --- a/browser/components/sessionstore/SessionStore.sys.mjs +++ b/browser/components/sessionstore/SessionStore.sys.mjs @@ -109,59 +109,6 @@ const WINDOW_OPEN_FEATURES_MAP = { statusbar: "status", }; -// Messages that will be received via the Frame Message Manager. -const MESSAGES = [ - // The content script sends us data that has been invalidated and needs to - // be saved to disk. - "SessionStore:update", - - // The restoreHistory code has run. This is a good time to run SSTabRestoring. - "SessionStore:restoreHistoryComplete", - - // The load for the restoring tab has begun. We update the URL bar at this - // time; if we did it before, the load would overwrite it. - "SessionStore:restoreTabContentStarted", - - // All network loads for a restoring tab are done, so we should - // consider restoring another tab in the queue. The document has - // been restored, and forms have been filled. We trigger - // SSTabRestored at this time. - "SessionStore:restoreTabContentComplete", - - // The content script encountered an error. - "SessionStore:error", -]; - -// The list of messages we accept from <xul:browser>s that have no tab -// assigned, or whose windows have gone away. Those are for example the -// ones that preload about:newtab pages, or from browsers where the window -// has just been closed. -const NOTAB_MESSAGES = new Set([ - // For a description see above. - "SessionStore:update", - - // For a description see above. - "SessionStore:error", -]); - -// The list of messages we accept without an "epoch" parameter. -// See getCurrentEpoch() and friends to find out what an "epoch" is. -const NOEPOCH_MESSAGES = new Set([ - // For a description see above. - "SessionStore:error", -]); - -// The list of messages we want to receive even during the short period after a -// frame has been removed from the DOM and before its frame script has finished -// unloading. -const CLOSED_MESSAGES = new Set([ - // For a description see above. - "SessionStore:update", - - // For a description see above. - "SessionStore:error", -]); - // These are tab events that we listen to. const TAB_EVENTS = [ "TabOpen", @@ -645,10 +592,6 @@ export var SessionStore = { SessionStoreInternal.deleteCustomGlobalValue(aKey); }, - persistTabAttribute: function ss_persistTabAttribute(aName) { - SessionStoreInternal.persistTabAttribute(aName); - }, - restoreLastSession: function ss_restoreLastSession() { SessionStoreInternal.restoreLastSession(); }, @@ -813,18 +756,6 @@ export var SessionStore = { }, /** - * Prepares to change the remoteness of the given browser, by ensuring that - * the local instance of session history is up-to-date. - */ - async prepareToChangeRemoteness(aTab) { - await SessionStoreInternal.prepareToChangeRemoteness(aTab); - }, - - finishTabRemotenessChange(aTab, aSwitchId) { - SessionStoreInternal.finishTabRemotenessChange(aTab, aSwitchId); - }, - - /** * Clear session store data for a given private browsing window. * @param {ChromeWindow} win - Open private browsing window to clear data for. */ @@ -1354,8 +1285,6 @@ var SessionStoreInternal = { "privacy.resistFingerprinting" ); Services.prefs.addObserver("privacy.resistFingerprinting", this); - - this._shistoryInParent = Services.appinfo.sessionHistoryInParent; }, /** @@ -1434,33 +1363,26 @@ var SessionStoreInternal = { } break; case "browsing-context-did-set-embedder": - if (Services.appinfo.sessionHistoryInParent) { - if ( - aSubject && - aSubject === aSubject.top && - aSubject.isContent && - aSubject.embedderElement && - aSubject.embedderElement.permanentKey - ) { - let permanentKey = aSubject.embedderElement.permanentKey; - this._browserSHistoryListener.get(permanentKey)?.unregister(); - this.getOrCreateSHistoryListener(permanentKey, aSubject, true); - } + if ( + aSubject && + aSubject === aSubject.top && + aSubject.isContent && + aSubject.embedderElement && + aSubject.embedderElement.permanentKey + ) { + let permanentKey = aSubject.embedderElement.permanentKey; + this._browserSHistoryListener.get(permanentKey)?.unregister(); + this.getOrCreateSHistoryListener(permanentKey, aSubject, true); } break; case "browsing-context-discarded": - if (Services.appinfo.sessionHistoryInParent) { - let permanentKey = aSubject?.embedderElement?.permanentKey; - if (permanentKey) { - this._browserSHistoryListener.get(permanentKey)?.unregister(); - } + let permanentKey = aSubject?.embedderElement?.permanentKey; + if (permanentKey) { + this._browserSHistoryListener.get(permanentKey)?.unregister(); } break; case "browser-shutdown-tabstate-updated": - if (Services.appinfo.sessionHistoryInParent) { - // Non-SHIP code calls this when the frame script is unloaded. - this.onFinalTabStateUpdateComplete(aSubject); - } + this.onFinalTabStateUpdateComplete(aSubject); this._notifyOfClosedObjectsChange(); break; } @@ -1573,10 +1495,6 @@ var SessionStoreInternal = { } } - if (!Services.appinfo.sessionHistoryInParent) { - throw new Error("This function should only be used with SHIP"); - } - if (!permanentKey || browsingContext !== browsingContext.top) { return null; } @@ -1691,29 +1609,27 @@ var SessionStoreInternal = { return; } - if (Services.appinfo.sessionHistoryInParent) { - let listener = this.getOrCreateSHistoryListener( - permanentKey, - browsingContext - ); + let listener = this.getOrCreateSHistoryListener( + permanentKey, + browsingContext + ); - if (listener) { - let historychange = - // If it is not the scheduled update (tab closed, window closed etc), - // try to store the loading non-web-controlled page opened in _blank - // first. - (forStorage && - lazy.SessionHistory.collectNonWebControlledBlankLoadingSession( - browsingContext - )) || - listener.collect(permanentKey, browsingContext, { - collectFull: !!update.sHistoryNeeded, - writeToCache: false, - }); + if (listener) { + let historychange = + // If it is not the scheduled update (tab closed, window closed etc), + // try to store the loading non-web-controlled page opened in _blank + // first. + (forStorage && + lazy.SessionHistory.collectNonWebControlledBlankLoadingSession( + browsingContext + )) || + listener.collect(permanentKey, browsingContext, { + collectFull: !!update.sHistoryNeeded, + writeToCache: false, + }); - if (historychange) { - update.data.historychange = historychange; - } + if (historychange) { + update.data.historychange = historychange; } } @@ -1724,98 +1640,6 @@ var SessionStoreInternal = { this.onTabStateUpdate(permanentKey, win, update); }, - /** - * This method handles incoming messages sent by the session store content - * script via the Frame Message Manager or Parent Process Message Manager, - * and thus enables communication with OOP tabs. - */ - receiveMessage(aMessage) { - if (Services.appinfo.sessionHistoryInParent) { - throw new Error( - `received unexpected message '${aMessage.name}' with ` + - `sessionHistoryInParent enabled` - ); - } - - // If we got here, that means we're dealing with a frame message - // manager message, so the target will be a <xul:browser>. - var browser = aMessage.target; - let win = browser.ownerGlobal; - let tab = win ? win.gBrowser.getTabForBrowser(browser) : null; - - // Ensure we receive only specific messages from <xul:browser>s that - // have no tab or window assigned, e.g. the ones that preload - // about:newtab pages, or windows that have closed. - if (!tab && !NOTAB_MESSAGES.has(aMessage.name)) { - throw new Error( - `received unexpected message '${aMessage.name}' ` + - `from a browser that has no tab or window` - ); - } - - let data = aMessage.data || {}; - let hasEpoch = data.hasOwnProperty("epoch"); - - // Most messages sent by frame scripts require to pass an epoch. - if (!hasEpoch && !NOEPOCH_MESSAGES.has(aMessage.name)) { - throw new Error(`received message '${aMessage.name}' without an epoch`); - } - - // Ignore messages from previous epochs. - if (hasEpoch && !this.isCurrentEpoch(browser.permanentKey, data.epoch)) { - return; - } - - switch (aMessage.name) { - case "SessionStore:update": - // |browser.frameLoader| might be empty if the browser was already - // destroyed and its tab removed. In that case we still have the last - // frameLoader we know about to compare. - let frameLoader = - browser.frameLoader || - this._lastKnownFrameLoader.get(browser.permanentKey); - - // If the message isn't targeting the latest frameLoader discard it. - if (frameLoader != aMessage.targetFrameLoader) { - return; - } - - this.onTabStateUpdate(browser.permanentKey, browser.ownerGlobal, data); - - // SHIP code will call this when it receives "browser-shutdown-tabstate-updated" - if (data.isFinal) { - if (!Services.appinfo.sessionHistoryInParent) { - this.onFinalTabStateUpdateComplete(browser); - } - } else if (data.flushID) { - // This is an update kicked off by an async flush request. Notify the - // TabStateFlusher so that it can finish the request and notify its - // consumer that's waiting for the flush to be done. - lazy.TabStateFlusher.resolve(browser, data.flushID); - } - - break; - case "SessionStore:restoreHistoryComplete": - this._restoreHistoryComplete(browser, data); - break; - case "SessionStore:restoreTabContentStarted": - this._restoreTabContentStarted(browser, data); - break; - case "SessionStore:restoreTabContentComplete": - this._restoreTabContentComplete(browser, data); - break; - case "SessionStore:error": - lazy.TabStateFlusher.resolveAll( - browser, - false, - "Received error from the content process" - ); - break; - default: - throw new Error(`received unknown message '${aMessage.name}'`); - } - }, - /* ........ Window Event Handlers .............. */ /** @@ -1917,21 +1741,6 @@ var SessionStoreInternal = { // internal data about the window. aWindow.__SSi = this._generateWindowID(); - if (!Services.appinfo.sessionHistoryInParent) { - let mm = aWindow.getGroupMessageManager("browsers"); - MESSAGES.forEach(msg => { - let listenWhenClosed = CLOSED_MESSAGES.has(msg); - mm.addMessageListener(msg, this, listenWhenClosed); - }); - - // Load the frame script after registering listeners. - mm.loadFrameScript( - "chrome://browser/content/content-sessionStore.js", - true, - true - ); - } - // and create its data object this._windows[aWindow.__SSi] = { tabs: [], @@ -2347,7 +2156,7 @@ var SessionStoreInternal = { // Save non-private windows if they have at // least one saveable tab or are the last window. if (!winData.isPrivate) { - this.maybeSaveClosedWindow(winData, isLastWindow, true); + this.maybeSaveClosedWindow(winData, isLastWindow); if (!isLastWindow && winData.closedId > -1) { this._addClosedAction( @@ -2402,11 +2211,6 @@ var SessionStoreInternal = { // Cache the window state until it is completely gone. DyingWindowCache.set(aWindow, winData); - if (!Services.appinfo.sessionHistoryInParent) { - let mm = aWindow.getGroupMessageManager("browsers"); - MESSAGES.forEach(msg => mm.removeMessageListener(msg, this)); - } - this._saveableClosedWindowData.delete(winData); delete aWindow.__SSi; }, @@ -2428,7 +2232,7 @@ var SessionStoreInternal = { * to call this method again asynchronously (for example, after * a window flush). */ - maybeSaveClosedWindow(winData, isLastWindow, recordTelemetry = false) { + maybeSaveClosedWindow(winData, isLastWindow) { // Make sure SessionStore is still running, and make sure that we // haven't chosen to forget this window. if ( @@ -2489,13 +2293,9 @@ var SessionStoreInternal = { this._removeClosedWindow(winIndex); return; } - // we only do this after the TabStateFlusher promise resolves in ssi_onClose - if (recordTelemetry) { - let closedTabsHistogram = Services.telemetry.getHistogramById( - "FX_SESSION_RESTORE_CLOSED_TABS_NOT_SAVED" - ); - closedTabsHistogram.add(winData._closedTabs.length); - } + this._log.warn( + `Discarding window with 0 saveable tabs and ${winData._closedTabs.length} closed tabs` + ); } } }, @@ -3644,7 +3444,7 @@ var SessionStoreInternal = { } // Create a new tab. - let userContextId = aTab.getAttribute("usercontextid"); + let userContextId = aTab.getAttribute("usercontextid") || ""; let tabOptions = { userContextId, @@ -4273,12 +4073,6 @@ var SessionStoreInternal = { this.saveStateDelayed(); }, - persistTabAttribute: function ssi_persistTabAttribute(aName) { - if (lazy.TabAttributes.persist(aName)) { - this.saveStateDelayed(); - } - }, - /** * Undoes the closing of a tab or window which corresponds * to the closedId passed in. @@ -5480,13 +5274,6 @@ var SessionStoreInternal = { tab.updateLastAccessed(tabData.lastAccessed); } - if ("attributes" in tabData) { - // Ensure that we persist tab attributes restored from previous sessions. - Object.keys(tabData.attributes).forEach(a => - lazy.TabAttributes.persist(a) - ); - } - if (!tabData.entries) { tabData.entries = []; } @@ -5656,7 +5443,6 @@ var SessionStoreInternal = { let browser = aTab.linkedBrowser; let window = aTab.ownerGlobal; - let tabbrowser = window.gBrowser; let tabData = lazy.TabState.clone(aTab, TAB_CUSTOM_VALUES.get(aTab)); let activeIndex = tabData.index - 1; let activePageData = tabData.entries[activeIndex] || null; @@ -5664,36 +5450,9 @@ var SessionStoreInternal = { this.markTabAsRestoring(aTab); - let isRemotenessUpdate = aOptions.isRemotenessUpdate; - let explicitlyUpdateRemoteness = !Services.appinfo.sessionHistoryInParent; - // If we aren't already updating the browser's remoteness, check if it's - // necessary. - if (explicitlyUpdateRemoteness && !isRemotenessUpdate) { - isRemotenessUpdate = tabbrowser.updateBrowserRemotenessByURL( - browser, - uri - ); - - if (isRemotenessUpdate) { - // We updated the remoteness, so we need to send the history down again. - // - // Start a new epoch to discard all frame script messages relating to a - // previous epoch. All async messages that are still on their way to chrome - // will be ignored and don't override any tab data set when restoring. - let epoch = this.startNextEpoch(browser.permanentKey); - - this._sendRestoreHistory(browser, { - tabData, - epoch, - loadArguments, - isRemotenessUpdate, - }); - } - } - this._sendRestoreTabContent(browser, { loadArguments, - isRemotenessUpdate, + isRemotenessUpdate: aOptions.isRemotenessUpdate, reason: aOptions.restoreContentReason || RESTORE_TAB_CONTENT_REASON.SET_STATE, }); @@ -6828,10 +6587,8 @@ var SessionStoreInternal = { // The browser is no longer in any sort of restoring state. TAB_STATE_FOR_BROWSER.delete(browser); - if (Services.appinfo.sessionHistoryInParent) { - this._restoreListeners.get(browser.permanentKey)?.unregister(); - browser.browsingContext.clearRestoreState(); - } + this._restoreListeners.get(browser.permanentKey)?.unregister(); + browser.browsingContext.clearRestoreState(); aTab.removeAttribute("pending"); @@ -6855,9 +6612,6 @@ var SessionStoreInternal = { return; } - if (!Services.appinfo.sessionHistoryInParent) { - browser.messageManager.sendAsyncMessage("SessionStore:resetRestore", {}); - } this._resetLocalTabRestoringState(tab); }, @@ -7048,7 +6802,7 @@ var SessionStoreInternal = { } catch {} // May have already gotten rid of the browser's webProgress. }, - onStateChange(webProgress, request, stateFlags, status) { + onStateChange(webProgress, request, stateFlags) { if ( webProgress.isTopLevel && stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW && @@ -7109,7 +6863,7 @@ var SessionStoreInternal = { OnHistoryPurge() {}, OnHistoryReplaceEntry() {}, - onStateChange(webProgress, request, stateFlags, status) { + onStateChange(webProgress, request, stateFlags) { if ( webProgress.isTopLevel && stateFlags & Ci.nsIWebProgressListener.STATE_IS_WINDOW && @@ -7143,10 +6897,6 @@ var SessionStoreInternal = { * history restores. */ _restoreHistory(browser, data) { - if (!Services.appinfo.sessionHistoryInParent) { - throw new Error("This function should only be used with SHIP"); - } - this._tabStateToRestore.set(browser.permanentKey, data); // In case about:blank isn't done yet. @@ -7190,7 +6940,7 @@ var SessionStoreInternal = { this._tabStateRestorePromises.delete(browser.permanentKey); - this._restoreHistoryComplete(browser, data); + this._restoreHistoryComplete(browser); }; promise.then(onResolve).catch(() => {}); @@ -7238,10 +6988,6 @@ var SessionStoreInternal = { * history restores. */ _restoreTabContent(browser, options = {}) { - if (!Services.appinfo.sessionHistoryInParent) { - throw new Error("This function should only be used with SHIP"); - } - this._restoreListeners.get(browser.permanentKey)?.unregister(); this._restoreTabContentStarted(browser, options); @@ -7266,17 +7012,10 @@ var SessionStoreInternal = { }, _sendRestoreTabContent(browser, options) { - if (Services.appinfo.sessionHistoryInParent) { - this._restoreTabContent(browser, options); - } else { - browser.messageManager.sendAsyncMessage( - "SessionStore:restoreTabContent", - options - ); - } + this._restoreTabContent(browser, options); }, - _restoreHistoryComplete(browser, data) { + _restoreHistoryComplete(browser) { let win = browser.ownerGlobal; let tab = win?.gBrowser.getTabForBrowser(browser); if (!tab) { @@ -7417,68 +7156,12 @@ var SessionStoreInternal = { delete options.tabData.storage; } - if (Services.appinfo.sessionHistoryInParent) { - this._restoreHistory(browser, options); - } else { - browser.messageManager.sendAsyncMessage( - "SessionStore:restoreHistory", - options - ); - } + this._restoreHistory(browser, options); if (browser && browser.frameLoader) { browser.frameLoader.requestEpochUpdate(options.epoch); } }, - - // Flush out session history state so that it can be used to restore the state - // into a new process in `finishTabRemotenessChange`. - // - // NOTE: This codepath is temporary while the Fission Session History rewrite - // is in process, and will be removed & replaced once that rewrite is - // complete. (bug 1645062) - async prepareToChangeRemoteness(aBrowser) { - aBrowser.messageManager.sendAsyncMessage( - "SessionStore:prepareForProcessChange" - ); - await lazy.TabStateFlusher.flush(aBrowser); - }, - - // Handle finishing the remoteness change for a tab by restoring session - // history state into it, and resuming the ongoing network load. - // - // NOTE: This codepath is temporary while the Fission Session History rewrite - // is in process, and will be removed & replaced once that rewrite is - // complete. (bug 1645062) - finishTabRemotenessChange(aTab, aSwitchId) { - let window = aTab.ownerGlobal; - if (!window || !window.__SSi || window.closed) { - return; - } - - let tabState = lazy.TabState.clone(aTab, TAB_CUSTOM_VALUES.get(aTab)); - let options = { - restoreImmediately: true, - restoreContentReason: RESTORE_TAB_CONTENT_REASON.NAVIGATE_AND_RESTORE, - isRemotenessUpdate: true, - loadArguments: { - redirectLoadSwitchId: aSwitchId, - // As we're resuming a load which has been redirected from another - // process, record the history index which is currently being requested. - // It has to be offset by 1 to get back to native history indices from - // SessionStore history indicies. - redirectHistoryIndex: tabState.requestedIndex - 1, - }, - }; - - // Need to reset restoring tabs. - if (TAB_STATE_FOR_BROWSER.has(aTab.linkedBrowser)) { - this._resetLocalTabRestoringState(aTab); - } - - // Restore the state into the tab. - this.restoreTab(aTab, tabState, options); - }, }; /** @@ -7689,7 +7372,7 @@ var DirtyWindows = { this._data.delete(window); }, - clear(window) { + clear(_window) { this._data = new WeakMap(); }, }; diff --git a/browser/components/sessionstore/StartupPerformance.sys.mjs b/browser/components/sessionstore/StartupPerformance.sys.mjs index a13333d9d1..c2b791609b 100644 --- a/browser/components/sessionstore/StartupPerformance.sys.mjs +++ b/browser/components/sessionstore/StartupPerformance.sys.mjs @@ -153,7 +153,7 @@ export var StartupPerformance = { }, COLLECT_RESULTS_AFTER_MS); }, - observe(subject, topic, details) { + observe(subject, topic) { try { switch (topic) { case "sessionstore-restoring-on-startup": diff --git a/browser/components/sessionstore/TabAttributes.sys.mjs b/browser/components/sessionstore/TabAttributes.sys.mjs index 1c7f54b6ab..ea53156d12 100644 --- a/browser/components/sessionstore/TabAttributes.sys.mjs +++ b/browser/components/sessionstore/TabAttributes.sys.mjs @@ -2,27 +2,13 @@ * 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/. */ -// We never want to directly read or write these attributes. -// 'image' should not be accessed directly but handled by using the -// gBrowser.getIcon()/setIcon() methods. -// 'muted' should not be accessed directly but handled by using the -// tab.linkedBrowser.audioMuted/toggleMuteAudio methods. -// 'pending' is used internal by sessionstore and managed accordingly. -const ATTRIBUTES_TO_SKIP = new Set([ - "image", - "muted", - "pending", - "skipbackgroundnotify", -]); +// Tab attributes which are persisted & restored by SessionStore. +const PERSISTED_ATTRIBUTES = ["customizemode"]; // A set of tab attributes to persist. We will read a given list of tab // attributes when collecting tab data and will re-set those attributes when // the given tab data is restored to a new tab. export var TabAttributes = Object.freeze({ - persist(name) { - return TabAttributesInternal.persist(name); - }, - get(tab) { return TabAttributesInternal.get(tab); }, @@ -33,21 +19,10 @@ export var TabAttributes = Object.freeze({ }); var TabAttributesInternal = { - _attrs: new Set(), - - persist(name) { - if (this._attrs.has(name) || ATTRIBUTES_TO_SKIP.has(name)) { - return false; - } - - this._attrs.add(name); - return true; - }, - get(tab) { let data = {}; - for (let name of this._attrs) { + for (let name of PERSISTED_ATTRIBUTES) { if (tab.hasAttribute(name)) { data[name] = tab.getAttribute(name); } @@ -57,15 +32,11 @@ var TabAttributesInternal = { }, set(tab, data = {}) { - // Clear attributes. - for (let name of this._attrs) { + // Clear & Set attributes. + for (let name of PERSISTED_ATTRIBUTES) { tab.removeAttribute(name); - } - - // Set attributes. - for (let [name, value] of Object.entries(data)) { - if (!ATTRIBUTES_TO_SKIP.has(name)) { - tab.setAttribute(name, value); + if (name in data) { + tab.setAttribute(name, data[name]); } } }, diff --git a/browser/components/sessionstore/TabStateFlusher.sys.mjs b/browser/components/sessionstore/TabStateFlusher.sys.mjs index e391abc970..ed7953e41e 100644 --- a/browser/components/sessionstore/TabStateFlusher.sys.mjs +++ b/browser/components/sessionstore/TabStateFlusher.sys.mjs @@ -2,11 +2,6 @@ * 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 lazy = {}; -ChromeUtils.defineESModuleGetters(lazy, { - SessionStore: "resource:///modules/sessionstore/SessionStore.sys.mjs", -}); - /** * A module that enables async flushes. Updates from frame scripts are * throttled to be sent only once per second. If an action wants a tab's latest @@ -33,23 +28,6 @@ export var TabStateFlusher = Object.freeze({ }, /** - * Resolves the flush request with the given flush ID. - * - * @param browser (<xul:browser>) - * The browser for which the flush is being resolved. - * @param flushID (int) - * The ID of the flush that was sent to the browser. - * @param success (bool, optional) - * Whether or not the flush succeeded. - * @param message (string, optional) - * An error message that will be sent to the Console in the - * event that a flush failed. - */ - resolve(browser, flushID, success = true, message = "") { - TabStateFlusherInternal.resolve(browser, flushID, success, message); - }, - - /** * Resolves all active flush requests for a given browser. This should be * used when the content process crashed or the final update message was * seen. In those cases we can't guarantee to ever hear back from the frame @@ -69,9 +47,6 @@ export var TabStateFlusher = Object.freeze({ }); var TabStateFlusherInternal = { - // Stores the last request ID. - _lastRequestID: 0, - // A map storing all active requests per browser. A request is a // triple of a map containing all flush requests, a promise that // resolve when a request for a browser is canceled, and the @@ -79,7 +54,6 @@ var TabStateFlusherInternal = { _requests: new WeakMap(), initEntry(entry) { - entry.perBrowserRequests = new Map(); entry.cancelPromise = new Promise(resolve => { entry.cancel = resolve; }).then(result => { @@ -96,7 +70,6 @@ var TabStateFlusherInternal = { * all the latest data. */ flush(browser) { - let id = ++this._lastRequestID; let nativePromise = Promise.resolve(); if (browser && browser.frameLoader) { /* @@ -106,24 +79,6 @@ var TabStateFlusherInternal = { nativePromise = browser.frameLoader.requestTabStateFlush(); } - if (!Services.appinfo.sessionHistoryInParent) { - /* - In the event that we have to trigger a process switch and thus change - browser remoteness, session store needs to register and track the new - browser window loaded and to have message manager listener registered - ** before ** TabStateFlusher send "SessionStore:flush" message. This fixes - the race where we send the message before the message listener is - registered for it. - */ - lazy.SessionStore.ensureInitialized(browser.ownerGlobal); - - let mm = browser.messageManager; - mm.sendAsyncMessage("SessionStore:flush", { - id, - epoch: lazy.SessionStore.getCurrentEpoch(browser), - }); - } - // Retrieve active requests for given browser. let permanentKey = browser.permanentKey; let request = this._requests.get(permanentKey); @@ -134,22 +89,10 @@ var TabStateFlusherInternal = { this._requests.set(permanentKey, request); } - // Non-SHIP flushes resolve this after the "SessionStore:update" message. We - // don't use that message for SHIP, so it's fine to resolve the request - // immediately after the native promise resolves, since SessionStore will - // have processed all updates from this browser by that point. - let requestPromise = Promise.resolve(); - if (!Services.appinfo.sessionHistoryInParent) { - requestPromise = new Promise(resolve => { - // Store resolve() so that we can resolve the promise later. - request.perBrowserRequests.set(id, resolve); - }); - } - - return Promise.race([ - nativePromise.then(_ => requestPromise), - request.cancelPromise, - ]); + // It's fine to resolve the request immediately after the native promise + // resolves, since SessionStore will have processed all updates from this + // browser by that point. + return Promise.race([nativePromise, request.cancelPromise]); }, /** @@ -167,41 +110,6 @@ var TabStateFlusherInternal = { }, /** - * Resolves the flush request with the given flush ID. - * - * @param browser (<xul:browser>) - * The browser for which the flush is being resolved. - * @param flushID (int) - * The ID of the flush that was sent to the browser. - * @param success (bool, optional) - * Whether or not the flush succeeded. - * @param message (string, optional) - * An error message that will be sent to the Console in the - * event that a flush failed. - */ - resolve(browser, flushID, success = true, message = "") { - // Nothing to do if there are no pending flushes for the given browser. - if (!this._requests.has(browser.permanentKey)) { - return; - } - - // Retrieve active requests for given browser. - let { perBrowserRequests } = this._requests.get(browser.permanentKey); - if (!perBrowserRequests.has(flushID)) { - return; - } - - if (!success) { - console.error("Failed to flush browser: ", message); - } - - // Resolve the request with the given id. - let resolve = perBrowserRequests.get(flushID); - perBrowserRequests.delete(flushID); - resolve(success); - }, - - /** * Resolves all active flush requests for a given browser. This should be * used when the content process crashed or the final update message was * seen. In those cases we can't guarantee to ever hear back from the frame diff --git a/browser/components/sessionstore/content/aboutSessionRestore.js b/browser/components/sessionstore/content/aboutSessionRestore.js index 51bed7c51b..2dfa45d40f 100644 --- a/browser/components/sessionstore/content/aboutSessionRestore.js +++ b/browser/components/sessionstore/content/aboutSessionRestore.js @@ -204,7 +204,7 @@ function startNewSession() { ), }); } else { - getBrowserWindow().BrowserHome(); + getBrowserWindow().BrowserCommands.home(); } } @@ -325,31 +325,31 @@ var treeView = { setTree(treeBox) { this.treeBox = treeBox; }, - getCellText(idx, column) { + getCellText(idx) { return gTreeData[idx].label; }, isContainer(idx) { return "open" in gTreeData[idx]; }, - getCellValue(idx, column) { + getCellValue(idx) { return gTreeData[idx].checked; }, isContainerOpen(idx) { return gTreeData[idx].open; }, - isContainerEmpty(idx) { + isContainerEmpty() { return false; }, - isSeparator(idx) { + isSeparator() { return false; }, isSorted() { return false; }, - isEditable(idx, column) { + isEditable() { return false; }, - canDrop(idx, orientation, dt) { + canDrop() { return false; }, getLevel(idx) { @@ -438,10 +438,10 @@ var treeView = { return null; }, - cycleHeader(column) {}, - cycleCell(idx, column) {}, + cycleHeader() {}, + cycleCell() {}, selectionChanged() {}, - getColumnProperties(column) { + getColumnProperties() { return ""; }, }; diff --git a/browser/components/sessionstore/content/content-sessionStore.js b/browser/components/sessionstore/content/content-sessionStore.js deleted file mode 100644 index a4bdea0bdc..0000000000 --- a/browser/components/sessionstore/content/content-sessionStore.js +++ /dev/null @@ -1,13 +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/. */ - -/* eslint-env mozilla/frame-script */ - -"use strict"; - -const { ContentSessionStore } = ChromeUtils.importESModule( - "resource:///modules/sessionstore/ContentSessionStore.sys.mjs" -); - -void new ContentSessionStore(this); diff --git a/browser/components/sessionstore/jar.mn b/browser/components/sessionstore/jar.mn index 7e5bc07dc6..b31a4fb351 100644 --- a/browser/components/sessionstore/jar.mn +++ b/browser/components/sessionstore/jar.mn @@ -5,4 +5,3 @@ browser.jar: * content/browser/aboutSessionRestore.xhtml (content/aboutSessionRestore.xhtml) content/browser/aboutSessionRestore.js (content/aboutSessionRestore.js) - content/browser/content-sessionStore.js (content/content-sessionStore.js) diff --git a/browser/components/sessionstore/moz.build b/browser/components/sessionstore/moz.build index 1536826733..cd3a0ad6fc 100644 --- a/browser/components/sessionstore/moz.build +++ b/browser/components/sessionstore/moz.build @@ -5,14 +5,12 @@ # file, You can obtain one at http://mozilla.org/MPL/2.0/. XPCSHELL_TESTS_MANIFESTS += ["test/unit/xpcshell.toml"] -BROWSER_CHROME_MANIFESTS += ["test/browser.toml"] +BROWSER_CHROME_MANIFESTS += ["test/browser.toml", "test/browser_oldformat.toml"] MARIONETTE_MANIFESTS += ["test/marionette/manifest.toml"] JAR_MANIFESTS += ["jar.mn"] EXTRA_JS_MODULES.sessionstore = [ - "ContentRestore.sys.mjs", - "ContentSessionStore.sys.mjs", "GlobalState.sys.mjs", "RecentlyClosedTabsAndWindowsMenuUtils.sys.mjs", "RunState.sys.mjs", diff --git a/browser/components/sessionstore/test/SessionStoreTestUtils.sys.mjs b/browser/components/sessionstore/test/SessionStoreTestUtils.sys.mjs index dd2885cee4..eecb1240e2 100644 --- a/browser/components/sessionstore/test/SessionStoreTestUtils.sys.mjs +++ b/browser/components/sessionstore/test/SessionStoreTestUtils.sys.mjs @@ -100,7 +100,7 @@ export var SessionStoreTestUtils = { expectedTabsRestored = aState.windows.length; } - function onSSTabRestored(aEvent) { + function onSSTabRestored() { if (++tabsRestored == expectedTabsRestored) { // Remove the event listener from each window windows.forEach(function (win) { @@ -118,7 +118,7 @@ export var SessionStoreTestUtils = { // Used to add our listener to further windows so we can catch SSTabRestored // coming from them when creating a multi-window state. - function windowObserver(aSubject, aTopic, aData) { + function windowObserver(aSubject, aTopic) { if (aTopic == "domwindowopened") { let newWindow = aSubject; newWindow.addEventListener( diff --git a/browser/components/sessionstore/test/browser.toml b/browser/components/sessionstore/test/browser.toml index 26fb4b4550..7d5b407d22 100644 --- a/browser/components/sessionstore/test/browser.toml +++ b/browser/components/sessionstore/test/browser.toml @@ -22,30 +22,11 @@ support-files = [ "browser_scrollPositions_readerModeArticle.html", "browser_sessionStorage.html", "browser_speculative_connect.html", - "browser_248970_b_sample.html", - "browser_339445_sample.html", - "browser_423132_sample.html", - "browser_447951_sample.html", - "browser_454908_sample.html", - "browser_456342_sample.xhtml", - "browser_463205_sample.html", - "browser_463206_sample.html", - "browser_466937_sample.html", - "browser_485482_sample.html", - "browser_637020_slow.sjs", - "browser_662743_sample.html", - "browser_739531_sample.html", - "browser_739531_frame.html", - "browser_911547_sample.html", - "browser_911547_sample.html^headers^", "coopHeaderCommon.sjs", "restore_redirect_http.html", "restore_redirect_http.html^headers^", "restore_redirect_js.html", "restore_redirect_target.html", - "browser_1234021_page.html", - "browser_1284886_suspend_tab.html", - "browser_1284886_suspend_tab_2.html", "empty.html", "coop_coep.html", "coop_coep.html^headers^", @@ -58,248 +39,6 @@ prefs = [ "browser.sessionstore.closedTabsFromClosedWindows=true", ] -#NB: the following are disabled -# browser_464620_a.html -# browser_464620_b.html -# browser_464620_xd.html - -#disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html -#disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html -#disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html - -["browser_1234021.js"] - -["browser_1284886_suspend_tab.js"] - -["browser_1446343-windowsize.js"] -skip-if = ["os == 'linux'"] # Bug 1600180 - -["browser_248970_b_perwindowpb.js"] -# Disabled because of leaks. -# Re-enabling and rewriting this test is tracked in bug 936919. -skip-if = ["true"] - -["browser_339445.js"] - -["browser_345898.js"] - -["browser_350525.js"] - -["browser_354894_perwindowpb.js"] - -["browser_367052.js"] - -["browser_393716.js"] -skip-if = ["debug"] # Bug 1507747 - -["browser_394759_basic.js"] -# Disabled for intermittent failures, bug 944372. -skip-if = ["true"] - -["browser_394759_behavior.js"] -https_first_disabled = true - -["browser_394759_perwindowpb.js"] - -["browser_394759_purge.js"] - -["browser_423132.js"] - -["browser_447951.js"] - -["browser_454908.js"] - -["browser_456342.js"] - -["browser_461634.js"] - -["browser_463205.js"] - -["browser_463206.js"] - -["browser_464199.js"] -# Disabled for frequent intermittent failures - -["browser_464620_a.js"] -skip-if = ["true"] - -["browser_464620_b.js"] -skip-if = ["true"] - -["browser_465215.js"] - -["browser_465223.js"] - -["browser_466937.js"] - -["browser_467409-backslashplosion.js"] - -["browser_477657.js"] -skip-if = ["os == 'linux' && os_version == '18.04'"] # bug 1610668 for ubuntu 18.04 - -["browser_480893.js"] - -["browser_485482.js"] - -["browser_485563.js"] - -["browser_490040.js"] - -["browser_491168.js"] - -["browser_491577.js"] -skip-if = [ - "verify && debug && os == 'mac'", - "verify && debug && os == 'win'", -] - -["browser_495495.js"] - -["browser_500328.js"] - -["browser_514751.js"] - -["browser_522375.js"] - -["browser_522545.js"] -skip-if = ["true"] # Bug 1380968 - -["browser_524745.js"] -skip-if = [ - "win10_2009 && !ccov", # Bug 1418627 - "os == 'linux'", # Bug 1803187 -] - -["browser_528776.js"] - -["browser_579868.js"] - -["browser_579879.js"] -skip-if = ["os == 'linux' && (debug || asan)"] # Bug 1234404 - -["browser_581937.js"] - -["browser_586068-apptabs.js"] - -["browser_586068-apptabs_ondemand.js"] -skip-if = ["verify && (os == 'mac' || os == 'win')"] - -["browser_586068-browser_state_interrupted.js"] - -["browser_586068-cascade.js"] - -["browser_586068-multi_window.js"] - -["browser_586068-reload.js"] -https_first_disabled = true - -["browser_586068-select.js"] - -["browser_586068-window_state.js"] - -["browser_586068-window_state_override.js"] - -["browser_586147.js"] - -["browser_588426.js"] - -["browser_590268.js"] - -["browser_590563.js"] - -["browser_595601-restore_hidden.js"] - -["browser_597071.js"] -skip-if = ["true"] # Needs to be rewritten as Marionette test, bug 995916 - -["browser_600545.js"] - -["browser_601955.js"] - -["browser_607016.js"] - -["browser_615394-SSWindowState_events_duplicateTab.js"] - -["browser_615394-SSWindowState_events_setBrowserState.js"] -skip-if = ["verify && debug && os == 'mac'"] - -["browser_615394-SSWindowState_events_setTabState.js"] - -["browser_615394-SSWindowState_events_setWindowState.js"] -https_first_disabled = true - -["browser_615394-SSWindowState_events_undoCloseTab.js"] - -["browser_615394-SSWindowState_events_undoCloseWindow.js"] -skip-if = [ - "os == 'win' && !debug", # Bug 1572554 - "os == 'linux'", # Bug 1572554 -] - -["browser_618151.js"] - -["browser_623779.js"] - -["browser_624727.js"] - -["browser_625016.js"] -skip-if = [ - "os == 'mac'", # Disabled on OS X: - "os == 'linux'", # linux, Bug 1348583 - "os == 'win' && debug", # Bug 1430977 -] - -["browser_628270.js"] - -["browser_635418.js"] - -["browser_636279.js"] - -["browser_637020.js"] - -["browser_645428.js"] - -["browser_659591.js"] - -["browser_662743.js"] - -["browser_662812.js"] -skip-if = ["verify"] - -["browser_665702-state_session.js"] - -["browser_682507.js"] - -["browser_687710.js"] - -["browser_687710_2.js"] -https_first_disabled = true - -["browser_694378.js"] - -["browser_701377.js"] -skip-if = [ - "verify && debug && os == 'win'", - "verify && debug && os == 'mac'", -] - -["browser_705597.js"] - -["browser_707862.js"] - -["browser_739531.js"] - -["browser_739805.js"] - -["browser_819510_perwindowpb.js"] -skip-if = ["true"] # Bug 1284312, Bug 1341980, bug 1381451 - -["browser_906076_lazy_tabs.js"] -https_first_disabled = true -skip-if = ["os == 'linux' && os_version == '18.04'"] # bug 1446464 - -["browser_911547.js"] - ["browser_aboutPrivateBrowsing.js"] ["browser_aboutSessionRestore.js"] @@ -316,7 +55,6 @@ support-files = ["file_async_flushes.html"] run-if = ["crashreporter"] ["browser_async_remove_tab.js"] -skip-if = ["!sessionHistoryInParent"] ["browser_async_window_flushing.js"] https_first_disabled = true @@ -393,6 +131,7 @@ https_first_disabled = true skip-if = ["verify && debug"] ["browser_formdata_cc.js"] +skip-if = ["asan"] # test runs too long ["browser_formdata_face.js"] @@ -466,12 +205,12 @@ skip-if = [ ["browser_privatetabs.js"] ["browser_purge_shistory.js"] -skip-if = ["!sessionHistoryInParent"] # Bug 1271024 ["browser_remoteness_flip_on_restore.js"] ["browser_reopen_all_windows.js"] https_first_disabled = true +skip-if = ["asan"] # high memory ["browser_replace_load.js"] skip-if = ["true"] # Bug 1646894 @@ -516,9 +255,6 @@ skip-if = [ ["browser_scrollPositionsReaderMode.js"] -["browser_send_async_message_oom.js"] -skip-if = ["sessionHistoryInParent"] # Tests that the frame script OOMs, which is unused when SHIP is enabled. - ["browser_sessionHistory.js"] https_first_disabled = true support-files = ["file_sessionHistory_hashchange.html"] diff --git a/browser/components/sessionstore/test/browser_354894_perwindowpb.js b/browser/components/sessionstore/test/browser_354894_perwindowpb.js index 90368536dc..30a065c1af 100644 --- a/browser/components/sessionstore/test/browser_354894_perwindowpb.js +++ b/browser/components/sessionstore/test/browser_354894_perwindowpb.js @@ -21,7 +21,7 @@ * not enabled on that platform (platform shim; the application is kept running * although there are no windows left) * @note There is a difference when closing a browser window with - * BrowserTryToCloseWindow() as opposed to close(). The former will make + * BrowserCommands.tryToCloseWindow() as opposed to close(). The former will make * nsSessionStore restore a window next time it gets a chance and will post * notifications. The latter won't. */ @@ -133,7 +133,7 @@ let setupTest = async function (options, testFunction) { * Helper: Will observe and handle the notifications for us */ let hitCount = 0; - function observer(aCancel, aTopic, aData) { + function observer(aCancel, aTopic) { // count so that we later may compare observing[aTopic]++; @@ -182,7 +182,7 @@ function injectTestTabs(win) { } /** - * Attempts to close a window via BrowserTryToCloseWindow so that + * Attempts to close a window via BrowserCommands.tryToCloseWindow so that * we get the browser-lastwindow-close-requested and * browser-lastwindow-close-granted observer notifications. * @@ -195,7 +195,7 @@ function injectTestTabs(win) { function closeWindowForRestoration(win) { return new Promise(resolve => { let closePromise = BrowserTestUtils.windowClosed(win); - win.BrowserTryToCloseWindow(); + win.BrowserCommands.tryToCloseWindow(); if (!win.closed) { resolve(false); return; @@ -415,7 +415,7 @@ add_task(async function test_open_close_restore_from_popup() { return; } - await setupTest({}, async function (newWin, obs) { + await setupTest({}, async function (newWin) { let newWin2 = await promiseNewWindowLoaded(); await injectTestTabs(newWin2); diff --git a/browser/components/sessionstore/test/browser_394759_basic.js b/browser/components/sessionstore/test/browser_394759_basic.js index 62d5c40e17..cc1c335165 100644 --- a/browser/components/sessionstore/test/browser_394759_basic.js +++ b/browser/components/sessionstore/test/browser_394759_basic.js @@ -74,7 +74,7 @@ function test() { let expectedTabs = data[0].tabs.length; newWin2.addEventListener( "SSTabRestored", - function sstabrestoredListener(aEvent) { + function sstabrestoredListener() { ++restoredTabs; info("Restored tab " + restoredTabs + "/" + expectedTabs); if (restoredTabs < expectedTabs) { diff --git a/browser/components/sessionstore/test/browser_394759_behavior.js b/browser/components/sessionstore/test/browser_394759_behavior.js index ee4b121e84..01217f86c9 100644 --- a/browser/components/sessionstore/test/browser_394759_behavior.js +++ b/browser/components/sessionstore/test/browser_394759_behavior.js @@ -34,7 +34,7 @@ function testWindows(windowsToOpen, expectedResults) { } let closedWindowData = ss.getClosedWindowData(); - let numPopups = closedWindowData.filter(function (el, i, arr) { + let numPopups = closedWindowData.filter(function (el) { return el.isPopup; }).length; let numNormal = ss.getClosedWindowCount() - numPopups; @@ -50,7 +50,7 @@ function testWindows(windowsToOpen, expectedResults) { is( numNormal, oResults.normal, - "There were " + oResults.normal + " normal windows to repoen" + "There were " + oResults.normal + " normal windows to reopen" ); })(); } @@ -63,14 +63,15 @@ add_task(async function test_closed_window_states() { let windowsToOpen = [ { isPopup: false }, - { isPopup: false }, + { isPopup: true }, + { isPopup: true }, { isPopup: true }, { isPopup: true }, { isPopup: true }, ]; let expectedResults = { - mac: { popup: 3, normal: 0 }, - other: { popup: 3, normal: 1 }, + mac: { popup: 5, normal: 0 }, + other: { popup: 5, normal: 1 }, }; await testWindows(windowsToOpen, expectedResults); @@ -81,10 +82,11 @@ add_task(async function test_closed_window_states() { { isPopup: false }, { isPopup: false }, { isPopup: false }, + { isPopup: false }, ]; let expectedResults2 = { - mac: { popup: 0, normal: 3 }, - other: { popup: 0, normal: 3 }, + mac: { popup: 0, normal: 5 }, + other: { popup: 0, normal: 5 }, }; await testWindows(windowsToOpen2, expectedResults2); diff --git a/browser/components/sessionstore/test/browser_394759_purge.js b/browser/components/sessionstore/test/browser_394759_purge.js index e5218c9936..ea75d6e4b2 100644 --- a/browser/components/sessionstore/test/browser_394759_purge.js +++ b/browser/components/sessionstore/test/browser_394759_purge.js @@ -9,7 +9,7 @@ let { ForgetAboutSite } = ChromeUtils.importESModule( function promiseClearHistory() { return new Promise(resolve => { let observer = { - observe(aSubject, aTopic, aData) { + observe() { Services.obs.removeObserver( this, "browser:purge-session-history-for-domain" diff --git a/browser/components/sessionstore/test/browser_459906.js b/browser/components/sessionstore/test/browser_459906.js index 6827f6ad1d..5a0c1aeea3 100644 --- a/browser/components/sessionstore/test/browser_459906.js +++ b/browser/components/sessionstore/test/browser_459906.js @@ -17,7 +17,7 @@ function test() { let tab = BrowserTestUtils.addTab(gBrowser, testURL); tab.linkedBrowser.addEventListener( "load", - function listener(aEvent) { + function listener() { // wait for all frames to load completely if (frameCount++ < 2) { return; @@ -31,7 +31,7 @@ function test() { let tab2 = gBrowser.duplicateTab(tab); tab2.linkedBrowser.addEventListener( "load", - function loadListener(eventTab2) { + function loadListener() { // wait for all frames to load (and reload!) completely if (frameCount++ < 2) { return; diff --git a/browser/components/sessionstore/test/browser_461743.js b/browser/components/sessionstore/test/browser_461743.js index fd4501b5ac..a27ccc7721 100644 --- a/browser/components/sessionstore/test/browser_461743.js +++ b/browser/components/sessionstore/test/browser_461743.js @@ -24,7 +24,7 @@ function test() { let tab2 = gBrowser.duplicateTab(tab); tab2.linkedBrowser.addEventListener( "461743", - function listener(eventTab2) { + function listener() { tab2.linkedBrowser.removeEventListener("461743", listener, true); is(aEvent.data, "done", "XSS injection was attempted"); diff --git a/browser/components/sessionstore/test/browser_464199.js b/browser/components/sessionstore/test/browser_464199.js index 4ac8fba1a5..98a17c4955 100644 --- a/browser/components/sessionstore/test/browser_464199.js +++ b/browser/components/sessionstore/test/browser_464199.js @@ -9,7 +9,7 @@ let { ForgetAboutSite } = ChromeUtils.importESModule( function promiseClearHistory() { return new Promise(resolve => { let observer = { - observe(aSubject, aTopic, aData) { + observe() { Services.obs.removeObserver( this, "browser:purge-session-history-for-domain" diff --git a/browser/components/sessionstore/test/browser_464620_a.js b/browser/components/sessionstore/test/browser_464620_a.js index 9052d7bec0..6a3b56f767 100644 --- a/browser/components/sessionstore/test/browser_464620_a.js +++ b/browser/components/sessionstore/test/browser_464620_a.js @@ -27,7 +27,7 @@ function test() { let tab2 = gBrowser.duplicateTab(tab); tab2.linkedBrowser.addEventListener( "464620_a", - function listener(eventTab2) { + function listener() { tab2.linkedBrowser.removeEventListener("464620_a", listener, true); is(aEvent.data, "done", "XSS injection was attempted"); diff --git a/browser/components/sessionstore/test/browser_464620_b.js b/browser/components/sessionstore/test/browser_464620_b.js index 005bb4cc27..3e2b46d685 100644 --- a/browser/components/sessionstore/test/browser_464620_b.js +++ b/browser/components/sessionstore/test/browser_464620_b.js @@ -27,7 +27,7 @@ function test() { let tab2 = gBrowser.duplicateTab(tab); tab2.linkedBrowser.addEventListener( "464620_b", - function listener(eventTab2) { + function listener() { tab2.linkedBrowser.removeEventListener("464620_b", listener, true); is(aEvent.data, "done", "XSS injection was attempted"); diff --git a/browser/components/sessionstore/test/browser_526613.js b/browser/components/sessionstore/test/browser_526613.js index ba3f03ef32..784febd3d5 100644 --- a/browser/components/sessionstore/test/browser_526613.js +++ b/browser/components/sessionstore/test/browser_526613.js @@ -45,7 +45,7 @@ function test() { }; let pass = 1; - function observer(aSubject, aTopic, aData) { + function observer(aSubject, aTopic) { is( aTopic, "sessionstore-browser-state-restored", diff --git a/browser/components/sessionstore/test/browser_580512.js b/browser/components/sessionstore/test/browser_580512.js index 1dfd696277..e27dc61ba3 100644 --- a/browser/components/sessionstore/test/browser_580512.js +++ b/browser/components/sessionstore/test/browser_580512.js @@ -32,10 +32,10 @@ function closeFirstWin(win) { win.gBrowser.pinTab(win.gBrowser.tabs[1]); let winClosed = BrowserTestUtils.windowClosed(win); - // We need to call BrowserTryToCloseWindow in order to trigger + // We need to call BrowserCommands.tryToCloseWindow in order to trigger // the machinery that chooses whether or not to save the session // for the last window. - win.BrowserTryToCloseWindow(); + win.BrowserCommands.tryToCloseWindow(); ok(win.closed, "window closed"); winClosed.then(() => { @@ -88,7 +88,7 @@ function openWinWithCb(cb, argURIs, expectedURIs) { var expectedLoads = expectedURIs.length; win.gBrowser.addTabsProgressListener({ - onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { + onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, _aStatus) { if ( aRequest && aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && diff --git a/browser/components/sessionstore/test/browser_586068-apptabs.js b/browser/components/sessionstore/test/browser_586068-apptabs.js index b2f92f760c..24878ba267 100644 --- a/browser/components/sessionstore/test/browser_586068-apptabs.js +++ b/browser/components/sessionstore/test/browser_586068-apptabs.js @@ -69,12 +69,7 @@ add_task(async function test() { let loadCount = 0; let promiseRestoringTabs = new Promise(resolve => { - gProgressListener.setCallback(function ( - aBrowser, - aNeedRestore, - aRestoring, - aRestored - ) { + gProgressListener.setCallback(function (aBrowser) { loadCount++; // We'll make sure that the loads we get come from pinned tabs or the diff --git a/browser/components/sessionstore/test/browser_586068-browser_state_interrupted.js b/browser/components/sessionstore/test/browser_586068-browser_state_interrupted.js index b729555ff1..6ef18e2b3a 100644 --- a/browser/components/sessionstore/test/browser_586068-browser_state_interrupted.js +++ b/browser/components/sessionstore/test/browser_586068-browser_state_interrupted.js @@ -147,12 +147,7 @@ add_task(async function test() { let loadCount = 0; let promiseRestoringTabs = new Promise(resolve => { - gProgressListener.setCallback(function ( - aBrowser, - aNeedRestore, - aRestoring, - aRestored - ) { + gProgressListener.setCallback(function (aBrowser, aNeedRestore) { loadCount++; if ( @@ -188,7 +183,7 @@ add_task(async function test() { }); // We also want to catch the extra windows (there should be 2), so we need to observe domwindowopened - Services.ww.registerNotification(function observer(aSubject, aTopic, aData) { + Services.ww.registerNotification(function observer(aSubject, aTopic) { if (aTopic == "domwindowopened") { let win = aSubject; win.addEventListener( diff --git a/browser/components/sessionstore/test/browser_586068-multi_window.js b/browser/components/sessionstore/test/browser_586068-multi_window.js index bf5d839812..352c5bcefb 100644 --- a/browser/components/sessionstore/test/browser_586068-multi_window.js +++ b/browser/components/sessionstore/test/browser_586068-multi_window.js @@ -72,12 +72,7 @@ add_task(async function test() { let loadCount = 0; let promiseRestoringTabs = new Promise(resolve => { - gProgressListener.setCallback(function ( - aBrowser, - aNeedRestore, - aRestoring, - aRestored - ) { + gProgressListener.setCallback(function (aBrowser, aNeedRestore) { if (++loadCount == numTabs) { // We don't actually care about load order in this test, just that they all // do load. @@ -91,7 +86,7 @@ add_task(async function test() { }); // We also want to catch the 2nd window, so we need to observe domwindowopened - Services.ww.registerNotification(function observer(aSubject, aTopic, aData) { + Services.ww.registerNotification(function observer(aSubject, aTopic) { if (aTopic == "domwindowopened") { let win = aSubject; win.addEventListener( diff --git a/browser/components/sessionstore/test/browser_586068-window_state.js b/browser/components/sessionstore/test/browser_586068-window_state.js index 69c3742a66..25066a2db4 100644 --- a/browser/components/sessionstore/test/browser_586068-window_state.js +++ b/browser/components/sessionstore/test/browser_586068-window_state.js @@ -82,12 +82,7 @@ add_task(async function test() { let loadCount = 0; let promiseRestoringTabs = new Promise(resolve => { - gProgressListener.setCallback(function ( - aBrowser, - aNeedRestore, - aRestoring, - aRestored - ) { + gProgressListener.setCallback(function (aBrowser, aNeedRestore) { // When loadCount == 2, we'll also restore state2 into the window if (++loadCount == 2) { ss.setWindowState(window, JSON.stringify(state2), false); diff --git a/browser/components/sessionstore/test/browser_586068-window_state_override.js b/browser/components/sessionstore/test/browser_586068-window_state_override.js index 8a6eac6de2..eb3d2c709b 100644 --- a/browser/components/sessionstore/test/browser_586068-window_state_override.js +++ b/browser/components/sessionstore/test/browser_586068-window_state_override.js @@ -82,12 +82,7 @@ add_task(async function test() { let loadCount = 0; let promiseRestoringTabs = new Promise(resolve => { - gProgressListener.setCallback(function ( - aBrowser, - aNeedRestore, - aRestoring, - aRestored - ) { + gProgressListener.setCallback(function (aBrowser, aNeedRestore) { // When loadCount == 2, we'll also restore state2 into the window if (++loadCount == 2) { executeSoon(() => diff --git a/browser/components/sessionstore/test/browser_589246.js b/browser/components/sessionstore/test/browser_589246.js index 2fd92b2b82..34d9dc97a8 100644 --- a/browser/components/sessionstore/test/browser_589246.js +++ b/browser/components/sessionstore/test/browser_589246.js @@ -164,7 +164,7 @@ function setupForTest(aConditions) { ss.setBrowserState(JSON.stringify(testState)); } -function onStateRestored(aSubject, aTopic, aData) { +function onStateRestored() { info("test #" + testNum + ": onStateRestored"); Services.obs.removeObserver( onStateRestored, @@ -183,7 +183,7 @@ function onStateRestored(aSubject, aTopic, aData) { ); newWin.addEventListener( "load", - function (aEvent) { + function () { promiseBrowserLoaded(newWin.gBrowser.selectedBrowser).then(() => { // pin this tab if (shouldPinTab) { @@ -216,12 +216,12 @@ function onStateRestored(aSubject, aTopic, aData) { newWin.gBrowser.removeTab(newTab); newWin.gBrowser.removeTab(newTab2); } - newWin.BrowserTryToCloseWindow(); + newWin.BrowserCommands.tryToCloseWindow(); }, { capture: true, once: true } ); } else { - newWin.BrowserTryToCloseWindow(); + newWin.BrowserCommands.tryToCloseWindow(); } }); }, @@ -230,7 +230,7 @@ function onStateRestored(aSubject, aTopic, aData) { } // This will be called before the window is actually closed -function onLastWindowClosed(aSubject, aTopic, aData) { +function onLastWindowClosed() { info("test #" + testNum + ": onLastWindowClosed"); Services.obs.removeObserver( onLastWindowClosed, @@ -261,7 +261,7 @@ function onWindowUnloaded() { ); newWin.addEventListener( "load", - function (aEvent) { + function () { newWin.gBrowser.selectedBrowser.addEventListener( "load", function () { diff --git a/browser/components/sessionstore/test/browser_590268.js b/browser/components/sessionstore/test/browser_590268.js index cde1a1cafa..eb1940e35d 100644 --- a/browser/components/sessionstore/test/browser_590268.js +++ b/browser/components/sessionstore/test/browser_590268.js @@ -52,7 +52,7 @@ function test() { } } - function onSSTabRestored(aEvent) { + function onSSTabRestored() { if (++restoredTabsCount < NUM_TABS) { return; } diff --git a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_duplicateTab.js b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_duplicateTab.js index b3ad6d240a..b2f7692b7c 100644 --- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_duplicateTab.js +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_duplicateTab.js @@ -29,11 +29,11 @@ function test_duplicateTab() { // We'll look to make sure this value is on the duplicated tab ss.setCustomTabValue(tab, "foo", "bar"); - function onSSWindowStateBusy(aEvent) { + function onSSWindowStateBusy() { busyEventCount++; } - function onSSWindowStateReady(aEvent) { + function onSSWindowStateReady() { newTab = gBrowser.tabs[2]; readyEventCount++; is(ss.getCustomTabValue(newTab, "foo"), "bar"); diff --git a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js index 4dfcbc844d..fbca3301e6 100644 --- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setBrowserState.js @@ -84,7 +84,7 @@ function test() { // waitForBrowserState does it's own observing for windows, but doesn't attach // the listeners we want here, so do it ourselves. let newWindow; - function windowObserver(aSubject, aTopic, aData) { + function windowObserver(aSubject, aTopic) { if (aTopic == "domwindowopened") { Services.ww.unregisterNotification(windowObserver); diff --git a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setTabState.js b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setTabState.js index a76a8b3dd5..4b0c256388 100644 --- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setTabState.js +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setTabState.js @@ -29,17 +29,17 @@ function test_setTabState() { let busyEventCount = 0; let readyEventCount = 0; - function onSSWindowStateBusy(aEvent) { + function onSSWindowStateBusy() { busyEventCount++; } - function onSSWindowStateReady(aEvent) { + function onSSWindowStateReady() { readyEventCount++; is(ss.getCustomTabValue(tab, "foo"), "bar"); ss.setCustomTabValue(tab, "baz", "qux"); } - function onSSTabRestoring(aEvent) { + function onSSTabRestoring() { is(busyEventCount, 1); is(readyEventCount, 1); is(ss.getCustomTabValue(tab, "baz"), "qux"); diff --git a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setWindowState.js b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setWindowState.js index c9d4bd00f5..daa40bd75a 100644 --- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setWindowState.js +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_setWindowState.js @@ -29,17 +29,17 @@ function test() { readyEventCount = 0, tabRestoredCount = 0; - function onSSWindowStateBusy(aEvent) { + function onSSWindowStateBusy() { busyEventCount++; } - function onSSWindowStateReady(aEvent) { + function onSSWindowStateReady() { readyEventCount++; is(ss.getCustomTabValue(gBrowser.tabs[0], "foo"), "bar"); is(ss.getCustomTabValue(gBrowser.tabs[1], "baz"), "qux"); } - function onSSTabRestored(aEvent) { + function onSSTabRestored() { if (++tabRestoredCount < 2) { return; } diff --git a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseTab.js b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseTab.js index 345bba516c..b5d5af2835 100644 --- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseTab.js +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseTab.js @@ -24,11 +24,11 @@ add_task(async function test_undoCloseTab() { ss.setCustomTabValue(tab, "foo", "bar"); - function onSSWindowStateBusy(aEvent) { + function onSSWindowStateBusy() { busyEventCount++; } - function onSSWindowStateReady(aEvent) { + function onSSWindowStateReady() { Assert.equal(gBrowser.tabs.length, 2, "Should only have 2 tabs"); lastTab = gBrowser.tabs[1]; readyEventCount++; diff --git a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseWindow.js b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseWindow.js index 0a5b07da29..7483583e5a 100644 --- a/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseWindow.js +++ b/browser/components/sessionstore/test/browser_615394-SSWindowState_events_undoCloseWindow.js @@ -71,7 +71,7 @@ function test() { let newWindow, reopenedWindow; - function firstWindowObserver(aSubject, aTopic, aData) { + function firstWindowObserver(aSubject, aTopic) { if (aTopic == "domwindowopened") { newWindow = aSubject; Services.ww.unregisterNotification(firstWindowObserver); @@ -107,15 +107,15 @@ function test() { readyEventCount = 0, tabRestoredCount = 0; // These will listen to the reopened closed window... - function onSSWindowStateBusy(aEvent) { + function onSSWindowStateBusy() { busyEventCount++; } - function onSSWindowStateReady(aEvent) { + function onSSWindowStateReady() { readyEventCount++; } - function onSSTabRestored(aEvent) { + function onSSTabRestored() { if (++tabRestoredCount < 4) { return; } diff --git a/browser/components/sessionstore/test/browser_618151.js b/browser/components/sessionstore/test/browser_618151.js index c38a349818..f3c44d1e88 100644 --- a/browser/components/sessionstore/test/browser_618151.js +++ b/browser/components/sessionstore/test/browser_618151.js @@ -46,7 +46,7 @@ function runNextTest() { } function test_setup() { - function onSSTabRestored(aEvent) { + function onSSTabRestored() { gBrowser.tabContainer.removeEventListener("SSTabRestored", onSSTabRestored); runNextTest(); } diff --git a/browser/components/sessionstore/test/browser_636279.js b/browser/components/sessionstore/test/browser_636279.js index 3b71fcbb4c..4842f145b2 100644 --- a/browser/components/sessionstore/test/browser_636279.js +++ b/browser/components/sessionstore/test/browser_636279.js @@ -129,7 +129,7 @@ var TabsProgressListener = { delete this.callback; }, - observe(browser, topic, data) { + observe(browser) { TabsProgressListener.onRestored(browser); }, diff --git a/browser/components/sessionstore/test/browser_645428.js b/browser/components/sessionstore/test/browser_645428.js index bbb3b1b299..3916c44a7e 100644 --- a/browser/components/sessionstore/test/browser_645428.js +++ b/browser/components/sessionstore/test/browser_645428.js @@ -6,7 +6,7 @@ const NOTIFICATION = "sessionstore-browser-state-restored"; function test() { waitForExplicitFinish(); - function observe(subject, topic, data) { + function observe(subject, topic) { if (NOTIFICATION == topic) { finish(); ok(true, "TOPIC received"); diff --git a/browser/components/sessionstore/test/browser_687710_2.js b/browser/components/sessionstore/test/browser_687710_2.js index 81d3c55379..190b5a718a 100644 --- a/browser/components/sessionstore/test/browser_687710_2.js +++ b/browser/components/sessionstore/test/browser_687710_2.js @@ -38,61 +38,31 @@ var state = { add_task(async function test() { let tab = BrowserTestUtils.addTab(gBrowser, "about:blank"); await promiseTabState(tab, state); - if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(tab.linkedBrowser, [], function () { - function compareEntries(i, j, history) { - let e1 = history.getEntryAtIndex(i); - let e2 = history.getEntryAtIndex(j); - ok(e1.sharesDocumentWith(e2), `${i} should share doc with ${j}`); - is(e1.childCount, e2.childCount, `Child count mismatch (${i}, ${j})`); + function compareEntries(i, j, history) { + let e1 = history.getEntryAtIndex(i); + let e2 = history.getEntryAtIndex(j); - for (let c = 0; c < e1.childCount; c++) { - let c1 = e1.GetChildAt(c); - let c2 = e2.GetChildAt(c); + ok(e1.sharesDocumentWith(e2), `${i} should share doc with ${j}`); + is(e1.childCount, e2.childCount, `Child count mismatch (${i}, ${j})`); - ok( - c1.sharesDocumentWith(c2), - `Cousins should share documents. (${i}, ${j}, ${c})` - ); - } - } + for (let c = 0; c < e1.childCount; c++) { + let c1 = e1.GetChildAt(c); + let c2 = e2.GetChildAt(c); - let history = docShell.browsingContext.childSessionHistory.legacySHistory; - - is(history.count, 2, "history.count"); - for (let i = 0; i < history.count; i++) { - for (let j = 0; j < history.count; j++) { - compareEntries(i, j, history); - } - } - }); - } else { - function compareEntries(i, j, history) { - let e1 = history.getEntryAtIndex(i); - let e2 = history.getEntryAtIndex(j); - - ok(e1.sharesDocumentWith(e2), `${i} should share doc with ${j}`); - is(e1.childCount, e2.childCount, `Child count mismatch (${i}, ${j})`); - - for (let c = 0; c < e1.childCount; c++) { - let c1 = e1.GetChildAt(c); - let c2 = e2.GetChildAt(c); - - ok( - c1.sharesDocumentWith(c2), - `Cousins should share documents. (${i}, ${j}, ${c})` - ); - } + ok( + c1.sharesDocumentWith(c2), + `Cousins should share documents. (${i}, ${j}, ${c})` + ); } + } - let history = tab.linkedBrowser.browsingContext.sessionHistory; + let history = tab.linkedBrowser.browsingContext.sessionHistory; - is(history.count, 2, "history.count"); - for (let i = 0; i < history.count; i++) { - for (let j = 0; j < history.count; j++) { - compareEntries(i, j, history); - } + is(history.count, 2, "history.count"); + for (let i = 0; i < history.count; i++) { + for (let j = 0; j < history.count; j++) { + compareEntries(i, j, history); } } diff --git a/browser/components/sessionstore/test/browser_705597.js b/browser/components/sessionstore/test/browser_705597.js index d497e46a97..10f4f08863 100644 --- a/browser/components/sessionstore/test/browser_705597.js +++ b/browser/components/sessionstore/test/browser_705597.js @@ -26,14 +26,8 @@ function test() { let browser = tab.linkedBrowser; promiseTabState(tab, tabState).then(() => { - let entry; - if (!Services.appinfo.sessionHistoryInParent) { - let sessionHistory = browser.sessionHistory; - entry = sessionHistory.legacySHistory.getEntryAtIndex(0); - } else { - let sessionHistory = browser.browsingContext.sessionHistory; - entry = sessionHistory.getEntryAtIndex(0); - } + let sessionHistory = browser.browsingContext.sessionHistory; + let entry = sessionHistory.getEntryAtIndex(0); whenChildCount(entry, 1, function () { whenChildCount(entry, 2, function () { diff --git a/browser/components/sessionstore/test/browser_707862.js b/browser/components/sessionstore/test/browser_707862.js index 765c63257f..4559362e21 100644 --- a/browser/components/sessionstore/test/browser_707862.js +++ b/browser/components/sessionstore/test/browser_707862.js @@ -26,26 +26,14 @@ function test() { let browser = tab.linkedBrowser; promiseTabState(tab, tabState).then(() => { - let entry; - if (!Services.appinfo.sessionHistoryInParent) { - let sessionHistory = browser.sessionHistory; - entry = sessionHistory.legacySHistory.getEntryAtIndex(0); - } else { - let sessionHistory = browser.browsingContext.sessionHistory; - entry = sessionHistory.getEntryAtIndex(0); - } + let sessionHistory = browser.browsingContext.sessionHistory; + let entry = sessionHistory.getEntryAtIndex(0); whenChildCount(entry, 1, function () { whenChildCount(entry, 2, function () { promiseBrowserLoaded(browser).then(() => { - let newEntry; - if (!Services.appinfo.sessionHistoryInParent) { - let newSessionHistory = browser.sessionHistory; - newEntry = newSessionHistory.legacySHistory.getEntryAtIndex(0); - } else { - let newSessionHistory = browser.browsingContext.sessionHistory; - newEntry = newSessionHistory.getEntryAtIndex(0); - } + let newSessionHistory = browser.browsingContext.sessionHistory; + let newEntry = newSessionHistory.getEntryAtIndex(0); whenChildCount(newEntry, 0, function () { // Make sure that we reset the state. diff --git a/browser/components/sessionstore/test/browser_739531.js b/browser/components/sessionstore/test/browser_739531.js index 507d10a5f1..e02a94d9a7 100644 --- a/browser/components/sessionstore/test/browser_739531.js +++ b/browser/components/sessionstore/test/browser_739531.js @@ -19,7 +19,7 @@ function test() { removeFunc = BrowserTestUtils.addContentEventListener( tab.linkedBrowser, "load", - function onLoad(aEvent) { + function onLoad() { // make sure both the page and the frame are loaded if (++loadCount < 2) { return; diff --git a/browser/components/sessionstore/test/browser_async_flushes.js b/browser/components/sessionstore/test/browser_async_flushes.js index e35593dc30..d0bf039ff2 100644 --- a/browser/components/sessionstore/test/browser_async_flushes.js +++ b/browser/components/sessionstore/test/browser_async_flushes.js @@ -44,58 +44,6 @@ add_task(async function test_flush() { gBrowser.removeTab(tab); }); -add_task(async function test_crash() { - if (Services.appinfo.sessionHistoryInParent) { - // This test relies on frame script message ordering. Since the frame script - // is unused with SHIP, there's no guarantee that we'll crash the frame - // before we've started the flush. - ok(true, "Test relies on frame script message ordering."); - return; - } - - // Create new tab. - let tab = BrowserTestUtils.addTab(gBrowser, URL); - gBrowser.selectedTab = tab; - let browser = tab.linkedBrowser; - await promiseBrowserLoaded(browser); - - // Flush to empty any queued update messages. - await TabStateFlusher.flush(browser); - - // There should be one history entry. - let { entries } = JSON.parse(ss.getTabState(tab)); - is(entries.length, 1, "there is a single history entry"); - - // Click the link to navigate. - await SpecialPowers.spawn(browser, [], async function () { - return new Promise(resolve => { - docShell.chromeEventHandler.addEventListener( - "hashchange", - () => resolve(), - { once: true, capture: true } - ); - - // Click the link. - content.document.querySelector("a").click(); - }); - }); - - // Crash the browser and flush. Both messages are async and will be sent to - // the content process. The "crash" message makes it first so that we don't - // get a chance to process the flush. The TabStateFlusher however should be - // notified so that the flush still completes. - let promise1 = BrowserTestUtils.crashFrame(browser); - let promise2 = TabStateFlusher.flush(browser); - await Promise.all([promise1, promise2]); - - // The pending update should be lost. - ({ entries } = JSON.parse(ss.getTabState(tab))); - is(entries.length, 1, "still only one history entry"); - - // Cleanup. - gBrowser.removeTab(tab); -}); - add_task(async function test_remove() { // Create new tab. let tab = BrowserTestUtils.addTab(gBrowser, URL); diff --git a/browser/components/sessionstore/test/browser_async_remove_tab.js b/browser/components/sessionstore/test/browser_async_remove_tab.js index 7f74c57b40..1e3a75adfa 100644 --- a/browser/components/sessionstore/test/browser_async_remove_tab.js +++ b/browser/components/sessionstore/test/browser_async_remove_tab.js @@ -92,15 +92,7 @@ add_task(async function save_worthy_tabs_remote_final() { ok(browser.isRemoteBrowser, "browser is still remote"); // Remove the tab before the update arrives. - let promise = promiseRemoveTabAndSessionState(tab); - - // With SHIP, we'll do the final tab state update sooner than we did before. - if (!Services.appinfo.sessionHistoryInParent) { - // No tab state worth saving (that we know about yet). - ok(!isValueInClosedData(r), "closed tab not saved"); - } - - await promise; + await promiseRemoveTabAndSessionState(tab); // Turns out there is a tab state worth saving. ok(isValueInClosedData(r), "closed tab saved"); @@ -117,15 +109,7 @@ add_task(async function save_worthy_tabs_nonremote_final() { ok(!browser.isRemoteBrowser, "browser is not remote anymore"); // Remove the tab before the update arrives. - let promise = promiseRemoveTabAndSessionState(tab); - - // With SHIP, we'll do the final tab state update sooner than we did before. - if (!Services.appinfo.sessionHistoryInParent) { - // No tab state worth saving (that we know about yet). - ok(!isValueInClosedData(r), "closed tab not saved"); - } - - await promise; + await promiseRemoveTabAndSessionState(tab); // Turns out there is a tab state worth saving. ok(isValueInClosedData(r), "closed tab saved"); @@ -151,15 +135,7 @@ add_task(async function dont_save_empty_tabs_final() { await entryReplaced; // Remove the tab before the update arrives. - let promise = promiseRemoveTabAndSessionState(tab); - - // With SHIP, we'll do the final tab state update sooner than we did before. - if (!Services.appinfo.sessionHistoryInParent) { - // Tab state deemed worth saving (yet). - ok(isValueInClosedData(r), "closed tab saved"); - } - - await promise; + await promiseRemoveTabAndSessionState(tab); // Turns out we don't want to save the tab state. ok(!isValueInClosedData(r), "closed tab not saved"); diff --git a/browser/components/sessionstore/test/browser_async_window_flushing.js b/browser/components/sessionstore/test/browser_async_window_flushing.js index d346f9eb1f..42e24bdd83 100644 --- a/browser/components/sessionstore/test/browser_async_window_flushing.js +++ b/browser/components/sessionstore/test/browser_async_window_flushing.js @@ -116,17 +116,10 @@ add_task(async function test_remove_uninteresting_window() { await SpecialPowers.spawn(browser, [], async function () { // Epic hackery to make this browser seem suddenly boring. docShell.setCurrentURIForSessionStore(Services.io.newURI("about:blank")); - - if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { - let { sessionHistory } = docShell.QueryInterface(Ci.nsIWebNavigation); - sessionHistory.legacySHistory.purgeHistory(sessionHistory.count); - } }); - if (SpecialPowers.Services.appinfo.sessionHistoryInParent) { - let { sessionHistory } = browser.browsingContext; - sessionHistory.purgeHistory(sessionHistory.count); - } + let { sessionHistory } = browser.browsingContext; + sessionHistory.purgeHistory(sessionHistory.count); // Once this windowClosed Promise resolves, we should have finished // the flush and revisited our decision to put this window into diff --git a/browser/components/sessionstore/test/browser_attributes.js b/browser/components/sessionstore/test/browser_attributes.js index a0ee6d5b0c..491ec5db22 100644 --- a/browser/components/sessionstore/test/browser_attributes.js +++ b/browser/components/sessionstore/test/browser_attributes.js @@ -38,45 +38,68 @@ add_task(async function test() { ok(tab.hasAttribute("muted"), "tab.muted exists"); // Make sure we do not persist 'image' and 'muted' attributes. - ss.persistTabAttribute("image"); - ss.persistTabAttribute("muted"); let { attributes } = JSON.parse(ss.getTabState(tab)); ok(!("image" in attributes), "'image' attribute not saved"); ok(!("muted" in attributes), "'muted' attribute not saved"); - ok(!("custom" in attributes), "'custom' attribute not saved"); - - // Test persisting a custom attribute. - tab.setAttribute("custom", "foobar"); - ss.persistTabAttribute("custom"); - - ({ attributes } = JSON.parse(ss.getTabState(tab))); - is(attributes.custom, "foobar", "'custom' attribute is correct"); - - // Make sure we're backwards compatible and restore old 'image' attributes. + ok(!("customizemode" in attributes), "'customizemode' attribute not saved"); + + // Test persisting a customizemode attribute. + { + let customizationReady = BrowserTestUtils.waitForEvent( + gNavToolbox, + "customizationready" + ); + gCustomizeMode.enter(); + await customizationReady; + } + + let customizeIcon = gBrowser.getIcon(gBrowser.selectedTab); + ({ attributes } = JSON.parse(ss.getTabState(gBrowser.selectedTab))); + ok(!("image" in attributes), "'image' attribute not saved"); + is(attributes.customizemode, "true", "'customizemode' attribute is correct"); + + { + let afterCustomization = BrowserTestUtils.waitForEvent( + gNavToolbox, + "aftercustomization" + ); + gCustomizeMode.exit(); + await afterCustomization; + } + + // Test restoring a customizemode tab. let state = { - entries: [{ url: "about:mozilla", triggeringPrincipal_base64 }], - attributes: { custom: "foobaz" }, - image: gBrowser.getIcon(tab), + entries: [], + attributes: { customizemode: "true", nonpersisted: "true" }, }; + // Customize mode doesn't like being restored on top of a non-blank tab. + // For the moment, it appears it isn't possible to restore customizemode onto + // an existing non-blank tab outside of tests, however this may be a latent + // bug if we ever try to do that in the future. + let principal = Services.scriptSecurityManager.createNullPrincipal({}); + tab.linkedBrowser.createAboutBlankDocumentViewer(principal, principal); + // Prepare a pending tab waiting to be restored. let promise = promiseTabRestoring(tab); ss.setTabState(tab, JSON.stringify(state)); await promise; ok(tab.hasAttribute("pending"), "tab is pending"); - is(gBrowser.getIcon(tab), state.image, "tab has correct icon"); + ok(tab.hasAttribute("customizemode"), "tab is in customizemode"); + ok(!tab.hasAttribute("nonpersisted"), "tab has no nonpersisted attribute"); + is(gBrowser.getIcon(tab), customizeIcon, "tab has correct icon"); ok(!state.attributes.image, "'image' attribute not saved"); // Let the pending tab load. gBrowser.selectedTab = tab; - await promiseTabRestored(tab); // Ensure no 'image' or 'pending' attributes are stored. ({ attributes } = JSON.parse(ss.getTabState(tab))); ok(!("image" in attributes), "'image' attribute not saved"); ok(!("pending" in attributes), "'pending' attribute not saved"); - is(attributes.custom, "foobaz", "'custom' attribute is correct"); + ok(!("nonpersisted" in attributes), "'nonpersisted' attribute not saved"); + is(attributes.customizemode, "true", "'customizemode' attribute is correct"); // Clean up. gBrowser.removeTab(tab); diff --git a/browser/components/sessionstore/test/browser_bfcache_telemetry.js b/browser/components/sessionstore/test/browser_bfcache_telemetry.js index 5faa2822ea..c1e9877505 100644 --- a/browser/components/sessionstore/test/browser_bfcache_telemetry.js +++ b/browser/components/sessionstore/test/browser_bfcache_telemetry.js @@ -39,7 +39,6 @@ async function test_bfcache_telemetry(probeInParent) { add_task(async () => { await test_bfcache_telemetry( - Services.appinfo.sessionHistoryInParent && - Services.prefs.getBoolPref("fission.bfcacheInParent") + Services.prefs.getBoolPref("fission.bfcacheInParent") ); }); diff --git a/browser/components/sessionstore/test/browser_closed_tabs_closed_windows.js b/browser/components/sessionstore/test/browser_closed_tabs_closed_windows.js index 081167acfa..c80e63df04 100644 --- a/browser/components/sessionstore/test/browser_closed_tabs_closed_windows.js +++ b/browser/components/sessionstore/test/browser_closed_tabs_closed_windows.js @@ -81,10 +81,6 @@ async function prepareClosedData() { const testWindow7 = await BrowserTestUtils.openNewBrowserWindow(); await openAndCloseTab(testWindow7, TEST_URLS[4]); - let closedTabsHistogram = TelemetryTestUtils.getAndClearHistogram( - "FX_SESSION_RESTORE_CLOSED_TABS_NOT_SAVED" - ); - await BrowserTestUtils.closeWindow(testWindow1); closedIds.testWindow1 = SessionStore.getClosedWindowData()[0].closedId; await BrowserTestUtils.closeWindow(testWindow2); @@ -100,13 +96,7 @@ async function prepareClosedData() { ); await BrowserTestUtils.closeWindow(testWindow6); - TelemetryTestUtils.assertHistogram(closedTabsHistogram, 0, 1); - closedTabsHistogram.clear(); - await BrowserTestUtils.closeWindow(testWindow7); - TelemetryTestUtils.assertHistogram(closedTabsHistogram, 1, 1); - closedTabsHistogram.clear(); - return closedIds; } diff --git a/browser/components/sessionstore/test/browser_cookies.js b/browser/components/sessionstore/test/browser_cookies.js index f514efc777..96244dda1a 100644 --- a/browser/components/sessionstore/test/browser_cookies.js +++ b/browser/components/sessionstore/test/browser_cookies.js @@ -14,7 +14,7 @@ function promiseSetCookie(cookie) { function waitForCookieChanged() { return new Promise(resolve => { - Services.obs.addObserver(function observer(subj, topic, data) { + Services.obs.addObserver(function observer(subj, topic) { Services.obs.removeObserver(observer, topic); resolve(); }, "session-cookie-changed"); diff --git a/browser/components/sessionstore/test/browser_crashedTabs.js b/browser/components/sessionstore/test/browser_crashedTabs.js index 32c064dd81..797cf5ecf8 100644 --- a/browser/components/sessionstore/test/browser_crashedTabs.js +++ b/browser/components/sessionstore/test/browser_crashedTabs.js @@ -82,7 +82,7 @@ function promiseTabCrashedReady(browser) { return new Promise(resolve => { browser.addEventListener( "AboutTabCrashedReady", - function ready(e) { + function ready() { browser.removeEventListener("AboutTabCrashedReady", ready, false, true); resolve(); }, diff --git a/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js b/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js index 1b152139d7..6fc212eb2b 100644 --- a/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js +++ b/browser/components/sessionstore/test/browser_docshell_uuid_consistency.js @@ -4,38 +4,18 @@ add_task(async function duplicateTab() { let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL); await BrowserTestUtils.browserLoaded(tab.linkedBrowser); - if (!Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(tab.linkedBrowser, [], function () { - let docshell = content.window.docShell.QueryInterface( - Ci.nsIWebNavigation - ); - let shEntry = docshell.sessionHistory.legacySHistory.getEntryAtIndex(0); - is(shEntry.docshellID.toString(), docshell.historyID.toString()); - }); - } else { - let historyID = tab.linkedBrowser.browsingContext.historyID; - let shEntry = - tab.linkedBrowser.browsingContext.sessionHistory.getEntryAtIndex(0); - is(shEntry.docshellID.toString(), historyID.toString()); - } + let historyID = tab.linkedBrowser.browsingContext.historyID; + let shEntry = + tab.linkedBrowser.browsingContext.sessionHistory.getEntryAtIndex(0); + is(shEntry.docshellID.toString(), historyID.toString()); let tab2 = gBrowser.duplicateTab(tab); await BrowserTestUtils.browserLoaded(tab2.linkedBrowser); - if (!Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(tab2.linkedBrowser, [], function () { - let docshell = content.window.docShell.QueryInterface( - Ci.nsIWebNavigation - ); - let shEntry = docshell.sessionHistory.legacySHistory.getEntryAtIndex(0); - is(shEntry.docshellID.toString(), docshell.historyID.toString()); - }); - } else { - let historyID = tab2.linkedBrowser.browsingContext.historyID; - let shEntry = - tab2.linkedBrowser.browsingContext.sessionHistory.getEntryAtIndex(0); - is(shEntry.docshellID.toString(), historyID.toString()); - } + historyID = tab2.linkedBrowser.browsingContext.historyID; + shEntry = + tab2.linkedBrowser.browsingContext.sessionHistory.getEntryAtIndex(0); + is(shEntry.docshellID.toString(), historyID.toString()); BrowserTestUtils.removeTab(tab); BrowserTestUtils.removeTab(tab2); @@ -47,24 +27,10 @@ add_task(async function contentToChromeNavigate() { let tab = BrowserTestUtils.addTab(gBrowser, TEST_URL); await BrowserTestUtils.browserLoaded(tab.linkedBrowser); - if (!Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(tab.linkedBrowser, [], function () { - let docshell = content.window.docShell.QueryInterface( - Ci.nsIWebNavigation - ); - let sh = docshell.sessionHistory; - is(sh.count, 1); - is( - sh.legacySHistory.getEntryAtIndex(0).docshellID.toString(), - docshell.historyID.toString() - ); - }); - } else { - let historyID = tab.linkedBrowser.browsingContext.historyID; - let sh = tab.linkedBrowser.browsingContext.sessionHistory; - is(sh.count, 1); - is(sh.getEntryAtIndex(0).docshellID.toString(), historyID.toString()); - } + let historyID = tab.linkedBrowser.browsingContext.historyID; + let sh = tab.linkedBrowser.browsingContext.sessionHistory; + is(sh.count, 1); + is(sh.getEntryAtIndex(0).docshellID.toString(), historyID.toString()); // Force the browser to navigate to the chrome process. BrowserTestUtils.startLoadingURIString(tab.linkedBrowser, "about:config"); @@ -74,31 +40,17 @@ add_task(async function contentToChromeNavigate() { let docShell = tab.linkedBrowser.frameLoader.docShell; // 'cause we're in the chrome process, we can just directly poke at the shistory. - if (!Services.appinfo.sessionHistoryInParent) { - let sh = docShell.QueryInterface(Ci.nsIWebNavigation).sessionHistory; - - is(sh.count, 2); - is( - sh.legacySHistory.getEntryAtIndex(0).docshellID.toString(), - docShell.historyID.toString() - ); - is( - sh.legacySHistory.getEntryAtIndex(1).docshellID.toString(), - docShell.historyID.toString() - ); - } else { - let sh = docShell.browsingContext.sessionHistory; - - is(sh.count, 2); - is( - sh.getEntryAtIndex(0).docshellID.toString(), - docShell.historyID.toString() - ); - is( - sh.getEntryAtIndex(1).docshellID.toString(), - docShell.historyID.toString() - ); - } + sh = docShell.browsingContext.sessionHistory; + + is(sh.count, 2); + is( + sh.getEntryAtIndex(0).docshellID.toString(), + docShell.historyID.toString() + ); + is( + sh.getEntryAtIndex(1).docshellID.toString(), + docShell.historyID.toString() + ); BrowserTestUtils.removeTab(tab); }); diff --git a/browser/components/sessionstore/test/browser_frame_history.js b/browser/components/sessionstore/test/browser_frame_history.js index 1db32e74ab..eeb6de177c 100644 --- a/browser/components/sessionstore/test/browser_frame_history.js +++ b/browser/components/sessionstore/test/browser_frame_history.js @@ -206,7 +206,7 @@ function waitForLoadsInBrowser(aBrowser, aLoadCount) { let loadCount = 0; aBrowser.addEventListener( "load", - function listener(aEvent) { + function listener() { if (++loadCount < aLoadCount) { info( "Got " + loadCount + " loads, waiting until we have " + aLoadCount diff --git a/browser/components/sessionstore/test/browser_frametree.js b/browser/components/sessionstore/test/browser_frametree.js index ce1f5cdf0b..06e0379c59 100644 --- a/browser/components/sessionstore/test/browser_frametree.js +++ b/browser/components/sessionstore/test/browser_frametree.js @@ -98,7 +98,7 @@ add_task(async function test_frametree_dynamic() { is(await enumerateIndexes(browser), "0,1", "correct indexes 0 and 1"); // Remopve a non-dynamic iframe. - await SpecialPowers.spawn(browser, [URL], async ([url]) => { + await SpecialPowers.spawn(browser, [URL], async () => { // Remove the first iframe, which should be a non-dynamic iframe. content.document.body.removeChild( content.document.getElementsByTagName("iframe")[0] diff --git a/browser/components/sessionstore/test/browser_history_persist.js b/browser/components/sessionstore/test/browser_history_persist.js index f6749b02e3..1cf8bf1b8d 100644 --- a/browser/components/sessionstore/test/browser_history_persist.js +++ b/browser/components/sessionstore/test/browser_history_persist.js @@ -25,54 +25,27 @@ add_task(async function check_history_not_persisted() { browser = tab.linkedBrowser; await promiseTabState(tab, state); - if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(browser, [], function () { - let sessionHistory = - docShell.browsingContext.childSessionHistory.legacySHistory; - - is(sessionHistory.count, 1, "Should be a single history entry"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:blank", - "Should be the right URL" - ); - }); - } else { - let sessionHistory = browser.browsingContext.sessionHistory; - - is(sessionHistory.count, 1, "Should be a single history entry"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:blank", - "Should be the right URL" - ); - } + let sessionHistory = browser.browsingContext.sessionHistory; + + is(sessionHistory.count, 1, "Should be a single history entry"); + is( + sessionHistory.getEntryAtIndex(0).URI.spec, + "about:blank", + "Should be the right URL" + ); // Load a new URL into the tab, it should replace the about:blank history entry BrowserTestUtils.startLoadingURIString(browser, "about:robots"); await promiseBrowserLoaded(browser, false, "about:robots"); - if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(browser, [], function () { - let sessionHistory = - docShell.browsingContext.childSessionHistory.legacySHistory; - - is(sessionHistory.count, 1, "Should be a single history entry"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:robots", - "Should be the right URL" - ); - }); - } else { - let sessionHistory = browser.browsingContext.sessionHistory; - - is(sessionHistory.count, 1, "Should be a single history entry"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:robots", - "Should be the right URL" - ); - } + + sessionHistory = browser.browsingContext.sessionHistory; + + is(sessionHistory.count, 1, "Should be a single history entry"); + is( + sessionHistory.getEntryAtIndex(0).URI.spec, + "about:robots", + "Should be the right URL" + ); // Cleanup. BrowserTestUtils.removeTab(tab); @@ -99,64 +72,33 @@ add_task(async function check_history_default_persisted() { tab = BrowserTestUtils.addTab(gBrowser, "about:blank"); browser = tab.linkedBrowser; await promiseTabState(tab, state); - if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(browser, [], function () { - let sessionHistory = - docShell.browsingContext.childSessionHistory.legacySHistory; - - is(sessionHistory.count, 1, "Should be a single history entry"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:blank", - "Should be the right URL" - ); - }); - } else { - let sessionHistory = browser.browsingContext.sessionHistory; - - is(sessionHistory.count, 1, "Should be a single history entry"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:blank", - "Should be the right URL" - ); - } + + let sessionHistory = browser.browsingContext.sessionHistory; + + is(sessionHistory.count, 1, "Should be a single history entry"); + is( + sessionHistory.getEntryAtIndex(0).URI.spec, + "about:blank", + "Should be the right URL" + ); // Load a new URL into the tab, it should replace the about:blank history entry BrowserTestUtils.startLoadingURIString(browser, "about:robots"); await promiseBrowserLoaded(browser, false, "about:robots"); - if (!SpecialPowers.Services.appinfo.sessionHistoryInParent) { - await SpecialPowers.spawn(browser, [], function () { - let sessionHistory = - docShell.browsingContext.childSessionHistory.legacySHistory; - - is(sessionHistory.count, 2, "Should be two history entries"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:blank", - "Should be the right URL" - ); - is( - sessionHistory.getEntryAtIndex(1).URI.spec, - "about:robots", - "Should be the right URL" - ); - }); - } else { - let sessionHistory = browser.browsingContext.sessionHistory; - - is(sessionHistory.count, 2, "Should be two history entries"); - is( - sessionHistory.getEntryAtIndex(0).URI.spec, - "about:blank", - "Should be the right URL" - ); - is( - sessionHistory.getEntryAtIndex(1).URI.spec, - "about:robots", - "Should be the right URL" - ); - } + + sessionHistory = browser.browsingContext.sessionHistory; + + is(sessionHistory.count, 2, "Should be two history entries"); + is( + sessionHistory.getEntryAtIndex(0).URI.spec, + "about:blank", + "Should be the right URL" + ); + is( + sessionHistory.getEntryAtIndex(1).URI.spec, + "about:robots", + "Should be the right URL" + ); // Cleanup. BrowserTestUtils.removeTab(tab); diff --git a/browser/components/sessionstore/test/browser_newtab_userTypedValue.js b/browser/components/sessionstore/test/browser_newtab_userTypedValue.js index 755a1f2859..cd17c9a9f0 100644 --- a/browser/components/sessionstore/test/browser_newtab_userTypedValue.js +++ b/browser/components/sessionstore/test/browser_newtab_userTypedValue.js @@ -16,7 +16,7 @@ add_task(async function () { ); // This opens about:newtab: - win.BrowserOpenTab(); + win.BrowserCommands.openTab(); let tab = await tabOpenedAndSwitchedTo; is(win.gURLBar.value, "", "URL bar should be empty"); is(tab.linkedBrowser.userTypedValue, null, "userTypedValue should be null"); @@ -55,7 +55,7 @@ add_task(async function () { for (let url of gInitialPages) { if (url == BROWSER_NEW_TAB_URL) { - continue; // We tested about:newtab using BrowserOpenTab() above. + continue; // We tested about:newtab using BrowserCommands.openTab() above. } info("Testing " + url + " - " + new Date()); await BrowserTestUtils.openNewForegroundTab(win.gBrowser, url); diff --git a/browser/components/sessionstore/test/browser_oldformat.toml b/browser/components/sessionstore/test/browser_oldformat.toml new file mode 100644 index 0000000000..7edc51dc67 --- /dev/null +++ b/browser/components/sessionstore/test/browser_oldformat.toml @@ -0,0 +1,301 @@ +[DEFAULT] +support-files = [ + "head.js", + "browser_formdata_sample.html", + "browser_formdata_xpath_sample.html", + "browser_frametree_sample.html", + "browser_frametree_sample_frameset.html", + "browser_frametree_sample_iframes.html", + "browser_frame_history_index.html", + "browser_frame_history_index2.html", + "browser_frame_history_index_blank.html", + "browser_frame_history_a.html", + "browser_frame_history_b.html", + "browser_frame_history_c.html", + "browser_frame_history_c1.html", + "browser_frame_history_c2.html", + "browser_formdata_format_sample.html", + "browser_sessionHistory_slow.sjs", + "browser_scrollPositions_sample.html", + "browser_scrollPositions_sample2.html", + "browser_scrollPositions_sample_frameset.html", + "browser_scrollPositions_readerModeArticle.html", + "browser_sessionStorage.html", + "browser_speculative_connect.html", + "browser_248970_b_sample.html", + "browser_339445_sample.html", + "browser_423132_sample.html", + "browser_447951_sample.html", + "browser_454908_sample.html", + "browser_456342_sample.xhtml", + "browser_463205_sample.html", + "browser_463206_sample.html", + "browser_466937_sample.html", + "browser_485482_sample.html", + "browser_637020_slow.sjs", + "browser_662743_sample.html", + "browser_739531_sample.html", + "browser_739531_frame.html", + "browser_911547_sample.html", + "browser_911547_sample.html^headers^", + "coopHeaderCommon.sjs", + "restore_redirect_http.html", + "restore_redirect_http.html^headers^", + "restore_redirect_js.html", + "restore_redirect_target.html", + "browser_1234021_page.html", + "browser_1284886_suspend_tab.html", + "browser_1284886_suspend_tab_2.html", + "empty.html", + "coop_coep.html", + "coop_coep.html^headers^", +] +# remove this after bug 1628486 is landed +prefs = [ + "network.cookie.cookieBehavior=5", + "gfx.font_rendering.fallback.async=false", + "browser.sessionstore.closedTabsFromAllWindows=true", + "browser.sessionstore.closedTabsFromClosedWindows=true", +] + +#NB: the following are disabled +# browser_464620_a.html +# browser_464620_b.html +# browser_464620_xd.html + +#disabled-for-intermittent-failures--bug-766044, browser_459906_empty.html +#disabled-for-intermittent-failures--bug-766044, browser_459906_sample.html +#disabled-for-intermittent-failures--bug-765389, browser_461743_sample.html + +["browser_1234021.js"] + +["browser_1284886_suspend_tab.js"] + +["browser_1446343-windowsize.js"] +skip-if = ["os == 'linux'"] # Bug 1600180 + +["browser_248970_b_perwindowpb.js"] +# Disabled because of leaks. +# Re-enabling and rewriting this test is tracked in bug 936919. +skip-if = ["true"] + +["browser_339445.js"] + +["browser_345898.js"] + +["browser_350525.js"] + +["browser_354894_perwindowpb.js"] + +["browser_367052.js"] + +["browser_393716.js"] +skip-if = ["debug"] # Bug 1507747 + +["browser_394759_basic.js"] +# Disabled for intermittent failures, bug 944372. +skip-if = ["true"] + +["browser_394759_behavior.js"] +https_first_disabled = true + +["browser_394759_perwindowpb.js"] + +["browser_394759_purge.js"] + +["browser_423132.js"] + +["browser_447951.js"] + +["browser_454908.js"] + +["browser_456342.js"] + +["browser_461634.js"] + +["browser_463205.js"] + +["browser_463206.js"] + +["browser_464199.js"] +# Disabled for frequent intermittent failures + +["browser_464620_a.js"] +skip-if = ["true"] + +["browser_464620_b.js"] +skip-if = ["true"] + +["browser_465215.js"] + +["browser_465223.js"] + +["browser_466937.js"] + +["browser_467409-backslashplosion.js"] + +["browser_477657.js"] +skip-if = ["os == 'linux' && os_version == '18.04'"] # bug 1610668 for ubuntu 18.04 + +["browser_480893.js"] + +["browser_485482.js"] + +["browser_485563.js"] + +["browser_490040.js"] + +["browser_491168.js"] + +["browser_491577.js"] +skip-if = [ + "verify && debug && os == 'mac'", + "verify && debug && os == 'win'", +] + +["browser_495495.js"] + +["browser_500328.js"] + +["browser_514751.js"] + +["browser_522375.js"] + +["browser_522545.js"] +skip-if = ["true"] # Bug 1380968 + +["browser_524745.js"] +skip-if = [ + "win10_2009 && !ccov", # Bug 1418627 + "os == 'linux'", # Bug 1803187 +] + +["browser_528776.js"] + +["browser_579868.js"] + +["browser_579879.js"] +skip-if = ["os == 'linux' && (debug || asan)"] # Bug 1234404 + +["browser_581937.js"] + +["browser_586068-apptabs.js"] + +["browser_586068-apptabs_ondemand.js"] +skip-if = ["verify && (os == 'mac' || os == 'win')"] + +["browser_586068-browser_state_interrupted.js"] + +["browser_586068-cascade.js"] + +["browser_586068-multi_window.js"] + +["browser_586068-reload.js"] +https_first_disabled = true + +["browser_586068-select.js"] + +["browser_586068-window_state.js"] + +["browser_586068-window_state_override.js"] + +["browser_586147.js"] + +["browser_588426.js"] + +["browser_590268.js"] + +["browser_590563.js"] + +["browser_595601-restore_hidden.js"] + +["browser_597071.js"] +skip-if = ["true"] # Needs to be rewritten as Marionette test, bug 995916 + +["browser_600545.js"] + +["browser_601955.js"] + +["browser_607016.js"] + +["browser_615394-SSWindowState_events_duplicateTab.js"] + +["browser_615394-SSWindowState_events_setBrowserState.js"] +skip-if = ["verify && debug && os == 'mac'"] + +["browser_615394-SSWindowState_events_setTabState.js"] + +["browser_615394-SSWindowState_events_setWindowState.js"] +https_first_disabled = true + +["browser_615394-SSWindowState_events_undoCloseTab.js"] + +["browser_615394-SSWindowState_events_undoCloseWindow.js"] +skip-if = [ + "os == 'win' && !debug", # Bug 1572554 + "os == 'linux'", # Bug 1572554 +] + +["browser_618151.js"] + +["browser_623779.js"] + +["browser_624727.js"] + +["browser_625016.js"] +skip-if = [ + "os == 'mac'", # Disabled on OS X: + "os == 'linux'", # linux, Bug 1348583 + "os == 'win' && debug", # Bug 1430977 +] + +["browser_628270.js"] + +["browser_635418.js"] + +["browser_636279.js"] + +["browser_637020.js"] + +["browser_645428.js"] + +["browser_659591.js"] + +["browser_662743.js"] + +["browser_662812.js"] +skip-if = ["verify"] + +["browser_665702-state_session.js"] + +["browser_682507.js"] + +["browser_687710.js"] + +["browser_687710_2.js"] +https_first_disabled = true + +["browser_694378.js"] + +["browser_701377.js"] +skip-if = [ + "verify && debug && os == 'win'", + "verify && debug && os == 'mac'", +] + +["browser_705597.js"] + +["browser_707862.js"] + +["browser_739531.js"] + +["browser_739805.js"] + +["browser_819510_perwindowpb.js"] +skip-if = ["true"] # Bug 1284312, Bug 1341980, bug 1381451 + +["browser_906076_lazy_tabs.js"] +https_first_disabled = true +skip-if = ["os == 'linux' && os_version == '18.04'"] # bug 1446464 + +["browser_911547.js"] diff --git a/browser/components/sessionstore/test/browser_parentProcessRestoreHash.js b/browser/components/sessionstore/test/browser_parentProcessRestoreHash.js index 442914d580..ad8144f864 100644 --- a/browser/components/sessionstore/test/browser_parentProcessRestoreHash.js +++ b/browser/components/sessionstore/test/browser_parentProcessRestoreHash.js @@ -12,7 +12,7 @@ const TESTURL = "about:testpageforsessionrestore#foo"; let TestAboutPage = { QueryInterface: ChromeUtils.generateQI(["nsIAboutModule"]), - getURIFlags(aURI) { + getURIFlags() { // No CAN_ or MUST_LOAD_IN_CHILD means this loads in the parent: return ( Ci.nsIAboutModule.ALLOW_SCRIPT | @@ -73,7 +73,7 @@ add_task(async function () { r => (resolveLocationChangePromise = r) ); let wpl = { - onStateChange(listener, request, state, status) { + onStateChange(listener, request, state, _status) { let location = request.QueryInterface(Ci.nsIChannel).originalURI; // Ignore about:blank loads. let docStop = diff --git a/browser/components/sessionstore/test/browser_restoreLastClosedTabOrWindowOrSession.js b/browser/components/sessionstore/test/browser_restoreLastClosedTabOrWindowOrSession.js index cc340c4617..10551238f5 100644 --- a/browser/components/sessionstore/test/browser_restoreLastClosedTabOrWindowOrSession.js +++ b/browser/components/sessionstore/test/browser_restoreLastClosedTabOrWindowOrSession.js @@ -208,7 +208,7 @@ add_task(async function test_reopen_last_tab_if_no_closed_actions() { gBrowser, url: "about:blank", }, - async browser => { + async () => { const TEST_URL = "https://example.com/"; let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, TEST_URL); let update = BrowserTestUtils.waitForSessionStoreUpdate(tab); diff --git a/browser/components/sessionstore/test/browser_send_async_message_oom.js b/browser/components/sessionstore/test/browser_send_async_message_oom.js deleted file mode 100644 index 7e807f2fbd..0000000000 --- a/browser/components/sessionstore/test/browser_send_async_message_oom.js +++ /dev/null @@ -1,75 +0,0 @@ -/* Any copyright is dedicated to the Public Domain. - http://creativecommons.org/publicdomain/zero/1.0/ */ -/* eslint-disable mozilla/no-arbitrary-setTimeout */ - -const HISTOGRAM_NAME = "FX_SESSION_RESTORE_SEND_UPDATE_CAUSED_OOM"; - -/** - * Test that an OOM in sendAsyncMessage in a framescript will be reported - * to Telemetry. - */ - -add_setup(async function () { - Services.telemetry.canRecordExtended = true; -}); - -function frameScript() { - // Make send[A]syncMessage("SessionStore:update", ...) simulate OOM. - // Other operations are unaffected. - let mm = docShell.messageManager; - - let wrap = function (original) { - return function (name, ...args) { - if (name != "SessionStore:update") { - return original(name, ...args); - } - throw new Components.Exception( - "Simulated OOM", - Cr.NS_ERROR_OUT_OF_MEMORY - ); - }; - }; - - mm.sendAsyncMessage = wrap(mm.sendAsyncMessage.bind(mm)); - mm.sendSyncMessage = wrap(mm.sendSyncMessage.bind(mm)); -} - -add_task(async function () { - // Capture original state. - let snapshot = Services.telemetry.getHistogramById(HISTOGRAM_NAME).snapshot(); - - // Open a browser, configure it to cause OOM. - let newTab = BrowserTestUtils.addTab(gBrowser, "about:robots"); - let browser = newTab.linkedBrowser; - await ContentTask.spawn(browser, null, frameScript); - - let promiseReported = new Promise(resolve => { - browser.messageManager.addMessageListener("SessionStore:error", resolve); - }); - - // Attempt to flush. This should fail. - let promiseFlushed = TabStateFlusher.flush(browser); - promiseFlushed.then(success => { - if (success) { - throw new Error("Flush should have failed"); - } - }); - - // The frame script should report an error. - await promiseReported; - - // Give us some time to handle that error. - await new Promise(resolve => setTimeout(resolve, 10)); - - // By now, Telemetry should have been updated. - let snapshot2 = Services.telemetry - .getHistogramById(HISTOGRAM_NAME) - .snapshot(); - gBrowser.removeTab(newTab); - - Assert.ok(snapshot2.sum > snapshot.sum); -}); - -add_task(async function cleanup() { - Services.telemetry.canRecordExtended = false; -}); diff --git a/browser/components/sessionstore/test/browser_sessionHistory.js b/browser/components/sessionstore/test/browser_sessionHistory.js index 69dcc4995b..34b1ef7d09 100644 --- a/browser/components/sessionstore/test/browser_sessionHistory.js +++ b/browser/components/sessionstore/test/browser_sessionHistory.js @@ -296,12 +296,9 @@ add_task(async function test_slow_subframe_load() { * Ensure that document wireframes can be persisted when they're enabled. */ add_task(async function test_wireframes() { - // Wireframes only works when Fission and SHIP are enabled. - if ( - !Services.appinfo.fissionAutostart || - !Services.appinfo.sessionHistoryInParent - ) { - ok(true, "Skipping test_wireframes when Fission or SHIP is not enabled."); + // Wireframes only works when Fission is enabled. + if (!Services.appinfo.fissionAutostart) { + ok(true, "Skipping test_wireframes when Fission is not enabled."); return; } diff --git a/browser/components/sessionstore/test/browser_sessionStoreContainer.js b/browser/components/sessionstore/test/browser_sessionStoreContainer.js index 86833dea82..e4f3ecea9f 100644 --- a/browser/components/sessionstore/test/browser_sessionStoreContainer.js +++ b/browser/components/sessionstore/test/browser_sessionStoreContainer.js @@ -14,7 +14,7 @@ add_task(async function () { await promiseBrowserLoaded(browser); let tab2 = gBrowser.duplicateTab(tab); - Assert.equal(tab2.getAttribute("usercontextid"), i); + Assert.equal(tab2.getAttribute("usercontextid") || "", i); let browser2 = tab2.linkedBrowser; await promiseTabRestored(tab2); diff --git a/browser/components/sessionstore/test/browser_should_restore_tab.js b/browser/components/sessionstore/test/browser_should_restore_tab.js index ab9513083a..958222141e 100644 --- a/browser/components/sessionstore/test/browser_should_restore_tab.js +++ b/browser/components/sessionstore/test/browser_should_restore_tab.js @@ -13,7 +13,7 @@ async function check_tab_close_notification(openedTab, expectNotification) { let tabClosed = BrowserTestUtils.waitForTabClosing(openedTab); let notified = false; - function topicObserver(_, topic) { + function topicObserver() { notified = true; } Services.obs.addObserver(topicObserver, NOTIFY_CLOSED_OBJECTS_CHANGED); @@ -73,7 +73,7 @@ add_task(async function test_about_new_tab() { () => {} ); // This opens about:newtab: - win.BrowserOpenTab(); + win.BrowserCommands.openTab(); let tab = await tabOpenedAndSwitchedTo; await check_tab_close_notification(tab, false); }); diff --git a/browser/components/sessionstore/test/browser_windowStateContainer.js b/browser/components/sessionstore/test/browser_windowStateContainer.js index f0d6f42d39..e2d2d256eb 100644 --- a/browser/components/sessionstore/test/browser_windowStateContainer.js +++ b/browser/components/sessionstore/test/browser_windowStateContainer.js @@ -11,7 +11,7 @@ add_setup(async function () { function promiseTabsRestored(win, nExpected) { return new Promise(resolve => { let nReceived = 0; - function handler(event) { + function handler() { if (++nReceived === nExpected) { win.gBrowser.tabContainer.removeEventListener( "SSTabRestored", diff --git a/browser/components/sessionstore/test/head.js b/browser/components/sessionstore/test/head.js index d475fa86a1..85db6e9d5e 100644 --- a/browser/components/sessionstore/test/head.js +++ b/browser/components/sessionstore/test/head.js @@ -144,7 +144,7 @@ function waitForTopic(aTopic, aTimeout, aCallback) { aCallback(false); }, aTimeout); - function observer(subject, topic, data) { + function observer() { removeObserver(); timeout = clearTimeout(timeout); executeSoon(() => aCallback(true)); @@ -268,7 +268,7 @@ var gWebProgressListener = { } }, - onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, aStatus) { + onStateChange(aBrowser, aWebProgress, aRequest, aStateFlags, _aStatus) { if ( aStateFlags & Ci.nsIWebProgressListener.STATE_STOP && aStateFlags & Ci.nsIWebProgressListener.STATE_IS_NETWORK && @@ -298,7 +298,7 @@ var gProgressListener = { } }, - observe(browser, topic, data) { + observe(browser) { gProgressListener.onRestored(browser); }, @@ -451,7 +451,7 @@ function modifySessionStorage(browser, storageData, storageOptions = {}) { return SpecialPowers.spawn( browsingContext, [[storageData, storageOptions]], - async function ([data, options]) { + async function ([data]) { let frame = content; let keys = new Set(Object.keys(data)); let isClearing = !keys.size; @@ -558,35 +558,9 @@ function setPropertyOfFormField(browserContext, selector, propName, newValue) { } function promiseOnHistoryReplaceEntry(browser) { - if (SpecialPowers.Services.appinfo.sessionHistoryInParent) { - return new Promise(resolve => { - let sessionHistory = browser.browsingContext?.sessionHistory; - if (sessionHistory) { - var historyListener = { - OnHistoryNewEntry() {}, - OnHistoryGotoIndex() {}, - OnHistoryPurge() {}, - OnHistoryReload() { - return true; - }, - - OnHistoryReplaceEntry() { - resolve(); - }, - - QueryInterface: ChromeUtils.generateQI([ - "nsISHistoryListener", - "nsISupportsWeakReference", - ]), - }; - - sessionHistory.addSHistoryListener(historyListener); - } - }); - } - - return SpecialPowers.spawn(browser, [], () => { - return new Promise(resolve => { + return new Promise(resolve => { + let sessionHistory = browser.browsingContext?.sessionHistory; + if (sessionHistory) { var historyListener = { OnHistoryNewEntry() {}, OnHistoryGotoIndex() {}, @@ -605,13 +579,8 @@ function promiseOnHistoryReplaceEntry(browser) { ]), }; - var { sessionHistory } = this.docShell.QueryInterface( - Ci.nsIWebNavigation - ); - if (sessionHistory) { - sessionHistory.legacySHistory.addSHistoryListener(historyListener); - } - }); + sessionHistory.addSHistoryListener(historyListener); + } }); } |